Fixed SSL support on the httpd component, and also on the EiffelWeb standalone connector.
- the standalone connector support for SSL, is using certicate files for now (no in-memory support).
- to enable ssl support, set ecf variable `httpd_ssl_enabled=true`.
- added the `simple_ssl` example to demonstrate how to have standalone ssl server.
(be careful when using EiffelNet SSL and the http_client library, disable the libcurl
via ecf variable `libcurl_http_client_disabled=true` )
Added support for recv timeout to the EiffelWeb standalone connector.
- made EiffelWeb compilable with 16.05 and upcoming 16.11.
Done via ecfs condition on version to accept EiffelNet with recv_timeout (from 16.11), and without (until 16.05).
- adding recv timeout prevents server to hang for ever if a client wait too long to send data.
Updated various comments.
This commit is contained in:
@@ -25,20 +25,27 @@ feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
if attached internal_client_socket as l_socket then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
debug ("dbglog")
|
||||
if
|
||||
attached internal_client_socket as l_socket and then
|
||||
l_socket.descriptor_available
|
||||
then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
release_pool_item
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,21 +18,28 @@ inherit
|
||||
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
|
||||
|
||||
release
|
||||
-- <Precursor>
|
||||
local
|
||||
d: STRING
|
||||
d: detachable STRING
|
||||
do
|
||||
-- FIXME: for log purpose
|
||||
if attached internal_client_socket as l_socket then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
debug ("dbglog")
|
||||
if
|
||||
attached internal_client_socket as l_socket and then
|
||||
l_socket.descriptor_available
|
||||
then
|
||||
d := l_socket.descriptor.out
|
||||
else
|
||||
d := "N/A"
|
||||
end
|
||||
dbglog (generator + ".release: ENTER {" + d + "}")
|
||||
end
|
||||
Precursor {HTTPD_REQUEST_HANDLER_I}
|
||||
debug ("dbglog")
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
if d /= Void then
|
||||
dbglog (generator + ".release: LEAVE {" + d + "}")
|
||||
else
|
||||
dbglog (generator + ".release: LEAVE {N/A}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ note
|
||||
deferred class
|
||||
HTTPD_CONFIGURATION_I
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
@@ -14,6 +19,7 @@ feature {NONE} -- Initialization
|
||||
max_concurrent_connections := default_max_concurrent_connections
|
||||
max_tcp_clients := default_max_tcp_clients
|
||||
socket_timeout := default_socket_timeout
|
||||
socket_recv_timeout := default_socket_recv_timeout
|
||||
keep_alive_timeout := default_keep_alive_timeout
|
||||
max_keep_alive_requests := default_max_keep_alive_requests
|
||||
is_secure := False
|
||||
@@ -21,15 +27,6 @@ feature {NONE} -- Initialization
|
||||
create ca_key.make_empty
|
||||
end
|
||||
|
||||
feature -- Defaults
|
||||
|
||||
default_http_server_port: INTEGER = 80
|
||||
default_max_concurrent_connections: INTEGER = 100
|
||||
default_max_tcp_clients: INTEGER = 100
|
||||
default_socket_timeout: INTEGER = 300 -- seconds
|
||||
default_keep_alive_timeout: INTEGER = 15 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 100
|
||||
|
||||
feature -- Access
|
||||
|
||||
Server_details: STRING_8
|
||||
@@ -45,7 +42,12 @@ feature -- Access
|
||||
socket_timeout: INTEGER assign set_socket_timeout
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
-- note: with timeout of 0, socket can wait for ever.
|
||||
-- By default: 300 seconds, which is appropriate for most situations.
|
||||
-- By default: 60 seconds, which is appropriate for most situations.
|
||||
|
||||
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
|
||||
-- Amount of seconds that the server waits for receiving data during communications.
|
||||
-- note: with timeout of 0, socket can wait for ever.
|
||||
-- By default: 5 seconds.
|
||||
|
||||
max_concurrent_connections: INTEGER assign set_max_concurrent_connections
|
||||
-- Max number of concurrent connections.
|
||||
@@ -83,8 +85,10 @@ feature -- Access
|
||||
Result.is_verbose := is_verbose
|
||||
Result.verbose_level := verbose_level
|
||||
Result.timeout := socket_timeout
|
||||
Result.socket_recv_timeout := socket_recv_timeout
|
||||
Result.keep_alive_timeout := keep_alive_timeout
|
||||
Result.max_keep_alive_requests := max_keep_alive_requests
|
||||
Result.is_secure := is_secure
|
||||
end
|
||||
|
||||
feature -- Access: SSL
|
||||
@@ -92,10 +96,10 @@ feature -- Access: SSL
|
||||
is_secure: BOOLEAN
|
||||
-- Is SSL/TLS session?.
|
||||
|
||||
ca_crt: IMMUTABLE_STRING_8
|
||||
ca_crt: detachable IMMUTABLE_STRING_32
|
||||
-- the signed certificate.
|
||||
|
||||
ca_key: IMMUTABLE_STRING_8
|
||||
ca_key: detachable IMMUTABLE_STRING_32
|
||||
-- private key to the certificate.
|
||||
|
||||
ssl_protocol: NATURAL
|
||||
@@ -103,6 +107,22 @@ feature -- Access: SSL
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_ssl_settings (v: detachable separate TUPLE [protocol: separate READABLE_STRING_GENERAL; ca_crt, ca_key: detachable separate READABLE_STRING_GENERAL])
|
||||
local
|
||||
prot: STRING_32
|
||||
do
|
||||
is_secure := False
|
||||
ca_crt := Void
|
||||
ca_key := Void
|
||||
if v /= Void then
|
||||
is_secure := True
|
||||
create prot.make_from_separate (v.protocol)
|
||||
set_ssl_protocol_from_string (prot)
|
||||
set_ca_crt (v.ca_crt)
|
||||
set_ca_key (v.ca_key)
|
||||
end
|
||||
end
|
||||
|
||||
set_http_server_name (v: detachable separate READABLE_STRING_8)
|
||||
do
|
||||
if v = Void then
|
||||
@@ -152,6 +172,14 @@ feature -- Element change
|
||||
socket_timeout_set: socket_timeout = a_nb_seconds
|
||||
end
|
||||
|
||||
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
|
||||
-- Set `socket_recv_timeout' with `a_nb_seconds'
|
||||
do
|
||||
socket_recv_timeout := a_nb_seconds
|
||||
ensure
|
||||
socket_recv_timeout_set: socket_recv_timeout = a_nb_seconds
|
||||
end
|
||||
|
||||
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
|
||||
-- Set `keep_alive_timeout' with `a_seconds'
|
||||
do
|
||||
@@ -198,17 +226,33 @@ feature -- Element change
|
||||
verbose_level_set: verbose_level = lev
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
if has_ssl_support then
|
||||
if b and has_ssl_support then
|
||||
is_secure := True
|
||||
if http_server_port = 80 then
|
||||
if
|
||||
http_server_port = 80
|
||||
then
|
||||
set_http_server_port (443)
|
||||
end
|
||||
else
|
||||
is_secure := False
|
||||
if
|
||||
http_server_port = 443
|
||||
then
|
||||
set_http_server_port (80)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
is_secure_set: has_ssl_support implies is_secure
|
||||
is_not_secure: not has_ssl_support implies not is_secure
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
do
|
||||
set_is_secure (True)
|
||||
ensure
|
||||
is_secure_set: has_ssl_support implies is_secure
|
||||
-- http_server_port_set: has_ssl_support implies http_server_port = 443
|
||||
@@ -218,16 +262,24 @@ feature -- Element change
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_ca_crt (a_value: separate READABLE_STRING_8)
|
||||
set_ca_crt (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_crt' from `a_value'.
|
||||
do
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
if a_value /= Void then
|
||||
create ca_crt.make_from_separate (a_value)
|
||||
else
|
||||
ca_crt := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ca_key (a_value: separate READABLE_STRING_8)
|
||||
set_ca_key (a_value: detachable separate READABLE_STRING_GENERAL)
|
||||
-- Set `ca_key' with `a_value'.
|
||||
do
|
||||
create ca_key.make_from_separate (a_value)
|
||||
if a_value /= Void then
|
||||
create ca_key.make_from_separate (a_value)
|
||||
else
|
||||
ca_key := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_ssl_protocol (a_version: NATURAL)
|
||||
@@ -238,6 +290,24 @@ feature -- Element change
|
||||
ssl_protocol_set: ssl_protocol = a_version
|
||||
end
|
||||
|
||||
set_ssl_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
|
||||
-- Set `ssl_protocol' with `a_ssl_version'
|
||||
do
|
||||
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
||||
set_ssl_protocol_to_ssl_2_or_3
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_0") then
|
||||
set_ssl_protocol_to_tls_1_0
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_1") then
|
||||
set_ssl_protocol_to_tls_1_1
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_2") then
|
||||
set_ssl_protocol_to_tls_1_2
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("dtls_1_0") then
|
||||
set_ssl_protocol_to_dtls_1_0
|
||||
else -- Default
|
||||
set_ssl_protocol_to_tls_1_2
|
||||
end
|
||||
end
|
||||
|
||||
feature -- SSL Helpers
|
||||
|
||||
set_ssl_protocol_to_ssl_2_or_3
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
note
|
||||
description: "[
|
||||
Various constant values used in httpd settings.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
feature -- Default connection settings
|
||||
|
||||
default_http_server_port: INTEGER = 80
|
||||
default_max_concurrent_connections: INTEGER = 100
|
||||
default_max_tcp_clients: INTEGER = 100
|
||||
|
||||
feature -- Default timeout settings
|
||||
|
||||
default_socket_timeout: INTEGER = 60 -- seconds
|
||||
default_socket_recv_timeout: INTEGER = 5 -- seconds
|
||||
|
||||
feature -- Default persistent connection settings
|
||||
|
||||
default_keep_alive_timeout: INTEGER = 15 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 100
|
||||
|
||||
end
|
||||
@@ -17,9 +17,15 @@ feature -- Access
|
||||
verbose_level: INTEGER assign set_verbose_level
|
||||
-- Verbosity of output.
|
||||
|
||||
is_secure: BOOLEAN assign set_is_secure
|
||||
-- Is using secure connection? i.e SSL?
|
||||
|
||||
timeout: INTEGER assign set_timeout
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
|
||||
socket_recv_timeout: INTEGER assign set_socket_recv_timeout
|
||||
-- Amount of seconds that the server waits for receiving data on socket during communications.
|
||||
|
||||
keep_alive_timeout: INTEGER assign set_keep_alive_timeout
|
||||
-- Keep-alive timeout, also known as persistent-connection timeout.
|
||||
-- Number of seconds the server waits after a request has been served before it closes the connection.
|
||||
@@ -42,12 +48,24 @@ feature -- Change
|
||||
verbose_level := lev
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set `is_secure' to `b'.
|
||||
do
|
||||
is_secure := b
|
||||
end
|
||||
|
||||
set_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
timeout := a_timeout_in_seconds
|
||||
end
|
||||
|
||||
set_socket_recv_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `socket_recv_timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
socket_recv_timeout := a_timeout_in_seconds
|
||||
end
|
||||
|
||||
set_keep_alive_timeout (a_timeout_in_seconds: INTEGER)
|
||||
-- Set `keep_alive_timeout' to `a_timeout_in_seconds'.
|
||||
do
|
||||
|
||||
@@ -10,20 +10,29 @@
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf" readonly="false"/>
|
||||
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<cluster name="network" location=".\network" recursive="false">
|
||||
<cluster name="ssl_network" location="$|ssl" recursive="true">
|
||||
<cluster name="network" location=".\network\">
|
||||
<cluster name="ssl_network" location="$|ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_until_16_05" location="$|until_16_05\">
|
||||
<condition>
|
||||
<version type="compiler" max="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_from_16_11" location="$|from_16_11\">
|
||||
<condition>
|
||||
<version type="compiler" min="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_until_16_05" location="$|until_16_05\">
|
||||
<condition>
|
||||
<version type="compiler" max="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_from_16_11" location="$|from_16_11\">
|
||||
<condition>
|
||||
<version type="compiler" min="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -30,6 +30,16 @@
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_until_16_05" location="$|until_16_05\">
|
||||
<condition>
|
||||
<version type="compiler" max="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_from_16_11" location="$|from_16_11\">
|
||||
<condition>
|
||||
<version type="compiler" min="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</cluster>
|
||||
<cluster name="httpd_server" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
|
||||
@@ -29,6 +29,16 @@
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_until_16_05" location="$|until_16_05\">
|
||||
<condition>
|
||||
<version type="compiler" max="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="network_from_16_11" location="$|from_16_11\">
|
||||
<condition>
|
||||
<version type="compiler" min="16.11.0.0"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</cluster>
|
||||
<cluster name="httpd_server" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
|
||||
@@ -11,6 +11,8 @@ inherit
|
||||
|
||||
HTTPD_LOGGER_CONSTANTS
|
||||
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
|
||||
@@ -18,11 +20,13 @@ feature {NONE} -- Initialization
|
||||
reset
|
||||
-- Import global request settings.
|
||||
timeout := a_request_settings.timeout -- seconds
|
||||
socket_recv_timeout := a_request_settings.socket_recv_timeout -- seconds
|
||||
keep_alive_timeout := a_request_settings.keep_alive_timeout -- seconds
|
||||
max_keep_alive_requests := a_request_settings.max_keep_alive_requests
|
||||
|
||||
is_verbose := a_request_settings.is_verbose
|
||||
verbose_level := a_request_settings.verbose_level
|
||||
is_secure := a_request_settings.is_secure
|
||||
end
|
||||
|
||||
reset
|
||||
@@ -68,7 +72,7 @@ feature -- Access
|
||||
do
|
||||
s := internal_client_socket
|
||||
if s = Void then
|
||||
create s.make_empty
|
||||
s := new_client_socket (is_secure)
|
||||
internal_client_socket := s
|
||||
end
|
||||
Result := s
|
||||
@@ -121,6 +125,10 @@ feature -- Settings
|
||||
verbose_level: INTEGER
|
||||
-- Output verbosity.
|
||||
|
||||
is_secure: BOOLEAN
|
||||
-- Is secure socket?
|
||||
-- i.e: SSL?
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN
|
||||
-- Is persistent connection supported?
|
||||
do
|
||||
@@ -134,6 +142,9 @@ feature -- Settings
|
||||
timeout: INTEGER -- seconds
|
||||
-- Amount of seconds that the server waits for receipts and transmissions during communications.
|
||||
|
||||
socket_recv_timeout: INTEGER -- seconds
|
||||
-- Amount of seconds that the server waits for receiving data on socket during communications.
|
||||
|
||||
max_keep_alive_requests: INTEGER
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
|
||||
@@ -187,6 +198,7 @@ feature -- Execution
|
||||
n,m: INTEGER
|
||||
do
|
||||
l_socket := client_socket
|
||||
l_socket.set_recv_timeout (socket_recv_timeout)
|
||||
check
|
||||
socket_attached: l_socket /= Void
|
||||
socket_valid: l_socket.is_open_read and then l_socket.is_open_write
|
||||
@@ -206,18 +218,24 @@ feature -- Execution
|
||||
log ("Reuse connection (" + n.out + ")", information_level)
|
||||
end
|
||||
-- FIXME: it seems to be called one more time, mostly to see this is done.
|
||||
execute_request
|
||||
execute_request (n > 1)
|
||||
l_exit := not is_persistent_connection_supported
|
||||
or not is_next_persistent_connection_supported -- related to `max_keep_alive_requests'
|
||||
or not is_persistent_connection_requested
|
||||
or has_error or l_socket.is_closed or not l_socket.is_open_read
|
||||
reset_request
|
||||
end
|
||||
if l_exit and has_error and not l_socket.is_closed then
|
||||
l_socket.close
|
||||
end
|
||||
end
|
||||
|
||||
execute_request
|
||||
execute_request (a_is_reusing_connection: BOOLEAN)
|
||||
-- Execute http request, and if `a_is_reusing_connection' is True
|
||||
-- the execution is reusing the persistent connection.
|
||||
require
|
||||
is_connected: is_connected
|
||||
reuse_connection_when_possible: a_is_reusing_connection implies is_persistent_connection_supported
|
||||
local
|
||||
l_remote_info: detachable like remote_info
|
||||
l_socket: like client_socket
|
||||
@@ -237,13 +255,16 @@ feature -- Execution
|
||||
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + " ENTER")
|
||||
end
|
||||
|
||||
--| TODO: add configuration options for socket timeout.
|
||||
--| set by default 5 seconds.
|
||||
l_socket.set_timeout (keep_alive_timeout) -- 5 seconds!
|
||||
l_is_ready := l_socket.ready_for_reading
|
||||
if a_is_reusing_connection then
|
||||
--| set by default 5 seconds.
|
||||
l_socket.set_recv_timeout (keep_alive_timeout) -- in seconds!
|
||||
l_is_ready := l_socket.ready_for_reading
|
||||
else
|
||||
l_is_ready := True
|
||||
end
|
||||
|
||||
if l_is_ready then
|
||||
l_socket.set_timeout (timeout) -- FIXME: return a 408 Request Timeout response ..
|
||||
l_socket.set_recv_timeout (socket_recv_timeout) -- FIXME: return a 408 Request Timeout response ..
|
||||
create l_remote_info
|
||||
if attached l_socket.peer_address as l_addr then
|
||||
l_remote_info.addr := l_addr.host_address.host_address
|
||||
@@ -326,8 +347,7 @@ feature -- Parsing
|
||||
has_error := True
|
||||
end
|
||||
l_is_verbose := is_verbose
|
||||
if not has_error or l_is_verbose then
|
||||
-- if `is_verbose' we can try to print the request, even if it is a bad HTTP request
|
||||
if not has_error then
|
||||
from
|
||||
line := next_line (a_socket)
|
||||
until
|
||||
|
||||
@@ -108,6 +108,7 @@ feature -- Execution
|
||||
log (" - max_tcp_clients = " + configuration.max_tcp_clients.out)
|
||||
log (" - max_concurrent_connections = " + configuration.max_concurrent_connections.out)
|
||||
log (" - socket_timeout = " + configuration.socket_timeout.out + " seconds")
|
||||
log (" - socket_recv_timeout = " + configuration.socket_recv_timeout.out + " seconds")
|
||||
log (" - keep_alive_timeout = " + configuration.keep_alive_timeout.out + " seconds")
|
||||
log (" - max_keep_alive_requests = " + configuration.max_keep_alive_requests.out)
|
||||
if configuration.verbose_level > 0 then
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
note
|
||||
description: "[
|
||||
Since 16.11, the EiffelNet socket interface has recv_timeout and send_timeout.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
TCP_STREAM_SOCKET_EXT
|
||||
|
||||
end
|
||||
@@ -62,6 +62,7 @@ feature {NONE} -- Initialization
|
||||
feature -- Change
|
||||
|
||||
set_timeout (n: INTEGER)
|
||||
-- Set timeout to `n' seconds.
|
||||
do
|
||||
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_timeout (n)
|
||||
@@ -82,6 +83,22 @@ feature -- Change
|
||||
end
|
||||
end
|
||||
|
||||
set_recv_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the receive timeout in seconds on Current socket.
|
||||
do
|
||||
if attached {TCP_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_recv_timeout (a_timeout_seconds)
|
||||
end
|
||||
end
|
||||
|
||||
set_send_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the send timeout in seconds on Current socket.
|
||||
do
|
||||
if attached {TCP_STREAM_SOCKET} socket as l_socket then
|
||||
l_socket.set_send_timeout (a_timeout_seconds)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING
|
||||
|
||||
@@ -17,58 +17,66 @@ inherit
|
||||
ready_for_writing,
|
||||
ready_for_reading,
|
||||
try_ready_for_reading,
|
||||
put_readable_string_8
|
||||
put_readable_string_8,
|
||||
make_empty
|
||||
end
|
||||
|
||||
create
|
||||
make_ssl_server_by_address_and_port, make_ssl_server_by_port,
|
||||
make_server_by_address_and_port, make_server_by_port,
|
||||
make_ssl_client_by_address_and_port, make_ssl_client_by_port,
|
||||
make_client_by_address_and_port, make_client_by_port
|
||||
make_client_by_address_and_port, make_client_by_port,
|
||||
make_empty
|
||||
|
||||
create {HTTPD_STREAM_SOCKET}
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_ssl_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
make_ssl_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_server_by_address_and_port (an_address, a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
end
|
||||
|
||||
make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_server_by_port (a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
end
|
||||
|
||||
make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_client_by_address_and_port (an_address, a_port)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
end
|
||||
|
||||
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
|
||||
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt_fn, a_key_fn: detachable READABLE_STRING_GENERAL)
|
||||
local
|
||||
l_socket: SSL_TCP_STREAM_SOCKET
|
||||
do
|
||||
create l_socket.make_client_by_port (a_peer_port, a_peer_host)
|
||||
l_socket.set_tls_protocol (a_ssl_protocol)
|
||||
socket := l_socket
|
||||
set_certificates (a_crt, a_key)
|
||||
set_certificates (a_crt_fn, a_key_fn)
|
||||
end
|
||||
|
||||
make_empty
|
||||
-- <Precursor>.
|
||||
do
|
||||
create {SSL_TCP_STREAM_SOCKET} socket.make_empty
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
@@ -136,15 +144,15 @@ feature -- Status Report
|
||||
|
||||
feature {HTTPD_STREAM_SOCKET} -- Implementation
|
||||
|
||||
set_certificates (a_crt: STRING; a_key: STRING)
|
||||
local
|
||||
a_file_name: FILE_NAME
|
||||
set_certificates (a_crt_filename, a_key_filename: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
if attached {SSL_NETWORK_STREAM_SOCKET} socket as l_socket then
|
||||
create a_file_name.make_from_string (a_crt)
|
||||
l_socket.set_certificate_file_name (a_file_name)
|
||||
create a_file_name.make_from_string (a_key)
|
||||
l_socket.set_key_file_name (a_file_name)
|
||||
if a_crt_filename /= Void then
|
||||
l_socket.set_certificate_file_name (a_crt_filename)
|
||||
end
|
||||
if a_key_filename /= Void then
|
||||
l_socket.set_key_file_name (a_key_filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ inherit
|
||||
make
|
||||
end
|
||||
|
||||
TCP_STREAM_SOCKET_EXT
|
||||
|
||||
create
|
||||
make_server_by_address_and_port,
|
||||
make_server_by_port,
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
note
|
||||
description: "[
|
||||
Until 16.05, the EiffelNet socket interface DOES NOT have recv_timeout and send_timeout.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
TCP_STREAM_SOCKET_EXT
|
||||
|
||||
feature -- Access
|
||||
|
||||
descriptor: INTEGER
|
||||
-- Socket descriptor of current socket
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Socket Recv and Send timeout.
|
||||
|
||||
-- recv_timeout: INTEGER
|
||||
-- -- Receive timeout in seconds on Current socket.
|
||||
-- do
|
||||
-- Result := c_get_sock_recv_timeout (descriptor, level_sol_socket)
|
||||
-- ensure
|
||||
-- result_not_negative: Result >= 0
|
||||
-- end
|
||||
--
|
||||
-- send_timeout: INTEGER
|
||||
-- -- Send timeout in seconds on Current socket.
|
||||
-- do
|
||||
-- Result := c_get_sock_send_timeout (descriptor, level_sol_socket)
|
||||
-- ensure
|
||||
-- result_not_negative: Result >= 0
|
||||
-- end
|
||||
|
||||
set_recv_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the receive timeout in seconds on Current socket.
|
||||
-- if `0' the related operations will never timeout.
|
||||
require
|
||||
positive_timeout: a_timeout_seconds >= 0
|
||||
do
|
||||
c_set_sock_recv_timeout (descriptor, level_sol_socket, a_timeout_seconds)
|
||||
end
|
||||
|
||||
set_send_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the send timeout in milliseconds on Current socket.
|
||||
-- if `0' the related operations will never timeout.
|
||||
require
|
||||
positive_timeout: a_timeout_seconds >= 0
|
||||
do
|
||||
c_set_sock_send_timeout (descriptor, level_sol_socket, a_timeout_seconds)
|
||||
end
|
||||
|
||||
feature {NONE} -- Externals
|
||||
|
||||
level_sol_socket: INTEGER
|
||||
-- SOL_SOCKET level of options
|
||||
deferred
|
||||
end
|
||||
|
||||
-- set_so_rcvtimeo (a_timeout_seconds: INTEGER)
|
||||
-- -- Set the receive timeout in seconds on Current socket.
|
||||
-- -- if `0' the related operations will never timeout.
|
||||
-- require
|
||||
-- positive_timeout: a_timeout_seconds >= 0
|
||||
-- do
|
||||
-- c_set_sock_recv_timeout (descriptor, level_sol_socket, a_timeout_seconds)
|
||||
-- end
|
||||
|
||||
c_set_sock_recv_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
|
||||
-- C routine to set socket option `SO_RCVTIMEO' with `a_timeout_seconds' seconds.
|
||||
external
|
||||
"C inline"
|
||||
alias
|
||||
"[
|
||||
#ifdef EIF_WINDOWS
|
||||
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
|
||||
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (char *) &arg, sizeof(arg));
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
|
||||
|
||||
setsockopt((int) $a_fd, (int) $a_level, (int) SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
|
||||
#endif
|
||||
]"
|
||||
end
|
||||
|
||||
c_set_sock_send_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
|
||||
-- C routine to set socket option `SO_SNDTIMEO' with `a_timeout_seconds' seconds.
|
||||
external
|
||||
"C inline"
|
||||
alias
|
||||
"[
|
||||
#ifdef EIF_WINDOWS
|
||||
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
|
||||
setsockopt((SOCKET) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (char *) &arg, sizeof(arg));
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
|
||||
|
||||
setsockopt((int) $a_fd, (int) $a_level, (int) SO_SNDTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
|
||||
#endif
|
||||
]"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
|
||||
do
|
||||
check not_secure: not a_is_secure end
|
||||
create Result.make_empty
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
note
|
||||
description: "Summary description for {HTTPD_SOCKET_FACTORY}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTPD_SOCKET_FACTORY
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_client_socket (a_is_secure: BOOLEAN): HTTPD_STREAM_SOCKET
|
||||
do
|
||||
if a_is_secure then
|
||||
create {HTTPD_STREAM_SSL_SOCKET} Result.make_empty
|
||||
else
|
||||
create Result.make_empty
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -230,6 +230,9 @@ feature -- Request processing
|
||||
set_environment_variable (l_server_port, "SERVER_PORT", Result)
|
||||
set_environment_variable (version, "SERVER_PROTOCOL", Result)
|
||||
set_environment_variable ({HTTPD_CONFIGURATION}.Server_details, "SERVER_SOFTWARE", Result)
|
||||
if is_secure then
|
||||
set_environment_variable ("on", "HTTPS", Result)
|
||||
end
|
||||
|
||||
--| Apply `base' value
|
||||
l_base := base
|
||||
|
||||
@@ -2,8 +2,8 @@ note
|
||||
description: "[
|
||||
Standalone Web Server connector.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $"
|
||||
revision: "$Revision: 99106 $"
|
||||
|
||||
class
|
||||
WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end]
|
||||
@@ -155,6 +155,12 @@ feature -- Element change
|
||||
set_is_verbose_on_configuration (b, configuration)
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set is_secure connection mode.
|
||||
-- i.e: using SSL.
|
||||
do
|
||||
set_is_secure_on_configuration (b, configuration)
|
||||
end
|
||||
|
||||
feature -- Server
|
||||
|
||||
@@ -242,6 +248,11 @@ feature {NONE} -- Implementation: element change
|
||||
cfg.set_is_verbose (b)
|
||||
end
|
||||
|
||||
set_is_secure_on_configuration (b: BOOLEAN; cfg: like configuration)
|
||||
do
|
||||
cfg.set_is_secure (b)
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
note
|
||||
description: "[
|
||||
Constants value related to Standalone connector,
|
||||
and indirectly to `httpd' component.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WGI_STANDALONE_CONSTANTS
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTPD_CONSTANTS
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user