Moved httpd from src to lib, under standalone connector.

This commit is contained in:
2016-06-15 18:04:00 +02:00
parent dfa60bf8f5
commit 71a5c086a5
39 changed files with 3 additions and 3 deletions

View File

@@ -1,86 +0,0 @@
note
description: "[
Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: none
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONNECTION_HANDLER
inherit
HTTPD_CONNECTION_HANDLER_I
create
make
feature {NONE} -- Initialization
initialize
do
end
feature -- Access
is_shutdown_requested: BOOLEAN
-- <Precursor>
shutdown_requested (a_server: like server): BOOLEAN
do
-- FIXME: we should probably remove this possibility, check with EWF if this is needed.
Result := a_server.controller.shutdown_requested
end
feature {HTTPD_SERVER_I} -- Execution
accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
local
cl: HTTPD_STREAM_SOCKET
do
is_shutdown_requested := is_shutdown_requested or shutdown_requested (server)
if is_shutdown_requested then
-- Cancel
elseif attached factory.new_handler as h then
cl := h.client_socket
a_listening_socket.accept_to (cl)
if h.is_connected then
h.safe_execute
end
else
check is_not_full: False end
end
update_is_shutdown_requested
end
update_is_shutdown_requested
do
is_shutdown_requested := shutdown_requested (server)
end
shutdown
do
if not is_shutdown_requested then
is_shutdown_requested := True
server.controller.shutdown
end
end
feature {HTTPD_SERVER_I} -- Status report
wait_for_completion
-- Wait until Current is ready for shutdown
do
-- no concurrency, then current task should be done.
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,32 +0,0 @@
note
description : "Concurrent specific feature to implement HTTPD_REQUEST_HANDLER"
date : "$Date$"
revision : "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER
inherit
HTTPD_REQUEST_HANDLER_I
redefine
is_persistent_connection_supported
end
feature -- Status report
is_persistent_connection_supported: BOOLEAN = False
-- <Precursor>
-- When there is no concurrency support, do not try to support
-- persistent connection!
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,15 +0,0 @@
note
description: "Implementation of request handler factory for concurrency mode: none"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER_FACTORY
inherit
HTTPD_REQUEST_HANDLER_FACTORY_I
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,146 +0,0 @@
note
description: "[
Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: SCOOP
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONNECTION_HANDLER
inherit
HTTPD_CONNECTION_HANDLER_I
redefine
initialize
end
create
make
feature {NONE} -- Initialization
initialize
local
n: INTEGER
p: like pool
do
n := max_concurrent_connections (server).max (1) -- At least one processor!
create p.make (n)
initialize_pool (p, n)
pool := p
end
initialize_pool (p: like pool; n: INTEGER)
-- Initialize Concurrent pool of `n' potential separate connection handlers.
do
p.set_count (n)
end
feature -- Access
is_shutdown_requested: BOOLEAN
-- <Precursor>
max_concurrent_connections (a_server: like server): INTEGER
-- Max concurrent connection settings from server `a_server'.
do
Result := a_server.configuration.max_concurrent_connections
end
feature {HTTPD_SERVER_I} -- Execution
shutdown
-- <Precursor>
do
if not is_shutdown_requested then
is_shutdown_requested := True
pool_gracefull_stop (pool)
end
end
pool_gracefull_stop (p: like pool)
-- Graceful stop concurrent pool of separate connection handlers.
do
p.gracefull_stop
end
accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
-- <Precursor>
do
accept_connection_on_pool (pool, a_listening_socket) -- Wait on not pool.is_full or is_stop_requested
end
accept_connection_on_pool (a_pool: like pool; a_listening_socket: HTTPD_STREAM_SOCKET)
-- 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
local
cl: separate HTTPD_STREAM_SOCKET
do
debug ("dbglog")
dbglog (generator + ".ENTER accept_connection_on_pool")
end
if is_shutdown_requested then
-- Cancel
elseif attached a_pool.separate_item (factory) as h then
cl := separate_client_socket (h)
a_listening_socket.accept_to (cl)
process_handler (h)
else
check is_not_full: False end
end
debug ("dbglog")
dbglog (generator + ".LEAVE accept_connection_on_pool")
end
end
process_handler (hdl: separate HTTPD_REQUEST_HANDLER)
-- Process request handler `hdl' as soon as `hdl' is connected to accepted socket.
require
hdl.is_connected
do
hdl.safe_execute
end
feature {HTTPD_SERVER_I} -- Status report
wait_for_completion
-- Wait until Current is ready for shutdown.
do
wait_for_pool_completion (pool)
end
wait_for_pool_completion (p: like pool)
-- Wait until concurrent pool is empty and terminated.
require
p.is_empty -- SCOOP wait condition.
do
p.terminate
end
feature {NONE} -- Implementation
separate_client_socket (hdl: separate HTTPD_REQUEST_HANDLER): separate HTTPD_STREAM_SOCKET
-- Client socket for request handler `hdl'.
do
Result := hdl.client_socket
end
pool: separate CONCURRENT_POOL [HTTPD_REQUEST_HANDLER]
-- Pool of separate connection handlers.
invariant
pool_attached: pool /= Void
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,55 +0,0 @@
note
description: "[
Instance of HTTPD_REQUEST_HANDLER will process the incoming connection
and extract information on the request and the server
]"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER
inherit
HTTPD_REQUEST_HANDLER_I
redefine
release
end
CONCURRENT_POOL_ITEM
rename
release as release_pool_item
end
feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release
-- <Precursor>
local
d: STRING
do
if attached internal_client_socket as l_socket then
d := l_socket.descriptor.out
else
d := "N/A"
end
debug ("dbglog")
dbglog (generator + ".release: ENTER {" + d + "}")
end
Precursor {HTTPD_REQUEST_HANDLER_I}
release_pool_item
debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}")
end
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,27 +0,0 @@
note
description: "Implementation of request handler factory for concurrency mode: SCOOP"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER_FACTORY
inherit
HTTPD_REQUEST_HANDLER_FACTORY_I
CONCURRENT_POOL_FACTORY [HTTPD_REQUEST_HANDLER]
rename
new_separate_item as new_handler
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,190 +0,0 @@
note
description: "Concurrent pool for SCOOP concurrency mode."
date: "$Date$"
revision: "$Revision$"
class
CONCURRENT_POOL [G -> CONCURRENT_POOL_ITEM]
inherit
HTTPD_DEBUG_FACILITIES
create
make
feature {NONE} -- Initialization
make (n: INTEGER)
do
capacity := n
create items.make_empty (n)
create busy_items.make_empty (n)
end
feature -- Access
count: INTEGER
-- Number of concurrent items managed by Current pool.
capacity: INTEGER
-- Maximum number of concurrent items managed by Current pool.
feature -- Status report
is_full: BOOLEAN
-- Pool is full?
do
Result := count >= capacity
end
is_empty: BOOLEAN
-- No concurrent item waiting in current pool.
do
Result := count = 0
end
stop_requested: BOOLEAN
-- Current pool received a request to terminate.
feature -- Access
separate_item (a_factory: separate CONCURRENT_POOL_FACTORY [G]): detachable separate G
-- Reused, or new separate item of type {G} created by `a_factory'.
require
is_not_full: not is_full
local
i,n,pos: INTEGER
lst: like busy_items
l_item: detachable separate G
do
if not stop_requested then
from
lst := busy_items
pos := -1
i := 0
n := lst.count - 1
until
i > n or l_item /= Void or pos >= 0
loop
if not lst [i] then -- is free (i.e not busy)
pos := i
if items.valid_index (pos) then
l_item := items [pos]
if l_item /= Void then
busy_items [pos] := True
end
end
if l_item = Void then
-- Empty, then let's create one.
l_item := a_factory.new_separate_item
register_item (l_item)
items [pos] := l_item
end
end
i := i + 1
end
if l_item = Void then
-- Pool is FULL ...
check overcapacity: False end
else
debug ("pool", "dbglog")
dbglog ("Lock pool item #" + pos.out + " (free:"+ (capacity - count).out +"))")
end
count := count + 1
busy_items [pos] := True
Result := l_item
a_factory.update_item (l_item)
end
end
end
feature -- Basic operation
gracefull_stop
-- Request the Current pool to terminate.
do
stop_requested := True
end
feature {NONE} -- Internal
items: SPECIAL [detachable separate G]
-- List of concurrent items.
busy_items: SPECIAL [BOOLEAN]
-- Map of items being proceed.
feature {CONCURRENT_POOL_ITEM} -- Change
release_item (a_item: separate G)
-- Unregister `a_item' from Current pool.
require
count > 0
local
i,n,pos: INTEGER
lst: like items
do
-- release handler for reuse
from
lst := items
i := 0
n := lst.count - 1
until
i > n or lst [i] = a_item
loop
i := i + 1
end
if i <= n then
pos := i
busy_items [pos] := False
count := count - 1
--reuse items [pos] := Void
debug ("pool", "dbglog")
dbglog ("Released pool item #" + i.out + " (free:"+ (capacity - count).out +"))")
end
else
check known_item: False end
end
end
feature -- Change
set_count (n: INTEGER)
-- Set capacity of Current pool to `n'.
local
g: detachable separate G
do
capacity := n
items.fill_with (g, 0, n - 1)
busy_items.fill_with (False, 0, n - 1)
end
terminate
-- Terminate current pool.
local
l_items: like items
do
l_items := items
l_items.wipe_out
end
feature {NONE} -- Implementation
register_item (a_item: separate G)
-- Adopt `a_item' in current pool.
do
a_item.set_pool (Current)
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,31 +0,0 @@
note
description: "Factory in charge of creating new concurrent pool item."
date: "$Date$"
revision: "$Revision$"
deferred class
CONCURRENT_POOL_FACTORY [G -> CONCURRENT_POOL_ITEM]
feature -- Access
update_item (a_item: separate G)
-- Update `a_item' for optionally purpose.
do
end
new_separate_item: separate G
-- New separated object of type {G}.
deferred
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,52 +0,0 @@
note
description: "[
Item create by the CONCURRENT_POOL_FACTORY, and managed by the CONCURRENT_POOL
for SCOOP concurrency mode.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
CONCURRENT_POOL_ITEM
feature {NONE} -- Access
pool: detachable separate CONCURRENT_POOL [CONCURRENT_POOL_ITEM]
-- Associated concurrent pool component.
feature {CONCURRENT_POOL} -- Change
set_pool (p: like pool)
-- Set associated `pool' to `p'.
do
pool := p
end
feature {CONCURRENT_POOL, HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release
-- Release Current pool item from associated pool.
do
if attached pool as p then
pool_release (p)
end
end
feature {NONE} -- Implementation
pool_release (p: separate CONCURRENT_POOL [CONCURRENT_POOL_ITEM])
do
p.release_item (Current)
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,103 +0,0 @@
note
description: "[
Implementation of HTTPD_CONNECTION_HANDLER_I for concurrency mode: Thread
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONNECTION_HANDLER
inherit
HTTPD_CONNECTION_HANDLER_I
redefine
initialize
end
create
make
feature {NONE} -- Initialization
initialize
local
n: INTEGER
do
n := max_concurrent_connections (server).max (1) -- At least one thread!
create pool.make (n.to_natural_32)
end
feature -- Access
is_shutdown_requested: BOOLEAN
max_concurrent_connections (a_server: like server): INTEGER
do
Result := a_server.configuration.max_concurrent_connections
end
feature {HTTPD_SERVER_I} -- Execution
shutdown
do
if not is_shutdown_requested then
is_shutdown_requested := True
pool_gracefull_stop (pool)
end
end
pool_gracefull_stop (p: like pool)
do
p.terminate
end
accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
local
cl: separate HTTPD_STREAM_SOCKET
do
debug ("dbglog")
dbglog (generator + ".ENTER accept_connection {"+ a_listening_socket.descriptor.out +"}")
end
if is_shutdown_requested then
-- cancel
elseif attached factory.new_handler as h then
cl := h.client_socket
a_listening_socket.accept_to (cl)
if h.is_connected then
pool.add_work (agent h.safe_execute)
end
end
debug ("dbglog")
dbglog (generator + ".LEAVE accept_incoming_connection {"+ a_listening_socket.descriptor.out +"}")
end
end
feature {HTTPD_SERVER_I} -- Status report
wait_for_completion
-- Wait until Current is ready for shutdown
do
pool.wait_for_completion
end
feature {NONE} -- Access
pool: THREAD_POOL [HTTPD_REQUEST_HANDLER] --ANY] --POOLED_THREAD [HTTP_REQUEST_HANDLER]]
-- Pool of concurrent connection handlers.
invariant
pool_attached: pool /= Void
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,49 +0,0 @@
note
description: "[
Instance of HTTPD_REQUEST_HANDLER will process the incoming connection
and extract information on the request and the server
]"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER
inherit
HTTPD_REQUEST_HANDLER_I
redefine
release
end
feature {HTTPD_CONNECTION_HANDLER_I} -- Basic operation
release
local
d: 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")
dbglog (generator + ".release: ENTER {" + d + "}")
end
Precursor {HTTPD_REQUEST_HANDLER_I}
debug ("dbglog")
dbglog (generator + ".release: LEAVE {" + d + "}")
end
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,15 +0,0 @@
note
description: "Implementation of request handler factory for concurrency mode: Thread"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER_FACTORY
inherit
HTTPD_REQUEST_HANDLER_FACTORY_I
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,121 +0,0 @@
note
description: "{POOLED_THREAD} is used in combination with {THREAD_POOL} to allow for pooled threads."
legal: "See notice at end of class."
status: "Community Preview 1.0"
date: "$Date: 2009-09-01 19:15:37 -0300 (mar 01 de sep de 2009) $"
revision: "$Revision: 80577 $"
class
POOLED_THREAD [G]
inherit
THREAD
rename
make as thread_make
end
create {THREAD_POOL}
make
feature {NONE} -- Initialization
make (a_thread_pool: THREAD_POOL [G]; a_semaphore: SEMAPHORE)
-- `a_thread_pool', the pool in which this thread is managed
-- `a_semaphore' is used for execution suspending
do
thread_make
thread_pool := a_thread_pool
semaphore := a_semaphore
end
feature {NONE} -- Access
thread_pool: THREAD_POOL [G]
-- Pool manager in which this thread is pooled
target: detachable G
-- Target on which the `thread_procedure' should be applied
-- Depending on which launch is used, target is not used
thread_procedure: detachable PROCEDURE
-- Work that should be executed by the thread
semaphore: SEMAPHORE
-- Semaphore share with all threads in a thread pool
-- to suspend execution until more work is available
feature -- Access
set_target (a_target: G)
-- Sets the target on which the work should be executed
do
target := a_target
end
feature {NONE} -- Implementation
execute
-- <Precursor>
local
done: BOOLEAN
do
from
semaphore.wait
thread_procedure := thread_pool.get_work (Current)
until
done
loop
if attached thread_procedure as l_work then
if attached target as t then
l_work.call ([t])
else
l_work.call (Void)
end
end
if thread_pool.over then
done := True
else
thread_procedure := thread_pool.get_work (Current)
if thread_procedure = Void then
semaphore.wait
thread_procedure := thread_pool.get_work (Current)
end
end
end
thread_pool.thread_terminated (Current)
end
note
copyright: "2011-2012, Javier Velilla and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
licensing_options: "http://www.eiffel.com/licensing"
copying: "[
This file is part of Eiffel Software's Eiffel Development Environment.
Eiffel Software's Eiffel Development Environment is free
software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published
by the Free Software Foundation, version 2 of the License
(available at the URL listed under "license" above).
Eiffel Software's Eiffel Development Environment is
distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with Eiffel Software's Eiffel Development
Environment; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
]"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,228 +0,0 @@
note
description: "[
A thread pool manager. Manages threads up to `capacity' and queue after that,
till threads get available again.
]"
legal: "See notice at end of class."
status: "Community Preview 1.0"
date: "$Date: 2009-09-01 19:15:37 -0300 (mar 01 de sep de 2009) $"
revision: "$Revision: 80577 $"
class
THREAD_POOL [G]
inherit
EXECUTION_ENVIRONMENT
create
make
feature {NONE} -- Initialization
make (n: like capacity)
-- Initialize current pool with capacity `n'.
require
n_positive: n > 0
n_not_too_large: n < {INTEGER_32}.max_value.as_natural_32
local
i: NATURAL
do
capacity := n
create work_queue.make (n.to_integer_32)
create work_queue_mutex.make
create over_mutex.make
create termination_mutex.make
create work_semaphore.make (capacity.as_integer_32)
from
i := 1
until
i > capacity
loop
work_semaphore.wait
i := i + 1
end
initialize_threads
terminated_count := capacity
is_over := False
ensure
capacity_set: capacity = n
work_queue_set: work_queue.is_empty
end
initialize_threads
-- Launches all threads
local
i: NATURAL
thread: POOLED_THREAD [G]
do
from
i := 1
until
i > capacity
loop
create thread.make (Current, work_semaphore)
thread.launch
i := i + 1
end
end
feature -- Access
capacity: NATURAL
-- Maximal number of threads allowed (queuing otherwise)
queue_count: NATURAL
-- Number of items in queue
do
work_queue_mutex.lock
Result := work_queue.count.as_natural_32
work_queue_mutex.unlock
end
feature -- Status report
valid_action (a_action: PROCEDURE): BOOLEAN
-- Is `a_action' a valid action for the current pool.
do
-- There should be no open operands.
Result := a_action.valid_operands (Void)
end
feature -- Basic operations
add_work (work: PROCEDURE)
-- Launches a thread with the specified argument `arg'. Reuse of thread if possible.
require
valid_action: valid_action (work)
do
work_queue_mutex.lock
work_queue.extend (work)
if work_queue.count <= capacity.as_integer_32 then
-- Let one thread wake up and do the work
work_semaphore.post
end
work_queue_mutex.unlock
end
over: BOOLEAN
-- Is the thread pool being terminated?
do
over_mutex.lock
Result := is_over
over_mutex.unlock
end
thread_terminated (a_thread: POOLED_THREAD [G])
-- Notifies the thread pool that a thread has terminated its execution.
do
termination_mutex.lock
terminated_count := terminated_count - 1
termination_mutex.unlock
end
get_work (requester: POOLED_THREAD [G]): detachable PROCEDURE
-- If there is work to do, it is returned
-- Yields Void otherwise
do
if not over then
work_queue_mutex.lock
if not work_queue.is_empty then
Result := work_queue.item
work_queue.remove
end
work_queue_mutex.unlock
end
end
wait_for_completion
-- Wait until there is no more work to be completed
local
done: BOOLEAN
do
from
until
done
loop
work_queue_mutex.lock
done := work_queue.is_empty
work_queue_mutex.unlock
if not done then
sleep (1)
end
end
end
terminate
-- Terminates all the threads after their execution
do
over_mutex.lock
is_over := True
over_mutex.unlock
from
termination_mutex.lock
until
terminated_count = 0
loop
work_semaphore.post
termination_mutex.unlock
termination_mutex.lock
end
termination_mutex.unlock
end
feature {NONE} -- Implementation: Access
work_queue: ARRAYED_QUEUE [PROCEDURE]
-- Queue that holds unprocessed requests as agents
-- Thread-safe access when accessor holds `queue_mutex'
work_queue_mutex: MUTEX
-- Mutex for the queue
work_semaphore: SEMAPHORE
-- Semaphore which hols the number of work to be done.
-- Needed to wake up worker threads
terminated_count: NATURAL
--
is_over: BOOLEAN
-- Is the thread pool being terminated?
over_mutex: MUTEX
-- Mutex for the `is_over' variable
termination_mutex: MUTEX
;note
copyright: "2011-2012, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
licensing_options: "http://www.eiffel.com/licensing"
copying: "[
This file is part of Eiffel Software's Eiffel Development Environment.
Eiffel Software's Eiffel Development Environment is free
software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published
by the Free Software Foundation, version 2 of the License
(available at the URL listed under "license" above).
Eiffel Software's Eiffel Development Environment is
distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with Eiffel Software's Eiffel Development
Environment; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
]"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,278 +0,0 @@
note
description: "Configuration for the standalone HTTPd server."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_CONFIGURATION_I
feature {NONE} -- Initialization
make
do
http_server_port := default_http_server_port
max_concurrent_connections := default_max_concurrent_connections
max_tcp_clients := default_max_tcp_clients
socket_timeout := default_socket_timeout
keep_alive_timeout := default_keep_alive_timeout
max_keep_alive_requests := default_max_keep_alive_requests
is_secure := False
create ca_crt.make_empty
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
-- Detail of the server.
deferred
end
http_server_name: detachable READABLE_STRING_8 assign set_http_server_name
http_server_port: INTEGER assign set_http_server_port
max_tcp_clients: INTEGER assign set_max_tcp_clients
-- Listen on socket for at most `queue' connections.
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.
max_concurrent_connections: INTEGER assign set_max_concurrent_connections
-- Max number of concurrent connections.
force_single_threaded: BOOLEAN assign set_force_single_threaded
do
Result := max_concurrent_connections = 0
end
is_verbose: BOOLEAN assign set_is_verbose
-- Display verbose message to the output?
verbose_level: INTEGER assign set_verbose_level
-- Verbosity of output.
keep_alive_timeout: INTEGER assign set_keep_alive_timeout
-- Persistent connection timeout.
-- Number of seconds the server waits after a request has been served before it closes the connection.
-- Timeout unit in Seconds.
-- By default: 5 seconds.
max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests
-- Maximum number of requests allowed per persistent connection.
-- Recommended a high setting.
-- To disable KeepAlive, set `max_keep_alive_requests' to 0.
-- By default: 100 .
has_ssl_support: BOOLEAN
-- Has SSL support?
deferred
end
request_settings: HTTPD_REQUEST_SETTINGS
do
Result.is_verbose := is_verbose
Result.verbose_level := verbose_level
Result.timeout := socket_timeout
Result.keep_alive_timeout := keep_alive_timeout
Result.max_keep_alive_requests := max_keep_alive_requests
end
feature -- Access: SSL
is_secure: BOOLEAN
-- Is SSL/TLS session?.
ca_crt: IMMUTABLE_STRING_8
-- the signed certificate.
ca_key: IMMUTABLE_STRING_8
-- private key to the certificate.
ssl_protocol: NATURAL
-- By default protocol is tls 1.2.
feature -- Element change
set_http_server_name (v: detachable separate READABLE_STRING_8)
do
if v = Void then
unset_http_server_name
else
create {IMMUTABLE_STRING_8} http_server_name.make_from_separate (v)
end
end
unset_http_server_name
-- Unset `http_server_name' value.
do
http_server_name := Void
ensure
unset_http_server_name: http_server_name = Void
end
set_http_server_port (v: like http_server_port)
-- Set `http_server_port' with `v'.
do
http_server_port := v
ensure
http_server_port_set: http_server_port = v
end
set_max_tcp_clients (v: like max_tcp_clients)
-- Set `max_tcp_clients' with `v'.
do
max_tcp_clients := v
ensure
max_tcp_clients_set: max_tcp_clients = v
end
set_max_concurrent_connections (v: like max_concurrent_connections)
-- Set `max_concurrent_connections' with `v'.
do
max_concurrent_connections := v
ensure
max_concurrent_connections_set : max_concurrent_connections = v
end
set_socket_timeout (a_nb_seconds: like socket_timeout)
-- Set `socket_timeout' with `a_nb_seconds'
do
socket_timeout := a_nb_seconds
ensure
socket_timeout_set: socket_timeout = a_nb_seconds
end
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
-- Set `keep_alive_timeout' with `a_seconds'
do
keep_alive_timeout := a_seconds
ensure
keep_alive_timeout_set: keep_alive_timeout = a_seconds
end
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
-- Set `max_keep_alive_requests' with `nb'
do
max_keep_alive_requests := nb
ensure
max_keep_alive_requests_set: max_keep_alive_requests = nb
end
set_force_single_threaded (v: like force_single_threaded)
-- Force server to handle incoming request in a single thread.
-- i.e set max_concurrent_connections to 0!
obsolete
"Use set_max_concurrent_connections (0) [June/2016]"
do
if v then
set_max_concurrent_connections (0)
end
--|Missing postcondition
--| force_single_thread_set: v implies max_concurrent_connections = 0
--| not_single_thread: not v implies max_concurrent_connections > 0
end
set_is_verbose (b: BOOLEAN)
-- Set `is_verbose' to `b'
do
is_verbose := b
ensure
is_verbose_set: is_verbose = b
end
set_verbose_level (lev: INTEGER)
-- Set `verbose_level' to `lev'.
do
verbose_level := lev
ensure
verbose_level_set: verbose_level = lev
end
mark_secure
-- Set is_secure in True
do
if has_ssl_support then
is_secure := True
if http_server_port = 80 then
set_http_server_port (443)
end
else
is_secure := False
end
ensure
is_secure_set: has_ssl_support implies is_secure
-- http_server_port_set: has_ssl_support implies http_server_port = 443
is_not_secure: not has_ssl_support implies not is_secure
-- default_port: not has_ssl_support implies http_server_port = 80
end
feature -- Element change
set_ca_crt (a_value: separate READABLE_STRING_8)
-- Set `ca_crt' from `a_value'.
do
create ca_crt.make_from_separate (a_value)
end
set_ca_key (a_value: STRING)
-- Set `ca_key' with `a_value'.
do
create ca_key.make_from_separate (a_value)
end
set_ssl_protocol (a_version: NATURAL)
-- Set `ssl_protocol' with `a_version'
do
ssl_protocol := a_version
ensure
ssl_protocol_set: ssl_protocol = a_version
end
feature -- SSL Helpers
set_ssl_protocol_to_ssl_2_or_3
-- Set `ssl_protocol' with `Ssl_23'.
deferred
end
set_ssl_protocol_to_tls_1_0
-- Set `ssl_protocol' with `Tls_1_0'.
deferred
end
set_ssl_protocol_to_tls_1_1
-- Set `ssl_protocol' with `Tls_1_1'.
deferred
end
set_ssl_protocol_to_tls_1_2
-- Set `ssl_protocol' with `Tls_1_2'.
deferred
end
set_ssl_protocol_to_dtls_1_0
-- Set `ssl_protocol' with `Dtls_1_0'.
deferred
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,64 +0,0 @@
note
description: "[
Request settings for the standalone HTTPd server.
]"
author: "$Author$"
date: "$Date$"
revision: "$Revision$"
expanded class
HTTPD_REQUEST_SETTINGS
feature -- Access
is_verbose: BOOLEAN assign set_is_verbose
-- Is verbose?
verbose_level: INTEGER assign set_verbose_level
-- Verbosity of output.
timeout: INTEGER assign set_timeout
-- Amount of seconds that the server waits for receipts and transmissions 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.
-- Unit in Seconds.
max_keep_alive_requests: INTEGER assign set_max_keep_alive_requests
-- Maximum number of requests allowed per persistent connection.
feature -- Change
set_is_verbose (b: BOOLEAN)
-- Set `is_verbose' to `b'.
do
is_verbose := b
end
set_verbose_level (lev: INTEGER)
-- Set `verbose_level' to `lev'.
do
verbose_level := lev
end
set_timeout (a_timeout_in_seconds: INTEGER)
-- Set `timeout' to `a_timeout_in_seconds'.
do
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
keep_alive_timeout := a_timeout_in_seconds
end
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
-- Set `max_keep_alive_requests' with `nb'
do
max_keep_alive_requests := nb
end
end

