LCOV - code coverage report
Current view: top level - wirestead/config - tcp_server_config.hpp (source / functions) Coverage Total Hit
Test: Wirestead Coverage Report Lines: 81.0 % 42 34
Test Date: 2026-08-30 10:35:09 Functions: 100.0 % 3 3
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 72.9 % 70 51

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * Copyright 2025 Jinwoo Sung
       3                 :             :  *
       4                 :             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :             :  * you may not use this file except in compliance with the License.
       6                 :             :  * You may obtain a copy of the License at
       7                 :             :  *
       8                 :             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :             :  *
      10                 :             :  * Unless required by applicable law or agreed to in writing, software
      11                 :             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :             :  * See the License for the specific language governing permissions and
      14                 :             :  * limitations under the License.
      15                 :             :  */
      16                 :             : 
      17                 :             : #pragma once
      18                 :             : 
      19                 :             : #include <cstdint>
      20                 :             : #include <string>
      21                 :             : 
      22                 :             : #include "wirestead/base/constants.hpp"
      23                 :             : #include "wirestead/util/input_validator.hpp"
      24                 :             : 
      25                 :             : namespace wirestead {
      26                 :             : namespace config {
      27                 :             : 
      28                 :             : struct TcpServerConfig {
      29                 :             :   std::string bind_address = "0.0.0.0";
      30                 :             :   uint16_t port = 9000;
      31                 :             :   size_t backpressure_threshold = base::constants::DEFAULT_BACKPRESSURE_THRESHOLD;
      32                 :             :   base::constants::BackpressureStrategy backpressure_strategy = base::constants::BackpressureStrategy::Reliable;
      33                 :             :   bool enable_memory_pool = true;
      34                 :             :   // #437: 0 (unlimited) used to be the default, risking unbounded memory
      35                 :             :   // growth from a large number of slow/malicious clients. 0 still means
      36                 :             :   // unlimited for callers who explicitly opt into it.
      37                 :             :   int max_connections = static_cast<int>(base::constants::DEFAULT_MAX_CONNECTIONS);
      38                 :             : 
      39                 :             :   // Port binding retry configuration
      40                 :             :   bool enable_port_retry = false;     // Enable port binding retry
      41                 :             :   int max_port_retries = 3;           // Maximum number of retry attempts
      42                 :             :   int port_retry_interval_ms = 1000;  // Retry interval in milliseconds
      43                 :             : 
      44                 :             :   // TLS. Both must be set for the server to serve TLS; leaving them empty keeps
      45                 :             :   // the connection in plaintext, which is the default. Only honoured in a build
      46                 :             :   // configured with WIRESTEAD_ENABLE_TLS - a build without it rejects a
      47                 :             :   // configured certificate at start() rather than silently serving plaintext.
      48                 :             :   std::string tls_certificate_file;
      49                 :             :   std::string tls_private_key_file;
      50                 :             : 
      51   [ +  +  +  - ]:         137 :   [[nodiscard]] bool tls_enabled() const { return !tls_certificate_file.empty() && !tls_private_key_file.empty(); }
      52                 :             : 
      53                 :             :   int idle_timeout_ms = static_cast<int>(base::constants::DEFAULT_IDLE_TIMEOUT_MS);  // 0 = disabled
      54                 :             :   bool tcp_no_delay = base::constants::DEFAULT_TCP_NO_DELAY;
      55                 :             :   bool keep_alive = base::constants::DEFAULT_KEEP_ALIVE;
      56                 :             :   size_t send_buffer_size = 0;
      57                 :             :   size_t receive_buffer_size = 0;
      58                 :             :   // Size of the per-connection userspace read buffer that each
      59                 :             :   // async_read_some() fills. Distinct from receive_buffer_size, which is the
      60                 :             :   // kernel's SO_RCVBUF. Raising this reduces read completions and callback
      61                 :             :   // dispatches on bulk transfers, at the cost of that much memory per
      62                 :             :   // connection.
      63                 :             :   size_t read_buffer_size = base::constants::DEFAULT_READ_BUFFER_SIZE;
      64                 :             : 
      65                 :             :   // Opt into the shared IoContextManager singleton instead of a dedicated
      66                 :             :   // io_context + thread (the default since #440). Only meaningful for
      67                 :             :   // deliberately trading per-instance parallelism for reduced thread/memory
      68                 :             :   // overhead across many instances in one process.
      69                 :             :   bool use_shared_context = false;
      70                 :             : 
      71                 :             :   // Validation methods
      72                 :          10 :   bool is_valid() const {
      73                 :          19 :     return read_buffer_size >= base::constants::MIN_READ_BUFFER_SIZE &&
      74         [ +  + ]:           9 :            read_buffer_size <= base::constants::MAX_READ_BUFFER_SIZE &&
      75   [ +  +  -  + ]:           8 :            (util::InputValidator::is_valid_ipv4(bind_address) || util::InputValidator::is_valid_ipv6(bind_address)) &&
      76   [ +  -  +  - ]:           7 :            port > 0 && backpressure_threshold >= base::constants::MIN_BACKPRESSURE_THRESHOLD &&
      77   [ +  -  +  - ]:           7 :            backpressure_threshold <= base::constants::MAX_BACKPRESSURE_THRESHOLD && max_connections >= 0 &&
      78   [ +  +  +  - ]:           7 :            (idle_timeout_ms == 0 || (idle_timeout_ms >= static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS) &&
      79         [ -  + ]:           1 :                                      idle_timeout_ms <= static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS))) &&
      80   [ +  +  +  + ]:           6 :            (send_buffer_size == 0 || (send_buffer_size >= base::constants::MIN_SOCKET_BUFFER_SIZE &&
      81   [ +  +  +  - ]:          20 :                                       send_buffer_size <= base::constants::MAX_SOCKET_BUFFER_SIZE)) &&
      82   [ +  +  +  - ]:           5 :            (receive_buffer_size == 0 || (receive_buffer_size >= base::constants::MIN_SOCKET_BUFFER_SIZE &&
      83         [ +  - ]:          11 :                                          receive_buffer_size <= base::constants::MAX_SOCKET_BUFFER_SIZE));
      84                 :             :   }
      85                 :             : 
      86                 :             :   // Apply validation and clamp values to valid ranges
      87                 :         145 :   void validate_and_clamp() {
      88         [ +  + ]:         145 :     if (read_buffer_size < base::constants::MIN_READ_BUFFER_SIZE) {
      89                 :           1 :       read_buffer_size = base::constants::MIN_READ_BUFFER_SIZE;
      90         [ +  + ]:         144 :     } else if (read_buffer_size > base::constants::MAX_READ_BUFFER_SIZE) {
      91                 :           2 :       read_buffer_size = base::constants::MAX_READ_BUFFER_SIZE;
      92                 :             :     }
      93         [ -  + ]:         145 :     if (backpressure_threshold < base::constants::MIN_BACKPRESSURE_THRESHOLD) {
      94                 :           0 :       backpressure_threshold = base::constants::MIN_BACKPRESSURE_THRESHOLD;
      95         [ -  + ]:         145 :     } else if (backpressure_threshold > base::constants::MAX_BACKPRESSURE_THRESHOLD) {
      96                 :           0 :       backpressure_threshold = base::constants::MAX_BACKPRESSURE_THRESHOLD;
      97                 :             :     }
      98                 :             : 
      99         [ -  + ]:         145 :     if (max_connections < 0) {
     100                 :           0 :       max_connections = 0;
     101         [ -  + ]:         145 :     } else if (max_connections > static_cast<int>(base::constants::MAX_MAX_CONNECTIONS)) {
     102                 :           0 :       max_connections = static_cast<int>(base::constants::MAX_MAX_CONNECTIONS);
     103                 :             :     }
     104                 :             : 
     105         [ -  + ]:         145 :     if (idle_timeout_ms < 0) {
     106                 :           0 :       idle_timeout_ms = 0;
     107         [ +  + ]:         145 :     } else if (idle_timeout_ms != 0) {
     108         [ -  + ]:           2 :       if (idle_timeout_ms < static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS)) {
     109                 :           0 :         idle_timeout_ms = static_cast<int>(base::constants::MIN_IDLE_TIMEOUT_MS);
     110         [ +  + ]:           2 :       } else if (idle_timeout_ms > static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS)) {
     111                 :           1 :         idle_timeout_ms = static_cast<int>(base::constants::MAX_IDLE_TIMEOUT_MS);
     112                 :             :       }
     113                 :             :     }
     114                 :             : 
     115   [ +  +  +  + ]:         145 :     if (send_buffer_size != 0 && send_buffer_size < base::constants::MIN_SOCKET_BUFFER_SIZE) {
     116                 :           1 :       send_buffer_size = base::constants::MIN_SOCKET_BUFFER_SIZE;
     117         [ -  + ]:         144 :     } else if (send_buffer_size > base::constants::MAX_SOCKET_BUFFER_SIZE) {
     118                 :           0 :       send_buffer_size = base::constants::MAX_SOCKET_BUFFER_SIZE;
     119                 :             :     }
     120                 :             : 
     121   [ +  +  -  + ]:         145 :     if (receive_buffer_size != 0 && receive_buffer_size < base::constants::MIN_SOCKET_BUFFER_SIZE) {
     122                 :           0 :       receive_buffer_size = base::constants::MIN_SOCKET_BUFFER_SIZE;
     123         [ +  + ]:         145 :     } else if (receive_buffer_size > base::constants::MAX_SOCKET_BUFFER_SIZE) {
     124                 :           1 :       receive_buffer_size = base::constants::MAX_SOCKET_BUFFER_SIZE;
     125                 :             :     }
     126                 :         145 :   }
     127                 :             : };
     128                 :             : 
     129                 :             : }  // namespace config
     130                 :             : }  // namespace wirestead
        

Generated by: LCOV version 2.0-1