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-03-17 15:52:49 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         271 :     explicit epoll_udp_service(capy::execution_context& ctx)
      51             271 :         : reactor_socket_service(ctx)
      52                 :     {
      53             271 :     }
      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              39 : inline epoll_udp_socket::epoll_udp_socket(epoll_udp_service& svc) noexcept
     142              39 :     : reactor_datagram_socket(svc)
     143                 : {
     144              39 : }
     145                 : 
     146              39 : 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                 :     std::stop_token token,
     157                 :     std::error_code* ec,
     158                 :     std::size_t* bytes_out)
     159                 : {
     160              11 :     return do_send_to(h, ex, buf, dest, token, ec, bytes_out);
     161                 : }
     162                 : 
     163                 : inline std::coroutine_handle<>
     164              16 : epoll_udp_socket::recv_from(
     165                 :     std::coroutine_handle<> h,
     166                 :     capy::executor_ref ex,
     167                 :     buffer_param buf,
     168                 :     endpoint* source,
     169                 :     std::stop_token token,
     170                 :     std::error_code* ec,
     171                 :     std::size_t* bytes_out)
     172                 : {
     173              16 :     return do_recv_from(h, ex, buf, source, token, ec, bytes_out);
     174                 : }
     175                 : 
     176                 : // Connected-mode I/O
     177                 : 
     178                 : inline std::coroutine_handle<>
     179               6 : epoll_udp_socket::connect(
     180                 :     std::coroutine_handle<> h,
     181                 :     capy::executor_ref ex,
     182                 :     endpoint ep,
     183                 :     std::stop_token token,
     184                 :     std::error_code* ec)
     185                 : {
     186               6 :     return do_connect(h, ex, ep, token, ec);
     187                 : }
     188                 : 
     189                 : inline std::coroutine_handle<>
     190               3 : epoll_udp_socket::send(
     191                 :     std::coroutine_handle<> h,
     192                 :     capy::executor_ref ex,
     193                 :     buffer_param buf,
     194                 :     std::stop_token token,
     195                 :     std::error_code* ec,
     196                 :     std::size_t* bytes_out)
     197                 : {
     198               3 :     return do_send(h, ex, buf, token, ec, bytes_out);
     199                 : }
     200                 : 
     201                 : inline std::coroutine_handle<>
     202               2 : epoll_udp_socket::recv(
     203                 :     std::coroutine_handle<> h,
     204                 :     capy::executor_ref ex,
     205                 :     buffer_param buf,
     206                 :     std::stop_token token,
     207                 :     std::error_code* ec,
     208                 :     std::size_t* bytes_out)
     209                 : {
     210               2 :     return do_recv(h, ex, buf, token, ec, bytes_out);
     211                 : }
     212                 : 
     213                 : inline endpoint
     214               2 : epoll_udp_socket::remote_endpoint() const noexcept
     215                 : {
     216               2 :     return reactor_datagram_socket::remote_endpoint();
     217                 : }
     218                 : 
     219                 : inline void
     220               2 : epoll_udp_socket::cancel() noexcept
     221                 : {
     222               2 :     do_cancel();
     223               2 : }
     224                 : 
     225                 : inline void
     226             152 : epoll_udp_socket::close_socket() noexcept
     227                 : {
     228             152 :     do_close_socket();
     229             152 : }
     230                 : 
     231                 : inline std::error_code
     232              37 : epoll_udp_service::open_datagram_socket(
     233                 :     udp_socket::implementation& impl, int family, int type, int protocol)
     234                 : {
     235              37 :     auto* epoll_impl = static_cast<epoll_udp_socket*>(&impl);
     236              37 :     epoll_impl->close_socket();
     237                 : 
     238              37 :     int fd = ::socket(family, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
     239              37 :     if (fd < 0)
     240 MIS           0 :         return make_err(errno);
     241                 : 
     242 HIT          37 :     if (family == AF_INET6)
     243                 :     {
     244               7 :         int one = 1;
     245               7 :         ::setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
     246                 :     }
     247                 : 
     248              37 :     epoll_impl->fd_ = fd;
     249                 : 
     250              37 :     epoll_impl->desc_state_.fd = fd;
     251                 :     {
     252              37 :         std::lock_guard lock(epoll_impl->desc_state_.mutex);
     253              37 :         epoll_impl->desc_state_.read_op    = nullptr;
     254              37 :         epoll_impl->desc_state_.write_op   = nullptr;
     255              37 :         epoll_impl->desc_state_.connect_op = nullptr;
     256              37 :     }
     257              37 :     scheduler().register_descriptor(fd, &epoll_impl->desc_state_);
     258                 : 
     259              37 :     return {};
     260                 : }
     261                 : 
     262                 : inline std::error_code
     263              21 : epoll_udp_service::bind_datagram(udp_socket::implementation& impl, endpoint ep)
     264                 : {
     265              21 :     return static_cast<epoll_udp_socket*>(&impl)->do_bind(ep);
     266                 : }
     267                 : 
     268                 : } // namespace boost::corosio::detail
     269                 : 
     270                 : #endif // BOOST_COROSIO_HAS_EPOLL
     271                 : 
     272                 : #endif // BOOST_COROSIO_NATIVE_DETAIL_EPOLL_EPOLL_UDP_SERVICE_HPP
        

Generated by: LCOV version 2.3