require 'socket' include Socket::Constants # A PipeSocket is an object that def error(msg) puts "PipeSocket: #{msg}" exit 1 end class PipeSocket def initialize(name, addr, port) @path = name @port = port @addr = addr if File.exist?(name) error("File #{name} already exists.") end end def connect puts "Opening #{@path} for read/write" File.mkfifo(@path) File.open(@path, "r+") { |pipe| loop do socket = Socket.tcp(@addr, @port) msg = pipe.gets socket.puts msg resp = socket.gets unless resp.nil? puts resp.chomp break if resp.chomp == "shutdown" end break if msg.chomp == "shutdown" socket.close end } puts "Closing #{@path}" File.delete(@path) end end #not useful? class SocketPipe def initialize(name, addr, port) @path, @addr, @port = name, addr, port if File.exist?(name) error("File #{name} already exists.") end end def listen puts "Opening #{@path} for reading" File.mkfifo(@path) Socket.tcp_server_loop(@port) { |sock| msg = sock.gets File.open(@path, "r+") { |pipe| pipe.puts msg } sock.close break if msg.chomp == "shutdown" } puts "Closing #{@path}" File.delete(@path) end end # BackShot should be a server listening for # a PipeSocket connection, which receives a # ruby file containing an instance of the # BackShot class class BackShot attr_accessor :send_back attr_accessor :command @@inst = 0 def initialize(addr, port) @name = "backshot#{@@inst}" @@inst += 1 @addr = addr @port = port @return = nil @execute = nil #a channel to send back the result end def BackShot.message(msg) puts "BackShot: #{msg}" end def listen BackShot.message "listening on port #{@port}" loop do #hello Socket.tcp_server_loop(@port) { |sock| msg = sock.gets if msg.chomp == "hello" sock.puts "hello" break else sock.puts "goodbye" end sock.close } def recv_file(filename, expected_size) Socket.tcp_server_loop(@port) { |sock| data = sock.recv(expected_size) File.open(filename, "w+") { |file| file.write data } sock.puts "ok" } end #recv files Socket.tcp_server_loop(@port) { |sock| msg = sock.gets if msg.start_with? "file" puts "file info recv" # file name size file, name, size = msg.split(" ") size = size.chomp sock.puts "ok" recv_file(name, size) elsif msg.start_with? "run" puts "run recv" # execute file exec, name = msg.split(" ") @execute = name sock.puts "ok" #sock.close elsif msg.start_with? "return" puts "return recv" ret, name = msg.split(" ") @return = name if @execute == nil sock.puts "error" # sock.close break end `./#{@execute}` sock.write File.read(@return) msg = sock.gets if msg.chomp == "thanks" @execute = nil #sock.close break end else sock.puts "what" #sock.close end } end end end bs = BackShot.new "127.0.0.1", 8081 bs.listen