LCOV - code coverage report
Current view: top level - include/fix - fix_messages.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.2 % 68 62
Test Date: 2025-12-19 03:13:09 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /**
       2              :  * @file fix_messages.hpp
       3              :  * @brief FIX 会话层消息工厂函数
       4              :  *
       5              :  * 提供创建标准 FIX 会话层消息的便捷函数,包括:
       6              :  * - Logon (A) - 登录
       7              :  * - Heartbeat (0) - 心跳
       8              :  * - TestRequest (1) - 测试请求
       9              :  * - Logout (5) - 登出
      10              :  */
      11              : 
      12              : #pragma once
      13              : 
      14              : #include "fix/fix_codec.hpp"
      15              : #include "fix/fix_tags.hpp"
      16              : #include "base/config.hpp"
      17              : 
      18              : namespace fix40 {
      19              : 
      20              : /**
      21              :  * @brief 创建 Logon 消息
      22              :  * @param sender 发送方 CompID
      23              :  * @param target 接收方 CompID
      24              :  * @param seq_num 消息序列号(默认为 1)
      25              :  * @param heart_bt 心跳间隔秒数(默认从配置读取)
      26              :  * @return FixMessage Logon 消息对象
      27              :  *
      28              :  * Logon 消息用于建立 FIX 会话,包含:
      29              :  * - MsgType (35) = "A"
      30              :  * - EncryptMethod (98) = "0" (无加密)
      31              :  * - HeartBtInt (108) = 心跳间隔
      32              :  */
      33          281 : inline FixMessage create_logon_message(const std::string& sender,
      34              :                                        const std::string& target,
      35              :                                        int seq_num = 1,
      36              :                                        int heart_bt = Config::instance().get_int("fix_session", "default_heartbeat_interval", 30),
      37              :                                        bool reset_seq_num = false) {
      38          281 :     FixMessage logon;
      39          562 :     logon.set(tags::MsgType, "A");
      40          281 :     logon.set(tags::EncryptMethod, "0");
      41          281 :     logon.set(tags::HeartBtInt, heart_bt);
      42          281 :     logon.set(tags::SenderCompID, sender);
      43          281 :     logon.set(tags::TargetCompID, target);
      44          281 :     logon.set(tags::MsgSeqNum, seq_num);
      45          281 :     if (reset_seq_num) {
      46           70 :         logon.set(tags::ResetSeqNumFlag, "Y");
      47              :     }
      48          281 :     return logon;
      49            0 : }
      50              : 
      51              : /**
      52              :  * @brief 创建 Heartbeat 消息
      53              :  * @param sender 发送方 CompID
      54              :  * @param target 接收方 CompID
      55              :  * @param seq_num 消息序列号
      56              :  * @param test_req_id TestReqID(响应 TestRequest 时填写,否则为空)
      57              :  * @return FixMessage Heartbeat 消息对象
      58              :  *
      59              :  * Heartbeat 消息用于:
      60              :  * 1. 定期发送以维持连接活跃
      61              :  * 2. 响应 TestRequest(此时需包含对应的 TestReqID)
      62              :  *
      63              :  * - MsgType (35) = "0"
      64              :  * - TestReqID (112) = 可选
      65              :  */
      66           14 : inline FixMessage create_heartbeat_message(const std::string& sender,
      67              :                                            const std::string& target,
      68              :                                            int seq_num,
      69              :                                            const std::string& test_req_id = "") {
      70           14 :     FixMessage hb;
      71           14 :     hb.set(tags::MsgType, "0");
      72           14 :     hb.set(tags::SenderCompID, sender);
      73           14 :     hb.set(tags::TargetCompID, target);
      74           14 :     hb.set(tags::MsgSeqNum, seq_num);
      75              : 
      76           14 :     if (!test_req_id.empty()) {
      77            4 :         hb.set(tags::TestReqID, test_req_id);
      78              :     }
      79              : 
      80           14 :     return hb;
      81            0 : }
      82              : 
      83              : /**
      84              :  * @brief 创建 TestRequest 消息
      85              :  * @param sender 发送方 CompID
      86              :  * @param target 接收方 CompID
      87              :  * @param seq_num 消息序列号
      88              :  * @param test_req_id 测试请求标识符(必填,对方需在 Heartbeat 中回传)
      89              :  * @return FixMessage TestRequest 消息对象
      90              :  *
      91              :  * TestRequest 消息用于检测对端是否存活。
      92              :  * 对端收到后应回复包含相同 TestReqID 的 Heartbeat。
      93              :  *
      94              :  * - MsgType (35) = "1"
      95              :  * - TestReqID (112) = 必填
      96              :  */
      97            3 : inline FixMessage create_test_request_message(const std::string& sender,
      98              :                                               const std::string& target,
      99              :                                               int seq_num,
     100              :                                               const std::string& test_req_id) {
     101            3 :     FixMessage tr;
     102            3 :     tr.set(tags::MsgType, "1");
     103            3 :     tr.set(tags::SenderCompID, sender);
     104            3 :     tr.set(tags::TargetCompID, target);
     105            3 :     tr.set(tags::MsgSeqNum, seq_num);
     106            3 :     tr.set(tags::TestReqID, test_req_id);
     107            3 :     return tr;
     108            0 : }
     109              : 
     110              : /**
     111              :  * @brief 创建 Logout 消息
     112              :  * @param sender 发送方 CompID
     113              :  * @param target 接收方 CompID
     114              :  * @param seq_num 消息序列号
     115              :  * @param text 登出原因(可选)
     116              :  * @return FixMessage Logout 消息对象
     117              :  *
     118              :  * Logout 消息用于优雅地终止 FIX 会话。
     119              :  * 发起方发送 Logout 后等待对方确认,然后关闭连接。
     120              :  *
     121              :  * - MsgType (35) = "5"
     122              :  * - Text (58) = 可选,说明登出原因
     123              :  */
     124           11 : inline FixMessage create_logout_message(const std::string& sender,
     125              :                                         const std::string& target,
     126              :                                         int seq_num,
     127              :                                         const std::string& text = "") {
     128           11 :     FixMessage lo;
     129           11 :     lo.set(tags::MsgType, "5");
     130           11 :     lo.set(tags::SenderCompID, sender);
     131           11 :     lo.set(tags::TargetCompID, target);
     132           11 :     lo.set(tags::MsgSeqNum, seq_num);
     133           11 :     if (!text.empty()) {
     134           10 :         lo.set(tags::Text, text);
     135              :     }
     136           11 :     return lo;
     137            0 : }
     138              : 
     139              : /**
     140              :  * @brief 创建 ResendRequest 消息
     141              :  * @param sender 发送方 CompID
     142              :  * @param target 接收方 CompID
     143              :  * @param seq_num 消息序列号
     144              :  * @param begin_seq_no 请求重传的起始序列号
     145              :  * @param end_seq_no 请求重传的结束序列号(0 表示到最新)
     146              :  * @return FixMessage ResendRequest 消息对象
     147              :  *
     148              :  * ResendRequest 消息用于请求对方重传指定范围的消息。
     149              :  * 当检测到序列号 gap 时发送此消息。
     150              :  *
     151              :  * - MsgType (35) = "2"
     152              :  * - BeginSeqNo (7) = 起始序列号
     153              :  * - EndSeqNo (16) = 结束序列号(0 表示无限)
     154              :  */
     155            3 : inline FixMessage create_resend_request_message(const std::string& sender,
     156              :                                                  const std::string& target,
     157              :                                                  int seq_num,
     158              :                                                  int begin_seq_no,
     159              :                                                  int end_seq_no) {
     160            3 :     FixMessage rr;
     161            3 :     rr.set(tags::MsgType, "2");
     162            3 :     rr.set(tags::SenderCompID, sender);
     163            3 :     rr.set(tags::TargetCompID, target);
     164            3 :     rr.set(tags::MsgSeqNum, seq_num);
     165            3 :     rr.set(tags::BeginSeqNo, begin_seq_no);
     166            3 :     rr.set(tags::EndSeqNo, end_seq_no);
     167            3 :     return rr;
     168            0 : }
     169              : 
     170              : /**
     171              :  * @brief 创建 SequenceReset 消息
     172              :  * @param sender 发送方 CompID
     173              :  * @param target 接收方 CompID
     174              :  * @param seq_num 消息序列号
     175              :  * @param new_seq_no 新的序列号
     176              :  * @param gap_fill 是否为 GapFill 模式
     177              :  * @return FixMessage SequenceReset 消息对象
     178              :  *
     179              :  * SequenceReset 消息用于:
     180              :  * 1. GapFill 模式:跳过管理消息(如 Heartbeat、TestRequest)
     181              :  * 2. Reset 模式:重置序列号(通常在会话重置时使用)
     182              :  *
     183              :  * - MsgType (35) = "4"
     184              :  * - NewSeqNo (36) = 新序列号
     185              :  * - GapFillFlag (123) = Y/N
     186              :  */
     187            2 : inline FixMessage create_sequence_reset_message(const std::string& sender,
     188              :                                                  const std::string& target,
     189              :                                                  int seq_num,
     190              :                                                  int new_seq_no,
     191              :                                                  bool gap_fill = true) {
     192            2 :     FixMessage sr;
     193            2 :     sr.set(tags::MsgType, "4");
     194            2 :     sr.set(tags::SenderCompID, sender);
     195            2 :     sr.set(tags::TargetCompID, target);
     196            2 :     sr.set(tags::MsgSeqNum, seq_num);
     197            2 :     sr.set(tags::NewSeqNo, new_seq_no);
     198            2 :     sr.set(tags::GapFillFlag, gap_fill ? "Y" : "N");
     199            2 :     return sr;
     200            0 : }
     201              : 
     202              : /**
     203              :  * @brief 判断消息类型是否为管理消息
     204              :  * @param msg_type 消息类型
     205              :  * @return true 如果是管理消息(Heartbeat、TestRequest、ResendRequest、SequenceReset、Logout、Logon)
     206              :  *
     207              :  * 管理消息在重传时应使用 SequenceReset-GapFill 跳过,而不是重新发送。
     208              :  */
     209           10 : inline bool is_admin_message(const std::string& msg_type) {
     210           10 :     return msg_type == "0" ||  // Heartbeat
     211            9 :            msg_type == "1" ||  // TestRequest
     212            8 :            msg_type == "2" ||  // ResendRequest
     213            7 :            msg_type == "4" ||  // SequenceReset
     214           24 :            msg_type == "5" ||  // Logout
     215           15 :            msg_type == "A";    // Logon
     216              : }
     217              : 
     218              : } // namespace fix40
        

Generated by: LCOV version 2.0-1