93.85% Lines (61/65) 100.00% Functions (14/14)
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   188 local_stream_socket::~local_stream_socket() 26   216 local_stream_socket::~local_stream_socket()
27   { 27   {
HITCBC 28   188 close(); 28   216 close();
HITCBC 29   188 } 29   216 }
30   30  
HITCBC 31   154 local_stream_socket::local_stream_socket(capy::execution_context& ctx) 31   182 local_stream_socket::local_stream_socket(capy::execution_context& ctx)
HITCBC 32   154 : io_object(create_handle<detail::local_stream_service>(ctx)) 32   182 : io_object(create_handle<detail::local_stream_service>(ctx))
33   { 33   {
HITCBC 34   154 } 34   182 }
35   35  
36   void 36   void
HITCBC 37   41 local_stream_socket::open(local_stream proto) 37   45 local_stream_socket::open(local_stream proto)
38   { 38   {
HITCBC 39   41 if (is_open()) 39   45 if (is_open())
MISUBC 40   return; 40   return;
HITCBC 41   41 open_for_family(proto.family(), proto.type(), proto.protocol()); 41   45 open_for_family(proto.family(), proto.type(), proto.protocol());
42   } 42   }
43   43  
44   void 44   void
HITCBC 45   41 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)
46   { 46   {
HITCBC 47   41 auto& svc = static_cast<detail::local_stream_service&>(h_.service()); 47   45 auto& svc = static_cast<detail::local_stream_service&>(h_.service());
HITCBC 48   41 std::error_code ec = svc.open_socket( 48   45 std::error_code ec = svc.open_socket(
HITCBC 49   41 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   41 if (ec) 51   45 if (ec)
MISUBC 52   detail::throw_system_error(ec, "local_stream_socket::open"); 52   detail::throw_system_error(ec, "local_stream_socket::open");
HITCBC 53   41 } 53   45 }
54   54  
55   void 55   void
HITCBC 56   196 local_stream_socket::close() 56   224 local_stream_socket::close()
57   { 57   {
HITCBC 58   196 if (!is_open()) 58   224 if (!is_open())
HITCBC 59   52 return; 59   59 return;
HITCBC 60   144 h_.service().close(h_); 60   165 h_.service().close(h_);
61   } 61   }
62   62  
63   void 63   void
HITCBC 64   8 local_stream_socket::cancel() 64   8 local_stream_socket::cancel()
65   { 65   {
HITCBC 66   8 if (!is_open()) 66   8 if (!is_open())
HITCBC 67   2 return; 67   2 return;
HITCBC 68   6 get().cancel(); 68   6 get().cancel();
69   } 69   }
70   70  
71   void 71   void
HITCBC 72   4 local_stream_socket::shutdown(shutdown_type what) 72   4 local_stream_socket::shutdown(shutdown_type what)
73   { 73   {
HITCBC 74   4 if (is_open()) 74   4 if (is_open())
75   { 75   {
76   // Best-effort: errors like ENOTCONN are expected and unhelpful 76   // Best-effort: errors like ENOTCONN are expected and unhelpful
HITCBC 77   2 [[maybe_unused]] auto ec = get().shutdown(what); 77   2 [[maybe_unused]] auto ec = get().shutdown(what);
78   } 78   }
HITCBC 79   4 } 79   4 }
80   80  
81   void 81   void
HITCBC 82   4 local_stream_socket::shutdown(shutdown_type what, std::error_code& ec) noexcept 82   4 local_stream_socket::shutdown(shutdown_type what, std::error_code& ec) noexcept
83   { 83   {
HITCBC 84   4 ec = {}; 84   4 ec = {};
HITCBC 85   4 if (is_open()) 85   4 if (is_open())
HITCBC 86   2 ec = get().shutdown(what); 86   2 ec = get().shutdown(what);
HITCBC 87   4 } 87   4 }
88   88  
89   void 89   void
HITCBC 90   90 local_stream_socket::assign(native_handle_type fd) 90   110 local_stream_socket::assign(native_handle_type fd)
91 - if (is_open())  
DCB 92 - 90 detail::throw_logic_error("assign: socket already open");  
ECB 93   2 { 91   {
HITCBC 94   88 auto& svc = static_cast<detail::local_stream_service&>(h_.service()); 92   110 auto& svc = static_cast<detail::local_stream_service&>(h_.service());
HITCBC 95   88 std::error_code ec = svc.assign_socket( 93   110 std::error_code ec = svc.assign_socket(
HITCBC 96   88 static_cast<local_stream_socket::implementation&>(*h_.get()), fd); 94   110 static_cast<local_stream_socket::implementation&>(*h_.get()), fd);
HITCBC 97   88 if (ec) 95   110 if (ec)
HITCBC 98   2 detail::throw_system_error(ec, "local_stream_socket::assign"); 96   9 detail::throw_system_error(ec, "local_stream_socket::assign");
HITCBC 99   86 } 97   101 }
100   98  
101   native_handle_type 99   native_handle_type
HITCBC 102   8 local_stream_socket::native_handle() const noexcept 100   10 local_stream_socket::native_handle() const noexcept
103   { 101   {
HITCBC 104   8 if (!is_open()) 102   10 if (!is_open())
105   #if BOOST_COROSIO_HAS_IOCP 103   #if BOOST_COROSIO_HAS_IOCP
106   return ~native_handle_type(0); 104   return ~native_handle_type(0);
107   #else 105   #else
HITCBC 108   2 return -1; 106   2 return -1;
109   #endif 107   #endif
HITCBC 110   6 return get().native_handle(); 108   8 return get().native_handle();
111   } 109   }
112   110  
113   native_handle_type 111   native_handle_type
HITCBC 114   4 local_stream_socket::release() 112   6 local_stream_socket::release()
115   { 113   {
HITCBC 116   4 if (!is_open()) 114   6 if (!is_open())
HITCBC 117   2 detail::throw_logic_error("release: socket not open"); 115   2 detail::throw_logic_error("release: socket not open");
HITCBC 118   2 return get().release_socket(); 116   4 return get().release_socket();
119   } 117   }
120   118  
121   std::size_t 119   std::size_t
HITCBC 122   6 local_stream_socket::available() const 120   6 local_stream_socket::available() const
123   { 121   {
HITCBC 124   6 if (!is_open()) 122   6 if (!is_open())
HITCBC 125   2 detail::throw_logic_error("available: socket not open"); 123   2 detail::throw_logic_error("available: socket not open");
126   #if BOOST_COROSIO_HAS_IOCP 124   #if BOOST_COROSIO_HAS_IOCP
127   u_long value = 0; 125   u_long value = 0;
128   if (::ioctlsocket( 126   if (::ioctlsocket(
129   static_cast<SOCKET>(native_handle()), FIONREAD, &value) != 0) 127   static_cast<SOCKET>(native_handle()), FIONREAD, &value) != 0)
130   detail::throw_system_error( 128   detail::throw_system_error(
131   std::error_code(::WSAGetLastError(), std::system_category()), 129   std::error_code(::WSAGetLastError(), std::system_category()),
132   "local_stream_socket::available"); 130   "local_stream_socket::available");
133   return static_cast<std::size_t>(value); 131   return static_cast<std::size_t>(value);
134   #else 132   #else
HITCBC 135   4 int value = 0; 133   4 int value = 0;
HITCBC 136   4 if (::ioctl(native_handle(), FIONREAD, &value) < 0) 134   4 if (::ioctl(native_handle(), FIONREAD, &value) < 0)
MISUBC 137   detail::throw_system_error( 135   detail::throw_system_error(
MISUBC 138   std::error_code(errno, std::system_category()), 136   std::error_code(errno, std::system_category()),
139   "local_stream_socket::available"); 137   "local_stream_socket::available");
HITCBC 140   4 return static_cast<std::size_t>(value); 138   4 return static_cast<std::size_t>(value);
141   #endif 139   #endif
142   } 140   }
143   141  
144   local_endpoint 142   local_endpoint
HITCBC 145   6 local_stream_socket::local_endpoint() const noexcept 143   6 local_stream_socket::local_endpoint() const noexcept
146   { 144   {
HITCBC 147   6 if (!is_open()) 145   6 if (!is_open())
HITCBC 148   2 return corosio::local_endpoint{}; 146   2 return corosio::local_endpoint{};
HITCBC 149   4 return get().local_endpoint(); 147   4 return get().local_endpoint();
150   } 148   }
151   149  
152   local_endpoint 150   local_endpoint
HITCBC 153   6 local_stream_socket::remote_endpoint() const noexcept 151   6 local_stream_socket::remote_endpoint() const noexcept
154   { 152   {
HITCBC 155   6 if (!is_open()) 153   6 if (!is_open())
HITCBC 156   2 return corosio::local_endpoint{}; 154   2 return corosio::local_endpoint{};
HITCBC 157   4 return get().remote_endpoint(); 155   4 return get().remote_endpoint();
158   } 156   }
159   157  
160   } // namespace boost::corosio 158   } // namespace boost::corosio
161   159  
162   #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP 160   #endif // BOOST_COROSIO_POSIX || BOOST_COROSIO_HAS_IOCP