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