LCOV - code coverage report
Current view: top level - corosio/native/detail/epoll - epoll_udp_service.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 73.2 % 82 60 22
Test Date: 2026-04-13 22:45:57 Functions: 78.3 % 23 18 5

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2026 Steve Gerbino
       3                 : //
       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)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/corosio
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
      11                 : #define BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
      12                 : 
      13                 : #include <boost/corosio/detail/platform.hpp>
      14                 : 
      15                 : #if BOOST_COROSIO_HAS_EPOLL
      16                 : 
      17                 : #include <boost/corosio/detail/config.hpp>
      18                 : #include <boost/corosio/detail/udp_service.hpp>
      19                 : 
      20                 : #include <boost/corosio/native/detail/epoll/epoll_udp_socket.hpp>
      21                 : #include <boost/corosio/native/detail/epoll/epoll_scheduler.hpp>
      22                 : #include <boost/corosio/native/detail/reactor/reactor_socket_service.hpp>
      23                 : 
      24                 : #include <boost/corosio/native/detail/reactor/reactor_op_complete.hpp>
      25                 : 
      26                 : #include <coroutine>
      27                 : #include <mutex>
      28                 : 
      29                 : #include <errno.h>
      30                 : #include <netinet/in.h>
      31                 : #include <sys/epoll.h>
      32                 : #include <sys/socket.h>
      33                 : #include <unistd.h>
      34                 : 
      35                 : namespace boost::corosio::detail {
      36                 : 
      37                 : /** epoll UDP service implementation.
      38                 : 
      39                 :     Inherits from udp_service to enable runtime polymorphism.
      40                 :     Uses key_type = udp_service for service lookup.
      41                 : */
      42                 : class BOOST_COROSIO_DECL epoll_udp_service final
      43                 :     : public reactor_socket_service<
      44                 :           epoll_udp_service,
      45                 :           udp_service,
      46                 :           epoll_scheduler,
      47                 :           epoll_udp_socket>
      48                 : {
      49                 : public:
      50 HIT         355 :     explicit epoll_udp_service(capy::execution_context& ctx)
      51             355 :         : reactor_socket_service(ctx)
      52                 :     {
      53             355 :     }
      54                 : 
      55                 :     std::error_code open_datagram_socket(
      56                 :         udp_socket::implementation& impl,
      57                 :         int family,
      58                 :         int type,
      59                 :         int protocol) override;
      60                 :     std::error_code
      61                 :     bind_datagram(udp_socket::implementation& impl, endpoint ep) override;
      62                 : };
      63                 : 
      64                 : // Cancellation for connectionless ops
      65                 : 
      66                 : inline void
      67 MIS           0 : epoll_send_to_op::cancel() noexcept
      68                 : {
      69               0 :     if (socket_impl_)
      70               0 :         socket_impl_->cancel_single_op(*this);
      71                 :     else
      72               0 :         request_cancel();
      73               0 : }
      74                 : 
      75                 : inline void
      76 HIT           1 : epoll_recv_from_op::cancel() noexcept
      77                 : {
      78               1 :     if (socket_impl_)
      79               1 :         socket_impl_->cancel_single_op(*this);
      80                 :     else
      81 MIS           0 :         request_cancel();
      82 HIT           1 : }
      83                 : 
      84                 : // Cancellation for connected-mode ops
      85                 : 
      86                 : inline void
      87 MIS           0 : epoll_udp_connect_op::cancel() noexcept
      88                 : {
      89               0 :     if (socket_impl_)
      90               0 :         socket_impl_->cancel_single_op(*this);
      91                 :     else
      92               0 :         request_cancel();
      93               0 : }
      94                 : 
      95                 : inline void
      96               0 : epoll_send_op::cancel() noexcept
      97                 : {
      98               0 :     if (socket_impl_)
      99               0 :         socket_impl_->cancel_single_op(*this);
     100                 :     else
     101               0 :         request_cancel();
     102               0 : }
     103                 : 
     104                 : inline void
     105               0 : epoll_recv_op::cancel() noexcept
     106                 : {
     107               0 :     if (socket_impl_)
     108               0 :         socket_impl_->cancel_single_op(*this);
     109                 :     else
     110               0 :         request_cancel();
     111               0 : }
     112                 : 
     113                 : // Completion handlers
     114                 : 
     115                 : inline void
     116 HIT           8 : epoll_datagram_op::operator()()
     117                 : {
     118               8 :     complete_io_op(*this);
     119               8 : }
     120                 : 
     121                 : inline void
     122               7 : epoll_recv_from_op::operator()()
     123                 : {
     124               7 :     complete_datagram_op(*this, this->source_out);
     125               7 : }
     126                 : 
     127                 : inline void
     128               5 : epoll_udp_connect_op::operator()()
     129                 : {
     130               5 :     complete_connect_op(*this);
     131               5 : }
     132                 : 
     133                 : inline void
     134               2 : epoll_recv_op::operator()()
     135                 : {
     136               2 :     complete_io_op(*this);
     137               2 : }
     138                 : 
     139                 : // Socket construction/destruction
     140                 : 
     141              43 : inline epoll_udp_socket::epoll_udp_socket(epoll_udp_service& svc) noexcept
     142              43 :     : reactor_datagram_socket(svc)
     143                 : {
     144              43 : }
     145                 : 
     146              43 : inline epoll_udp_socket::~epoll_udp_socket() = default;
     147                 : 
     148                 : // Connectionless I/O
     149                 : 
     150                 : inline std::coroutine_handle<>
     151              11 : epoll_udp_socket::send_to(
     152                 :     std::coroutine_handle<> h,
     153                 :     capy::executor_ref ex,
     154                 :     buffer_param buf,
     155                 :     endpoint dest,
     156                 :     int flags,
     157                 :     std::stop_token token,
     158                 :     std::error_code* ec,
     159                 :     std::size_t* bytes_out)
     160                 : {
     161              11 :     return do_send_to(h, ex, buf, dest, flags, token, ec, bytes_out);
     162                 : }
     163                 : 
     164                 : inline std::coroutine_handle<>
     165              16 : epoll_udp_socket::recv_from(
     166                 :     std::coroutine_handle<> h,
     167                 :     capy::executor_ref ex,
     168                 :     buffer_param buf,
     169                 :     endpoint* source,
     170                 :     int flags,
     171                 :     std::stop_token token,
     172                 :     std::error_code* ec,
     173                 :     std::size_t* bytes_out)
     174                 : {
     175              16 :     return do_recv_from(h, ex, buf, source, flags, token, ec, bytes_out);
     176                 : }
     177                 : 
     178                 : // Connected-mode I/O
     179                 : 
     180                 : inline std::coroutine_handle<>
     181               6 : epoll_udp_socket::connect(
     182                 :     std::coroutine_handle<> h,
     183                 :     capy::executor_ref ex,
     184                 :     endpoint ep,
     185                 :     std::stop_token token,
     186                 :     std::error_code* ec)
     187                 : {
     188               6 :     return do_connect(h, ex, ep, token, ec);
     189                 : }
     190                 : 
     191                 : inline std::coroutine_handle<>
     192               3 : epoll_udp_socket::send(
     193                 :     std::coroutine_handle<> h,
     194                 :     capy::executor_ref ex,
     195                 :     buffer_param buf,
     196                 :     int flags,
     197                 :     std::stop_token token,
     198                 :     std::error_code* ec,
     199                 :     std::size_t* bytes_out)
     200                 : {
     201               3 :     return do_send(h, ex, buf, flags, token, ec, bytes_out);
     202                 : }
     203                 : 
     204                 : inline std::coroutine_handle<>
     205               2 : epoll_udp_socket::recv(
     206                 :     std::coroutine_handle<> h,
     207                 :     capy::executor_ref ex,
     208                 :     buffer_param buf,
     209                 :     int flags,
     210                 :     std::stop_token token,
     211                 :     std::error_code* ec,
     212                 :     std::size_t* bytes_out)
     213                 : {
     214               2 :     return do_recv(h, ex, buf, flags, token, ec, bytes_out);
     215                 : }
     216                 : 
     217                 : inline endpoint
     218               2 : epoll_udp_socket::remote_endpoint() const noexcept
     219                 : {
     220               2 :     return reactor_datagram_socket::remote_endpoint();
     221                 : }
     222                 : 
     223                 : inline void
     224               2 : epoll_udp_socket::cancel() noexcept
     225                 : {
     226               2 :     do_cancel();
     227               2 : }
     228                 : 
     229                 : inline void
     230             166 : epoll_udp_socket::close_socket() noexcept
     231                 : {
     232             166 :     do_close_socket();
     233             166 : }
     234                 : 
     235                 : inline std::error_code
     236              40 : epoll_udp_service::open_datagram_socket(
     237                 :     udp_socket::implementation& impl, int family, int type, int protocol)
     238                 : {
     239              40 :     auto* epoll_impl = static_cast<epoll_udp_socket*>(&impl);
     240              40 :     epoll_impl->close_socket();
     241                 : 
     242              40 :     int fd = ::socket(family, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
     243              40 :     if (fd < 0)
     244 MIS           0 :         return make_err(errno);
     245                 : 
     246 HIT          40 :     if (family == AF_INET6)
     247                 :     {
     248               7 :         int one = 1;
     249               7 :         ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
     250                 :     }
     251                 : 
     252              40 :     epoll_impl->fd_ = fd;
     253                 : 
     254              40 :     epoll_impl->desc_state_.fd = fd;
     255                 :     {
     256              40 :         std::lock_guard lock(epoll_impl->desc_state_.mutex);
     257              40 :         epoll_impl->desc_state_.read_op    = nullptr;
     258              40 :         epoll_impl->desc_state_.write_op   = nullptr;
     259              40 :         epoll_impl->desc_state_.connect_op = nullptr;
     260              40 :     }
     261              40 :     scheduler().register_descriptor(fd, &epoll_impl->desc_state_);
     262                 : 
     263              40 :     return {};
     264                 : }
     265                 : 
     266                 : inline std::error_code
     267              24 : epoll_udp_service::bind_datagram(udp_socket::implementation& impl, endpoint ep)
     268                 : {
     269              24 :     return static_cast<epoll_udp_socket*>(&impl)->do_bind(ep);
     270                 : }
     271                 : 
     272                 : } // namespace boost::corosio::detail
     273                 : 
     274                 : #endif // BOOST_COROSIO_HAS_EPOLL
     275                 : 
     276                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
        

Generated by: LCOV version 2.3