LCOV - code coverage report
Current view: top level - src/fix - fix_frame_decoder.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 41 41
Test Date: 2025-12-19 03:13:09 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /**
       2              :  * @file fix_frame_decoder.cpp
       3              :  * @brief FixFrameDecoder 类实现
       4              :  */
       5              : 
       6              : #include "fix/fix_frame_decoder.hpp"
       7              : #include "base/config.hpp"
       8              : #include <stdexcept>
       9              : #include <iostream>
      10              : 
      11              : namespace fix40 {
      12              : 
      13           15 : FixFrameDecoder::FixFrameDecoder(size_t max_buffer_size, size_t max_body_length)
      14           15 :     : max_buffer_size_(max_buffer_size), max_body_length_(max_body_length) {}
      15              : 
      16            8 : bool FixFrameDecoder::can_append(size_t len) const {
      17            8 :     if (buffer_.size() >= max_buffer_size_) return false;
      18            7 :     if (len > max_buffer_size_ - buffer_.size()) return false;
      19            4 :     return true;
      20              : }
      21              : 
      22           41 : void FixFrameDecoder::append(const char* data, size_t len) {
      23              :     // 安全的溢出防护:使用减法代替加法
      24              :     // 当 buffer_.size() + len 可能超过 SIZE_MAX 时,这可以防止整数溢出
      25           41 :     if (buffer_.size() >= max_buffer_size_ || len > max_buffer_size_ - buffer_.size()) {
      26              :         // 让上层 Connection 或 Session 来决定如何处理这个错误
      27            1 :         throw std::runtime_error("Buffer size limit exceeded. Closing connection.");
      28              :     }
      29           40 :     buffer_.append(data, len);
      30           40 : }
      31              : 
      32           15 : bool FixFrameDecoder::next_message(std::string& message) {
      33           15 :     if (buffer_.empty()) {
      34            3 :         return false;
      35              :     }
      36              : 
      37              :     // --- FIX 消息分架逻辑 ---
      38           12 :     const auto begin_string_pos = buffer_.find("8=FIX.4.0\x01");
      39           12 :     if (begin_string_pos == std::string::npos) {
      40              :         // 未找到有效的开头。为了防止缓冲增长,直接清空
      41              :         // 更健壮的实现也许会有不同策略
      42            1 :         buffer_.clear();
      43            1 :         return false;
      44              :     }
      45           11 :     if (begin_string_pos > 0) {
      46              :         // 丢弃消息开头前的无用数据
      47            1 :         buffer_.erase(0, begin_string_pos);
      48              :     }
      49              : 
      50           11 :     const auto body_length_tag_pos = buffer_.find("\x01""9=");
      51           11 :     if (body_length_tag_pos == std::string::npos) return false; // 未得到 BodyLength 标签所需的数据
      52              : 
      53           11 :     const auto body_length_val_pos = body_length_tag_pos + 3;
      54           11 :     const auto body_length_end_pos = buffer_.find('\x01', body_length_val_pos);
      55           11 :     if (body_length_end_pos == std::string::npos) return false; // BodyLength 值数据不足
      56              : 
      57           11 :     int body_length = 0;
      58              :     try {
      59           11 :         const std::string body_length_str = buffer_.substr(body_length_val_pos, body_length_end_pos - body_length_val_pos);
      60           11 :         body_length = std::stoi(body_length_str);
      61           10 :         if (body_length < 0 || static_cast<size_t>(body_length) > max_body_length_) { // 基本有效性检查
      62            2 :             throw std::runtime_error("Invalid BodyLength value");
      63              :         }
      64           14 :     } catch (const std::exception&) {
      65              :         // 如果 BodyLength 无效,这是一个严重的协议错误,我们应该丢弃缓冲区的数据以避免死循环
      66            3 :         buffer_.clear(); 
      67              :         // 也许应该向上层报告这个错误
      68            3 :         throw; 
      69            3 :     }
      70              :     
      71              :     // 计算总的预期消息长度
      72            8 :     const size_t soh_after_body_length_pos = body_length_end_pos + 1;
      73            8 :     const size_t total_msg_len = soh_after_body_length_pos + body_length + 7; // "10=NNN\x01" 为 7 个字符
      74              : 
      75            8 :     if (buffer_.size() < total_msg_len) {
      76              :         // 数据不足以形成完整消息
      77            2 :         return false;
      78              :     }
      79              : 
      80              :     // 已经抽出一个完整消息
      81            6 :     message = buffer_.substr(0, total_msg_len);
      82              :     
      83              :     // 从缓冲中移除已处理的消息
      84            6 :     buffer_.erase(0, total_msg_len);
      85              : 
      86            6 :     return true;
      87              : }
      88              : 
      89              : } // namespace fix40 
        

Generated by: LCOV version 2.0-1