LCOV - code coverage report
Current view: top level - asio/sockets - tcp_socket.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 92.6 % 81 75
Test Date: 2026-04-21 17:49:55 Functions: 92.6 % 27 25

            Line data    Source code
       1              : #include <iostream>
       2              : #include "tcp_socket.hpp"
       3              : 
       4              : namespace thinger::asio {
       5              : 
       6       769493 : tcp_socket::tcp_socket(const std::string& context, boost::asio::io_context& io_context)
       7       769493 :     : socket(context, io_context), socket_(io_context) {
       8       769493 : }
       9              : 
      10            0 : tcp_socket::tcp_socket(const std::string& context, const std::shared_ptr<tcp_socket>& tcp_socket)
      11            0 :     : socket(context, tcp_socket->get_io_context()), socket_(std::move(tcp_socket->get_socket())) {
      12            0 : }
      13              : 
      14           15 : tcp_socket::tcp_socket(const std::string& context, boost::asio::ip::tcp::socket&& sock)
      15           15 :     : socket(context, static_cast<boost::asio::io_context&>(sock.get_executor().context())), socket_(std::move(sock)) {
      16           15 : }
      17              : 
      18       769508 : tcp_socket::~tcp_socket() {
      19       769508 :     LOG_TRACE("releasing tcp connection");
      20       769508 :     close();
      21       769508 : }
      22              : 
      23       770687 : void tcp_socket::close() {
      24       770687 :     boost::system::error_code ec;
      25       770687 :     if (socket_.is_open()) {
      26         1901 :         socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
      27              :     }
      28       770687 :     socket_.close(ec);
      29       770687 :     LOG_TRACE("closing tcp socket result: {}", ec.message());
      30       770687 : }
      31              : 
      32          104 : void tcp_socket::cancel() {
      33          104 :     socket_.cancel();
      34          100 : }
      35              : 
      36          927 : awaitable<boost::system::error_code> tcp_socket::connect(
      37              :     const std::string& host,
      38              :     const std::string& port,
      39              :     std::chrono::seconds timeout)
      40              : {
      41              :     close();
      42              : 
      43              :     // Resolve host
      44              :     boost::asio::ip::tcp::resolver resolver(io_context_);
      45              :     auto [ec_resolve, endpoints] = co_await resolver.async_resolve(
      46              :         host, port, use_nothrow_awaitable);
      47              : 
      48              :     if (ec_resolve) {
      49              :         co_return ec_resolve;
      50              :     }
      51              : 
      52              :     // Setup timeout timer
      53              :     boost::asio::steady_timer timer(io_context_);
      54              :     timer.expires_after(timeout);
      55              : 
      56              :     // Race between connect and timeout
      57              :     bool timed_out = false;
      58              :     boost::system::error_code connect_ec;
      59              : 
      60              :     // Start timeout
      61          918 :     auto timeout_coro = [&]() -> awaitable<void> {
      62              :         auto [ec] = co_await timer.async_wait(use_nothrow_awaitable);
      63              :         if (!ec) {
      64              :             timed_out = true;
      65              :             socket_.cancel();
      66              :         }
      67         1836 :     };
      68              : 
      69              :     // Start connect
      70          918 :     auto connect_coro = [&]() -> awaitable<void> {
      71              :         auto [ec, endpoint] = co_await boost::asio::async_connect(
      72              :             socket_, endpoints, use_nothrow_awaitable);
      73              :         timer.cancel();
      74              :         if (ec) {
      75              :             connect_ec = timed_out ? boost::asio::error::timed_out : ec;
      76              :         }
      77         1836 :     };
      78              : 
      79              :     // Wait for connect (timeout will cancel if needed)
      80              :     co_spawn(io_context_, timeout_coro(), detached);
      81              :     co_await connect_coro();
      82              : 
      83              :     if (connect_ec) {
      84              :         co_return connect_ec;
      85              :     }
      86              : 
      87              :     // Run handshake if required (for SSL sockets)
      88              :     if (requires_handshake()) {
      89              :         auto hs_ec = co_await handshake(host);
      90              :         if (hs_ec) {
      91              :             close();
      92              :             co_return hs_ec;
      93              :         }
      94              :     }
      95              : 
      96              :     co_return boost::system::error_code{};
      97         1854 : }
      98              : 
      99         1704 : boost::asio::ip::tcp::socket& tcp_socket::get_socket() {
     100         1704 :     return socket_;
     101              : }
     102              : 
     103          971 : std::string tcp_socket::get_remote_ip() const {
     104          971 :     boost::system::error_code ec;
     105          971 :     auto remote_ep = socket_.remote_endpoint(ec);
     106          971 :     if (!ec) {
     107          971 :         return remote_ep.address().to_string();
     108              :     }
     109            0 :     return "0.0.0.0";
     110              : }
     111              : 
     112          974 : std::string tcp_socket::get_local_port() const {
     113          974 :     boost::system::error_code ec;
     114          974 :     auto local_ep = socket_.local_endpoint(ec);
     115          974 :     if (!ec) {
     116          974 :         return std::to_string(local_ep.port());
     117              :     }
     118            0 :     return "0";
     119              : }
     120              : 
     121            3 : std::string tcp_socket::get_remote_port() const {
     122            3 :     boost::system::error_code ec;
     123            3 :     auto remote_ep = socket_.remote_endpoint(ec);
     124            3 :     if (!ec) {
     125            3 :         return std::to_string(remote_ep.port());
     126              :     }
     127            0 :     return "0";
     128              : }
     129              : 
     130         4178 : awaitable<io_result> tcp_socket::read_some(uint8_t* buffer, size_t max_size) {
     131              :     co_return co_await socket_.async_read_some(
     132              :         boost::asio::buffer(buffer, max_size),
     133              :         use_nothrow_awaitable);
     134         8356 : }
     135              : 
     136          559 : awaitable<io_result> tcp_socket::read(uint8_t* buffer, size_t size) {
     137              :     co_return co_await boost::asio::async_read(
     138              :         socket_,
     139              :         boost::asio::buffer(buffer, size),
     140              :         boost::asio::transfer_exactly(size),
     141              :         use_nothrow_awaitable);
     142         1118 : }
     143              : 
     144            3 : awaitable<io_result> tcp_socket::read(boost::asio::streambuf& buffer, size_t size) {
     145              :     co_return co_await boost::asio::async_read(
     146              :         socket_,
     147              :         buffer,
     148              :         boost::asio::transfer_exactly(size),
     149              :         use_nothrow_awaitable);
     150            6 : }
     151              : 
     152            3 : awaitable<io_result> tcp_socket::read_until(boost::asio::streambuf& buffer, std::string_view delim) {
     153              :     co_return co_await boost::asio::async_read_until(
     154              :         socket_,
     155              :         buffer,
     156              :         std::string(delim),
     157              :         use_nothrow_awaitable);
     158            6 : }
     159              : 
     160          846 : awaitable<io_result> tcp_socket::write(const uint8_t* buffer, size_t size) {
     161              :     co_return co_await boost::asio::async_write(
     162              :         socket_,
     163              :         boost::asio::buffer(buffer, size),
     164              :         use_nothrow_awaitable);
     165         1692 : }
     166              : 
     167           12 : awaitable<io_result> tcp_socket::write(std::string_view str) {
     168              :     co_return co_await boost::asio::async_write(
     169              :         socket_,
     170              :         boost::asio::buffer(str.data(), str.size()),
     171              :         use_nothrow_awaitable);
     172           24 : }
     173              : 
     174         1943 : awaitable<io_result> tcp_socket::write(const std::vector<boost::asio::const_buffer>& buffers) {
     175              :     co_return co_await boost::asio::async_write(
     176              :         socket_,
     177              :         buffers,
     178              :         use_nothrow_awaitable);
     179         3886 : }
     180              : 
     181            6 : awaitable<boost::system::error_code> tcp_socket::wait(boost::asio::socket_base::wait_type type) {
     182              :     auto [ec] = co_await socket_.async_wait(type, use_nothrow_awaitable);
     183              :     co_return ec;
     184           12 : }
     185              : 
     186          973 : void tcp_socket::enable_tcp_no_delay() {
     187          973 :     socket_.set_option(boost::asio::ip::tcp::no_delay(true));
     188          971 : }
     189              : 
     190            5 : void tcp_socket::disable_tcp_no_delay() {
     191            5 :     socket_.set_option(boost::asio::ip::tcp::no_delay(false));
     192            3 : }
     193              : 
     194         5131 : bool tcp_socket::is_open() const {
     195         5131 :     return socket_.is_open();
     196              : }
     197              : 
     198         1860 : bool tcp_socket::is_secure() const {
     199         1860 :     return false;
     200              : }
     201              : 
     202            7 : size_t tcp_socket::available() const {
     203            7 :     boost::system::error_code ec;
     204            7 :     auto size = socket_.available(ec);
     205            7 :     if (ec) {
     206            4 :         LOG_ERROR("error while getting socket available bytes ({}): {}", size, ec.message());
     207              :     }
     208            7 :     return size;
     209              : }
     210              : 
     211              : }
        

Generated by: LCOV version 2.0-1