fixed up the ol' http server

git-svn-id: file:///home/svn/incoming/trunk@2843 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Matt Miller 2005-08-22 02:36:09 +00:00
parent d99e5b4f89
commit 2b82d4c4c4
3 changed files with 146 additions and 75 deletions

View File

@ -40,6 +40,131 @@ module StreamServer
super super
end end
##
#
# Default server monitoring and client management implementation follows
# below.
#
##
def on_client_connect(client)
if (on_client_connect_proc)
on_client_connect_proc.call(client)
end
end
def on_client_data(client)
if (on_client_data_proc)
on_client_data_proc.call(client)
end
end
def on_client_close(client)
if (on_client_close_proc)
on_client_close_proc.call(client)
end
end
#
# Start monitoring the listener socket for connections and keep track of
# all client connections.
#
def start
self.clients = []
self.clifds = []
self.fd2cli = {}
self.listener_thread = Thread.new {
monitor_listener
}
self.clients_thread = Thread.new {
monitor_clients
}
end
#
# Terminates the listener monitoring threads and closes all active clients.
#
def stop
self.listener_thread.kill
self.clients_thread.kill
self.clients.each { |cli|
close_client(cli)
}
end
#
# Closes a client connection.
#
def close_client(client)
if (client)
fd2cli.delete(client.sock)
clifds.delete(client.sock)
clients.delete(client)
client.close
end
end
#
# Callback procedures.
#
attr_accessor :on_client_connect_proc
attr_accessor :on_client_data_proc
attr_accessor :on_client_close_proc
protected
attr_accessor :clients, :clifds, :fd2cli
attr_accessor :listener_thread, :clients_thread
#
# Monitors the listener socket for new connections
#
def monitor_listener
begin
sd = Rex::ThreadSafe.select([ poll_fd ])
# Accept the new client connection
if (sd[0].length > 0)
cli = accept
next if (!cli)
# Insert it into some lists
self.clients << cli
self.clifds << cli.sock
self.fd2cli[cli.sock] = cli
on_client_connect(cli)
end
rescue
elog("Error in stream server listener monitor: #{$!}")
end while true
end
#
# Monitors clients for data.
#
def monitor_clients
begin
if (clients.length == 0)
Rex::ThreadSafe::sleep(0.2)
next
end
sd = Rex::ThreadSafe.select(clifds)
sd[0].each { |fd|
on_client_data(self.fd2cli[fd])
}
rescue
elog("Error in stream server client monitor: #{$!}")
end while true
end
end end
end end

View File

@ -78,9 +78,6 @@ class Server
self.listen_port = port self.listen_port = port
self.listen_host = listen_host self.listen_host = listen_host
self.listener = nil self.listener = nil
self.clients = []
self.clifds = []
self.fd2cli = {}
self.resources = {} self.resources = {}
end end
@ -92,39 +89,30 @@ class Server
'LocalHost' => self.listen_host, 'LocalHost' => self.listen_host,
'LocalPort' => self.listen_port) 'LocalPort' => self.listen_port)
self.listener_thread = Thread.new { # Register callbacks
monitor_listener self.listener.on_client_connect_proc = Proc.new { |cli|
on_client_connect(cli)
} }
self.clients_thread = Thread.new { self.listener.on_client_data_proc = Proc.new { |cli|
monitor_clients on_client_data(cli)
} }
self.listener.start
end end
# #
# Terminates the monitor thread and turns off the listener. # Terminates the monitor thread and turns off the listener.
# #
def stop def stop
self.listener_thread.kill self.listener.stop
self.clients_thread.kill
self.clients.each { |cli|
close_client(cli)
}
self.listener.close self.listener.close
end end
# #
# Closes the supplied client connection and removes it from the internal # Closes the supplied client, if valid.
# hashes and lists.
# #
def close_client(cli) def close_client(cli)
if (cli) listener.close_client(cli)
self.fd2cli.delete(cli.sock)
self.clifds.delete(cli.sock)
self.clients.delete(cli)
cli.close
end
end end
# #
@ -153,7 +141,7 @@ class Server
end end
# #
# Adds Server headers and stuff # Adds Server headers and stuff.
# #
def add_response_headers(resp) def add_response_headers(resp)
resp['Server'] = DefaultServer resp['Server'] = DefaultServer
@ -163,63 +151,21 @@ class Server
protected protected
attr_accessor :listener attr_accessor :listener, :resources
attr_accessor :listener_thread, :clients_thread
attr_accessor :clients, :clifds, :fd2cli
attr_accessor :resources
# #
# Monitors the listener for new connections # Extends new clients with the ServerClient module and initializes them.
# #
def monitor_listener def on_client_connect(cli)
begin
sd = Rex::ThreadSafe.select([ listener.sock ])
# Accept the new client connection
if (sd[0].length > 0)
cli = listener.accept
next if (!cli)
cli.extend(ServerClient) cli.extend(ServerClient)
# Initialize the server client extension
cli.init_cli(self) cli.init_cli(self)
# Insert it into some lists
self.clients << cli
self.clifds << cli.sock
self.fd2cli[cli.sock] = cli
end
rescue
elog("Exception caught in HTTP server listener monitor: #{$!}")
end while true
end end
# #
# Monitors client connections for data # Processes data coming in from a client.
# #
def monitor_clients def on_client_data(cli)
begin
if (clients.length == 0)
Rex::ThreadSafe::sleep(0.2)
next
end
sd = Rex::ThreadSafe.select(clifds)
sd[0].each { |fd|
process_client(self.fd2cli[fd])
}
rescue
elog("Exception caught in HTTP server clients monitor: #{$!}")
end while true
end
#
# Processes data coming in from a client
#
def process_client(cli)
begin begin
case cli.request.parse(cli.get) case cli.request.parse(cli.get)
when Packet::ParseCode::Completed when Packet::ParseCode::Completed

View File

@ -80,7 +80,7 @@ class Rex::Socket::Parameters
self.server = hash['Server'] || false self.server = hash['Server'] || false
# The communication subsystem to use to create the socket # The communication subsystem to use to create the socket
self.comm = hash['Comm'] || Rex::Socket::Comm::Local; self.comm = hash['Comm'] || Rex::Socket::Comm::Local
# The number of connection retries to make (client only) # The number of connection retries to make (client only)
self.retries = hash['Retries'] || 0 self.retries = hash['Retries'] || 0