Skip to content

Commit 0e3e555

Browse files
committed
Add accept_socket() to tcp and tls servers
This will allow for a graceful shutdown via the socket.shutdown(how) functions Closes #377
1 parent c301d7d commit 0e3e555

File tree

7 files changed

+49
-7
lines changed

7 files changed

+49
-7
lines changed

include/coro/net/socket.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class socket
6868

6969
/**
7070
* @param how Shuts the socket down with the given operations.
71-
* @param Returns true if the sockets given operations were shutdown.
71+
* @return Returns true if the sockets given operations were shutdown.
7272
*/
7373
auto shutdown(poll_op how = poll_op::read_write) -> bool;
7474

include/coro/net/tcp/client.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ class client
5252
* @return The tcp socket this client is using.
5353
* @{
5454
**/
55-
auto socket() -> net::socket& { return m_socket; }
56-
auto socket() const -> const net::socket& { return m_socket; }
55+
[[nodiscard]] auto socket() -> net::socket& { return m_socket; }
56+
[[nodiscard]] auto socket() const -> const net::socket& { return m_socket; }
5757
/** @} */
5858

5959
/**

include/coro/net/tcp/server.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,19 @@ class server
5656

5757
/**
5858
* Accepts an incoming tcp client connection. On failure the tls clients socket will be set to
59-
* and invalid state, use the socket.is_value() to verify the client was correctly accepted.
59+
* and invalid state, use the socket.is_valid() to verify the client was correctly accepted.
6060
* @return The newly connected tcp client connection.
6161
*/
6262
auto accept() -> coro::net::tcp::client;
6363

64+
/**
65+
* @return The tcp accept socket this server is using.
66+
* @{
67+
**/
68+
[[nodiscard]] auto accept_socket() -> net::socket& { return m_accept_socket; }
69+
[[nodiscard]] auto accept_socket() const -> const net::socket& { return m_accept_socket; }
70+
/** @} */
71+
6472
private:
6573
friend client;
6674
/// The io scheduler for awaiting new connections.

include/coro/net/tls/client.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ class client
5858
* @return The tcp socket this client is using.
5959
* @{
6060
**/
61-
auto socket() -> net::socket& { return m_socket; }
62-
auto socket() const -> const net::socket& { return m_socket; }
61+
[[nodiscard]] auto socket() -> net::socket& { return m_socket; }
62+
[[nodiscard]] auto socket() const -> const net::socket& { return m_socket; }
6363
/** @} */
6464

6565
/**

include/coro/net/tls/server.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ class server
6666
*/
6767
auto accept(std::chrono::milliseconds timeout = std::chrono::seconds{30}) -> coro::task<coro::net::tls::client>;
6868

69+
/**
70+
* @return The tcp accept socket this server is using.
71+
* @{
72+
**/
73+
[[nodiscard]] auto accept_socket() -> net::socket& { return m_accept_socket; }
74+
[[nodiscard]] auto accept_socket() const -> const net::socket& { return m_accept_socket; }
75+
/** @} */
76+
6977
private:
7078
/// The io scheduler for awaiting new connections.
7179
std::shared_ptr<io_scheduler> m_io_scheduler{nullptr};

src/detail/io_notifier_epoll.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ auto io_notifier_epoll::watch(fd_t fd, coro::poll_op op, void* data, bool keep)
6565
auto io_notifier_epoll::watch(detail::poll_info& pi) -> bool
6666
{
6767
auto event_data = event_t{};
68-
event_data.events = static_cast<uint32_t>(pi.m_op) | EPOLLONESHOT | EPOLLRDHUP;
68+
event_data.events = static_cast<uint32_t>(pi.m_op) | EPOLLONESHOT | EPOLLRDHUP | EPOLLHUP;
6969
event_data.data.ptr = static_cast<void*>(&pi);
7070
return ::epoll_ctl(m_fd, EPOLL_CTL_ADD, pi.m_fd, &event_data) != -1;
7171
}

test/net/test_tcp_server.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,30 @@ TEST_CASE("tcp_server concurrent polling on the same socket", "[tcp_server]")
175175
REQUIRE(request == response);
176176
}
177177

178+
TEST_CASE("tcp_server graceful shutdown via socket", "[tcp_server]")
179+
{
180+
auto scheduler = coro::io_scheduler::make_shared(coro::io_scheduler::options{
181+
.execution_strategy = coro::io_scheduler::execution_strategy_t::process_tasks_inline});
182+
coro::net::tcp::server server{scheduler};
183+
184+
auto make_accept_task = [](coro::net::tcp::server& server) -> coro::task<void>
185+
{
186+
std::cerr << "make accept task start\n";
187+
auto poll_result = co_await server.poll(std::chrono::seconds{3});
188+
REQUIRE(poll_result == coro::poll_status::closed);
189+
auto client = server.accept();
190+
REQUIRE_FALSE(client.socket().is_valid());
191+
std::cerr << "make accept task completed\n";
192+
};
193+
194+
scheduler->spawn(make_accept_task(server));
195+
196+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
197+
198+
server.accept_socket().shutdown(coro::poll_op::read_write);
199+
200+
scheduler->shutdown();
201+
}
202+
178203
#endif // LIBCORO_FEATURE_NETWORKING
204+

0 commit comments

Comments
 (0)