LCOV - code coverage report
Current view: top level - http/client - websocket_util.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 29 29
Test Date: 2026-11-10 10:38:07 Functions: 100.0 % 4 4

            Line data    Source code
       1              : #include "websocket_util.hpp"
       2              : #include "../../util/base64.hpp"
       3              : #include "../../util/sha1.hpp"
       4              : 
       5              : #include <random>
       6              : #include <regex>
       7              : #include <array>
       8              : 
       9              : namespace thinger::http::websocket_util {
      10              : 
      11          632 : std::optional<url_components> parse_websocket_url(const std::string& url) {
      12              :     // Longer URLs are refused before the regex, whose matching recurses per character in
      13              :     // libstdc++
      14          632 :     if (url.size() > 8192) return std::nullopt;
      15              :     // Compiled once (thread-safe), not on every call
      16          629 :     static const std::regex url_regex(R"(^(wss?)://([^/:]+)(?::(\d+))?(/.*)?$)", std::regex::icase);
      17          629 :     std::smatch match;
      18              : 
      19          629 :     if (!std::regex_match(url, match, url_regex)) {
      20          316 :         return std::nullopt;
      21              :     }
      22              : 
      23          313 :     url_components result;
      24          313 :     result.scheme = match[1].str();
      25          313 :     result.host = match[2].str();
      26          313 :     result.secure = (result.scheme == "wss" || result.scheme == "WSS");
      27          355 :     result.port = match[3].matched ? match[3].str() : (result.secure ? "443" : "80");
      28          313 :     result.path = match[4].matched ? match[4].str() : "/";
      29              : 
      30          313 :     return result;
      31          629 : }
      32              : 
      33          310 : std::string generate_websocket_key() {
      34          310 :     std::random_device rd;
      35          310 :     std::mt19937 gen(rd());
      36          310 :     std::uniform_int_distribution<> dis(0, 255);
      37              : 
      38              :     std::array<uint8_t, 16> bytes;
      39         5270 :     for (auto& b : bytes) {
      40         4960 :         b = static_cast<uint8_t>(dis(gen));
      41              :     }
      42              : 
      43          930 :     return ::thinger::util::base64::encode(bytes.data(), bytes.size());
      44          310 : }
      45              : 
      46          307 : std::string accept_key(const std::string& sent_key) {
      47          307 :     std::string sha1_hash = ::thinger::util::sha1::hash(sent_key + WS_GUID);
      48              :     return ::thinger::util::base64::encode(
      49          307 :         reinterpret_cast<const unsigned char*>(sha1_hash.data()),
      50              :         sha1_hash.size()
      51          921 :     );
      52          307 : }
      53              : 
      54          265 : bool validate_accept_key(const std::string& accept_key, const std::string& sent_key) {
      55          265 :     return accept_key == websocket_util::accept_key(sent_key);
      56              : }
      57              : 
      58              : } // namespace thinger::http::websocket_util
        

Generated by: LCOV version 2.0-1