LCOV - code coverage report
Current view: top level - corosio/test - socket_pair.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 75.8 % 33 25 8
Test Date: 2026-02-17 21:42:07 Functions: 100.0 % 9 9

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : // Copyright (c) 2026 Steve Gerbino
       4                 : //
       5                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7                 : //
       8                 : // Official repository: https://github.com/cppalliance/corosio
       9                 : //
      10                 : 
      11                 : #ifndef BOOST_COROSIO_TEST_SOCKET_PAIR_HPP
      12                 : #define BOOST_COROSIO_TEST_SOCKET_PAIR_HPP
      13                 : 
      14                 : #include <boost/corosio/io_context.hpp>
      15                 : #include <boost/corosio/tcp_acceptor.hpp>
      16                 : #include <boost/corosio/tcp_socket.hpp>
      17                 : #include <boost/capy/ex/run_async.hpp>
      18                 : #include <boost/capy/task.hpp>
      19                 : 
      20                 : #include <cstdio>
      21                 : #include <stdexcept>
      22                 : #include <system_error>
      23                 : #include <utility>
      24                 : 
      25                 : namespace boost::corosio::test {
      26                 : 
      27                 : /** Create a connected pair of sockets.
      28                 : 
      29                 :     Creates two sockets connected via loopback TCP sockets.
      30                 :     Data written to one socket can be read from the other.
      31                 : 
      32                 :     @tparam Socket The socket type (default `tcp_socket`).
      33                 :     @tparam Acceptor The acceptor type (default `tcp_acceptor`).
      34                 : 
      35                 :     @param ctx The I/O context for the sockets.
      36                 : 
      37                 :     @return A pair of connected sockets.
      38                 : */
      39                 : template<class Socket = tcp_socket, class Acceptor = tcp_acceptor>
      40                 : std::pair<Socket, Socket>
      41 HIT           4 : make_socket_pair(io_context& ctx)
      42                 : {
      43               4 :     auto ex = ctx.get_executor();
      44                 : 
      45               4 :     std::error_code accept_ec;
      46               4 :     std::error_code connect_ec;
      47               4 :     bool accept_done  = false;
      48               4 :     bool connect_done = false;
      49                 : 
      50               4 :     Acceptor acc(ctx);
      51               4 :     if (auto ec = acc.listen(endpoint(ipv4_address::loopback(), 0)))
      52 MIS           0 :         throw std::runtime_error("socket_pair listen failed: " + ec.message());
      53 HIT           4 :     auto port = acc.local_endpoint().port();
      54                 : 
      55               4 :     Socket s1(ctx);
      56               4 :     Socket s2(ctx);
      57               4 :     s2.open();
      58                 : 
      59               4 :     capy::run_async(ex)(
      60               8 :         [](Acceptor& a, Socket& s, std::error_code& ec_out,
      61                 :            bool& done_out) -> capy::task<> {
      62                 :             auto [ec] = co_await a.accept(s);
      63                 :             ec_out    = ec;
      64                 :             done_out  = true;
      65                 :         }(acc, s1, accept_ec, accept_done));
      66                 : 
      67               4 :     capy::run_async(ex)(
      68               8 :         [](Socket& s, endpoint ep, std::error_code& ec_out,
      69                 :            bool& done_out) -> capy::task<> {
      70                 :             auto [ec] = co_await s.connect(ep);
      71                 :             ec_out    = ec;
      72                 :             done_out  = true;
      73                 :         }(s2, endpoint(ipv4_address::loopback(), port), connect_ec,
      74                 :                            connect_done));
      75                 : 
      76               4 :     ctx.run();
      77               4 :     ctx.restart();
      78                 : 
      79               4 :     if (!accept_done || accept_ec)
      80                 :     {
      81 MIS           0 :         std::fprintf(
      82                 :             stderr, "socket_pair: accept failed (done=%d, ec=%s)\n",
      83                 :             accept_done, accept_ec.message().c_str());
      84               0 :         acc.close();
      85               0 :         throw std::runtime_error("socket_pair accept failed");
      86                 :     }
      87                 : 
      88 HIT           4 :     if (!connect_done || connect_ec)
      89                 :     {
      90 MIS           0 :         std::fprintf(
      91                 :             stderr, "socket_pair: connect failed (done=%d, ec=%s)\n",
      92                 :             connect_done, connect_ec.message().c_str());
      93               0 :         acc.close();
      94               0 :         s1.close();
      95               0 :         throw std::runtime_error("socket_pair connect failed");
      96                 :     }
      97                 : 
      98 HIT           4 :     acc.close();
      99                 : 
     100               4 :     s1.set_linger(true, 0);
     101               4 :     s2.set_linger(true, 0);
     102                 : 
     103               8 :     return {std::move(s1), std::move(s2)};
     104               4 : }
     105                 : 
     106                 : } // namespace boost::corosio::test
     107                 : 
     108                 : #endif
        

Generated by: LCOV version 2.3