This mixin provides the framework and interface for implementing a streaming server that can listen for and accept stream client connections. Stream servers extend this class and are required to implement the following methods:
accept fd
This callback procedure can be set and will be called when a client disconnects from the server.
This method closes a client connection and cleans up the resources associated with it.
# File lib/rex/io/stream_server.rb, line 92 def close_client(client) if (client) clients.delete(client) begin client.close rescue IOError end end end
This callback is notified when a client connection has closed.
# File lib/rex/io/stream_server.rb, line 54 def on_client_close(client) if (on_client_close_proc) on_client_close_proc.call(client) end end
This callback is notified when a client connects.
# File lib/rex/io/stream_server.rb, line 35 def on_client_connect(client) if (on_client_connect_proc) on_client_connect_proc.call(client) end end
This callback is notified when a client connection has data that needs to be processed.
# File lib/rex/io/stream_server.rb, line 45 def on_client_data(client) if (on_client_data_proc) on_client_data_proc.call(client) end end
Start monitoring the listener socket for connections and keep track of all client connections.
# File lib/rex/io/stream_server.rb, line 64 def start self.clients = [] self.client_waiter = ::Queue.new self.listener_thread = Rex::ThreadFactory.spawn("StreamServerListener", false) { monitor_listener } self.clients_thread = Rex::ThreadFactory.spawn("StreamServerClientMonitor", false) { monitor_clients } end
This method monitors client connections for data and calls the on_client_data routine when new data arrives.
# File lib/rex/io/stream_server.rb, line 178 def monitor_clients begin # Wait for a notify if our client list is empty if (clients.length == 0) self.client_waiter.pop next end sd = Rex::ThreadSafe.select(clients, nil, nil, nil) sd[0].each { |cfd| begin on_client_data(cfd) rescue ::EOFError, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED on_client_close(cfd) close_client(cfd) rescue ::Interrupt raise $! rescue ::Exception close_client(cfd) elog("Error in stream server client monitor: #{$!}") rlog(ExceptionCallStack) end } rescue ::Rex::StreamClosedError => e # Remove the closed stream from the list clients.delete(e.stream) rescue ::Interrupt raise $! rescue ::Exception elog("Error in stream server client monitor: #{$!}") rlog(ExceptionCallStack) end while true end
This method monitors the listener socket for new connections and calls the on_client_connect callback routine.
# File lib/rex/io/stream_server.rb, line 142 def monitor_listener while true begin cli = accept if not cli elog("The accept() returned nil in stream server listener monitor: #{fd.inspect}") ::IO.select(nil, nil, nil, 0.10) next end # Append to the list of clients self.clients << cli # Initialize the connection processing on_client_connect(cli) # Notify the client monitor self.client_waiter.push(cli) # Skip exceptions caused by accept() [ SSL ] rescue ::EOFError, ::Errno::ECONNRESET, ::Errno::ENOTCONN, ::Errno::ECONNABORTED rescue ::Interrupt raise $! rescue ::Exception elog("Error in stream server server monitor: #{$!}") rlog(ExceptionCallStack) break end end end
Generated with the Darkfish Rdoc Generator 2.