View File

@@ -1,60 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="httpd" uuid="50FE258D-CC94-4748-9223-55F1129E5FB3" library_target="httpd">
<target name="httpd">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<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_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</library>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf">
<condition>
<concurrency excluded_value="none"/>
</condition>
</library>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="httpd_server" location=".\" recursive="true">
<file_rule>
<exclude>/concurrency$</exclude>
<exclude>/no_ssl$</exclude>
<exclude>/ssl$</exclude>
</file_rule>
<cluster name="no_ssl" location="$|no_ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" excluded_value="true"/>
</condition>
</cluster>
<cluster name="ssl" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</cluster>
<cluster name="concurrency_none" location="$|concurrency\none\" recursive="true">
<condition>
<concurrency value="none"/>
</condition>
</cluster>
<cluster name="concurrency_scoop" location="$|concurrency\scoop\" recursive="true">
<condition>
<concurrency value="scoop"/>
</condition>
</cluster>
<cluster name="concurrency_thread" location="$|concurrency\thread\" recursive="true">
<condition>
<concurrency value="thread"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="httpd" uuid="50FE258D-CC94-4748-9223-55F1129E5FB3" library_target="httpd">
<target name="httpd">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/.svn$</exclude>
<exclude>/EIFGENs$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl.ecf">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</library>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf">
<condition>
<concurrency excluded_value="none"/>
</condition>
</library>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="httpd_server" location=".\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/concurrency$</exclude>
<exclude>/no_ssl$</exclude>
<exclude>/ssl$</exclude>
</file_rule>
<cluster name="no_ssl" location="$|no_ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" excluded_value="true"/>
</condition>
</cluster>
<cluster name="ssl" location="$|ssl\" recursive="true">
<condition>
<custom name="httpd_ssl_enabled" value="true"/>
</condition>
</cluster>
<cluster name="concurrency_none" location="$|concurrency\none\" recursive="true">
<condition>
<concurrency value="none"/>
</condition>
</cluster>
<cluster name="concurrency_scoop" location="$|concurrency\scoop\" recursive="true">
<condition>
<concurrency value="scoop"/>
</condition>
</cluster>
<cluster name="concurrency_thread" location="$|concurrency\thread\" recursive="true">
<condition>
<concurrency value="thread"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -1,97 +0,0 @@
note
description: "[
Interface for the incoming connection handler.
Each incoming socket connection is processed by
an implementation of HTTPD_CONNECTION_HANDLER_I.
Note there are 3 implementations, one for each concurrent mode: none, thread, scoop.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_CONNECTION_HANDLER_I
inherit
HTTPD_DEBUG_FACILITIES
feature {NONE} -- Initialization
frozen make (a_server: like server)
do
server := a_server
factory := separate_factory (a_server)
initialize
end
initialize
deferred
end
feature {NONE} -- Access
factory: separate HTTPD_REQUEST_HANDLER_FACTORY
-- Request handler factory.
server: separate HTTPD_SERVER_I
-- Associated server.
feature {HTTPD_SERVER_I} -- Execution
accept_incoming_connection (a_listening_socket: HTTPD_STREAM_SOCKET)
-- Accept incoming connection from `a_listening_socket'.
deferred
end
shutdown
-- Shutdown server.
deferred
end
wait_for_completion
-- Wait until Current completed any pending task.
--| Used for SCOOP synchronisation.
deferred
end
feature {HTTPD_SERVER} -- Status report
is_shutdown_requested: BOOLEAN
-- Any request to shutdown the server?
deferred
end
feature {NONE} -- Implementation
log (a_message: separate READABLE_STRING_8)
-- Log `a_message'
do
-- FIXME: Concurrency issue on `server'
separate_server_log (server, a_message)
end
separate_factory (a_server: like server): like factory
-- Separate factory from `a_server'.
--| required by SCOOP design.
do
Result := a_server.factory
end
separate_server_log (a_server: like server; a_message: separate READABLE_STRING_8)
-- Concurrent call to `a_server.log (a_message)'.
do
a_server.log (a_message)
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,28 +0,0 @@
note
description: "[
Object used to control (i.e shutdown) the server.
Mostly needed in SCOOP concurrency mode.
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONTROLLER
feature -- Operation
shutdown
-- Request the associated server to be shutdown.
do
shutdown_requested := True
end
feature -- Status report.
shutdown_requested: BOOLEAN
-- Shutdown requested.
;note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,50 +0,0 @@
note
description: " Routines used for debug logging."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_DEBUG_FACILITIES
feature {NONE} -- Output
dbglog (m: READABLE_STRING_8)
require
not m.ends_with_general ("%N")
local
s: STRING
do
debug ("dbglog")
create s.make (24)
s.append ("[EWF/DBG] <#")
s.append_integer (processor_id_from_object (Current))
s.append ("> ")
s.append (generator)
s.append (create {STRING}.make_filled (' ', (46 - s.count).max (0)))
s.append (" | ")
s.append (m)
s.append ("%N")
print (s)
end
end
feature -- runtime
frozen processor_id_from_object (a_object: separate ANY): INTEGER_32
external
"C inline use %"eif_scoop.h%""
alias
"RTS_PID(eif_access($a_object))"
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,26 +0,0 @@
note
description: "Logging facilities component"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_LOGGER
feature -- Logs
log (a_message: separate READABLE_STRING_8)
-- Log `a_message'
deferred
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,22 +0,0 @@
note
description: "[
Constant value to define the logging level.
]"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_LOGGER_CONSTANTS
feature -- Access
alert_level: INTEGER = 1 -- 0000 0001
critical_level: INTEGER = 2 -- 0000 0010
error_level: INTEGER = 4 -- 0000 0100
warning_level: INTEGER = 8 -- 0000 1000
notice_level: INTEGER = 16 -- 0001 0000
information_level: INTEGER = 32 -- 0010 0000
debug_level: INTEGER = 64 -- 0100 0000
end

