@@ -3,6 +3,14 @@ mod info;
33mod session_ref;
44mod state;
55
6+ use crate :: config:: SessionConfig ;
7+ use crate :: message:: FixMessage ;
8+ use crate :: message:: generate_message;
9+ use crate :: message:: heartbeat:: Heartbeat ;
10+ use crate :: message:: logon:: { Logon , ResetSeqNumConfig } ;
11+ use crate :: message:: parser:: RawFixMessage ;
12+ use crate :: store:: MessageStore ;
13+ use crate :: transport:: writer:: WriterRef ;
614use anyhow:: { Result , anyhow} ;
715use chrono:: Utc ;
816use hotfix_message:: dict:: Dictionary ;
@@ -12,16 +20,7 @@ use std::pin::Pin;
1220use tokio:: select;
1321use tokio:: sync:: mpsc;
1422use tokio:: time:: { Duration , Instant , Sleep , sleep, sleep_until} ;
15- use tracing:: { debug, error, info, warn} ;
16-
17- use crate :: config:: SessionConfig ;
18- use crate :: message:: FixMessage ;
19- use crate :: message:: generate_message;
20- use crate :: message:: heartbeat:: Heartbeat ;
21- use crate :: message:: logon:: { Logon , ResetSeqNumConfig } ;
22- use crate :: message:: parser:: RawFixMessage ;
23- use crate :: store:: MessageStore ;
24- use crate :: transport:: writer:: WriterRef ;
23+ use tracing:: { debug, enabled, error, info, warn} ;
2524
2625use crate :: error:: { CompIdType , MessageVerificationError } ;
2726use crate :: message:: logout:: Logout ;
@@ -362,25 +361,46 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
362361 }
363362
364363 async fn on_resend_request ( & mut self , message : & Message ) -> Result < ( ) > {
365- // TODO: verify message and send reject as necessary
364+ if !self . state . is_connected ( ) {
365+ warn ! ( "received resend request while disconnected, ignoring" ) ;
366+ }
366367
367- let begin_seq_number: usize = message. get ( fix44:: BEGIN_SEQ_NO ) . unwrap_or_else ( |_| {
368- // TODO: send reject if there is no valid begin number
369- todo ! ( )
370- } ) ;
368+ let begin_seq_number: u64 = match message. get ( fix44:: BEGIN_SEQ_NO ) {
369+ Ok ( seq_number) => seq_number,
370+ Err ( _) => {
371+ let reject = Reject :: new (
372+ message
373+ . header ( )
374+ . get ( fix44:: MSG_SEQ_NUM )
375+ . map_err ( |_| anyhow ! ( "failed to get seq number" ) ) ?,
376+ )
377+ . session_reject_reason ( SessionRejectReason :: RequiredTagMissing )
378+ . text ( "missing begin sequence number for resend request" ) ;
379+ self . send_message ( reject) . await ;
380+ return Ok ( ( ) ) ;
381+ }
382+ } ;
371383
372- let end_seq_number: usize = match message. get ( fix44:: END_SEQ_NO ) {
384+ let end_seq_number: u64 = match message. get ( fix44:: END_SEQ_NO ) {
373385 Ok ( seq_number) => {
374- let last_seq_number = self . store . next_sender_seq_number ( ) as usize - 1 ;
386+ let last_seq_number = self . store . next_sender_seq_number ( ) - 1 ;
375387 if seq_number == 0 {
376388 last_seq_number
377389 } else {
378390 std:: cmp:: min ( seq_number, last_seq_number)
379391 }
380392 }
381393 Err ( _) => {
382- // send reject if there is no valid end number
383- todo ! ( )
394+ let reject = Reject :: new (
395+ message
396+ . header ( )
397+ . get ( fix44:: MSG_SEQ_NUM )
398+ . map_err ( |_| anyhow ! ( "failed to get seq number" ) ) ?,
399+ )
400+ . session_reject_reason ( SessionRejectReason :: RequiredTagMissing )
401+ . text ( "missing end sequence number for resend request" ) ;
402+ self . send_message ( reject) . await ;
403+ return Ok ( ( ) ) ;
384404 }
385405 } ;
386406
@@ -583,19 +603,21 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
583603 } ;
584604 }
585605
586- async fn resend_messages ( & mut self , begin : usize , end : usize , _message : & Message ) {
587- debug ! ( begin, end, "resending messages as requested" ) ;
588- let messages = self . store . get_slice ( begin, end) . await . unwrap ( ) ;
606+ async fn resend_messages ( & mut self , begin : u64 , end : u64 , _message : & Message ) {
607+ info ! ( begin, end, "resending messages as requested" ) ;
608+ let messages = self
609+ . store
610+ . get_slice ( begin as usize , end as usize )
611+ . await
612+ . unwrap ( ) ;
589613
590614 let no = messages. len ( ) ;
591- debug ! ( no, "number of messages" ) ;
615+ debug ! ( number_of_messages = no, "number of messages" ) ;
592616
593617 let mut reset_start: Option < u64 > = None ;
594618 let mut sequence_number = 0 ;
595619
596620 for msg in messages {
597- let m = String :: from_utf8 ( msg. clone ( ) ) . unwrap ( ) ;
598- debug ! ( m, "resending message" ) ;
599621 let mut message = self
600622 . message_builder
601623 . build ( msg. as_slice ( ) )
@@ -609,7 +631,6 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
609631 . to_string ( ) ;
610632
611633 if is_admin ( message_type. as_str ( ) ) {
612- debug ! ( "skipping message as it's an admin message" ) ;
613634 if reset_start. is_none ( ) {
614635 reset_start = Some ( sequence_number) ;
615636 }
@@ -618,6 +639,7 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
618639
619640 if let Some ( begin) = reset_start {
620641 let end = sequence_number;
642+ Self :: log_skipped_admin_messages ( begin, end) ;
621643 self . send_sequence_reset ( begin, end) . await ;
622644 reset_start = None ;
623645 }
@@ -633,16 +655,28 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
633655 message. encode ( & self . message_config ) . unwrap ( ) ,
634656 )
635657 . await ;
636- debug ! ( sequence_number, "resent message" ) ;
658+
659+ if enabled ! ( tracing:: Level :: DEBUG ) {
660+ let m = String :: from_utf8 ( msg. clone ( ) ) . unwrap ( ) ;
661+ debug ! ( sequence_number, message = m, "resent message" ) ;
662+ }
637663 }
638664
639665 if let Some ( begin) = reset_start {
640666 // the final reset if needed
641667 let end = sequence_number;
668+ Self :: log_skipped_admin_messages ( begin, end) ;
642669 self . send_sequence_reset ( begin, end) . await ;
643670 }
644671 }
645672
673+ fn log_skipped_admin_messages ( begin : u64 , end : u64 ) {
674+ info ! (
675+ begin,
676+ end, "skipped admin message(s) during resend, requesting reset for these"
677+ ) ;
678+ }
679+
646680 fn reset_heartbeat_timer ( & mut self ) {
647681 self . state
648682 . reset_heartbeat_timer ( self . config . heartbeat_interval ) ;
0 commit comments