class Tork::Server
Public Class Methods
address(program=$0)
click to toggle source
# File lib/tork/server.rb, line 10 def self.address program=$0 ".#{program}.sock" end
new()
click to toggle source
# File lib/tork/server.rb, line 14 def initialize begin @welcome = UNIXServer.open(address = Server.address) # UNIX domain socket files are not automatically deleted on close at_exit { File.delete address if File.socket? address } rescue Errno::EADDRINUSE # another instance of this program is already running in the same # directory so become a remote control for it rather than exiting warn "#{$0}: remotely controlling existing instance..." exec 'tork-remote', $0, *ARGV end # only JSON messages are supposed to be emitted on STDOUT # so make puts() in the user code write to STDERR instead @stdout = STDOUT.dup STDOUT.reopen STDERR @servers = Set.new.add(@welcome) @clients = Set.new; join STDIN # parent process connected on STDIN end
Public Instance Methods
loop()
click to toggle source
# File lib/tork/server.rb, line 35 def loop catch :quit do while @clients.include? STDIN IO.select((@servers + @clients).to_a).first.each do |stream| if stream == @welcome join stream.accept elsif (stream.eof? rescue true) part stream elsif @command = hear(stream, stream.gets) and not @command.empty? recv stream, @command end end end end end
quit()
click to toggle source
# File lib/tork/server.rb, line 53 def quit throw :quit end
Protected Instance Methods
hear(sender, message)
click to toggle source
Returns nil if the message received was not meant for processing.
# File lib/tork/server.rb, line 68 def hear sender, message JSON.parse message rescue JSON::ParserError => error if @clients.include? sender # accept non-JSON "command lines" from clients Shellwords.split message else # forward tell() output from servers to clients tell @clients, message, false nil end end
join(client)
click to toggle source
# File lib/tork/server.rb, line 59 def join client @clients.add client end
part(client)
click to toggle source
# File lib/tork/server.rb, line 63 def part client @clients.delete client end
pclose(child)
click to toggle source
# File lib/tork/server.rb, line 128 def pclose child child.disconnect if @servers.delete? child end
popen(command)
click to toggle source
# File lib/tork/server.rb, line 122 def popen command child = Bridge.new(command) @servers.add child child end
recv(client, command)
click to toggle source
Sets the @client variable to the client we are currently serving.
# File lib/tork/server.rb, line 82 def recv client, command @client = client __send__(*command) rescue => error tell client, error end
send(one_or_more_clients, message)
click to toggle source
# File lib/tork/server.rb, line 89 def send one_or_more_clients, message tell one_or_more_clients, JSON.dump(message), false end
tell(one_or_more_clients, message, prefix=true)
click to toggle source
# File lib/tork/server.rb, line 93 def tell one_or_more_clients, message, prefix=true if message.kind_of? Exception message = [message.inspect, message.backtrace] end if prefix message = Array(message).join("\n").gsub(/^/, "#{$0}: ") end targets = if one_or_more_clients.respond_to? :to_io [one_or_more_clients] else Array(one_or_more_clients) end targets.each do |target| target = @stdout if target == STDIN begin target.puts message target.flush rescue Errno::EPIPE # the target closed itself asynchronously # https://github.com/sunaku/tork/issues/53 next end end end