View File

@@ -1,26 +0,0 @@
note
description: "Summary description for {HTTPD_REQUEST_HANDLER_FACTORY_I}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER_FACTORY_I
feature -- Factory
new_handler: separate HTTPD_REQUEST_HANDLER
deferred
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,477 +0,0 @@
note
description: "HTTPD handler interface processing request."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_REQUEST_HANDLER_I
inherit
HTTPD_DEBUG_FACILITIES
HTTPD_LOGGER_CONSTANTS
feature {NONE} -- Initialization
make (a_request_settings: HTTPD_REQUEST_SETTINGS)
do
reset
-- Import global request settings.
timeout := a_request_settings.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
end
reset
do
reset_request
has_error := False
if attached internal_client_socket as l_sock then
l_sock.cleanup
end
internal_client_socket := Void
end
reset_request
do
version := Void
remote_info := 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)
is_persistent_connection_requested := False
end
feature -- Status report
is_connected: BOOLEAN
-- Is handler connected to incoming request via `client_socket'?
do
Result := client_socket.descriptor_available
end
feature -- Access
internal_client_socket: detachable HTTPD_STREAM_SOCKET
client_socket: HTTPD_STREAM_SOCKET
local
s: like internal_client_socket
do
s := internal_client_socket
if s = Void then
create s.make_empty
internal_client_socket := s
end
Result := s
end
request_header: STRING
-- Header' source
request_header_map: HASH_TABLE [STRING, STRING]
-- Contains key:value of the header
method: STRING
-- http verb
uri: STRING
-- http endpoint
version: detachable STRING
-- http_version
--| unused for now
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
-- Information related to remote client
is_persistent_connection_requested: BOOLEAN
-- Persistent connection requested?
-- either has "Connection: keep-alive" header,
-- or is HTTP/1.1 and no header "Connection: close".
is_http_version_1_0: BOOLEAN
do
Result := not attached version as v or else v.same_string ("HTTP/1.0")
end
is_http_version_1_1: BOOLEAN
do
Result := not attached version as v or else v.same_string ("HTTP/1.1")
end
is_http_version_2: BOOLEAN
do
Result := not attached version as v or else v.same_string ("HTTP/2.0")
end
feature -- Settings
is_verbose: BOOLEAN
-- Output messages?
verbose_level: INTEGER
-- Output verbosity.
is_persistent_connection_supported: BOOLEAN
-- Is persistent connection supported?
do
Result := {HTTPD_SERVER}.is_persistent_connection_supported and then max_keep_alive_requests > 0
end
is_next_persistent_connection_supported: BOOLEAN
-- Is next persistent connection supported?
-- note: it is relevant only if `is_persistent_connection_supported' is True.
timeout: INTEGER -- seconds
-- Amount of seconds that the server waits for receipts and transmissions during communications.
max_keep_alive_requests: INTEGER
-- Maximum number of requests allowed per persistent connection.
keep_alive_timeout: INTEGER -- seconds
-- Number of seconds for persistent connection timeout.
feature -- Status report
has_error: BOOLEAN
-- Error occurred during `analyze_request_message'
feature -- Change
set_is_verbose (b: BOOLEAN)
-- Set `is_verbose' with `b'.
do
is_verbose := b
ensure
is_verbose_set: is_verbose = b
end
feature -- Execution
safe_execute
-- Execute accepted incoming connection as request.
local
retried: BOOLEAN
do
if retried then
release
else
if
not has_error and then
is_connected
then
execute
end
release
end
rescue
retried := True
retry
end
execute
require
is_connected: is_connected
local
l_socket: like client_socket
l_exit: BOOLEAN
n,m: INTEGER
do
l_socket := client_socket
check
socket_attached: l_socket /= Void
socket_valid: l_socket.is_open_read and then l_socket.is_open_write
end
from
-- Process persistent connection as long the socket is not closed.
n := 0
m := max_keep_alive_requests
is_next_persistent_connection_supported := True
until
l_exit
loop
n := n + 1
if n >= m then
is_next_persistent_connection_supported := False
end
-- FIXME: it seems to be called one more time, mostly to see this is done.
execute_request
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
end
execute_request
require
is_connected: is_connected
local
l_remote_info: detachable like remote_info
l_socket: like client_socket
l_is_ready: BOOLEAN
do
l_socket := client_socket
check
socket_attached: l_socket /= Void
socket_valid: l_socket.is_open_read and then l_socket.is_open_write
end
if l_socket.is_closed then
debug ("dbglog")
dbglog (generator + ".execute_request {socket is Closed!}")
end
else
debug ("dbglog")
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 l_is_ready then
l_socket.set_timeout (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
l_remote_info.hostname := l_addr.host_address.host_name
l_remote_info.port := l_addr.port
remote_info := l_remote_info
end
analyze_request_message (l_socket)
else
has_error := True
debug ("dbglog")
dbglog (generator + ".execute_request socket=" + l_socket.descriptor.out + "} timeout!")
end
end
if has_error then
if l_is_ready then
-- check catch_bad_incoming_connection: False end
if is_verbose then
log (request_header + "%NWARNING: invalid HTTP incoming request", warning_level)
end
end
else
if is_verbose then
log (request_header, information_level)
end
process_request (l_socket)
end
debug ("dbglog")
dbglog (generator + ".execute_request {" + l_socket.descriptor.out + "} LEAVE")
end
end
end
release
do
reset
end
feature -- Request processing
process_request (a_socket: HTTPD_STREAM_SOCKET)
-- Process request ...
require
no_error: not has_error
a_uri_attached: uri /= Void
a_method_attached: method /= Void
a_header_map_attached: request_header_map /= Void
a_header_text_attached: request_header /= Void
a_socket_attached: a_socket /= Void
deferred
end
feature -- Parsing
analyze_request_message (a_socket: HTTPD_STREAM_SOCKET)
-- Analyze message extracted from `a_socket' as HTTP request
require
input_readable: a_socket /= Void and then a_socket.is_open_read
local
end_of_stream: BOOLEAN
pos, n: INTEGER
line: detachable STRING
k, val: STRING
txt: STRING
l_is_verbose: BOOLEAN
do
create txt.make (64)
request_header := txt
if
not has_error and then
a_socket.is_readable and then
attached next_line (a_socket) as l_request_line and then
not l_request_line.is_empty
then
txt.append (l_request_line)
txt.append_character ('%N')
analyze_request_line (l_request_line)
else
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
from
line := next_line (a_socket)
until
line = Void or end_of_stream or has_error
loop
n := line.count
debug ("ew_standalone")
if l_is_verbose then
log (line, debug_level)
end
end
pos := line.index_of (':', 1)
if pos > 0 then
k := line.substring (1, pos - 1)
if line [pos + 1].is_space then
pos := pos + 1
end
if line [n] = '%R' then
n := n - 1
end
val := line.substring (pos + 1, n)
request_header_map.put (val, k)
end
txt.append (line)
txt.append_character ('%N')
if line.is_empty or else line [1] = '%R' then
end_of_stream := True
else
line := next_line (a_socket)
end
end
-- Except for HTTP/1.0, persistent connection is the default.
is_persistent_connection_requested := True
if is_http_version_1_0 then
is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then
l_connection.is_case_insensitive_equal_general ("keep-alive")
else
-- By default HTTP:1/1 support persistent connection.
if attached request_header_map.item ("Connection") as l_connection then
if l_connection.is_case_insensitive_equal_general ("close") then
is_persistent_connection_requested := False
end
else
is_persistent_connection_requested := True
end
end
end
end
analyze_request_line (line: STRING)
-- Analyze `line' as a HTTP request line
require
valid_line: line /= Void and then not line.is_empty
local
n, pos, next_pos: INTEGER
do
debug ("ew_standalone")
if is_verbose then
log ("%N## Parse HTTP request line ##", debug_level)
log (line, debug_level)
end
end
pos := line.index_of (' ', 1)
method := line.substring (1, pos - 1)
next_pos := line.index_of (' ', pos + 1)
uri := line.substring (pos + 1, next_pos - 1)
n := line.count
if line[n] = '%R' then
n := n - 1
end
version := line.substring (next_pos + 1, n)
has_error := method.is_empty
end
next_line (a_socket: HTTPD_STREAM_SOCKET): detachable STRING
-- Next line fetched from `a_socket' is available.
require
not_has_error: not has_error or is_verbose
is_readable: a_socket.is_open_read
local
retried: BOOLEAN
do
if retried then
has_error := True
Result := Void
elseif a_socket.readable then
a_socket.read_line_thread_aware
Result := a_socket.last_string
-- Do no check `socket_ok' before socket operation,
-- otherwise it may be False, due to error during other socket operation in same thread.
if not a_socket.socket_ok then
has_error := True
if is_verbose then
log (request_header +"%N" + Result + "%N## socket_ok=False! ##", debug_level)
end
end
else
-- Error with socket...
has_error := True
if is_verbose then
log (request_header + "%N## Socket is not readable! ##", debug_level)
end
end
rescue
retried := True
retry
end
feature -- Output
logger: detachable HTTPD_LOGGER
set_logger (a_logger: like logger)
-- Set `logger' with `a_logger'.
do
logger := a_logger
ensure
logger_set: logger = a_logger
end
log (m: STRING; a_level: INTEGER)
-- Log message `m'.
require
is_verbose: is_verbose
do
if is_verbose and (verbose_level & a_level) = a_level then
if attached logger as l_logger then
l_logger.log (m)
else
io.put_string (m + "%N")
end
end
end
invariant
request_header_attached: request_header /= Void
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,367 +0,0 @@
note
description: "HTTPD server interface"
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_SERVER_I
inherit
HTTPD_DEBUG_FACILITIES
HTTPD_LOGGER
feature {NONE} -- Initialization
make (a_factory: like factory)
-- Create current httpd server with `a_factory' of connection handlers.
-- `a_factory': connection handler builder
require
a_factory_is_separated: {PLATFORM}.is_scoop_capable implies not attached {HTTPD_REQUEST_HANDLER_FACTORY} a_factory
do
make_configured (create {like configuration}.make, a_factory)
end
make_configured (a_cfg: like configuration; a_factory: like factory)
-- `a_cfg': server configuration
-- `a_factory': connection handler builder
do
configuration := a_cfg
factory := a_factory
build_controller
initialize
end
build_controller
-- Build `controller'.
do
create <NONE> controller
end
initialize
-- Initialize Current server.
do
is_shutdown_requested := False
end
feature -- Access
is_verbose: BOOLEAN
-- Is verbose for output messages.
verbose_level: INTEGER
-- Verbosity of output.
configuration: HTTPD_CONFIGURATION
-- Associated server configuration.
controller: separate HTTPD_CONTROLLER
factory: separate HTTPD_REQUEST_HANDLER_FACTORY
is_persistent_connection_supported: BOOLEAN = True
-- Is persistent connection supported?
feature -- Callbacks
observer: detachable separate HTTPD_SERVER_OBSERVER
set_observer (obs: like observer)
-- Set `observer' to `obs'.
do
observer := obs
end
feature -- Access: listening
port: INTEGER
-- Effective listening port.
--| If 0 then it is not launched successfully!
feature -- Status: listening
is_launched: BOOLEAN
-- Server launched and listening on `port'
is_terminated: BOOLEAN
-- Is terminated?
is_shutdown_requested: BOOLEAN
-- Set true to stop accept loop
feature {NONE} -- Access: server
request_counter: INTEGER
-- request counter, incremented for each new incoming connection.
feature -- Execution
launch
do
apply_configuration
is_terminated := False
if is_verbose then
log ("%N%NStarting Web Application Server ...")
log (" - port = " + configuration.http_server_port.out)
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 (" - 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
log (" - verbose_level = " + configuration.verbose_level.out)
end
end
is_shutdown_requested := False
listen
is_terminated := True
on_terminated
end
shutdown_server
do
debug ("dbglog")
dbglog ("Shutdown requested")
end
is_shutdown_requested := True
controller_shutdown (controller)
end
controller_shutdown (ctl: attached like controller)
do
ctl.shutdown
end
feature -- Listening
listen
-- <Precursor>
-- Creates a socket and connects to the http server.
-- `a_server': The main server object
local
l_listening_socket: detachable HTTPD_STREAM_SOCKET
l_http_port: INTEGER
l_connection_handler: HTTPD_CONNECTION_HANDLER
do
is_terminated := False
is_launched := False
port := 0
is_shutdown_requested := False
l_http_port := configuration.http_server_port
if
attached configuration.http_server_name as l_servername and then
attached (create {INET_ADDRESS_FACTORY}).create_from_name (l_servername) as l_addr
then
l_listening_socket := new_listening_socket (l_addr, l_http_port)
else
l_listening_socket := new_listening_socket (Void, l_http_port)
end
if not l_listening_socket.is_bound then
if is_verbose then
log ("Socket could not be bound on port " + l_http_port.out + " !")
end
else
l_http_port := l_listening_socket.port
create l_connection_handler.make (Current)
from
l_listening_socket.listen (configuration.max_tcp_clients)
if is_verbose then
if configuration.is_secure then
log ("%NListening on port " + l_http_port.out +" : https://localhost:" + l_http_port.out + "/")
else
log ("%NListening on port " + l_http_port.out +" : http://localhost:" + l_http_port.out + "/")
end
end
on_launched (l_http_port)
until
is_shutdown_requested
loop
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)
l_listening_socket.cleanup
check
socket_is_closed: l_listening_socket.is_closed
end
end
if is_launched then
on_stopped
end
if is_verbose then
log ("HTTP Connection Server ends.")
end
rescue
log ("HTTP Connection Server shutdown due to exception. Please relaunch manually.")
if l_listening_socket /= Void then
l_listening_socket.cleanup
check
listening_socket_is_closed: l_listening_socket.is_closed
end
end
if is_launched then
on_stopped
end
is_shutdown_requested := True
retry
end
feature {NONE} -- Factory
new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET
do
if a_addr /= Void then
create Result.make_server_by_address_and_port (a_addr, a_http_port)
else
create Result.make_server_by_port (a_http_port)
end
end
feature {NONE} -- Helpers
wait_for_connection_handler_completion (h: HTTPD_CONNECTION_HANDLER)
do
h.wait_for_completion
debug ("dbglog")
dbglog ("Shutdown ready from connection_handler point of view")
end
end
update_is_shutdown_requested (a_connection_handler: HTTPD_CONNECTION_HANDLER)
do
is_shutdown_requested := is_shutdown_requested or shutdown_requested (controller)
if is_shutdown_requested then
a_connection_handler.shutdown
end
end
shutdown_requested (a_controller: separate HTTPD_CONTROLLER): BOOLEAN
-- Shutdown requested on concurrent `a_controller'?
do
Result := a_controller.shutdown_requested
end
feature -- Event
on_launched (a_port: INTEGER)
-- Server launched using port `a_port'
require
not_launched: not is_launched
do
is_launched := True
port := a_port
if attached observer as obs then
observer_on_launched (obs, a_port)
end
ensure
is_launched: is_launched
end
on_stopped
-- Server stopped
require
is_launched: is_launched
do
if attached observer as obs then
observer_on_stopped (obs)
end
end
on_terminated
-- Server terminated
require
is_terminated
do
if is_terminated and is_verbose then
log ("%N%NTerminating Web Application Server (port="+ port.out +"):%N")
end
if attached output as o then
o.flush
o.close
end
if attached observer as obs then
observer_on_terminated (obs)
end
end
feature {NONE} -- Separate event
observer_on_launched (obs: attached like observer; a_port: INTEGER)
do
obs.on_launched (a_port)
end
observer_on_stopped (obs: attached like observer)
do
obs.on_stopped
end
observer_on_terminated (obs: attached like observer)
do
obs.on_terminated
end
feature -- Configuration change
apply_configuration
require
is_not_launched: not is_launched
do
is_verbose := configuration.is_verbose
verbose_level := configuration.verbose_level
end
feature -- Output
output: detachable FILE
set_log_output (f: FILE)
-- Set `output' to `f'.
do
output := f
ensure
output_set: output = f
end
log (a_message: separate READABLE_STRING_8)
-- Log `a_message'.
local
m: STRING
do
create m.make_from_separate (a_message)
if attached output as o then
o.put_string (m)
o.put_new_line
else
io.error.put_string (m)
io.error.put_new_line
end
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,27 +0,0 @@
note
description: "Summary description for {HTTPD_SERVER_OBSERVER}."
date: "$Date$"
revision: "$Revision$"
deferred class
HTTPD_SERVER_OBSERVER
feature -- Event
on_launched (a_port: INTEGER)
-- Associated server launched listening on port `a_port'.
deferred
end
on_stopped
-- Associated server stopped.
--| the server may restart itself after being rescued.
deferred
end
on_terminated
-- Associated server terminated.
deferred
end
end

