class MindControl::Server
Listens UNIX socket and starts REPL
sessions.
Attributes
repl[R]
socket_path[R]
Public Class Methods
new( socket_path, repl )
click to toggle source
@param [String] socket_path
Absolute path of UNIX socket. @param [#start] repl Instance of REPL
(@see MindControl::REPL
).
# File lib/mind_control/server.rb, line 23 def initialize( socket_path, repl ) @socket_path, @repl = socket_path, repl end
Public Instance Methods
get_client_id( socket )
click to toggle source
Return id string for connected client.
@param [UNIXSocket] socket Client
socket. @return [String]
# File lib/mind_control/server.rb, line 111 def get_client_id( socket ) # UNIX socket return effective UID/GID for connected client euid, _ = socket.getpeereid # Find record in /etc/passwd user_info = Etc.getpwuid euid return "#{user_info.name} (#{user_info.gecos})" end
handle_client_connection( socket, client_id )
click to toggle source
Starts REPL
session in separate thread for connected client.
@param [Socket] socket Client
socket. @param [String] client_id ID string for connected client.
# File lib/mind_control/server.rb, line 127 def handle_client_connection( socket, client_id ) info "Starting new MindControl session for user #{client_id} ..." # Client will send us his STDIN and STDOUT client_stdin, client_stdout = socket.recv_io, socket.recv_io # Start REPL repl.start client_stdin, client_stdout info "MindControl session for user #{client_id} has ended!" rescue Exception => e error_message = "REPL exception: #{e.message} (#{e.class.name})\n#{e.backtrace.join( "\n" )}" error error_message # Send error to client client_stdout.puts error_message if client_stdout end
running?()
click to toggle source
Server
is running?
# File lib/mind_control/server.rb, line 79 def running? @server_thread && @server_thread.alive? end
start()
click to toggle source
Start server.
# File lib/mind_control/server.rb, line 30 def start return if running? info "Starting MindControl server on #{socket_path} ..." # Storage for client threads client_threads = ThreadGroup.new # Start acceptor thread @server_thread = Thread.new do begin start_server_loop( socket_path ) do |client_socket| # Process client in new thread client_threads.add Thread.new { begin handle_client_connection( client_socket, get_client_id( client_socket )) ensure # We MUST close the socket client_socket.close end } end ensure # Kill all client threads on server stop client_threads.list.each( &:kill ) end end # We should known if our server has failed @server_thread.abort_on_exception = true end
start_server_loop( socket_path, &block )
click to toggle source
Starts UNIX server, accepts clients and yields its sockets in loop.
@param [String] socket_path
Path to UNIX socket to bind to. @yeilds [UNIXSocket]
# File lib/mind_control/server.rb, line 89 def start_server_loop( socket_path, &block ) # Remove old file FileUtils.rm_f socket_path FileUtils.mkdir_p File.dirname( socket_path ) UNIXServer.open( socket_path ) do |server| loop do # Wait for client block.call server.accept end end ensure # Cleanup FileUtils.rm socket_path end
stop()
click to toggle source
Stop server.
# File lib/mind_control/server.rb, line 65 def stop return unless running? info "Stopping MindControl server ..." # Kill acceptor thread @server_thread.kill @server_thread.join @server_thread = nil end