10 #include <type_traits>
16 #include <unordered_map>
18 #include "core/compiler/hints_hot_code.h"
19 #include "core/compiler/hints_branch_predictor.h"
21 #include "core/os/vdso.h"
23 #include "core/utilities/logger.h"
24 #include "core/utilities/object_cache.h"
25 #include "core/utilities/spsc_bounded_queue.h"
26 #include "core/utilities/std_string_utilities.h"
27 #include "core/utilities/configuration.h"
28 #include "core/utilities/userspace_spinlock.h"
30 #include "electronic_trading/common/message_serialiser.h"
32 #include "electronic_trading/session/session_state.h"
33 #include "electronic_trading/session/sequence_store.h"
34 #include "electronic_trading/session/session_schedule_validator.h"
35 #include "electronic_trading/session/throttler.h"
37 #include "electronic_trading/managed_instance/managed_instance_session.h"
38 #include "electronic_trading/managed_instance/modifying_admin_command.h"
40 #include "fix_constants.h"
41 #include "fix_string.h"
42 #include "fix_string_view.h"
43 #include "fix_utilities.h"
44 #include "fix_session_settings.h"
45 #include "fix_parser_error_codes.h"
46 #include "incoming_fix_repeating_group_specs.h"
47 #include "incoming_fix_message.h"
48 #include "outgoing_fix_message.h"
50 #ifdef LLFIX_ENABLE_DICTIONARY // VOLTRON_EXCLUDE
51 #include "fix_dictionary.h"
52 #include "fix_dictionary_loader.h"
53 #include "fix_dictionary_validator.h"
54 #endif // VOLTRON_EXCLUDE
56 #ifdef LLFIX_ENABLE_BINARY_FIELDS // VOLTRON_EXCLUDE
57 #include "incoming_fix_binary_field_specs.h"
58 #endif // VOLTRON_EXCLUDE
63 using MessageSerialiserType = MessageSerialiser<FixMessageSequenceNumberExtractor>;
81 m_sequence_store.save_to_disc();
83 if (m_tx_encode_buffer)
85 Allocator::deallocate(m_tx_encode_buffer, m_settings.tx_encode_buffer_capacity);
86 m_tx_encode_buffer =
nullptr;
90 bool initialise(
const std::string& name,
const FixSessionSettings& settings)
95 if(m_name.length()==0)
97 LLFIX_LOG_ERROR(
"Session names can't be empty");
101 if(m_name.length()>32)
103 LLFIX_LOG_ERROR(
"Session names can have max 32 characters. Failed name : " + m_name);
107 if (settings.validate() ==
false)
109 LLFIX_LOG_ERROR(
"FixSessionSettings for session " + m_name +
" validation failed : " + settings.validation_error);
115 m_settings = settings;
117 m_incoming_throttler_exceed_count = 0;
119 set_state(SessionState::DISCONNECTED);
121 if (m_settings.schedule_week_days.length() > 0) m_schedule_validator.add_allowed_weekdays_from_dash_separated_string(m_settings.schedule_week_days);
122 m_schedule_validator.set_start_and_end_times(m_settings.start_hour_utc, m_settings.start_minute_utc, m_settings.end_hour_utc, m_settings.end_minute_utc);
124 if (m_admin_commands.create(128) ==
false)
126 LLFIX_LOG_ERROR(
"Failed to create admin commands queue for session " + m_name);
130 if(m_settings.throttle_limit>0)
132 if (m_throttler.initialise(m_settings.throttle_window_in_milliseconds * 1
'000'000, m_settings.throttle_limit) ==
false)
134 LLFIX_LOG_ERROR(
"Session " + m_name +
" : failed to initialise throttler. Check the throttle_limit config.");
139 if (open_or_create_sequence_store(m_settings.sequence_store_file_path) ==
false)
141 LLFIX_LOG_ERROR(
"Session " + m_name +
" : failed to initialise sequence store. Check the sequence_store_file_path config.");
145 if(m_settings.max_serialised_file_size > 0)
147 if (m_incoming_messages_serialiser.initialise(m_settings.incoming_message_serialisation_path, m_settings.max_serialised_file_size,
false) ==
false)
149 LLFIX_LOG_ERROR(
"Session " + m_name +
" : failed to initialise incoming message serialiser. Check serialisation path and serialised file max size configs.");
153 if (m_outgoing_messages_serialiser.initialise(m_settings.outgoing_message_serialisation_path, m_settings.max_serialised_file_size, m_settings.replay_messages_on_incoming_resend_request, m_settings.replay_message_cache_initial_size) ==
false)
155 LLFIX_LOG_ERROR(
"Session " + m_name +
" : failed to initialise incoming message serialiser. Check serialisation path and serialised file max size configs.");
162 LLFIX_LOG_ERROR(
"Session " + m_name +
" : OutgoingFixMessage creation failed.");
166 if (m_incoming_fix_message.initialise() ==
false)
168 LLFIX_LOG_ERROR(
"Session " + m_name +
" : IncomingFixMessage creation failed.");
172 if (m_fix_string_view_cache.create(1024) ==
false)
174 LLFIX_LOG_ERROR(
"Session " + m_name +
" : FixStringView cache creation failed.");
178 m_tx_encode_buffer =
reinterpret_cast<char*
>(Allocator::allocate(m_settings.tx_encode_buffer_capacity));
180 if (m_tx_encode_buffer ==
nullptr)
182 LLFIX_LOG_ERROR(
"Session " + m_name +
" : TX encode buffer allocation failed");
186 catch (
const std::bad_alloc&)
188 LLFIX_LOG_FATAL(
"Session " + m_name +
" : Insufficient memory.");
194 if (m_settings.additional_static_header_tags.length() > 0)
196 auto tag_value_pairs = StringUtilities::split(m_settings.additional_static_header_tags,
',');
198 for (
auto pair : tag_value_pairs)
200 auto tokens = StringUtilities::split(pair,
'=');
202 if (tokens.size() != 2)
204 LLFIX_LOG_ERROR(
"Invalid FixSession config value for 'additional_static_header_tags' : " + m_settings.additional_static_header_tags);
208 int tag = std::stoi(tokens[0]);
212 LLFIX_LOG_ERROR(
"Invalid FixSession config value for 'additional_static_header_tags' : " + m_settings.additional_static_header_tags +
" , tag numbers must be positive integers.");
216 m_outgoing_fix_message.set_additional_static_header_tag(
static_cast<uint32_t
>(tag), tokens[1]);
222 LLFIX_LOG_ERROR(
"Session " + m_name +
" : failed to initialise, check config value for 'additional_static_header_tags'.");
226 #ifdef LLFIX_ENABLE_DICTIONARY
227 bool dictionary_load_success =
false;
231 dictionary_load_success = initialise_dictionary_validator();
236 if(dictionary_load_success==
false)
238 LLFIX_LOG_ERROR(
"Session " + m_name +
" : dictionary loading failed.");
243 LLFIX_LOG_INFO(
"Session " + m_name +
" : session config loaded =>\n" + m_settings.to_string());
256 std::string
get_name()
const override {
return m_name; }
258 FixSessionSettings* settings() {
return &m_settings; }
260 std::string get_display_text()
const
262 std::stringstream ret;
264 ret <<
"Session state : " << convert_session_state_to_string(
static_cast<SessionState
>(m_state.load())) <<
'\n';
274 void set_state(SessionState state)
276 m_state =
static_cast<int>(state);
323 return static_cast<SessionState
>(m_state.load());
328 bool open_or_create_sequence_store(
const std::string_view& path)
330 return m_sequence_store.open(path);
343 return &m_sequence_store;
346 uint32_t get_last_processed_sequence_number()
const {
return m_sequence_store.
get_incoming_seq_no(); }
350 Throttler* throttler() {
return &m_throttler; }
352 uint32_t get_incoming_throttler_exceed_count()
const {
return m_incoming_throttler_exceed_count; }
353 void increment_incoming_throttler_exceed_count() { m_incoming_throttler_exceed_count++; }
357 MessageSerialiserType* get_incoming_message_serialiser() {
return &m_incoming_messages_serialiser; }
358 MessageSerialiserType* get_outgoing_message_serialiser() {
return &m_outgoing_messages_serialiser; }
359 bool serialisation_enabled()
const {
return m_settings.max_serialised_file_size>0; }
360 void reinitialise_outgoing_serialiser() { m_outgoing_messages_serialiser.initialise(m_settings.outgoing_message_serialisation_path, m_settings.max_serialised_file_size, m_settings.replay_messages_on_incoming_resend_request, m_settings.replay_message_cache_initial_size); }
364 bool expecting_response_for_outgoing_test_request()
const {
return m_expecting_response_for_outgoing_test_request; }
365 void set_expecting_response_for_outgoing_test_request(
bool b) { m_expecting_response_for_outgoing_test_request =b; }
367 uint64_t outgoing_test_request_timestamp_nanoseconds()
const {
return m_outgoing_test_request_timestamp_nanoseconds; }
368 void set_outgoing_test_request_timestamp_nanoseconds(uint64_t val) { m_outgoing_test_request_timestamp_nanoseconds = val; }
372 bool needs_to_send_resend_request()
const {
return m_needs_to_send_resend_request; }
373 void set_needs_to_send_resend_request(
bool b) { m_needs_to_send_resend_request = b; }
375 uint32_t get_outgoing_resend_request_begin_no()
const {
return m_outgoing_resend_request_begin_no; }
376 uint32_t get_outgoing_resend_request_end_no()
const {
return m_outgoing_resend_request_end_no; }
378 void queue_outgoing_resend_request(uint32_t sequence_store_incoming_seq_no, uint32_t live_incoming_seq_no)
380 m_needs_to_send_resend_request =
true;
382 m_outgoing_resend_request_begin_no = sequence_store_incoming_seq_no;
383 m_outgoing_resend_request_end_no = live_incoming_seq_no;
386 uint64_t outgoing_resend_request_timestamp_nanoseconds()
const {
return m_outgoing_resend_request_timestamp_nanoseconds; }
387 void set_outgoing_resend_request_timestamp_nanoseconds(uint64_t val) { m_outgoing_resend_request_timestamp_nanoseconds = val; }
391 bool needs_responding_to_incoming_resend_request()
const {
return m_needs_responding_to_incoming_resend_request; }
392 void set_needs_responding_to_incoming_resend_request(
bool b) { m_needs_responding_to_incoming_resend_request = b; }
394 uint32_t get_incoming_resend_request_begin_no()
const {
return m_incoming_resend_request_begin_no; }
395 uint32_t get_incoming_resend_request_end_no()
const {
return m_incoming_resend_request_end_no; }
399 bool needs_responding_to_incoming_test_request()
const {
return m_needs_responding_to_incoming_test_request; }
400 void set_needs_responding_to_incoming_test_request(
bool b) { m_needs_responding_to_incoming_test_request = b; }
402 FixString* get_incoming_test_request_id() {
return &m_incoming_test_request_id; }
406 bool received_logout_response()
const {
return m_received_logout_response; }
407 void set_received_logout_response(
bool b) { m_received_logout_response = b; }
411 uint64_t last_received_message_timestamp_nanoseconds()
const {
return m_last_received_message_timestamp_nanoseconds; }
412 void set_last_received_message_timestamp_nanoseconds(uint64_t val) { m_last_received_message_timestamp_nanoseconds = val; }
414 uint64_t last_sent_message_timestamp_nanoseconds()
const {
return m_last_sent_message_timestamp_nanoseconds; }
415 void set_last_sent_message_timestamp_nanoseconds(uint64_t val) { m_last_sent_message_timestamp_nanoseconds = val; }
436 template <
typename T>
443 if constexpr (std::is_same_v<T, std::string>)
445 m_attributes.add_attribute(attribute, value);
447 else if constexpr (std::is_arithmetic_v<T>)
449 m_attributes.add_attribute(attribute, std::to_string(value));
453 std::ostringstream oss;
455 m_attributes.add_attribute(attribute, oss.str());
478 if(m_attributes.does_attribute_exist(attribute))
480 value = m_attributes.get_string_value(attribute);
489 uint64_t get_heartbeart_interval_in_nanoseconds()
const {
return m_settings.heartbeat_interval_in_nanoseconds; }
491 uint64_t get_outgoing_test_request_interval_in_nanoseconds()
const
493 return m_settings.outgoing_test_request_interval_in_nanoseconds;
496 bool enable_simd_avx2()
const {
return m_settings.enable_simd_avx2; }
497 VDSO::SubsecondPrecision get_timestamp_subsecond_precision()
const {
return m_settings.timestamp_subseconds_precision; }
499 void set_heartbeart_interval_in_nanoseconds(uint64_t value)
501 m_settings.heartbeat_interval_in_nanoseconds = value;
504 void set_outgoing_test_request_interval_in_nanoseconds(uint64_t value)
506 m_settings.outgoing_test_request_interval_in_nanoseconds = value;
509 void set_enable_simd_avx2(
bool b) { m_settings.enable_simd_avx2 = b; }
511 int get_protocol_version()
const {
return m_settings.protocol_version; }
515 const std::string& get_begin_string()
const {
return m_settings.begin_string; }
516 const std::string& get_compid()
const {
return m_settings.sender_comp_id; }
517 const std::string& get_target_compid()
const {
return m_settings.target_comp_id; }
518 bool include_last_processed_seqnum_in_header()
const {
return m_settings.include_last_processed_seqnum_in_header; }
520 void set_begin_string(
const std::string& str) { m_settings.begin_string = str; }
521 void set_compid(
const std::string_view& identifier) { m_settings.sender_comp_id = identifier; }
522 void set_target_compid(
const std::string_view& identifier) { m_settings.target_comp_id = identifier; }
526 const std::string& get_default_app_ver_id()
const {
return m_settings.default_app_ver_id; }
527 const std::string& get_username()
const {
return m_settings.logon_username; }
528 const std::string& get_password()
const {
return m_settings.logon_password; }
529 std::string logon_message_new_password()
const {
return m_settings.logon_message_new_password; }
530 bool logon_reset_sequence_numbers_flag()
const {
return m_settings.logon_reset_sequence_numbers; }
531 bool logon_include_next_expected_seq_no()
const {
return m_settings.logon_include_next_expected_seq_no; }
535 bool validations_enabled()
const {
return m_settings.validations_enabled; }
536 void set_validations_enabled(
bool b) { m_settings.validations_enabled = b; }
538 bool validate_repeating_groups_enabled()
const {
return m_settings.validate_repeating_groups; }
539 void set_validate_repeating_groups_enabled(
bool b) { m_settings.validate_repeating_groups = b; }
543 bool replay_messages_on_incoming_resend_request()
const {
return m_settings.replay_messages_on_incoming_resend_request; }
544 bool include_t97_during_resends()
const {
return m_settings.include_t97_during_resends; }
545 std::size_t max_resend_range()
const {
return m_settings.max_resend_range; }
546 void set_replay_messages_on_incoming_resend_request (
bool b) { m_settings.replay_messages_on_incoming_resend_request=b; }
550 int outgoing_resend_request_expire_secs()
const {
return m_settings.outgoing_resend_request_expire_in_secs; }
554 void build_heartbeat_message(OutgoingFixMessage* message, FixString* test_request_id)
556 message->set_msg_type(FixConstants::MSG_TYPE_HEARTBEAT);
558 if (test_request_id !=
nullptr)
560 message->set_tag(FixConstants::TAG_TEST_REQ_ID, test_request_id);
564 void build_test_request_message(OutgoingFixMessage* message)
566 message->set_msg_type(FixConstants::MSG_TYPE_TEST_REQUEST);
567 m_outgoing_test_request_id++;
568 message->set_tag(FixConstants::TAG_TEST_REQ_ID, m_outgoing_test_request_id);
571 void build_resend_request_message(OutgoingFixMessage* message,
const std::string& end_no)
573 message->set_msg_type(FixConstants::MSG_TYPE_RESEND_REQUEST);
574 message->set_tag(FixConstants::TAG_BEGIN_SEQ_NO, m_outgoing_resend_request_begin_no);
575 message->set_tag(FixConstants::TAG_END_SEQ_NO, end_no);
578 void build_logout_message(OutgoingFixMessage* message,
const std::string& reason_text =
"")
580 message->set_msg_type(FixConstants::MSG_TYPE_LOGOUT);
582 if (reason_text.length() > 0)
584 message->set_tag(FixConstants::TAG_TEXT, reason_text);
588 void build_session_level_reject_message(OutgoingFixMessage* message, uint32_t reject_reason_code,
const char* reject_reason_text, uint32_t error_tag=0)
590 message->set_msg_type(FixConstants::MSG_TYPE_REJECT);
592 if (m_incoming_fix_message.
has_tag(FixConstants::TAG_MSG_SEQ_NUM))
594 message->set_tag(FixConstants::TAG_REF_SEQ_NUM, m_incoming_fix_message.
get_tag_value_as<uint32_t>(FixConstants::TAG_MSG_SEQ_NUM));
599 message->set_tag(FixConstants::TAG_REF_TAG, error_tag);
602 if (m_incoming_fix_message.
has_tag(FixConstants::TAG_MSG_TYPE))
604 message->set_tag(FixConstants::TAG_REF_MSG_TYPE, m_incoming_fix_message.
get_tag_value_as<std::string>(FixConstants::TAG_MSG_TYPE));
607 message->set_tag(FixConstants::TAG_SESSION_REJECT_REASON, reject_reason_code);
608 message->set_tag(FixConstants::TAG_TEXT, reject_reason_text);
611 void build_gap_fill_message(OutgoingFixMessage* message)
613 message->set_msg_type(FixConstants::MSG_TYPE_SEQUENCE_RESET);
620 message->set_tag(FixConstants::TAG_NEW_SEQ_NO, next_outgoing_sequence_no);
623 message->set_tag(FixConstants::TAG_GAP_FILL_FLAG, FixConstants::FIX_BOOLEAN_TRUE);
626 void build_sequence_reset_message(OutgoingFixMessage* message, uint32_t desired_sequence_no)
631 message->set_msg_type(FixConstants::MSG_TYPE_SEQUENCE_RESET);
634 message->set_tag(FixConstants::TAG_NEW_SEQ_NO, desired_sequence_no + 1);
639 bool process_incoming_sequence_reset_message(
const IncomingFixMessage& message)
643 if (message.has_tag(FixConstants::TAG_NEW_SEQ_NO))
645 if (message.is_tag_value_numeric(FixConstants::TAG_NEW_SEQ_NO))
647 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming sequence reset message tag36(new seq no) : " + message.get_tag_value_as<std::string>(FixConstants::TAG_NEW_SEQ_NO));
649 auto new_incoming_seq_no = message.get_tag_value_as<uint32_t>(FixConstants::TAG_NEW_SEQ_NO);
651 if(new_incoming_seq_no==0)
653 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : received invalid new tag sequence number(0) for sequence reset.");
659 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : the sequence reset can only increase the sequence number.");
664 set_state(SessionState::LOGGED_ON);
668 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming sequence reset message has invalid tag36(new seq no).");
673 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming sequence reset message does not have tag36(new seq no).");
679 void process_resend_request(
const IncomingFixMessage& message)
681 if (message.has_tag(FixConstants::TAG_BEGIN_SEQ_NO) && message.has_tag(FixConstants::TAG_END_SEQ_NO))
683 bool is_tag_7_numeric = message.is_tag_value_numeric(FixConstants::TAG_BEGIN_SEQ_NO);
684 bool is_tag_16_numeric = message.is_tag_value_numeric(FixConstants::TAG_END_SEQ_NO);
686 if (is_tag_7_numeric && is_tag_16_numeric)
688 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming resend request tag7(begin seq no) : " + message.get_tag_value_as<std::string>(FixConstants::TAG_BEGIN_SEQ_NO) +
" tag16(end seq no) : " + message.get_tag_value_as<std::string>(FixConstants::TAG_END_SEQ_NO));
690 set_state(llfix::SessionState::IN_RETRANSMISSION_INITIATED_BY_PEER);
692 m_incoming_resend_request_begin_no = message.get_tag_value_as<uint32_t>(FixConstants::TAG_BEGIN_SEQ_NO);
694 m_incoming_resend_request_end_no = message.get_tag_value_as<uint32_t>(FixConstants::TAG_END_SEQ_NO);
696 m_needs_responding_to_incoming_resend_request =
true;
700 if (is_tag_7_numeric ==
false)
702 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming resend request message has invalid tag7(begin seq no).");
705 if (is_tag_16_numeric ==
false)
707 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming resend request message has invalid tag16(end seq no).");
713 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming resend request message does not have one or both of tag7(begin seq no) and tag16(end seq no).");
717 void process_test_request_message(
const IncomingFixMessage& message)
719 LLFIX_LOG_DEBUG(
"Session " + m_name +
" : incoming test request");
721 if (m_expecting_response_for_outgoing_test_request ==
false)
723 m_needs_responding_to_incoming_test_request =
true;
725 if (message.has_tag(FixConstants::TAG_TEST_REQ_ID))
727 auto test_request_id = message.get_tag_value(FixConstants::TAG_TEST_REQ_ID);
728 m_incoming_test_request_id.copy_from(test_request_id->data(), test_request_id->length());
735 bool is_now_valid_session_datetime()
const
737 return m_schedule_validator.is_now_valid_datetime();
740 static void validate_header_tags_order(uint32_t tag, uint32_t tag_index, uint32_t& parser_reject_code)
746 if (llfix_unlikely(tag != FixConstants::TAG_BEGIN_STRING))
748 parser_reject_code = FixParserErrorCodes::OUT_OF_ORDER_HEADER_FIELDS;
751 else if (tag_index == 2)
753 if (llfix_unlikely(tag != FixConstants::TAG_BODY_LENGTH))
755 parser_reject_code = FixParserErrorCodes::OUT_OF_ORDER_HEADER_FIELDS;
758 else if (tag_index == 3)
760 if (llfix_unlikely(tag != FixConstants::TAG_MSG_TYPE))
762 parser_reject_code = FixParserErrorCodes::OUT_OF_ORDER_HEADER_FIELDS;
768 static void validate_tag_format(
const char* buffer, std::size_t buffer_len,
bool& is_numeric, uint32_t& parser_reject_code)
770 if (llfix_unlikely(buffer_len == 0 || buffer_len>10))
772 parser_reject_code = FixConstants::FIX_ERROR_CODE_INVALID_TAG_NUMBER;
777 for (std::size_t i = 0; i < buffer_len; i++)
781 if (llfix_unlikely(c < '0' || c >
'9'))
783 parser_reject_code = FixConstants::FIX_ERROR_CODE_INVALID_TAG_NUMBER;
790 static void validate_tag9_and_tag35(IncomingFixMessage* incoming_message,
int tag_10_start_index,
int tag_35_tag_start_index, uint32_t& parser_reject_code)
792 if (llfix_likely(tag_35_tag_start_index != -1))
794 if (llfix_likely(incoming_message->has_tag(FixConstants::TAG_BODY_LENGTH)))
796 if (llfix_likely(incoming_message->is_tag_value_numeric(FixConstants::TAG_BODY_LENGTH)))
798 auto msg_body_len_val = incoming_message->get_tag_value_as<uint32_t>(FixConstants::TAG_BODY_LENGTH);
800 if (llfix_unlikely(
static_cast<int>(msg_body_len_val) != (tag_10_start_index - tag_35_tag_start_index)))
802 parser_reject_code = FixParserErrorCodes::WRONG_BODY_LENGTH;
807 parser_reject_code = FixParserErrorCodes::INVALID_TAG_9;
812 parser_reject_code = FixParserErrorCodes::NO_TAG_9;
817 parser_reject_code = FixParserErrorCodes::NO_TAG_35;
821 bool validate_fix_message(
const IncomingFixMessage& incoming_message,
const char* buffer_message, std::size_t buffer_message_length, uint32_t reject_reason_code, uint32_t& out_reject_message_code)
824 if (incoming_message.has_tag(FixConstants::TAG_MSG_SEQ_NUM) ==
false)
826 set_last_error_tag(0);
827 LLFIX_LOG_DEBUG(
"Session " + m_name +
" received a message with no tag34(sequence number) : " +
FixUtilities::fix_to_human_readible(buffer_message, buffer_message_length));
832 if (incoming_message.is_tag_value_numeric(FixConstants::TAG_MSG_SEQ_NUM) ==
false)
834 set_last_error_tag(0);
835 LLFIX_LOG_DEBUG(
"Session " + m_name +
" received a message with invalid tag34(sequence number) : " +
FixUtilities::fix_to_human_readible(buffer_message, buffer_message_length));
840 if (llfix_unlikely(reject_reason_code !=
static_cast<uint32_t
>(-1)))
842 set_last_error_tag(0);
844 if (reject_reason_code > FixConstants::FIX_MAX_ERROR_CODE)
846 std::string log_message =
"Session " + m_name +
" " + FixParserErrorCodes::get_internal_parser_error_description(reject_reason_code) +
" : " +
FixUtilities::fix_to_human_readible(buffer_message, buffer_message_length);
847 LLFIX_LOG_DEBUG(log_message);
851 out_reject_message_code = reject_reason_code;
858 if (incoming_message.has_tag(FixConstants::TAG_BEGIN_STRING) ==
false)
860 set_last_error_tag(0);
866 if (!incoming_message.get_tag_value(FixConstants::TAG_BEGIN_STRING)->equals(m_settings.begin_string.c_str()))
868 set_last_error_tag(0);
874 if (incoming_message.has_tag(FixConstants::TAG_SENDER_COMP_ID) ==
false)
876 set_last_error_tag(0);
882 if (!incoming_message.get_tag_value(FixConstants::TAG_SENDER_COMP_ID)->equals(m_settings.target_comp_id.c_str()))
884 set_last_error_tag(0);
885 out_reject_message_code = FixConstants::FIX_ERROR_CODE_COMPID_PROBLEM;
890 if (incoming_message.has_tag(FixConstants::TAG_TARGET_COMP_ID) ==
false)
892 set_last_error_tag(0);
898 if (!incoming_message.get_tag_value(FixConstants::TAG_TARGET_COMP_ID)->equals(m_settings.sender_comp_id.c_str()))
900 set_last_error_tag(0);
901 out_reject_message_code = FixConstants::FIX_ERROR_CODE_COMPID_PROBLEM;
906 if (incoming_message.is_tag_value_numeric(FixConstants::TAG_CHECKSUM) ==
false)
908 set_last_error_tag(0);
914 const uint32_t actual_checksum = incoming_message.get_tag_value_as<uint32_t>(FixConstants::TAG_CHECKSUM);
916 if (m_settings.enable_simd_avx2)
918 if (FixUtilities::validate_checksum_simd_avx2(buffer_message, buffer_message_length - 7, actual_checksum) ==
false)
920 set_last_error_tag(0);
927 if (FixUtilities::validate_checksum_no_simd(buffer_message, buffer_message_length - 7, actual_checksum) ==
false)
929 set_last_error_tag(0);
936 if (incoming_message.has_tag(FixConstants::TAG_SENDING_TIME) ==
false)
938 set_last_error_tag(0);
944 if(m_settings.max_allowed_message_age_seconds > 0)
946 auto sending_time = incoming_message.get_tag_value(FixConstants::TAG_SENDING_TIME);
948 if(sending_time->is_timestamp() ==
false)
950 set_last_error_tag(FixConstants::TAG_SENDING_TIME);
951 out_reject_message_code = FixConstants::FIX_ERROR_CODE_FORMAT_INCORRECT_FOR_TAG;
956 if(FixUtilities::is_utc_timestamp_stale(sending_time->to_string_view(),
static_cast<int>(m_settings.max_allowed_message_age_seconds)))
958 set_last_error_tag(0);
959 out_reject_message_code = FixConstants::FIX_ERROR_CODE_SENDING_TIME_ACCURACY_PROBLEM;
965 #ifdef LLFIX_ENABLE_DICTIONARY
967 if (m_settings.dictionary_validations_enabled ==
true)
969 if (m_validator_id >= 0)
971 if (get_validator(m_validator_id).validate(m_incoming_fix_message, out_reject_message_code) ==
false)
973 set_last_error_tag(get_validator(m_validator_id).get_last_error_tag());
978 if (validate_repeating_groups_enabled())
980 if (get_validator(m_validator_id).validate_repeating_groups(m_incoming_fix_message, out_reject_message_code) ==
false)
982 set_last_error_tag(get_validator(m_validator_id).get_last_error_tag());
993 uint32_t get_last_error_tag()
const {
return m_last_error_tag; }
997 IncomingFixMessage* get_incoming_fix_message() {
return &m_incoming_fix_message; }
998 OutgoingFixMessage* get_outgoing_fix_message() {
return &m_outgoing_fix_message; }
1000 ObjectCache<FixStringView>* get_fix_string_view_cache() {
return &m_fix_string_view_cache; }
1001 char* get_tx_encode_buffer() {
return m_tx_encode_buffer; }
1002 SPSCBoundedQueue<ModifyingAdminCommand*>* get_admin_commands() {
return &m_admin_commands; }
1006 m_needs_responding_to_incoming_test_request =
false;
1007 m_expecting_response_for_outgoing_test_request =
false;
1008 m_needs_responding_to_incoming_resend_request =
false;
1009 m_needs_to_send_resend_request =
false;
1010 m_received_logout_response =
false;
1012 m_incoming_throttler_exceed_count = 0;
1015 static bool is_a_hard_sequence_reset_message(
const IncomingFixMessage& message)
1017 if (message.has_tag(FixConstants::TAG_MSG_TYPE) ==
false)
1022 if (message.get_tag_value_as<
char>(FixConstants::TAG_MSG_TYPE) != FixConstants::MSG_TYPE_SEQUENCE_RESET)
1027 if (message.has_tag(FixConstants::TAG_GAP_FILL_FLAG))
1029 if (message.get_tag_value_as<
char>(FixConstants::TAG_GAP_FILL_FLAG) == FixConstants::FIX_BOOLEAN_TRUE)
1054 static IncomingFixRepeatingGroupSpecs& get_repeating_group_specs()
1056 return m_repeating_group_specs;
1059 #ifdef LLFIX_ENABLE_DICTIONARY
1060 LLFIX_FORCE_INLINE
static FixDictionaryValidator::Validator& get_validator(uint32_t validator_id)
1062 assert(m_validators.find(validator_id) != m_validators.end());
1063 return m_validators[validator_id];
1067 #ifdef LLFIX_ENABLE_BINARY_FIELDS
1068 static IncomingFixBinaryFieldSpecs& get_binary_field_specs()
1070 return m_binary_field_specs;
1075 std::atomic<int> m_state =
static_cast<int>(SessionState::NONE);
1077 SequenceStore m_sequence_store;
1078 Throttler m_throttler;
1079 MessageSerialiserType m_outgoing_messages_serialiser;
1080 MessageSerialiserType m_incoming_messages_serialiser;
1081 Configuration m_attributes;
1083 FixSessionSettings m_settings;
1085 uint64_t m_last_sent_message_timestamp_nanoseconds = 0;
1086 uint64_t m_last_received_message_timestamp_nanoseconds = 0;
1087 uint32_t m_incoming_throttler_exceed_count = 0;
1089 char* m_tx_encode_buffer =
nullptr;
1091 OutgoingFixMessage m_outgoing_fix_message;
1093 IncomingFixMessage m_incoming_fix_message;
1094 ObjectCache<FixStringView> m_fix_string_view_cache;
1096 UserspaceSpinlock<> m_lock;
1099 FixString m_incoming_test_request_id;
1100 bool m_needs_responding_to_incoming_test_request =
false;
1103 uint32_t m_outgoing_test_request_id = 0;
1104 uint64_t m_outgoing_test_request_timestamp_nanoseconds = 0;
1105 bool m_expecting_response_for_outgoing_test_request =
false;
1108 bool m_needs_responding_to_incoming_resend_request =
false;
1109 uint32_t m_incoming_resend_request_begin_no = 0;
1110 uint32_t m_incoming_resend_request_end_no = 0;
1113 bool m_needs_to_send_resend_request =
false;
1114 uint32_t m_outgoing_resend_request_begin_no = 0;
1115 uint32_t m_outgoing_resend_request_end_no = 0;
1117 uint64_t m_outgoing_resend_request_timestamp_nanoseconds = 0;
1120 bool m_received_logout_response =
false;
1123 SPSCBoundedQueue<ModifyingAdminCommand*> m_admin_commands;
1126 SessionScheduleValidator m_schedule_validator;
1127 uint32_t m_last_error_tag=0;
1129 static inline IncomingFixRepeatingGroupSpecs m_repeating_group_specs;
1131 #ifdef LLFIX_ENABLE_BINARY_FIELDS
1132 static inline IncomingFixBinaryFieldSpecs m_binary_field_specs;
1135 #ifdef LLFIX_ENABLE_DICTIONARY
1136 static inline UserspaceSpinlock<> m_validators_initialisation_lock;
1137 static inline std::unordered_map<std::string, int> m_path_validator_id_table;
1138 static inline int m_latest_validator_id = 0;
1139 static inline std::unordered_map<int, FixDictionaryValidator::Validator> m_validators;
1141 int m_validator_id = -1;
1142 std::unique_ptr<std::vector<std::string>> m_dictionary_load_errors;
1144 void on_dictionary_load_error(
const std::string& message)
1146 m_dictionary_load_errors->push_back(message);
1149 bool initialise_dictionary_validator()
1151 const std::lock_guard<UserspaceSpinlock<>> lock(m_validators_initialisation_lock);
1153 if (m_settings.application_dictionary_path.length() == 0)
1158 bool already_loaded_dictionary =
false;
1160 if (m_path_validator_id_table.find(m_settings.application_dictionary_path) != m_path_validator_id_table.end())
1162 m_validator_id = m_path_validator_id_table[m_settings.application_dictionary_path];
1163 already_loaded_dictionary =
true;
1167 m_latest_validator_id++;
1168 m_validator_id = m_latest_validator_id;
1172 m_dictionary_load_errors.reset(
new std::vector<std::string>);
1173 std::unique_ptr<FixDictionaryLoader> dictionary_loader(
new FixDictionaryLoader);
1175 auto get_dictionary_load_errors = [&]()
1179 auto dictionary_load_errors = *dictionary_loader->errors();
1181 for (
const auto& error : dictionary_load_errors)
1183 ret += error +
"\n";
1189 if (m_settings.transport_dictionary_path.length() > 0)
1191 if (dictionary_loader->load_from(m_settings.transport_dictionary_path,
true) ==
false)
1193 LLFIX_LOG_ERROR(
"Session " + m_name +
" transport dictionary loading errors :" + get_dictionary_load_errors());
1198 if (m_settings.application_dictionary_path.length() > 0)
1200 if (dictionary_loader->load_from(m_settings.application_dictionary_path,
false) ==
false)
1202 LLFIX_LOG_ERROR(
"Session " + m_name +
" application dictionary loading errors :" + get_dictionary_load_errors());
1208 std::string dictionary_begin_string;
1210 if (dictionary_loader->get_dictionary()->get_begin_string(dictionary_begin_string))
1212 if (m_settings.begin_string != dictionary_begin_string)
1214 LLFIX_LOG_ERROR(
"Session " + m_name +
" : begin string specified in config file (" + m_settings.begin_string +
") does not match the dictionary (" + dictionary_begin_string +
")");
1220 LLFIX_LOG_ERROR(
"Session " + m_name +
" failed to retrieve begin string from dictionary.");
1225 FixDictionaryValidator::Validator validator;
1227 if (already_loaded_dictionary ==
false)
1229 auto fields = *dictionary_loader->get_dictionary()->fields();
1232 for (
const auto& field : fields)
1234 FixDictionaryValidator::FieldDefinition field_definition;
1235 field_definition.m_type = get_validator_field_type(field.second.type);
1237 if (field_definition.m_type != FixDictionaryValidator::FieldType::NONE)
1239 for (
const auto& allowed_value : field.second.values)
1241 field_definition.add_allowed_value(allowed_value);
1244 validator.specify_field_definition(field.second.tag, field_definition);
1249 load_validator_message_definitions(validator, dictionary_loader->get_dictionary(), fields);
1252 load_validator_repeating_group_definitions(validator, dictionary_loader->get_dictionary(), fields);
1254 #ifdef LLFIX_ENABLE_BINARY_FIELDS
1256 load_binary_fields(dictionary_loader->get_dictionary(), fields);
1261 for (
const auto& dict_error : *m_dictionary_load_errors)
1263 LLFIX_LOG_ERROR(
"Session " + m_name +
" dictionary error : " + dict_error);
1266 if (m_dictionary_load_errors->size() > 0)
1272 if (already_loaded_dictionary ==
false)
1274 m_validators[m_validator_id] = validator;
1275 m_path_validator_id_table[m_settings.application_dictionary_path] = m_validator_id;
1281 void get_all_non_repeating_group_fields_of_component_recursively(std::unordered_map<std::string, Component>& components,
const std::string& component_name,
bool is_parent_required, std::vector<MessageField>& target,
int& depth)
1285 if (components.find(component_name) != components.end())
1287 Component& component = components[component_name];
1289 for (
const auto& field : component.fields)
1292 cp.name = field.name;
1296 cp.required = field.required && is_parent_required;
1298 target.push_back(cp);
1301 for (
const auto& component_field : component.components)
1303 get_all_non_repeating_group_fields_of_component_recursively(components, component_field.name, component_field.required && is_parent_required, target, depth);
1309 on_dictionary_load_error(
"Could not find component " + component_name);
1313 void load_validator_message_definitions(FixDictionaryValidator::Validator& target_validator, FixDictionary* dictionary, std::unordered_map<std::string, Field>& fields)
1315 auto messages = dictionary->messages();
1316 auto components = *dictionary->components();
1317 auto header = dictionary->header();
1318 auto trailer = dictionary->trailer();
1320 auto add_field_to_message_definition = [&](
const std::string& field_name,
bool required, FixDictionaryValidator::MessageDefinition& target)
1322 if (fields.find(field_name) != fields.end())
1326 auto current_tag = fields[field_name].tag;
1327 if(current_tag != FixConstants::TAG_BEGIN_STRING && current_tag != FixConstants::TAG_BODY_LENGTH && current_tag != FixConstants::TAG_MSG_SEQ_NUM && current_tag != FixConstants::TAG_MSG_TYPE && current_tag != FixConstants::TAG_SENDER_COMP_ID && current_tag != FixConstants::TAG_SENDING_TIME && current_tag != FixConstants::TAG_TARGET_COMP_ID)
1328 target.add_required_field({ current_tag });
1330 target.add_non_required_field({ current_tag });
1334 target.add_non_required_field({ fields[field_name].tag });
1339 on_dictionary_load_error(
"Could not find field " + field_name);
1343 std::vector<MessageField> header_component_fields;
1344 for (
const auto& component : header->components)
1347 get_all_non_repeating_group_fields_of_component_recursively(components, component.name, component.required, header_component_fields, depth);
1350 std::vector<MessageField> trailer_component_fields;
1351 for (
const auto& component : trailer->components)
1354 get_all_non_repeating_group_fields_of_component_recursively(components, component.name, component.required, trailer_component_fields, depth);
1357 for (
const auto& message : *messages)
1359 auto message_type = message.second.msg_type;
1360 FixDictionaryValidator::MessageDefinition message_definition;
1363 for (
auto& field : message.second.fields)
1365 add_field_to_message_definition(field.name, field.required, message_definition);
1369 for (
const auto& component : message.second.components)
1371 std::vector<MessageField> component_fields;
1373 get_all_non_repeating_group_fields_of_component_recursively(components, component.name, component.required, component_fields, depth);
1375 for (
const auto& field : component_fields)
1377 add_field_to_message_definition(field.name, (component.required && field.required), message_definition);
1382 for (
const auto& field : header->fields)
1384 if (fields.find(field.name) != fields.end())
1386 add_field_to_message_definition(field.name, field.required, message_definition);
1390 on_dictionary_load_error(
"Could not find field " + field.name);
1395 for (
const auto& field : header_component_fields)
1397 if (fields.find(field.name) != fields.end())
1399 add_field_to_message_definition(field.name, field.required, message_definition);
1403 on_dictionary_load_error(
"Could not find field " + field.name);
1408 for (
const auto& field : trailer->fields)
1410 if (fields.find(field.name) != fields.end())
1412 add_field_to_message_definition(field.name, field.required, message_definition);
1416 on_dictionary_load_error(
"Could not find field " + field.name);
1421 for (
const auto& field : trailer_component_fields)
1423 if (fields.find(field.name) != fields.end())
1425 add_field_to_message_definition(field.name, field.required, message_definition);
1429 on_dictionary_load_error(
"Could not find field " + field.name);
1433 target_validator.specify_message_definition(message_type, message_definition);
1437 #ifdef LLFIX_ENABLE_BINARY_FIELDS
1438 void load_binary_fields(FixDictionary* dictionary, std::unordered_map<std::string, Field>& fields)
1440 auto messages = *dictionary->messages();
1441 auto header = *dictionary->header();
1442 auto trailer = *dictionary->trailer();
1443 auto components = *dictionary->components();
1445 for (
auto& message : messages)
1448 process_field_vector(message.second.fields, message.first, fields);
1451 for (
auto component : message.second.components)
1453 process_component_binary_fields_recursively(component, components, fields, message.first);
1457 for (
auto group_field : message.second.groups)
1459 process_group_binary_fields_recursively(group_field, components, fields, message.first);
1463 process_field_vector(header.fields, message.first, fields);
1466 for (
auto component : header.components)
1468 process_component_binary_fields_recursively(component, components, fields, message.first);
1472 for (
auto group : header.groups)
1474 process_group_binary_fields_recursively(group, components, fields, message.first);
1478 process_field_vector(trailer.fields, message.first, fields);
1481 for (
auto component : trailer.components)
1483 process_component_binary_fields_recursively(component, components, fields, message.first);
1487 for (
auto group : trailer.groups)
1489 process_group_binary_fields_recursively(group, components, fields, message.first);
1494 void process_component_binary_fields_recursively(ComponentField& component, std::unordered_map<std::string, Component>& components, std::unordered_map<std::string, Field>& fields,
const std::string& message_type)
1496 if (components.find(component.name) != components.end())
1498 process_field_vector(components[component.name].fields, message_type, fields);
1500 for (
auto& nested_component : components[component.name].components)
1502 process_component_binary_fields_recursively(nested_component, components, fields, message_type);
1505 for (
auto& nested_group_field : components[component.name].groups)
1507 process_group_binary_fields_recursively(nested_group_field, components, fields, message_type);
1513 on_dictionary_load_error(
"Could not find component " + component.name);
1517 void process_group_binary_fields_recursively(GroupField& group_field, std::unordered_map<std::string, Component>& components, std::unordered_map<std::string, Field>& fields,
const std::string& message_type)
1519 process_field_vector(group_field.fields, message_type, fields);
1521 for (
auto& nested_component : group_field.component_fields)
1523 process_component_binary_fields_recursively(nested_component, components, fields, message_type);
1526 for (
auto& nested_group_field : group_field.group_fields)
1528 process_group_binary_fields_recursively(nested_group_field, components, fields, message_type);
1532 void process_field_vector(std::vector<MessageField>& field_vector,
const std::string& message_type, std::unordered_map<std::string, Field>& fields)
1535 uint32_t current_length_tag = 0;
1536 int current_length_index = 0;
1538 for (
auto& field : field_vector)
1542 if (fields.find(field.name) != fields.end())
1544 auto current_field_type = fields[field.name].type;
1546 if (current_field_type == FieldType::LENGTH)
1548 current_length_tag = fields[field.name].tag;
1549 current_length_index = index;
1551 else if (current_field_type == FieldType::DATA)
1553 if (index == current_length_index + 1)
1555 m_binary_field_specs.specify_binary_field(message_type, current_length_tag, fields[field.name].tag);
1561 on_dictionary_load_error(
"Could not find field " + field.name);
1567 void load_validator_repeating_group_definitions(FixDictionaryValidator::Validator& target_validator, FixDictionary* dictionary, std::unordered_map<std::string, Field>& fields)
1569 auto messages = *dictionary->messages();
1570 auto header = *dictionary->header();
1571 auto trailer = *dictionary->trailer();
1572 auto components = *dictionary->components();
1574 std::vector<uint32_t> count_tags_stack;
1575 count_tags_stack.reserve(4);
1577 for (
const auto& message : messages)
1580 for (
const auto& component : message.second.components)
1582 if (components.find(component.name) != components.end())
1585 process_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, components[component.name], component.required, depth);
1589 on_dictionary_load_error(
"Could not find component " + component.name);
1594 for (
const auto& component : header.components)
1596 if (components.find(component.name) != components.end())
1599 process_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, components[component.name], component.required, depth);
1603 on_dictionary_load_error(
"Could not find component " + component.name);
1608 for (
const auto& component : trailer.components)
1610 if (components.find(component.name) != components.end())
1613 process_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, components[component.name], component.required, depth);
1617 on_dictionary_load_error(
"Could not find component " + component.name);
1622 for (
const auto& group_field : message.second.groups)
1625 process_group_field_rg_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, group_field, group_field.required, depth);
1629 for (
const auto& group_field : header.groups)
1632 process_group_field_rg_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, group_field, group_field.required, depth);
1636 for (
const auto& group_field : trailer.groups)
1639 process_group_field_rg_tags_recursively(target_validator, components, fields, count_tags_stack, message.first, group_field, group_field.required, depth);
1645 void process_rg_component_tags_recursively(FixDictionaryValidator::Validator& target_validator, std::unordered_map<std::string, Component>& components, std::unordered_map<std::string, Field>& fields, std::vector<uint32_t>& count_tags_stack,
const std::string& message_type,
const Component& component,
bool is_parent_required,
int& depth)
1649 for (
const auto& group : component.groups)
1651 int group_traversal_depth{ 0 };
1652 process_group_field_rg_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, group, group.required && is_parent_required, group_traversal_depth);
1655 for (
const auto& nested_component_field : component.components)
1657 if (components.find(nested_component_field.name) != components.end())
1659 process_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, components[nested_component_field.name], nested_component_field.required && is_parent_required, depth);
1664 on_dictionary_load_error(
"Could not find component " + nested_component_field.name);
1670 void process_non_rg_component_tags_recursively(FixDictionaryValidator::Validator& target_validator, std::unordered_map<std::string, Component>& components, std::unordered_map<std::string, Field>& fields, std::vector<uint32_t>& count_tags_stack,
const std::string& message_type,
const Component& component,
bool is_parent_required,
int& depth)
1674 for (
const auto& field : component.fields)
1676 process_repeating_group_tag(target_validator, fields, count_tags_stack, field.name, message_type, field.required && is_parent_required,
false);
1679 for (
const auto& nested_component : component.components)
1681 if (components.find(nested_component.name) != components.end())
1683 process_non_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, components[nested_component.name], nested_component.required && is_parent_required, depth);
1688 on_dictionary_load_error(
"Could not find component " + nested_component.name);
1693 void process_group_field_rg_tags_recursively(FixDictionaryValidator::Validator& target_validator, std::unordered_map<std::string, Component>& components, std::unordered_map<std::string, Field>& fields, std::vector<uint32_t>& count_tags_stack,
const std::string& message_type,
const GroupField& group_field ,
bool is_parent_required,
int& depth)
1697 auto count_tag = fields[group_field.name].tag;
1699 count_tags_stack.push_back(count_tag);
1701 process_repeating_group_tag(target_validator, fields, count_tags_stack, group_field.name, message_type, group_field.required && is_parent_required,
true);
1703 for (
const auto& field : group_field.fields)
1705 process_repeating_group_tag(target_validator, fields, count_tags_stack, field.name, message_type, field.required && is_parent_required,
false);
1708 for (
const auto& nested_component : group_field.component_fields)
1710 if (components.find(nested_component.name) != components.end())
1712 int nested_component_traversal_depth{ 0 };
1713 process_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, components[nested_component.name], nested_component.required && is_parent_required, nested_component_traversal_depth);
1715 nested_component_traversal_depth = 0;
1716 process_non_rg_component_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, components[nested_component.name], nested_component.required && is_parent_required, nested_component_traversal_depth);
1720 on_dictionary_load_error(
"Could not find component " + nested_component.name);
1724 for (
const auto& nested_group : group_field.group_fields)
1726 process_group_field_rg_tags_recursively(target_validator, components, fields, count_tags_stack, message_type, nested_group, nested_group.required && is_parent_required, depth);
1730 count_tags_stack.pop_back();
1733 void process_repeating_group_tag(FixDictionaryValidator::Validator& target_validator, std::unordered_map<std::string, Field>& fields, std::vector<uint32_t>& count_tags_stack,
const std::string& field_name,
const std::string& message_type,
bool required,
bool is_count_tag)
1735 if (fields.find(field_name) != fields.end())
1737 uint32_t current_tag = fields[field_name].tag;
1741 m_repeating_group_specs.add_count_tag(message_type, current_tag);
1744 for (
auto it = count_tags_stack.begin(); it != count_tags_stack.end() - 1; ++it)
1746 m_repeating_group_specs.add_repeating_group_tag(message_type, *it, current_tag);
1751 target_validator.specify_repeating_group_count_tag(message_type, current_tag);
1756 for (
const auto& parent_count_tag : count_tags_stack)
1758 m_repeating_group_specs.add_repeating_group_tag(message_type, parent_count_tag, current_tag);
1764 on_dictionary_load_error(
"Could not find field " + field_name);
1768 static FixDictionaryValidator::FieldType get_validator_field_type(FieldType type)
1773 case FieldType::CHAR:
return FixDictionaryValidator::FieldType::CHAR;
1775 case FieldType::BOOLEAN:
return FixDictionaryValidator::FieldType::BOOL;
1778 case FieldType::INT:
return FixDictionaryValidator::FieldType::INT;
1779 case FieldType::TAGNUM:
return FixDictionaryValidator::FieldType::INT;
1780 case FieldType::SEQNUM:
return FixDictionaryValidator::FieldType::INT;
1781 case FieldType::NUMINGROUP:
return FixDictionaryValidator::FieldType::INT;
1782 case FieldType::LENGTH:
return FixDictionaryValidator::FieldType::INT;
1785 case FieldType::FLOAT:
return FixDictionaryValidator::FieldType::FLOAT;
1786 case FieldType::AMT:
return FixDictionaryValidator::FieldType::FLOAT;
1787 case FieldType::PRICE:
return FixDictionaryValidator::FieldType::FLOAT;
1788 case FieldType::PRICEOFFSET:
return FixDictionaryValidator::FieldType::FLOAT;
1789 case FieldType::QTY:
return FixDictionaryValidator::FieldType::FLOAT;
1790 case FieldType::QUANTITY:
return FixDictionaryValidator::FieldType::FLOAT;
1791 case FieldType::PERCENTAGE:
return FixDictionaryValidator::FieldType::FLOAT;
1794 case FieldType::UTCTIMESTAMP:
return FixDictionaryValidator::FieldType::TIMESTAMP;
1795 case FieldType::TZTIMESTAMP:
return FixDictionaryValidator::FieldType::TIMESTAMP;
1798 case FieldType::UTCTIMEONLY:
return FixDictionaryValidator::FieldType::TIME_ONLY;
1799 case FieldType::TZTIMEONLY:
return FixDictionaryValidator::FieldType::TIME_ONLY;
1800 case FieldType::UTCTIME:
return FixDictionaryValidator::FieldType::TIME_ONLY;
1801 case FieldType::TIME:
return FixDictionaryValidator::FieldType::TIME_ONLY;
1802 case FieldType::LOCALMKTTIME:
return FixDictionaryValidator::FieldType::TIME_ONLY;
1805 case FieldType::UTCDATEONLY:
return FixDictionaryValidator::FieldType::DATE_ONLY;
1806 case FieldType::UTCDATE:
return FixDictionaryValidator::FieldType::DATE_ONLY;
1807 case FieldType::DATE:
return FixDictionaryValidator::FieldType::DATE_ONLY;
1808 case FieldType::LOCALMKTDATE:
return FixDictionaryValidator::FieldType::DATE_ONLY;
1811 case FieldType::MONTHYEAR:
return FixDictionaryValidator::FieldType::STRING;
1812 case FieldType::DAYOFMONTH:
return FixDictionaryValidator::FieldType::INT;
1815 case FieldType::DATA:
return FixDictionaryValidator::FieldType::DATA;
1816 case FieldType::XMLDATA:
return FixDictionaryValidator::FieldType::DATA;
1819 case FieldType::STRING:
return FixDictionaryValidator::FieldType::STRING;
1820 case FieldType::MULTIPLESTRINGVALUE:
return FixDictionaryValidator::FieldType::STRING;
1821 case FieldType::MULTIPLEVALUESTRING:
return FixDictionaryValidator::FieldType::STRING;
1822 case FieldType::MULTIPLEVALUECHAR:
return FixDictionaryValidator::FieldType::STRING;
1823 case FieldType::MULTIPLECHARVALUE:
return FixDictionaryValidator::FieldType::STRING;
1824 case FieldType::COUNTRY:
return FixDictionaryValidator::FieldType::STRING;
1825 case FieldType::CURRENCY:
return FixDictionaryValidator::FieldType::STRING;
1826 case FieldType::EXCHANGE:
return FixDictionaryValidator::FieldType::STRING;
1827 case FieldType::LANGUAGE:
return FixDictionaryValidator::FieldType::STRING;
1828 case FieldType::RESERVED100PLUS:
return FixDictionaryValidator::FieldType::STRING;
1829 case FieldType::RESERVED1000PLUS:
return FixDictionaryValidator::FieldType::STRING;
1830 case FieldType::RESERVED4000PLUS:
return FixDictionaryValidator::FieldType::STRING;
1831 case FieldType::PATTERN:
return FixDictionaryValidator::FieldType::STRING;
1832 case FieldType::TENOR:
return FixDictionaryValidator::FieldType::STRING;
1833 case FieldType::XID:
return FixDictionaryValidator::FieldType::STRING;
1834 case FieldType::XIDREF:
return FixDictionaryValidator::FieldType::STRING;
1837 case FieldType::NONE:
return FixDictionaryValidator::FieldType::NONE;
1838 default:
return FixDictionaryValidator::FieldType::NONE;
1843 void set_last_error_tag(uint32_t tag)
1845 m_last_error_tag = tag;
1848 FixSession(
const FixSession& other) =
delete;
1849 FixSession& operator= (
const FixSession& other) =
delete;
1850 FixSession(FixSession&& other) =
delete;
1851 FixSession& operator=(FixSession&& other) =
delete;