2 * Copyright (c) 2014, Peter Thorson. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of the WebSocket++ Project nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef WEBSOCKETPP_SERVER_ENDPOINT_HPP
29 #define WEBSOCKETPP_SERVER_ENDPOINT_HPP
31 #include <websocketpp/endpoint.hpp>
33 #include <websocketpp/logger/levels.hpp>
35 #include <websocketpp/common/system_error.hpp>
37 namespace websocketpp {
39 /// Server endpoint role based on the given config
43 template <typename config>
44 class server : public endpoint<connection<config>,config> {
46 /// Type of this endpoint
47 typedef server<config> type;
49 /// Type of the endpoint concurrency component
50 typedef typename config::concurrency_type concurrency_type;
51 /// Type of the endpoint transport component
52 typedef typename config::transport_type transport_type;
54 /// Type of the connections this server will create
55 typedef connection<config> connection_type;
56 /// Type of a shared pointer to the connections this server will create
57 typedef typename connection_type::ptr connection_ptr;
59 /// Type of the connection transport component
60 typedef typename transport_type::transport_con_type transport_con_type;
61 /// Type of a shared pointer to the connection transport component
62 typedef typename transport_con_type::ptr transport_con_ptr;
64 /// Type of the endpoint component of this server
65 typedef endpoint<connection_type,config> endpoint_type;
67 friend class connection<config>;
69 explicit server() : endpoint_type(true)
71 endpoint_type::m_alog.write(log::alevel::devel, "server constructor");
77 #ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
78 // no copy constructor because endpoints are not copyable
79 server<config>(server<config> &) = delete;
81 // no copy assignment operator because endpoints are not copyable
82 server<config> & operator=(server<config> const &) = delete;
83 #endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
85 #ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
87 server<config>(server<config> && o) : endpoint<connection<config>,config>(std::move(o)) {}
89 #ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
90 // no move assignment operator because of const member variables
91 server<config> & operator=(server<config> &&) = delete;
92 #endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
94 #endif // _WEBSOCKETPP_MOVE_SEMANTICS_
96 /// Create and initialize a new connection
98 * The connection will be initialized and ready to begin. Call its start()
99 * method to begin the processing loop.
101 * Note: The connection must either be started or terminated using
102 * connection::terminate in order to avoid memory leaks.
104 * @return A pointer to the new connection.
106 connection_ptr get_connection() {
107 return endpoint_type::create_connection();
110 /// Starts the server's async connection acceptance loop (exception free)
112 * Initiates the server connection acceptance loop. Must be called after
113 * listen. This method will have no effect until the underlying io_service
114 * starts running. It may be called after the io_service is already running.
116 * Refer to documentation for the transport policy you are using for
117 * instructions on how to stop this acceptance loop.
119 * @param [out] ec A status code indicating an error, if any.
121 void start_accept(lib::error_code & ec) {
122 if (!transport_type::is_listening()) {
123 ec = error::make_error_code(error::async_accept_not_listening);
127 ec = lib::error_code();
128 connection_ptr con = get_connection();
130 transport_type::async_accept(
131 lib::static_pointer_cast<transport_con_type>(con),
132 lib::bind(&type::handle_accept,this,con,lib::placeholders::_1),
137 // If the connection was constructed but the accept failed,
138 // terminate the connection to prevent memory leaks
139 con->terminate(lib::error_code());
143 /// Starts the server's async connection acceptance loop
145 * Initiates the server connection acceptance loop. Must be called after
146 * listen. This method will have no effect until the underlying io_service
147 * starts running. It may be called after the io_service is already running.
149 * Refer to documentation for the transport policy you are using for
150 * instructions on how to stop this acceptance loop.
152 void start_accept() {
160 /// Handler callback for start_accept
161 void handle_accept(connection_ptr con, lib::error_code const & ec) {
165 if (ec == error::operation_canceled) {
166 endpoint_type::m_elog.write(log::elevel::info,
167 "handle_accept error: "+ec.message());
169 endpoint_type::m_elog.write(log::elevel::rerror,
170 "handle_accept error: "+ec.message());
176 lib::error_code start_ec;
177 start_accept(start_ec);
178 if (start_ec == error::async_accept_not_listening) {
179 endpoint_type::m_elog.write(log::elevel::info,
180 "Stopping acceptance of new connections because the underlying transport is no longer listening.");
181 } else if (start_ec) {
182 endpoint_type::m_elog.write(log::elevel::rerror,
183 "Restarting async_accept loop failed: "+ec.message());
188 } // namespace websocketpp
190 #endif //WEBSOCKETPP_SERVER_ENDPOINT_HPP