Skip to content

Commit c4c63a8

Browse files
committed
Align error handling of sync/async socket operations
Currently, if an error occurs on asynchronous operations, the socket is closed and the error is logged. Do the same for synchronous operations.
1 parent 6fc739d commit c4c63a8

9 files changed

+92
-24
lines changed

fly/net/socket/listen_socket.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ bool ListenSocket<EndpointType>::is_listening() const
8383

8484
//==================================================================================================
8585
template <typename EndpointType>
86-
std::optional<TcpSocket<EndpointType>> ListenSocket<EndpointType>::accept() const
86+
std::optional<TcpSocket<EndpointType>> ListenSocket<EndpointType>::accept()
8787
{
8888
EndpointType client_endpoint;
8989
bool would_block = false;
@@ -94,6 +94,9 @@ std::optional<TcpSocket<EndpointType>> ListenSocket<EndpointType>::accept() cons
9494
return TcpSocket<EndpointType>(*client, io_mode());
9595
}
9696

97+
SLOGW(handle(), "Could not accept new socket, closing");
98+
close();
99+
97100
return std::nullopt;
98101
}
99102

fly/net/socket/listen_socket.hpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,20 @@ class ListenSocket :
7171
bool is_listening() const;
7272

7373
/**
74-
* Accept an incoming connection on this listening socket.
74+
* Accept an incoming connection on this listening socket. If an error occurs on the socket, the
75+
* socket will be closed.
7576
*
7677
* @return If successful, the accepted socket. Otherwise, an uninitialized value.
7778
*/
78-
std::optional<TcpSocket<EndpointType>> accept() const;
79+
std::optional<TcpSocket<EndpointType>> accept();
7980

8081
/**
8182
* Asynchronously accept an incoming connection on this listening socket. May only be used if
8283
* this socket was created through a socket service.
8384
*
8485
* If successful, the provided callback will be invoked with the accepted socket upon
85-
* completion. Otherwise, the provided callback will be invoked with a null socket.
86+
* completion. Otherwise, the provided callback will be invoked with an uninitialized value, and
87+
* the socket will be closed before the invocation.
8688
*
8789
* @param callback The callback to invoke when the operation has completed.
8890
*
@@ -119,7 +121,8 @@ class ListenSocket :
119121
* When the socket service indicates the socket is available for reading, attempt to accept an
120122
* incoming connection. If successful, the provided callback will be invoked with the accepted
121123
* socket. If unsuccessful because the operation would still block, queue another attempt.
122-
* Otherwise, the callback will be invoked with a null socket.
124+
* Otherwise, the socket will be closed and the callback will be invoked with an uninitialized
125+
* value.
123126
*
124127
* @param callback The callback to invoke when the operation has completed.
125128
*/

fly/net/socket/tcp_socket.cpp

+28-4
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,22 @@ bool TcpSocket<EndpointType>::is_connected() const
226226

227227
//==================================================================================================
228228
template <typename EndpointType>
229-
std::size_t TcpSocket<EndpointType>::send(std::string_view message) const
229+
std::size_t TcpSocket<EndpointType>::send(std::string_view message)
230230
{
231231
bool would_block = false;
232-
return fly::net::detail::send(handle(), std::move(message), would_block);
232+
std::size_t bytes_sent = fly::net::detail::send(handle(), std::move(message), would_block);
233+
234+
if (bytes_sent == 0)
235+
{
236+
SLOGW(handle(), "Error sending, closing");
237+
close();
238+
}
239+
else
240+
{
241+
SLOGD(handle(), "Sent {} bytes", bytes_sent);
242+
}
243+
244+
return bytes_sent;
233245
}
234246