View File

@@ -1,341 +0,0 @@
note
description: "[
Summary description for {HTTPD_STREAM_SOCKET}
that can be used for http or https connection.
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_STREAM_SOCKET
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty
create {HTTPD_STREAM_SOCKET}
make
feature {NONE} -- Initialization
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
do
create {TCP_STREAM_SOCKET} socket.make_server_by_address_and_port (an_address, a_port)
end
make_server_by_port (a_port: INTEGER)
do
create {TCP_STREAM_SOCKET} socket.make_server_by_port (a_port)
end
make_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
do
create {TCP_STREAM_SOCKET} socket.make_client_by_address_and_port (an_address, a_port)
end
make_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING)
do
create {TCP_STREAM_SOCKET} socket.make_client_by_port (a_peer_port, a_peer_host)
end
make_from_separate (s: separate HTTPD_STREAM_SOCKET)
require
descriptor_available: s.descriptor_available
do
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
end
feature -- Change
set_timeout (n: INTEGER)
do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_timeout (n)
end
end
set_connect_timeout (n: INTEGER)
do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_connect_timeout (n)
end
end
set_accept_timeout (n: INTEGER)
do
if attached {NETWORK_STREAM_SOCKET} socket as l_socket then
l_socket.set_accept_timeout (n)
end
end
feature -- Access
last_string: STRING
do
Result := socket.last_string
end
last_character: CHARACTER
do
Result := socket.last_character
end
peer_address: detachable NETWORK_SOCKET_ADDRESS
-- Peer address of socket
do
if attached {NETWORK_SOCKET_ADDRESS} socket.peer_address as l_peer_address then
Result := l_peer_address
end
end
feature -- Input
read_line_thread_aware
do
socket.read_line_thread_aware
end
read_stream_thread_aware (nb: INTEGER)
do
socket.read_stream_thread_aware (nb)
end
read_stream (nb: INTEGER)
do
socket.read_stream (nb)
end
read_character
do
socket.read_character
end
bytes_read: INTEGER
do
Result := socket.bytes_read
end
feature -- Output
send_message (a_msg: STRING)
do
put_string (a_msg)
end
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
do
if attached {TCP_STREAM_SOCKET} socket as l_tcp_stream_socket then
l_tcp_stream_socket.put_readable_string_8 (s)
else
put_string (s)
end
end
put_string (s: STRING)
do
socket.put_string (s)
end
put_character (c: CHARACTER)
do
socket.put_character (c)
end
feature -- Status Report
descriptor_available: BOOLEAN
-- Is descriptor available?
do
Result := socket.descriptor_available
end
descriptor: INTEGER
do
Result := socket.descriptor
end
port: INTEGER
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.port
end
end
exists: BOOLEAN
do
Result := socket.exists
end
is_blocking: BOOLEAN
do
Result := socket.is_blocking
end
is_bound: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.is_bound
end
end
is_connected: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.is_connected
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
end
is_open_read: BOOLEAN
do
Result := socket.is_open_read
end
is_open_write: BOOLEAN
do
Result := socket.is_open_write
end
is_closed: BOOLEAN
do
Result := socket.is_closed
end
is_readable: BOOLEAN
do
Result := socket.is_readable
end
cleanup
do
socket.cleanup
end
ready_for_writing: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.ready_for_writing
end
end
connect
do
socket.connect
end
close
do
socket.close
end
listen (a_queue: INTEGER)
do
socket.listen (a_queue)
end
accept
do
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
end
set_non_blocking
do
socket.set_non_blocking
end
readable: BOOLEAN
do
Result := socket.readable
end
ready_for_reading: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.ready_for_reading
end
end
try_ready_for_reading: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.try_ready_for_reading
end
end
accepted: detachable HTTPD_STREAM_SOCKET
do
if attached {NETWORK_STREAM_SOCKET} socket.accepted as l_accepted then
create Result.make (l_accepted)
end
end
feature {HTTPD_STREAM_SOCKET} -- Implementation
make (a_socket: STREAM_SOCKET)
do
socket := a_socket
end
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-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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,96 +0,0 @@
note
description: "Summary description for {TCP_STREAM_SOCKET}."
date: "$Date$"
revision: "$Revision$"
class
TCP_STREAM_SOCKET
inherit
NETWORK_STREAM_SOCKET
redefine
make
end
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty
create {NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
make
-- Create a network stream socket.
do
Precursor
debug
set_reuse_address
end
end
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
-- Create server socket on `an_address' and `a_port'.
require
valid_port: a_port >= 0
do
make
create address.make_from_address_and_port (an_address, a_port)
bind
end
make_from_separate (s: separate STREAM_SOCKET)
require
descriptor_available: s.descriptor_available
do
create_from_descriptor (s.descriptor)
end
feature -- Basic operation
send_message (a_msg: STRING)
do
put_string (a_msg)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
feature -- Status report
try_ready_for_reading: BOOLEAN
-- Is data available for reading from the socket right now?
require
socket_exists: exists
local
retval: INTEGER
do
retval := c_select_poll_with_timeout (descriptor, True, 0)
Result := (retval > 0)
end
note
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
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,66 +0,0 @@
note
description: "Standalone server configuration (ssl NOT supported)."
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONFIGURATION
inherit
HTTPD_CONFIGURATION_I
create
make
feature -- Status
Server_details: STRING_8 = "Server: Standalone Eiffel Server"
has_ssl_support: BOOLEAN = False
-- Precursor
feature -- SSL Helpers
set_ssl_protocol_to_ssl_2_or_3
-- Set `ssl_protocol' with `Ssl_23'.
do
-- Ignored
end
set_ssl_protocol_to_tls_1_0
-- Set `ssl_protocol' with `Tls_1_0'.
do
-- Ignored
end
set_ssl_protocol_to_tls_1_1
-- Set `ssl_protocol' with `Tls_1_1'.
do
-- Ignored
end
set_ssl_protocol_to_tls_1_2
-- Set `ssl_protocol' with `Tls_1_2'.
do
-- Ignored
end
set_ssl_protocol_to_dtls_1_0
-- Set `ssl_protocol' with `Dtls_1_0'.
do
-- Ignored
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,27 +0,0 @@
note
description: "[
httpd server
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_SERVER
inherit
HTTPD_SERVER_I
create
make
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,20 +0,0 @@
package httpd
project
httpd = "httpd-safe.ecf"
httpd = "httpd.ecf"
note
title: HTTP server
description: "[
Simple HTTP listener and handler, that can be extended easily.
]"
tags: http,httpd,server,web
collection: EWF
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
link[license]: http://www.eiffel.com/licensing/forum.txt
link[source]: "Github" https://github.com/EiffelWebFramework/EWF/library/server/httpd
link[doc]: "Documentation" http://eiffelwebframework.github.io/EWF/
end

