@@ -36,12 +36,14 @@ use crate::message::verification::verify_message;
3636use crate :: message:: verification_error:: { CompIdType , MessageVerificationError } ;
3737use crate :: message_utils:: { is_admin, prepare_message_for_resend} ;
3838use crate :: session:: admin_request:: AdminRequest ;
39+ pub use crate :: session:: error:: { SendError , SendOutcome } ;
3940pub use crate :: session:: info:: { SessionInfo , Status } ;
4041pub use crate :: session:: session_handle:: SessionHandle ;
4142#[ cfg( not( feature = "test-utils" ) ) ]
4243pub ( crate ) use crate :: session:: session_ref:: InternalSessionRef ;
4344#[ cfg( feature = "test-utils" ) ]
4445pub use crate :: session:: session_ref:: InternalSessionRef ;
46+ use crate :: session:: session_ref:: OutboundRequest ;
4547use crate :: session:: state:: SessionState ;
4648use crate :: session:: state:: { AwaitingResendTransitionOutcome , TestRequestId } ;
4749use crate :: session_schedule:: SessionSchedule ;
@@ -819,6 +821,66 @@ where
819821 Ok ( ( ) )
820822 }
821823
824+ async fn send_app_message_with_confirmation (
825+ & mut self ,
826+ message : Outbound ,
827+ ) -> Result < SendOutcome , SendError > {
828+ if !self . state . is_connected ( ) {
829+ return Err ( SendError :: Disconnected ) ;
830+ }
831+
832+ match self . application . on_outbound_message ( & message) . await {
833+ OutboundDecision :: Send => {
834+ let sequence_number = self . send_message_returning_seq ( message) . await ?;
835+ Ok ( SendOutcome :: Sent { sequence_number } )
836+ }
837+ OutboundDecision :: Drop => {
838+ debug ! ( "dropped outbound message as instructed by the application" ) ;
839+ Ok ( SendOutcome :: Dropped )
840+ }
841+ OutboundDecision :: TerminateSession => {
842+ warn ! ( "the application indicated we should terminate the session" ) ;
843+ self . state . disconnect_writer ( ) . await ;
844+ Err ( SendError :: SessionTerminated )
845+ }
846+ }
847+ }
848+
849+ async fn send_message_returning_seq (
850+ & mut self ,
851+ message : impl OutboundMessage ,
852+ ) -> Result < u64 , SendError > {
853+ let seq_num = self . store . next_sender_seq_number ( ) ;
854+ let msg_type = message. message_type ( ) . as_bytes ( ) . to_vec ( ) ;
855+ let msg = generate_message (
856+ & self . config . begin_string ,
857+ & self . config . sender_comp_id ,
858+ & self . config . target_comp_id ,
859+ seq_num,
860+ message,
861+ )
862+ . map_err ( |e| {
863+ SendError :: Persist ( crate :: store:: StoreError :: PersistMessage {
864+ sequence_number : seq_num,
865+ source : e. into ( ) ,
866+ } )
867+ } ) ?;
868+
869+ self . store
870+ . increment_sender_seq_number ( )
871+ . await
872+ . map_err ( SendError :: SequenceNumber ) ?;
873+
874+ self . store
875+ . add ( seq_num, & msg)
876+ . await
877+ . map_err ( SendError :: Persist ) ?;
878+
879+ self . send_raw ( & msg_type, msg) . await ;
880+
881+ Ok ( seq_num)
882+ }
883+
822884 async fn send_message ( & mut self , message : impl OutboundMessage ) -> Result < ( ) > {
823885 let seq_num = self . store . next_sender_seq_number ( ) ;
824886 let msg_type = message. message_type ( ) . as_bytes ( ) . to_vec ( ) ;
@@ -957,9 +1019,19 @@ where
9571019 }
9581020 }
9591021
960- async fn handle_outbound_message ( & mut self , message : Outbound ) {
961- if let Err ( err) = self . send_app_message ( message) . await {
962- error ! ( err = ?err, "failed to send app message: {err}" ) ;
1022+ async fn handle_outbound_message ( & mut self , request : OutboundRequest < Outbound > ) {
1023+ let OutboundRequest { message, confirm } = request;
1024+ match confirm {
1025+ Some ( tx) => {
1026+ let result = self . send_app_message_with_confirmation ( message) . await ;
1027+ // Ignore send errors - receiver may have been dropped
1028+ let _ = tx. send ( result) ;
1029+ }
1030+ None => {
1031+ if let Err ( err) = self . send_app_message ( message) . await {
1032+ error ! ( err = ?err, "failed to send app message: {err}" ) ;
1033+ }
1034+ }
9631035 }
9641036 }
9651037
@@ -1069,7 +1141,7 @@ where
10691141async fn run_session < App , Inbound , Outbound , Store > (
10701142 mut session : Session < App , Inbound , Outbound , Store > ,
10711143 mut event_receiver : mpsc:: Receiver < SessionEvent > ,
1072- mut outbound_message_receiver : mpsc:: Receiver < Outbound > ,
1144+ mut outbound_message_receiver : mpsc:: Receiver < OutboundRequest < Outbound > > ,
10731145 mut admin_request_receiver : mpsc:: Receiver < AdminRequest > ,
10741146) where
10751147 App : Application < Inbound , Outbound > ,
@@ -1094,9 +1166,9 @@ async fn run_session<App, Inbound, Outbound, Store>(
10941166 None => break ,
10951167 }
10961168 }
1097- next_outbound_message = outbound_message_receiver. recv( ) => {
1098- match next_outbound_message {
1099- Some ( message ) => session. handle_outbound_message( message ) . await ,
1169+ next_outbound_request = outbound_message_receiver. recv( ) => {
1170+ match next_outbound_request {
1171+ Some ( request ) => session. handle_outbound_message( request ) . await ,
11001172 None => break ,
11011173 }
11021174 }
0 commit comments