94.83% Lines (55/58) 100.00% Functions (13/13)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2026 Michael Vandeberg 2   // Copyright (c) 2026 Michael Vandeberg
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/corosio 7   // Official repository: https://github.com/cppalliance/corosio
8   // 8   //
9   9  
10   #include <boost/corosio/detail/platform.hpp> 10   #include <boost/corosio/detail/platform.hpp>
11   11  
12   #if BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP 12   #if BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP
13   13  
14   #include <boost/corosio/local_stream_socket.hpp> 14   #include <boost/corosio/local_stream_socket.hpp>
15   #include <boost/corosio/detail/except.hpp> 15   #include <boost/corosio/detail/except.hpp>
16   #include <boost/corosio/detail/local_stream_service.hpp> 16   #include <boost/corosio/detail/local_stream_service.hpp>
17   17  
18   #if BOOST_COROSIO_POSIX 18   #if BOOST_COROSIO_POSIX
19   #include <sys/ioctl.h> 19   #include <sys/ioctl.h>
20   #elif BOOST_COROSIO_HAS_IOCP 20   #elif BOOST_COROSIO_HAS_IOCP
21   #include <boost/corosio/native/detail/iocp/win_windows.hpp> 21   #include <boost/corosio/native/detail/iocp/win_windows.hpp>
22   #endif 22   #endif
23   23  
24   namespace boost::corosio { 24   namespace boost::corosio {
25   25  
HITCBC 26   216 local_stream_socket::~local_stream_socket() 26   234 local_stream_socket::~local_stream_socket()
27   { 27   {
HITCBC 28   216 close(); 28   234 close();
HITCBC 29   216 } 29   234 }
30   30  
HITCBC 31   182 local_stream_socket::local_stream_socket(capy::execution_context& ctx) 31   190 local_stream_socket::local_stream_socket(capy::execution_context& ctx)
HITCBC 32   182 : io_object(create_handle<detail::local_stream_service>(ctx)) 32   190 : io_object(create_handle<detail::local_stream_service>(ctx))
33   { 33   {
HITCBC 34   182 } 34   190 }
35   35  
36 - void 36 + std::error_code
HITCBC 37 - 45 local_stream_socket::open(local_stream proto) 37 + 45 local_stream_socket::open(local_stream proto) noexcept
38   { 38   {
HITCBC 39   45 if (is_open()) 39   45 if (is_open())
MISUBC 40 - return; 40 + return {};
HITCBC 41 - 45 open_for_family(proto.family(), proto.type(), proto.protocol()); 41 + 45 return open_for_family(proto.family(), proto.type(), proto.protocol());
42   } 42   }
43   43  
44 - void 44 + std::error_code
HITCBC 45 - 45 local_stream_socket::open_for_family(int family, int type, int protocol) 45 + 45 local_stream_socket::open_for_family(int family, int type, int protocol) noexcept
46   { 46   {
HITCBC 47   45 auto& svc = static_cast<detail::local_stream_service&>(h_.service()); 47   45 auto& svc = static_cast<detail::local_stream_service&>(h_.service());
HITCBC 48   45 std::error_code ec = svc.open_socket( 48   45 std::error_code ec = svc.open_socket(
HITCBC 49   45 static_cast<local_stream_socket::implementation&>(*h_.get()), 49   45 static_cast<local_stream_socket::implementation&>(*h_.get()),
50   family, type, protocol); 50   family, type, protocol);
HITCBC 51 - 45 if (ec) 51 + 45 return ec;
DUB 52 - detail::throw_system_error(ec, "local_stream_socket::open");  
ECB 53   45 } 52   }
54   53  
55   void 54   void
HITCBC 56 - 224 local_stream_socket::close() 55 + 242 local_stream_socket::close() noexcept
57   { 56   {
HITCBC 58   224 if (!is_open()) 57   242 if (!is_open())
HITCBC 59   59 return; 58   73 return;
HITCBC 60   165 h_.service().close(h_); 59   169 h_.service().close(h_);
61   } 60   }
62   61  
63   void 62   void
HITCBC 64 - 8 local_stream_socket::cancel() 63 + 8 local_stream_socket::cancel() noexcept
65   { 64   {
HITCBC 66   8 if (!is_open()) 65   8 if (!is_open())
HITCBC 67   2 return; 66   2 return;
HITCBC 68   6 get().cancel(); 67   6 get().cancel();
69   } 68   }
70   69  
71 - void 70 + std::error_code
HITCBC 72 - 4 local_stream_socket::shutdown(shutdown_type what) 71 + 6 local_stream_socket::shutdown(shutdown_type what) noexcept
73 - {  
DCB 74 - 4 if (is_open())  
75 - {  
76 - // Best-effort: errors like ENOTCONN are expected and unhelpful  
DCB 77 - 2 [[maybe_unused]] auto ec = get().shutdown(what);  
78 - }  
DCB 79 - 4 }  
80 -  
81 - void  
DCB 82 - 4 local_stream_socket::shutdown(shutdown_type what, std::error_code& ec) noexcept  
83   { 72   {
HITCBC 84 - 4 ec = {}; 73 + 6 if (!is_open())
HITCBC 85 - 4 if (is_open()) 74 + 2 return make_error_code(std::errc::bad_file_descriptor);
HITCBC 86 - 2 ec = get().shutdown(what); 75 + 4 return get().shutdown(what);
ECB 87   4 } 76   }
88   77  
89 - void 78 + std::error_code
HITCBC 90 - 110 local_stream_socket::assign(native_handle_type fd) 79 + 114 local_stream_socket::assign(native_handle_type fd) noexcept
91   { 80   {
HITCBC 92   110 auto& svc = static_cast<detail::local_stream_service&>(h_.service()); 81   114 auto& svc = static_cast<detail::local_stream_service&>(h_.service());
HITCBC 93   110 std::error_code ec = svc.assign_socket( 82   114 std::error_code ec = svc.assign_socket(
HITCBC 94   110 static_cast<local_stream_socket::implementation&>(*h_.get()), fd); 83   114 static_cast<local_stream_socket::implementation&>(*h_.get()), fd);
HITCBC 95 - 110 if (ec) 84 + 114 return ec;
DCB 96 - 9 detail::throw_system_error(ec, "local_stream_socket::assign");  
ECB 97   101 } 85   }
98   86  
99   native_handle_type 87   native_handle_type
HITCBC 100   10 local_stream_socket::native_handle() const noexcept 88   10 local_stream_socket::native_handle() const noexcept
101   { 89   {
HITCBC 102   10 if (!is_open()) 90   10 if (!is_open())
103   #if BOOST_COROSIO_HAS_IOCP 91   #if BOOST_COROSIO_HAS_IOCP
104   return ~native_handle_type(0); 92   return ~native_handle_type(0);
105   #else 93   #else
HITCBC 106   2 return -1; 94   2 return -1;
107   #endif 95   #endif
HITCBC 108   8 return get().native_handle(); 96   8 return get().native_handle();
109   } 97   }
110   98  
111   native_handle_type 99   native_handle_type
HITCBC 112   6 local_stream_socket::release() 100   6 local_stream_socket::release()
113   { 101   {
HITCBC 114   6 if (!is_open()) 102   6 if (!is_open())
HITCBC 115 - 2 detail::throw_logic_error("release: socket not open"); 103 + 2 detail::throw_system_error(
HITGNC   104 + 2 make_error_code(std::errc::bad_file_descriptor),
  105 + "local_stream_socket::release");
HITCBC 116   4 return get().release_socket(); 106   4 return get().release_socket();
117   } 107   }
118   108  
119   std::size_t 109   std::size_t
HITCBC 120   6 local_stream_socket::available() const 110   6 local_stream_socket::available() const
121   { 111   {
HITCBC 122   6 if (!is_open()) 112   6 if (!is_open())
HITCBC 123 - 2 detail::throw_logic_error("available: socket not open"); 113 + 2 detail::throw_system_error(
HITGNC   114 + 4 make_error_code(std::errc::bad_file_descriptor),
  115 + "local_stream_socket::available");
124   #if BOOST_COROSIO_HAS_IOCP 116   #if BOOST_COROSIO_HAS_IOCP
125   u_long value = 0; 117   u_long value = 0;
126   if (::ioctlsocket( 118   if (::ioctlsocket(
127   static_cast<SOCKET>(native_handle()), FIONREAD, &value) != 0) 119   static_cast<SOCKET>(native_handle()), FIONREAD, &value) != 0)
128   detail::throw_system_error( 120   detail::throw_system_error(
129   std::error_code(::WSAGetLastError(), std::system_category()), 121   std::error_code(::WSAGetLastError(), std::system_category()),
130   "local_stream_socket::available"); 122   "local_stream_socket::available");
131   return static_cast<std::size_t>(value); 123   return static_cast<std::size_t>(value);
132   #else 124   #else
HITCBC 133   4 int value = 0; 125   4 int value = 0;
HITCBC 134   4 if (::ioctl(native_handle(), FIONREAD, &value) < 0) 126   4 if (::ioctl(native_handle(), FIONREAD, &value) < 0)
MISUBC 135   detail::throw_system_error( 127   detail::throw_system_error(
MISUBC 136   std::error_code(errno, std::system_category()), 128   std::error_code(errno, std::system_category()),
137   "local_stream_socket::available"); 129   "local_stream_socket::available");
HITCBC 138   4 return static_cast<std::size_t>(value); 130   4 return static_cast<std::size_t>(value);
139   #endif 131   #endif
140   } 132   }
141   133  
142   local_endpoint 134   local_endpoint
HITCBC 143   6 local_stream_socket::local_endpoint() const noexcept 135   6 local_stream_socket::local_endpoint() const noexcept
144   { 136   {
HITCBC 145   6 if (!is_open()) 137   6 if (!is_open())
HITCBC 146   2 return corosio::local_endpoint{}; 138   2 return corosio::local_endpoint{};
HITCBC 147   4 return get().local_endpoint(); 139   4 return get().local_endpoint();
148   } 140   }
149   141  
150   local_endpoint 142   local_endpoint
HITCBC 151   6 local_stream_socket::remote_endpoint() const noexcept 143   6 local_stream_socket::remote_endpoint() const noexcept
152   { 144   {
HITCBC 153   6 if (!is_open()) 145   6 if (!is_open())
HITCBC 154   2 return corosio::local_endpoint{}; 146   2 return corosio::local_endpoint{};
HITCBC 155   4 return get().remote_endpoint(); 147   4 return get().remote_endpoint();
156   } 148   }
157   149  
158   } // namespace boost::corosio 150   } // namespace boost::corosio
159   151  
160   #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP 152   #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP