LCOV - code coverage report
Current view: top level - corosio/native/detail/reactor - reactor_basic_socket.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 100.0 % 36 36
Test Date: 2026-10-17 04:01:32 Functions: 90.9 % 88 80 8

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       3                 : // Copyright (c) 2026 Michael Vandeberg
       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_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
      12                 : #define BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
      13                 : 
      14                 : #include <boost/corosio/detail/config.hpp>
      15                 : #include <boost/corosio/detail/intrusive.hpp>
      16                 : #include <boost/corosio/detail/native_handle.hpp>
      17                 : #include <boost/corosio/endpoint.hpp>
      18                 : #include <boost/corosio/native/detail/native_socket_base.hpp>
      19                 : #include <boost/corosio/native/detail/reactor/reactor_io_core.hpp>
      20                 : #include <boost/corosio/native/detail/make_err.hpp>
      21                 : #include <boost/corosio/native/detail/endpoint_convert.hpp>
      22                 : 
      23                 : #include <cstring>
      24                 : #include <memory>
      25                 : #include <mutex>
      26                 : #include <utility>
      27                 : 
      28                 : #include <errno.h>
      29                 : #include <netinet/in.h>
      30                 : #include <sys/socket.h>
      31                 : #include <unistd.h>
      32                 : 
      33                 : namespace boost::corosio::detail {
      34                 : 
      35                 : /** CRTP base for reactor-backed socket implementations.
      36                 : 
      37                 :     Extracts the shared data members and virtual overrides that are
      38                 :     identical across TCP (reactor_stream_socket) and UDP
      39                 :     (reactor_datagram_socket). The register/park/cancel/teardown
      40                 :     protocol lives in reactor_io_core.
      41                 : 
      42                 :     Derived classes provide CRTP callbacks that enumerate their
      43                 :     specific op slots so cancel/close can iterate them generically.
      44                 : 
      45                 :     @tparam Derived   The concrete socket type (CRTP).
      46                 :     @tparam ImplBase  The public vtable base (tcp_socket::implementation
      47                 :                       or udp_socket::implementation).
      48                 :     @tparam Service   The backend's service type.
      49                 :     @tparam DescState The backend's descriptor_state type.
      50                 :     @tparam Endpoint  The endpoint type (endpoint or local_endpoint).
      51                 : */
      52                 : template<
      53                 :     class Derived,
      54                 :     class ImplBase,
      55                 :     class Service,
      56                 :     class DescState,
      57                 :     class Endpoint = endpoint>
      58                 : class reactor_basic_socket
      59                 :     : public native_socket_base<Derived, ImplBase, Endpoint>
      60                 :     , public reactor_io_core<Derived, Service, DescState>
      61                 :     , public intrusive_list<Derived>::node
      62                 : {
      63                 :     friend Derived;
      64                 : 
      65                 :     template<class, class, class, class, class, class, class, class, class>
      66                 :     friend class reactor_stream_socket;
      67                 : 
      68                 :     template<
      69                 :         class,
      70                 :         class,
      71                 :         class,
      72                 :         class,
      73                 :         class,
      74                 :         class,
      75                 :         class,
      76                 :         class,
      77                 :         class,
      78                 :         class,
      79                 :         class>
      80                 :     friend class reactor_datagram_socket;
      81                 : 
      82                 :     using core_type = reactor_io_core<Derived, Service, DescState>;
      83                 : 
      84 HIT        5656 :     explicit reactor_basic_socket(Service& svc) noexcept : core_type(svc) {}
      85                 : 
      86                 : protected:
      87                 :     // fd_ / local_endpoint_ and the synchronous accessors (native_handle,
      88                 :     // is_open, set_option/get_option, set_socket/set_local_endpoint, do_bind)
      89                 :     // live in native_socket_base — the readiness/completion-agnostic base
      90                 :     // shared with io_uring's sockets. The using-declarations make the
      91                 :     // inherited members visible to this template's own unqualified
      92                 :     // references below (two-phase lookup).
      93                 :     using native_socket_base<Derived, ImplBase, Endpoint>::fd_;
      94                 :     using native_socket_base<Derived, ImplBase, Endpoint>::local_endpoint_;
      95                 : 
      96                 : public:
      97            5656 :     ~reactor_basic_socket() override = default;
      98                 : 
      99                 :     /** Assign the fd, initialize descriptor state, and register with
     100                 :         the reactor.
     101                 : 
     102                 :         @param fd The descriptor to adopt.
     103                 : 
     104                 :         @return The error if the reactor rejects the descriptor, in
     105                 :         which case the implementation is left closed and the caller
     106                 :         retains ownership of @a fd; otherwise a default constructed
     107                 :         error code.
     108                 :     */
     109           14051 :     std::error_code init_and_register(int fd) noexcept
     110                 :     {
     111           14051 :         fd_ = fd;
     112           14051 :         if (auto ec = this->register_fd(fd))
     113                 :         {
     114               3 :             fd_ = -1;
     115               3 :             return ec;
     116                 :         }
     117           14048 :         return {};
     118                 :     }
     119                 : 
     120                 :     /// Cancel all pending operations.
     121             293 :     void do_cancel() noexcept
     122                 :     {
     123             293 :         this->cancel_all();
     124             293 :     }
     125                 : 
     126                 :     /** Close the socket and cancel pending operations.
     127                 : 
     128                 :         Invoked by the derived class's close_socket(). The
     129                 :         derived class may add backend-specific cleanup after
     130                 :         calling this method.
     131                 :     */
     132           84002 :     void do_close_socket() noexcept
     133                 :     {
     134           84002 :         this->abandon_all();
     135           84002 :         if (fd_ >= 0)
     136                 :         {
     137           20541 :             ::close(fd_);
     138           20541 :             fd_ = -1;
     139                 :         }
     140           84002 :         local_endpoint_ = Endpoint{};
     141           84002 :     }
     142                 : 
     143                 :     /** Release the socket without closing the fd.
     144                 : 
     145                 :         Like do_close_socket() but does not call ::close().
     146                 :         Returns the fd so the caller can take ownership.
     147                 :     */
     148              20 :     native_handle_type do_release_socket() noexcept
     149                 :     {
     150              20 :         this->abandon_all();
     151              20 :         native_handle_type released = fd_;
     152              20 :         fd_                         = -1;
     153              20 :         local_endpoint_             = Endpoint{};
     154              20 :         return released;
     155                 :     }
     156                 : 
     157                 :     /** Reset descriptor state for recycling.
     158                 : 
     159                 :         Called by the owning service's `construct()` when popping this
     160                 :         impl back off the free list. Actively re-initializes every
     161                 :         field it owns rather than trusting `close_socket()`'s prior
     162                 :         writes to still be there — `poison()` below depends on that,
     163                 :         and a future field added to either side without the other
     164                 :         would otherwise go unnoticed until this one re-sets it.
     165                 :         `object_ref_` and `is_enqueued_` are asserted instead: `poison()`
     166                 :         never touches them, so they must already hold their
     167                 :         zero-action-complete state.
     168                 : 
     169                 :         @pre refs_ == 0, fd closed and deregistered, no op in flight.
     170                 :     */
     171           21191 :     void reuse() noexcept
     172                 :     {
     173           21191 :         fd_             = -1;
     174           21191 :         local_endpoint_ = Endpoint{};
     175           21191 :         this->reset_desc_state();
     176           21191 :     }
     177                 : 
     178                 : #if !defined(NDEBUG)
     179                 :     /** Poison the fields `reuse()` re-initializes, before the pool
     180                 :         parks this impl on the free list.
     181                 : 
     182                 :         A field `reuse()` forgets to reset then reads back as this
     183                 :         unmistakable byte pattern instead of silently matching
     184                 :         whatever `close_socket()` happened to leave, turning a missed
     185                 :         reset into an immediate, loud failure rather than a latent
     186                 :         stale-state bug. See `reactor_io_core::poison_desc_state()`
     187                 :         for what is left alone.
     188                 : 
     189                 :         @pre refs_ == 0, fd closed and deregistered, no op in flight.
     190                 :     */
     191           26847 :     void poison() noexcept
     192                 :     {
     193           53694 :         auto smash = [](auto& field) {
     194           53694 :             std::memset(static_cast<void*>(&field), 0xDB, sizeof(field));
     195                 :         };
     196           26847 :         smash(fd_);
     197           26847 :         smash(local_endpoint_);
     198           26847 :         this->poison_desc_state();
     199           26847 :     }
     200                 : #endif
     201                 : };
     202                 : 
     203                 : } // namespace boost::corosio::detail
     204                 : 
     205                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_REACTOR_REACTOR_BASIC_SOCKET_HPP
        

Generated by: LCOV version 2.3