235247
//==================================================================================================
@@ -253,10 +265,22 @@ bool TcpSocket<EndpointType>::send_async(std::string_view message, SendCompletio
253265

254266
//==================================================================================================
255267
template <typename EndpointType>
256-
std::string TcpSocket<EndpointType>::receive() const
268+
std::string TcpSocket<EndpointType>::receive()
257269
{
258270
bool would_block = false;
259-
return fly::net::detail::recv(handle(), m_packet_size, would_block);
271+
const std::string received = fly::net::detail::recv(handle(), m_packet_size, would_block);
272+
273+
if (received.size() == 0)
274+
{
275+
SLOGW(handle(), "Error receiving, closing");
276+
close();
277+
}
278+
else
279+
{
280+
SLOGD(handle(), "Received {} bytes", received.size());
281+
}
282+
283+
return received;
260284
}
261285

262286
//==================================================================================================

fly/net/socket/tcp_socket.hpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,14 @@ class TcpSocket :
149149
bool is_connected() const;
150150

151151
/**
152-
* Transmit a message to the connected remote socket.
152+
* Transmit a message to the connected remote socket. If an error occurs on the socket, the
153+
* socket will be closed.
153154
*
154155
* @param message The message to transmit.
155156
*
156157
* @return The number of bytes transmitted.
157158
*/
158-
std::size_t send(std::string_view message) const;
159+
std::size_t send(std::string_view message);
159160

160161
/**
161162
* Asynchronously transmit a message to the connected remote socket. May only be used if this
@@ -174,11 +175,12 @@ class TcpSocket :
174175
bool send_async(std::string_view message, SendCompletion &&callback);
175176

176177
/**
177-
* Receive a message from the connected remote socket.
178+
* Receive a message from the connected remote socket. If an error occurs on the socket, the
179+
* socket will be closed.
178180
*
179181
* @return The message received.
180182
*/
181-
std::string receive() const;
183+
std::string receive();
182184

183185
/**
184186
* Asynchronously receive a message from the connected remote socket. May only be used if this

fly/net/socket/udp_socket.cpp

+30-5
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,35 @@ UdpSocket<EndpointType> &UdpSocket<EndpointType>::operator=(UdpSocket &&socket)
6161

6262
//==================================================================================================
6363
template <typename EndpointType>
64-
size_t UdpSocket<EndpointType>::send(const EndpointType &endpoint, std::string_view message) const
64+
size_t UdpSocket<EndpointType>::send(const EndpointType &endpoint, std::string_view message)
6565
{
6666
bool would_block = false;
6767

68-
return fly::net::detail::send_to(
68+
std::size_t bytes_sent = fly::net::detail::send_to(
6969
handle(),
7070
endpoint,
7171
std::move(message),
7272
m_packet_size,
7373
would_block);
74+
75+
if (bytes_sent == 0)
76+
{
77+
SLOGW(handle(), "Error sending to {}, closing", endpoint);
78+
close();
79+
}
80+
else
81+
{
82+
SLOGD(handle(), "Sent {} bytes to {}", bytes_sent, endpoint);
83+
}
84+
85+
return bytes_sent;
7486
}
7587

7688
//==================================================================================================
7789
template <typename EndpointType>
7890
size_t
7991
UdpSocket<EndpointType>::send(std::string_view hostname, port_type port, std::string_view message)
80-
const
92+
8193
{
8294
if (auto endpoint = hostname_to_endpoint(std::move(hostname)); endpoint)
8395
{
@@ -130,12 +142,25 @@ bool UdpSocket<EndpointType>::send_async(
130142

131143
//==================================================================================================
132144
template <typename EndpointType>
133-
std::string UdpSocket<EndpointType>::receive() const
145+
std::string UdpSocket<EndpointType>::receive()
134146
{
135147
EndpointType endpoint;
136148
bool would_block = false;
137149

138-
return fly::net::detail::recv_from(handle(), endpoint, m_packet_size, would_block);
150+
const std::string received =
151+
fly::net::detail::recv_from(handle(), endpoint, m_packet_size, would_block);
152+
153+
if (received.size() == 0)
154+
{
155+
SLOGW(handle(), "Error receiving, closing");
156+
close();
157+
}
158+
else
159+
{
160+
SLOGD(handle(), "Received {} bytes from {}", received.size(), endpoint);
161+
}
162+
163+
return received;
139164
}
140165

141166
//==================================================================================================

fly/net/socket/udp_socket.hpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,27 @@ class UdpSocket :
5858
UdpSocket &operator=(UdpSocket &&socket) noexcept;
5959

6060
/**
61-
* Transmit a message to a specific remote endpoint.
61+
* Transmit a message to a specific remote endpoint. If an error occurs on the socket, the
62+
* socket will be closed.
6263
*
6364
* @param endpoint The remote endpoint to transmit to.
6465
* @param message The message to transmit.
6566
*
6667
* @return The number of bytes transmitted.
6768
*/
68-
std::size_t send(const EndpointType &endpoint, std::string_view message) const;
69+
std::size_t send(const EndpointType &endpoint, std::string_view message);
6970

7071
/**
71-
* Transmit a message to a specific remote endpoint.
72+
* Transmit a message to a specific remote endpoint. If an error occurs on the socket, the
73+
* socket will be closed.
7274
*
7375
* @param hostname The hostname or IP address string to transmit to.
7476
* @param port The port to transmit to.
7577
* @param message The message to transmit.
7678
*
7779
* @return The number of bytes transmitted.
7880
*/
79-
std::size_t send(std::string_view hostname, port_type port, std::string_view message) const;
81+
std::size_t send(std::string_view hostname, port_type port, std::string_view message);
8082

8183
/**
8284
* Asynchronously transmit a message to a specific remote endpoint. May only be used if this
@@ -119,11 +121,12 @@ class UdpSocket :
119121
SendCompletion &&callback);
120122

121123
/**
122-
* Receive a message from an unspecified remote endpoint.
124+
* Receive a message from an unspecified remote endpoint. If an error occurs on the socket, the
125+
* socket will be closed.
123126
*
124127
* @return The message received.
125128
*/
126-
std::string receive() const;
129+
std::string receive();
127130

128131
/**
129132
* Asynchronously receive a message from an unspecified remote endpoint. May only be used if

test/net/listen_socket.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ CATCH_TEMPLATE_TEST_CASE("ListenSocket", "[net]", fly::net::IPv4Address, fly::ne
169169
CATCH_REQUIRE(socket);
170170

171171
CATCH_CHECK_FALSE(socket->accept());
172+
CATCH_CHECK_FALSE(socket->is_valid());
172173
}
173174

174175
#if defined(FLY_LINUX)
@@ -285,6 +286,7 @@ CATCH_TEMPLATE_TEST_CASE("ListenSocket", "[net]", fly::net::IPv4Address, fly::ne
285286
CATCH_CHECK(socket->listen());
286287

287288
CATCH_CHECK_FALSE(socket->accept());
289+
CATCH_CHECK_FALSE(socket->is_valid());
288290
}
289291

290292
#endif

test/net/tcp_socket.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ CATCH_TEMPLATE_TEST_CASE("TcpSocket", "[net]", fly::net::IPv4Address, fly::net::
150150
CATCH_REQUIRE(socket);
151151

152152
CATCH_CHECK(socket->send(message) == 0);
153+
CATCH_CHECK_FALSE(socket->is_valid());
153154
}
154155

155156
CATCH_SECTION("Disconnected sockets may not receive messages")
@@ -158,6 +159,7 @@ CATCH_TEMPLATE_TEST_CASE("TcpSocket", "[net]", fly::net::IPv4Address, fly::net::
158159
CATCH_REQUIRE(socket);
159160

160161
CATCH_CHECK(socket->receive().empty());
162+
CATCH_CHECK_FALSE(socket->is_valid());
161163
}
162164

163165
CATCH_SECTION("Connected sockets may send and receive messages")
@@ -299,6 +301,7 @@ CATCH_TEMPLATE_TEST_CASE("TcpSocket", "[net]", fly::net::IPv4Address, fly::net::
299301
CATCH_REQUIRE(socket);
300302

301303
CATCH_CHECK(socket->send(message) == 0);
304+
CATCH_CHECK_FALSE(socket->is_valid());
302305
}
303306

304307
CATCH_SECTION("Socket receiving fails due to ::recv() system call")
@@ -309,6 +312,7 @@ CATCH_TEMPLATE_TEST_CASE("TcpSocket", "[net]", fly::net::IPv4Address, fly::net::
309312
CATCH_REQUIRE(socket);
310313

311314
CATCH_CHECK(socket->receive().empty());
315+
CATCH_CHECK_FALSE(socket->is_valid());
312316
}
313317

314318
#endif

test/net/udp_socket.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ CATCH_TEMPLATE_TEST_CASE("UdpSocket", "[net]", fly::net::IPv4Address, fly::net::
237237
CATCH_REQUIRE(socket);
238238

239239
CATCH_CHECK(socket->send(s_localhost, s_port, message) == 0);
240+
CATCH_CHECK_FALSE(socket->is_valid());
240241
}
241242

242243
CATCH_SECTION("Socket receiving fails due to ::recvfrom() system call")
@@ -247,6 +248,7 @@ CATCH_TEMPLATE_TEST_CASE("UdpSocket", "[net]", fly::net::IPv4Address, fly::net::
247248
CATCH_REQUIRE(socket);
248249

249250
CATCH_CHECK(socket->receive().empty());
251+
CATCH_CHECK_FALSE(socket->is_valid());
250252
}
251253
#endif
252254
}

0 commit comments

Comments
 (0)