View File

@@ -1,79 +0,0 @@
note
description: "Standalone server configuration (ssl supported)."
date: "$Date$"
revision: "$Revision$"
class
HTTPD_CONFIGURATION
inherit
HTTPD_CONFIGURATION_I
redefine
make
end
create
make
feature {NONE} -- Initialization
make
-- Create a new instance and set ssl protocol to tls_1_2.
do
Precursor
set_ssl_protocol_to_tls_1_2
ensure then
ssl_protocol_set: ssl_protocol = {SSL_PROTOCOL}.tls_1_2
end
feature -- Access
Server_details: STRING_8 = "Server: Standalone Eiffel Server (https)"
has_ssl_support: BOOLEAN = True
-- Precursor
feature -- SSL Helpers
set_ssl_protocol_to_ssl_2_or_3
-- Set `ssl_protocol' with `Ssl_23'.
do
set_ssl_protocol ({SSL_PROTOCOL}.Ssl_23)
end
set_ssl_protocol_to_tls_1_0
-- Set `ssl_protocol' with `Tls_1_0'.
do
set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_0)
end
set_ssl_protocol_to_tls_1_1
-- Set `ssl_protocol' with `Tls_1_1'.
do
set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_1)
end
set_ssl_protocol_to_tls_1_2
-- Set `ssl_protocol' with `Tls_1_2'.
do
set_ssl_protocol ({SSL_PROTOCOL}.Tls_1_2)
end
set_ssl_protocol_to_dtls_1_0
-- Set `ssl_protocol' with `Dtls_1_0'.
do
set_ssl_protocol ({SSL_PROTOCOL}.Dtls_1_0)
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,35 +0,0 @@
note
description: "[
SSL enabled server
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_SERVER
inherit
HTTPD_SERVER_I
redefine
new_listening_socket
end
create
make
feature {NONE} -- Factory
new_listening_socket (a_addr: detachable INET_ADDRESS; a_http_port: INTEGER): HTTPD_STREAM_SOCKET
do
if configuration.is_secure then
if a_addr /= Void then
create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_address_and_port (a_addr, a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key)
else
create {HTTPD_STREAM_SSL_SOCKET} Result.make_ssl_server_by_port (a_http_port, configuration.ssl_protocol, configuration.ca_crt, configuration.ca_key)
end
else
Result := Precursor (a_addr, a_http_port)
end
end
end

