From 557b11f4e677b2cd96be5280abf645ce772f7045 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 17 Mar 2015 09:48:11 +0100 Subject: [PATCH] First attempt to use `{NETWORK_STREAM_SOCKET}.accept_to' --- .../scoop/httpd_connection_handler.e | 39 ++++++----------- .../concurrency/scoop/httpd_request_handler.e | 43 +++++-------------- .../src/httpd/httpd_connection_handler_i.e | 4 +- .../httpd/src/httpd/httpd_request_handler_i.e | 23 +++------- .../httpd/src/httpd/httpd_server_i.e | 32 ++++++-------- .../src/httpd/network/httpd_stream_socket.e | 38 ++++++++++++++-- .../src/httpd/network/tcp_stream_socket.e | 10 +++-- 7 files changed, 88 insertions(+), 101 deletions(-) diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e index fcf5c3d7..79afe9f5 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_connection_handler.e @@ -57,45 +57,33 @@ feature {HTTPD_SERVER_I} -- Execution p.gracefull_stop end - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) - -- + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) do - debug ("dbglog") - dbglog (generator + ".before process_incoming_connection {"+ a_socket.descriptor.out +"} -- SCOOP WAIT!") - end --- if is_shutdown_requested then --- a_socket.cleanup --- else - process_connection_on_pool (a_socket, pool) -- Wait on not pool.is_full or is_stop_requested --- end - debug ("dbglog") - dbglog (generator + ".after process_incoming_connection {"+ a_socket.descriptor.out +"}") - end + accept_connection_on_pool (a_listening_socket, pool) -- Wait on not pool.is_full or is_stop_requested end - process_connection_on_pool (a_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) - -- Process incoming connection + accept_connection_on_pool (a_listening_socket: HTTPD_STREAM_SOCKET; a_pool: like pool) + -- Process accept connection -- note that the precondition matters for scoop synchronization. require concurrency: not a_pool.is_full or is_shutdown_requested or a_pool.stop_requested do debug ("dbglog") - dbglog (generator + ".ENTER process_connection {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".ENTER accept_connection_on_pool") end if is_shutdown_requested then - a_socket.cleanup + -- Cancel elseif attached a_pool.separate_item (factory) as h then - process_request_handler (h, a_socket) + process_request_handler_on_accept (h, a_listening_socket) else check is_not_full: False end - a_socket.cleanup end debug ("dbglog") - dbglog (generator + ".LEAVE process_connection {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE accept_connection_on_pool") end end - process_request_handler (hdl: separate HTTPD_REQUEST_HANDLER; a_socket: HTTPD_STREAM_SOCKET) + process_request_handler_on_accept (hdl: separate HTTPD_REQUEST_HANDLER; a_listening_socket: HTTPD_STREAM_SOCKET) require not hdl.has_error do @@ -103,20 +91,21 @@ feature {HTTPD_SERVER_I} -- Execution --| also handle permanent connection...? debug ("dbglog") - dbglog (generator + ".ENTER process_request_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".ENTER process_request_handler_on_accept") end - hdl.set_client_socket (a_socket) + hdl.accept_from_listening_socket (a_listening_socket) if hdl.has_error then - log ("Internal error (set_client_socket failed)") + log ("Internal error (accept_from_listening_socket failed)") else -- hdl.set_logger (server) if attached hdl.separate_execution as l_result then + end hdl.separate_release end debug ("dbglog") - dbglog (generator + ".LEAVE process_request_handler {"+ a_socket.descriptor.out +"}") + dbglog (generator + ".LEAVE process_request_handler_on_accept") end rescue log ("Releasing handler after exception!") diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e index 2c5754fc..1f41852d 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/concurrency/scoop/httpd_request_handler.e @@ -12,9 +12,7 @@ deferred class inherit HTTPD_REQUEST_HANDLER_I redefine --- set_client_socket, - release, - reset + release end CONCURRENT_POOL_ITEM @@ -22,42 +20,23 @@ inherit release as release_pool_item end -feature {NONE} -- Initialization - - reset - do - if attached client_socket_source as l_sock then - cleanup_separate_socket (l_sock) - end - Precursor - client_socket_source := Void - end - - cleanup_separate_socket (a_socket: attached like client_socket_source) - do - a_socket.cleanup - end - -feature -- Access - - client_socket: detachable HTTPD_STREAM_SOCKET - - client_socket_source: detachable separate HTTPD_STREAM_SOCKET - -- Associated original client socket - -- kept to avoid being closed when disposed, - -- and thus avoid closing related `client_socket'. - feature -- Change - set_client_socket (a_socket: separate HTTPD_STREAM_SOCKET) + accept_from_listening_socket (a_listening_socket: separate HTTPD_STREAM_SOCKET) local retried: BOOLEAN + s: like client_socket do if retried then has_error := True else - create client_socket.make_from_separate (a_socket) - client_socket_source := a_socket + create s.make_empty + client_socket := s + a_listening_socket.accept_to (s) + if not s.is_created then + has_error := True + client_socket := Void + end end rescue retried := True @@ -99,7 +78,7 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e index d9708723..99d4acc0 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_connection_handler_i.e @@ -38,7 +38,7 @@ feature {NONE} -- Access feature {HTTPD_SERVER_I} -- Execution - process_incoming_connection (a_socket: HTTPD_STREAM_SOCKET) + accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET) deferred end @@ -72,7 +72,7 @@ feature {NONE} -- Output end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e index 5be6fca8..dd3ce531 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_request_handler_i.e @@ -23,21 +23,22 @@ feature {NONE} -- Initialization version := Void remote_info := Void --- if attached client_socket as l_sock then --- l_sock.cleanup --- end --- client_socket := Void + if attached client_socket as l_sock then + l_sock.cleanup + end + client_socket := Void -- FIXME: optimize to just wipe_out if needed create method.make_empty create uri.make_empty create request_header.make_empty create request_header_map.make (10) + end feature -- Access --- client_socket: detachable TCP_STREAM_SOCKET + client_socket: detachable HTTPD_STREAM_SOCKET request_header: STRING -- Header' source @@ -69,16 +70,6 @@ feature -- Status report feature -- Change --- set_client_socket (a_socket: separate TCP_STREAM_SOCKET) --- require --- socket_attached: a_socket /= Void --- socket_valid: a_socket.is_open_read and then a_socket.is_open_write --- a_http_socket: not a_socket.is_closed --- deferred --- ensure --- attached client_socket as s implies s.descriptor = a_socket.descriptor --- end - set_is_verbose (b: BOOLEAN) do is_verbose := b @@ -265,7 +256,7 @@ invariant request_header_attached: request_header /= Void note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e index c0f92b47..ff9adcb9 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/httpd_server_i.e @@ -126,8 +126,7 @@ feature -- Listening -- Creates a socket and connects to the http server. -- `a_server': The main server object local - l_listening_socket, - l_accepted_socket: detachable HTTPD_STREAM_SOCKET + l_listening_socket: detachable HTTPD_STREAM_SOCKET l_http_port: INTEGER l_connection_handler: HTTPD_CONNECTION_HANDLER do @@ -164,23 +163,18 @@ feature -- Listening until is_shutdown_requested loop - l_listening_socket.accept - if not is_shutdown_requested then - l_accepted_socket := l_listening_socket.accepted - if l_accepted_socket /= Void then - request_counter := request_counter + 1 - if is_verbose then - log ("#" + request_counter.out + "# Incoming connection...(socket:" + l_accepted_socket.descriptor.out + ")") - end - debug ("dbglog") - dbglog (generator + ".before process_incoming_connection {" + l_accepted_socket.descriptor.out + "}" ) - end - l_connection_handler.process_incoming_connection (l_accepted_socket) - debug ("dbglog") - dbglog (generator + ".after process_incoming_connection {" + l_accepted_socket.descriptor.out + "}") - end - end + request_counter := request_counter + 1 + if is_verbose then + log ("#" + request_counter.out + "# Waiting connection...(listening socket:" + l_listening_socket.descriptor.out + ")") end + debug ("dbglog") + dbglog (generator + ".before process_waiting_incoming_connection") + end + l_connection_handler.accept_incoming_connection (l_listening_socket) + debug ("dbglog") + dbglog (generator + ".after process_waiting_incoming_connection") + end + update_is_shutdown_requested (l_connection_handler) end wait_for_connection_handler_completion (l_connection_handler) @@ -304,7 +298,7 @@ feature -- Output end note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e index ff4a6361..4cf3f162 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/httpd_stream_socket.e @@ -12,7 +12,8 @@ class create make_server_by_address_and_port, make_server_by_port, - make_from_separate + make_from_separate, + make_empty create {HTTPD_STREAM_SOCKET} make @@ -36,6 +37,11 @@ feature {NONE} -- Initialization create {TCP_STREAM_SOCKET} socket.make_from_separate (s.socket) end + make_empty + do + create {TCP_STREAM_SOCKET} socket.make_empty + end + retrieve_socket (s: HTTPD_STREAM_SOCKET): INTEGER do Result := s.socket.descriptor @@ -147,6 +153,13 @@ feature -- Status Report end end + is_created: BOOLEAN + do + if attached {NETWORK_SOCKET} socket as l_socket then + Result := l_socket.is_created + end + end + socket_ok: BOOLEAN do Result := socket.socket_ok @@ -194,6 +207,18 @@ feature -- Status Report socket.accept end + accept_to (other: separate HTTPD_STREAM_SOCKET) + -- Accept a new connection on listen socket. + -- Socket of accepted connection is available in `other'. + do + if + attached {NETWORK_STREAM_SOCKET} socket as l_socket and then + attached {separate NETWORK_STREAM_SOCKET} other.socket as l_other_socket + then + l_socket.accept_to (l_other_socket) + end + end + set_blocking do socket.set_blocking @@ -225,7 +250,7 @@ feature -- Status Report accepted: detachable HTTPD_STREAM_SOCKET do - if attached socket.accepted as l_accepted then + if attached {NETWORK_STREAM_SOCKET} socket.accepted as l_accepted then create Result.make (l_accepted) end end @@ -239,8 +264,15 @@ feature {HTTPD_STREAM_SOCKET} -- Implementation socket: STREAM_SOCKET + network_stream_socket: detachable NETWORK_STREAM_SOCKET + do + if attached {NETWORK_STREAM_SOCKET} socket as s then + Result := s + end + end + ;note - copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e index 1713779d..2e88f192 100644 --- a/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e +++ b/library/server/ewsgi/connectors/httpd/src/httpd/network/tcp_stream_socket.e @@ -15,11 +15,11 @@ inherit create make_server_by_address_and_port, make_server_by_port, - make_from_separate + make_from_separate, + make_empty create {NETWORK_STREAM_SOCKET} - make_from_descriptor_and_address, - make_empty + make_from_descriptor_and_address feature {NONE} -- Initialization @@ -27,7 +27,9 @@ feature {NONE} -- Initialization -- Create a network stream socket. do Precursor - set_reuse_address + debug + set_reuse_address + end end make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)