LCOV - code coverage report
Current view: top level - http/server - server_standalone.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 91.3 % 69 63
Test Date: 2026-04-21 17:49:55 Functions: 90.9 % 11 10

            Line data    Source code
       1              : #include "server_standalone.hpp"
       2              : #include "../../util/logger.hpp"
       3              : #include "../../asio/ssl/certificate_manager.hpp"
       4              : #include <future>
       5              : 
       6              : namespace thinger::http {
       7              : 
       8          809 : server::server() {
       9          809 :     LOG_DEBUG("Created standalone HTTP server (single-threaded)");
      10          809 : }
      11              : 
      12          809 : server::~server() {
      13          809 :     LOG_DEBUG("Destroying standalone HTTP server");
      14          809 :     if (running_) {
      15           12 :         stop();
      16              :     }
      17          809 : }
      18              : 
      19              : 
      20          696 : std::unique_ptr<asio::socket_server> server::create_socket_server(
      21              :     const std::string& host, const std::string& port) {
      22              :     
      23              :     // Both acceptor and connections use our io_context
      24         2321 :     auto context_provider = [this]() -> boost::asio::io_context& {
      25         2321 :         return io_context_;
      26          696 :     };
      27              :     
      28              :     auto server = std::make_unique<asio::socket_server>(
      29              :         host, port,
      30              :         context_provider,    // acceptor context
      31              :         context_provider     // connection context
      32          696 :     );
      33              :     
      34              :     // Configure SSL if enabled
      35          696 :     if (ssl_enabled_) {
      36           52 :         server->enable_ssl(true);
      37              :         
      38           52 :         auto& cert_mgr = asio::certificate_manager::instance();
      39           52 :         auto default_ctx = cert_mgr.get_default_certificate();
      40              :         
      41           52 :         if (!default_ctx) {
      42            0 :             LOG_ERROR("No default SSL certificate configured");
      43            0 :             return nullptr;
      44              :         }
      45              : 
      46           52 :         server->set_ssl_context(default_ctx);
      47           52 :         server->set_sni_callback(asio::certificate_manager::sni_callback);
      48           52 :     }
      49              : 
      50          696 :     return server;
      51          696 : }
      52              : 
      53           48 : std::unique_ptr<asio::unix_socket_server> server::create_unix_socket_server(
      54              :     const std::string& unix_path) {
      55              :     
      56              :     // Both acceptor and connections use our io_context
      57           48 :     auto context_provider = [this]() -> boost::asio::io_context& {
      58           48 :         return io_context_;
      59           48 :     };
      60              :     
      61              :     auto server = std::make_unique<asio::unix_socket_server>(
      62              :         unix_path,
      63              :         context_provider,    // acceptor context
      64              :         context_provider     // connection context
      65           48 :     );
      66              :     
      67           96 :     return server;
      68              : }
      69              : 
      70          699 : bool server::listen(const std::string& host, uint16_t port) {
      71          699 :     if (running_) {
      72            3 :         LOG_WARNING("Server already running");
      73            3 :         return false;
      74              :     }
      75              :     
      76              :     // Restart io_context if it was previously stopped
      77          696 :     io_context_.restart();
      78              :     
      79              :     // Call base implementation to setup socket server
      80          696 :     if (!http_server_base::listen(host, port)) {
      81            6 :         return false;
      82              :     }
      83              :     
      84              :     // Create work guard to keep io_context running
      85          690 :     work_guard_ = std::make_unique<work_guard_type>(io_context_.get_executor());
      86              :     
      87              :     // Mark as running
      88          690 :     running_ = true;
      89          690 :     LOG_INFO("Standalone server listening on {}:{} (single-threaded)", host, port);
      90              :     
      91              :     // Note: io_context_.run() will be called in wait() method
      92              :     
      93          690 :     return true;
      94              : }
      95              : 
      96           48 : bool server::listen_unix(const std::string& unix_path) {
      97           48 :     if (running_) {
      98            0 :         LOG_WARNING("Server already running");
      99            0 :         return false;
     100              :     }
     101              : 
     102              :     // Restart io_context if it was previously stopped
     103           48 :     io_context_.restart();
     104              : 
     105              :     // Call base implementation to setup unix socket server
     106           48 :     if (!http_server_base::listen_unix(unix_path)) {
     107            0 :         return false;
     108              :     }
     109              : 
     110              :     // Create work guard to keep io_context running
     111           48 :     work_guard_ = std::make_unique<work_guard_type>(io_context_.get_executor());
     112              : 
     113              :     // Mark as running
     114           48 :     running_ = true;
     115           48 :     LOG_INFO("Standalone server listening on unix:{} (single-threaded)", unix_path);
     116              : 
     117           48 :     return true;
     118              : }
     119              : 
     120          717 : void server::wait() {
     121          717 :     if (!running_) {
     122            0 :         return;
     123              :     }
     124              :     
     125              :     // Run io_context in the current thread
     126              :     // This blocks until the server is stopped
     127          717 :     LOG_DEBUG("Running io_context in current thread");
     128          717 :     io_context_.run();
     129          717 :     LOG_DEBUG("io_context stopped");
     130              : }
     131              : 
     132          743 : bool server::stop() {
     133          743 :     if (!running_) {
     134            5 :         return false;
     135              :     }
     136              :     
     137          738 :     LOG_DEBUG("Stopping standalone HTTP server");
     138          738 :     running_ = false;
     139              :     
     140              :     // Stop accepting new connections first (this is always safe to call)
     141          738 :     http_server_base::stop();
     142              :     
     143              :     // Reset work guard to allow io_context to stop when it's running
     144          738 :     work_guard_.reset();
     145              :     
     146              :     // Stop the io_context if it's running
     147              :     // Note: io_context_.stop() is safe to call even if not running
     148          738 :     io_context_.stop();
     149              :     
     150          738 :     LOG_DEBUG("Standalone HTTP server stopped");
     151          738 :     return true;
     152              : }
     153              : 
     154              : } // namespace thinger::http
        

Generated by: LCOV version 2.0-1