View File

@@ -1,161 +0,0 @@
note
description: "[
Summary description for {HTTPD_STREAM_SSL_SOCKET}
that can be used for http or https connection.
]"
date: "$Date$"
revision: "$Revision$"
class
HTTPD_STREAM_SSL_SOCKET
inherit
HTTPD_STREAM_SOCKET
redefine
port,
is_bound,
ready_for_writing,
ready_for_reading,
try_ready_for_reading,
put_readable_string_8
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
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)
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)
end
make_ssl_server_by_port (a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
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)
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)
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)
end
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
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)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
l_ssl_socket.put_readable_string_8 (s)
else
Precursor (s)
end
end
feature -- Status Report
port: INTEGER
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.port
else
Result := Precursor
end
end
is_bound: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.is_bound
else
Result := Precursor
end
end
ready_for_writing: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.ready_for_writing
else
Result := Precursor
end
end
ready_for_reading: BOOLEAN
-- <Precursor>
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_ssl_socket then
Result := l_ssl_socket.ready_for_reading
else
Result := Precursor
end
end
try_ready_for_reading: BOOLEAN
do
if attached {SSL_TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.try_ready_for_reading
else
Result := Precursor
end
end
feature {HTTPD_STREAM_SOCKET} -- Implementation
set_certificates (a_crt: STRING; a_key: STRING)
local
a_file_name: FILE_NAME
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)
end
end
note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -1,73 +0,0 @@
note
description: "SSL tcp stream socket."
date: "$Date$"
revision: "$Revision$"
class
SSL_TCP_STREAM_SOCKET
inherit
SSL_NETWORK_STREAM_SOCKET
create
make_server_by_address_and_port, make_server_by_port,
make_client_by_address_and_port, make_client_by_port,
make_empty
create {SSL_NETWORK_STREAM_SOCKET}
make_from_descriptor_and_address
feature {NONE} -- Initialization
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
-- Create server socket on `an_address' and `a_port'.
require
valid_port: a_port >= 0
do
make
create address.make_from_address_and_port (an_address, a_port)
bind
end
feature -- Basic operation
send_message (a_msg: STRING)
do
put_string (a_msg)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)
-- Write readable string `s' to socket.
local
ext: C_STRING
do
create ext.make (s)
put_managed_pointer (ext.managed_data, 0, s.count)
end
feature -- Status report
try_ready_for_reading: BOOLEAN
-- Is data available for reading from the socket right now?
require
socket_exists: exists
local
retval: INTEGER
do
retval := c_select_poll_with_timeout (descriptor, True, 0)
Result := (retval > 0)
end
feature {NONE}-- Implementation
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end