Skip to content

Commit 9d8eced

Browse files
committed
Refactored server_endpoint to allow end users to access start_accept error states references XRPLF#335
also more documentation
1 parent fd0c62a commit 9d8eced

File tree

2 files changed

+62
-37
lines changed

2 files changed

+62
-37
lines changed

changelog.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ HEAD
3030
short reads and quasi-expected socket shutdown related errors will no longer
3131
be reported as unclean WebSocket shutdowns to the application. Information
3232
about them will remain in the info error channel for debugging purposes.
33+
- Improvement: `start_accept` errors are now reported to the caller either via
34+
an exception or an ec parameter.
3335
- Bug: Fix some cases of calls to empty lib::function objects.
3436
- Bug: Fix memory leak of connection objects due to cached handlers holding on to
3537
reference counted pointers. #310 Thank you otaras for reporting.
@@ -48,7 +50,8 @@ HEAD
4850
code. Thank you Robin Rowe for reporting.
4951
- Bug: Fix an issue where custom timeout values weren't being propagated from
5052
endpoints to new connections.
51-
- Bug: Fix a memory leak when a connection fails. #323 Thank you droppy for
53+
- Bug: Fix a number of memory leaks related to server connection failures. #323
54+
#333 #334 #335 Thank you droppy and aydany for reporting and patches.
5255
reporting.
5356
- Compatibility: Fix compile time conflict with Visual Studio's MIN/MAX macros.
5457
Thank you Robin Rowe for reporting.

websocketpp/roles/server_endpoint.hpp

+58-36
Original file line numberDiff line numberDiff line change
@@ -64,60 +64,76 @@ class server : public endpoint<connection<config>,config> {
6464
/// Type of the endpoint component of this server
6565
typedef endpoint<connection_type,config> endpoint_type;
6666

67-
68-
// TODO: clean up these types
69-
7067
explicit server() : endpoint_type(true)
7168
{
7269
endpoint_type::m_alog.write(log::alevel::devel, "server constructor");
7370
}
7471

75-
// return an initialized connection_ptr. Call start() on this object to
76-
// begin the processing loop.
72+
/// Create and initialize a new connection
73+
/**
74+
* The connection will be initialized and ready to begin. Call its start()
75+
* method to begin the processing loop.
76+
*
77+
* Note: The connection must either be started or terminated using
78+
* connection::terminate in order to avoid memory leaks.
79+
*
80+
* @return A pointer to the new connection.
81+
*/
7782
connection_ptr get_connection() {
78-
connection_ptr con = endpoint_type::create_connection();
79-
80-
return con;
83+
return endpoint_type::create_connection();
8184
}
8285

83-
// Starts the server's async connection acceptance loop.
84-
void start_accept() {
86+
/// Starts the server's async connection acceptance loop (exception free)
87+
/**
88+
* Initiates the server connection acceptance loop. Must be called after
89+
* listen. This method will have no effect until the underlying io_service
90+
* starts running. It may be called after the io_service is already running.
91+
*
92+
* Refer to documentation for the transport policy you are using for
93+
* instructions on how to stop this acceptance loop.
94+
*
95+
* @param [out] ec A status code indicating an error, if any.
96+
*/
97+
void start_accept(lib::error_code & ec) {
8598
if (!transport_type::is_listening()) {
86-
endpoint_type::m_elog.write(log::elevel::info,
87-
"Stopping acceptance of new connections because the underlying transport is no longer listening.");
99+
ec = error::make_error_code(error::async_accept_not_listening);
88100
return;
89101
}
90102

103+
ec = lib::error_code();
91104
connection_ptr con = get_connection();
92105

93-
lib::error_code ec;
94-
95106
transport_type::async_accept(
96107
lib::static_pointer_cast<transport_con_type>(con),
97-
lib::bind(
98-
&type::handle_accept,
99-
this,
100-
con,
101-
lib::placeholders::_1
102-
),
108+
lib::bind(&type::handle_accept,this,con,lib::placeholders::_1),
103109
ec
104110
);
105111

106-
if (ec == error::async_accept_not_listening) {
107-
endpoint_type::m_elog.write(log::elevel::info,
108-
"Stopping acceptance of new connections because the underlying transport is no longer listening.");
109-
} else if (ec) {
110-
endpoint_type::m_elog.write(log::elevel::rerror,
111-
"start_accept error: "+ec.message());
112+
if (ec && con) {
113+
// If the connection was constructed but the accept failed,
114+
// terminate the connection to prevent memory leaks
115+
con->terminate(lib::error_code());
112116
}
113-
114-
if (ec && con) {
115-
// Terminate the connection to prevent memory leaks.
116-
lib::error_code con_ec;
117-
con->terminate(con_ec);
118-
}
119-
}
117+
}
120118

119+
/// Starts the server's async connection acceptance loop
120+
/**
121+
* Initiates the server connection acceptance loop. Must be called after
122+
* listen. This method will have no effect until the underlying io_service
123+
* starts running. It may be called after the io_service is already running.
124+
*
125+
* Refer to documentation for the transport policy you are using for
126+
* instructions on how to stop this acceptance loop.
127+
*/
128+
void start_accept() {
129+
lib::error_code ec;
130+
start_accept(ec);
131+
if (ec) {
132+
throw ec;
133+
}
134+
}
135+
136+
/// Handler callback for start_accept
121137
void handle_accept(connection_ptr con, lib::error_code const & ec) {
122138
if (ec) {
123139
con->terminate(ec);
@@ -133,10 +149,16 @@ class server : public endpoint<connection<config>,config> {
133149
con->start();
134150
}
135151

136-
137-
start_accept();
152+
lib::error_code start_ec;
153+
start_accept(start_ec);
154+
if (start_ec == error::async_accept_not_listening) {
155+
endpoint_type::m_elog.write(log::elevel::info,
156+
"Stopping acceptance of new connections because the underlying transport is no longer listening.");
157+
} else if (start_ec) {
158+
endpoint_type::m_elog.write(log::elevel::rerror,
159+
"Restarting async_accept loop failed: "+ec.message());
160+
}
138161
}
139-
private:
140162
};
141163

142164
} // namespace websocketpp

0 commit comments

Comments
 (0)