@@ -270,7 +270,6 @@ impl Streaming {
270
270
SessionHeaderType :: PubSub => {
271
271
// send the packet to the application
272
272
process_message_from_gw( msg, session_id, & mut state. receiver, & source, max_retries, timeout, & timer_tx, & send_gw, & send_app) . await ;
273
-
274
273
}
275
274
SessionHeaderType :: RtxRequest => {
276
275
// handle RTX request
@@ -353,15 +352,17 @@ async fn process_incoming_rtx_request(
353
352
msg_rtx_id, session_id
354
353
) ;
355
354
// search the packet in the producer buffer
355
+ let pkt_src = msg. get_source ( ) ;
356
+ let incoming_conn = msg. get_incoming_conn ( ) ;
357
+
356
358
let rtx_pub = match producer. buffer . get ( msg_rtx_id as usize ) {
357
359
Some ( packet) => {
358
360
trace ! (
359
361
"packet {} exists in the producer buffer, create rtx reply" ,
360
362
msg_rtx_id
361
363
) ;
362
- // the packet exists, send it to the source of the RTX
363
- let pkt_src = msg. get_source ( ) ;
364
364
365
+ // the packet exists, send it to the source of the RTX
365
366
let payload = match packet. get_payload ( ) {
366
367
Some ( p) => p,
367
368
None => {
@@ -370,8 +371,6 @@ async fn process_incoming_rtx_request(
370
371
}
371
372
} ;
372
373
373
- let incoming_conn = msg. get_incoming_conn ( ) ;
374
-
375
374
let agp_header = Some ( AgpHeader :: new (
376
375
source,
377
376
pkt_src. agent_type ( ) ,
@@ -392,21 +391,37 @@ async fn process_incoming_rtx_request(
392
391
Message :: new_publish_with_headers ( agp_header, session_header, "" , payload. blob . to_vec ( ) )
393
392
}
394
393
None => {
395
- // the packet does not exist so do nothing
396
- // TODO(micpapal): improve by returning a rtx nack so that the remote app does not
397
- // wait too long for all the retransmissions
394
+ // the packet does not exist return an empty RtxReply with the error flag set
398
395
debug ! (
399
- "received and RTX messages for an old packet on producer session {}" ,
396
+ "received an RTX messages for an old packet on session {}" ,
400
397
session_id
401
398
) ;
402
- return ;
399
+
400
+ let flags = AgpHeaderFlags :: default ( )
401
+ . with_forward_to ( incoming_conn)
402
+ . with_error ( true ) ;
403
+
404
+ let agp_header = Some ( AgpHeader :: new (
405
+ source,
406
+ pkt_src. agent_type ( ) ,
407
+ Some ( pkt_src. agent_id ( ) ) ,
408
+ Some ( flags) ,
409
+ ) ) ;
410
+
411
+ let session_header = Some ( SessionHeader :: new (
412
+ SessionHeaderType :: RtxReply . into ( ) ,
413
+ session_id,
414
+ msg_rtx_id,
415
+ ) ) ;
416
+
417
+ Message :: new_publish_with_headers ( agp_header, session_header, "" , vec ! [ ] )
403
418
}
404
419
} ;
405
420
406
421
trace ! ( "send rtx reply for message {}" , msg_rtx_id) ;
407
422
if send_gw. send ( Ok ( rtx_pub) ) . await . is_err ( ) {
408
423
error ! (
409
- "error sending RTX packet to the gateway on producer session {}" ,
424
+ "error sending RTX packet to the gateway on session {}" ,
410
425
session_id
411
426
) ;
412
427
}
@@ -421,10 +436,7 @@ async fn process_message_from_app(
421
436
send_app : & mpsc:: Sender < Result < SessionMessage , SessionError > > ,
422
437
) {
423
438
// set the session header, add the message to the buffer and send it
424
- trace ! (
425
- "received message from the app on producer session {}" ,
426
- session_id
427
- ) ;
439
+ trace ! ( "received message from the app on session {}" , session_id) ;
428
440
429
441
if is_bidirectional {
430
442
msg. set_header_type ( SessionHeaderType :: PubSub ) ;
@@ -450,7 +462,7 @@ async fn process_message_from_app(
450
462
451
463
if send_gw. send ( Ok ( msg) ) . await . is_err ( ) {
452
464
error ! (
453
- "error sending publication packet to the gateway on producer session {}" ,
465
+ "error sending publication packet to the gateway on session {}" ,
454
466
session_id
455
467
) ;
456
468
send_app
@@ -500,8 +512,12 @@ async fn process_message_from_gw(
500
512
} ;
501
513
502
514
let header_type = msg. get_header_type ( ) ;
515
+ let mut error_rtx = false ;
503
516
if header_type == SessionHeaderType :: RtxReply {
504
517
let rtx_msg_id = msg. get_id ( ) ;
518
+ if msg. get_error ( ) . is_some ( ) && msg. get_error ( ) . unwrap ( ) {
519
+ error_rtx = true ;
520
+ }
505
521
506
522
// try to clean local state
507
523
match receiver. timers_map . get ( & rtx_msg_id) {
@@ -518,43 +534,34 @@ async fn process_message_from_gw(
518
534
}
519
535
} else if header_type != SessionHeaderType :: Stream && header_type != SessionHeaderType :: PubSub {
520
536
error ! (
521
- "received packet with invalid header type {} on receiver session {}" ,
537
+ "received packet with invalid header type {} on session {}" ,
522
538
i32 :: from( header_type) ,
523
539
session_id
524
540
) ;
525
541
return ;
526
542
}
527
543
544
+ if error_rtx {
545
+ // a message cannot be recovered
546
+ let msg_id = msg. get_id ( ) ;
547
+ debug ! ( "received an error RTX reply for message {}" , msg_id) ;
548
+ match receiver. buffer . on_lost_message ( msg_id) {
549
+ Ok ( recv) => {
550
+ send_message_to_app ( recv, session_id, send_app) . await ;
551
+ }
552
+ Err ( e) => {
553
+ error ! ( "error adding message lost to the buffer: {}" , e. to_string( ) ) ;
554
+ }
555
+ }
556
+ return ;
557
+ }
558
+
528
559
match receiver. buffer . on_received_message ( msg) {
529
560
Ok ( ( recv, rtx) ) => {
530
- for opt in recv {
531
- trace ! (
532
- "send recv packet to the application on receiver session {}" ,
533
- session_id
534
- ) ;
535
- match opt {
536
- Some ( m) => {
537
- // send message to the app
538
- let info = Info :: from ( & m) ;
539
- let session_msg = SessionMessage :: new ( m, info) ;
540
- if send_app. send ( Ok ( session_msg) ) . await . is_err ( ) {
541
- error ! (
542
- "error sending packet to the application on receiver session {}" ,
543
- session_id
544
- ) ;
545
- }
546
- }
547
- None => {
548
- warn ! (
549
- "a message was definitely lost in receiver session {}" ,
550
- session_id
551
- ) ;
552
- let _ = send_app
553
- . send ( Err ( SessionError :: MessageLost ( session_id. to_string ( ) ) ) )
554
- . await ;
555
- }
556
- }
557
- }
561
+ // send packets to the app
562
+ send_message_to_app ( recv, session_id, send_app) . await ;
563
+
564
+ // send RTX
558
565
for r in rtx {
559
566
debug ! (
560
567
"packet loss detected on session {}, send RTX for id {}" ,
@@ -635,7 +642,7 @@ async fn handle_timeout(
635
642
636
643
if send_gw. send ( Ok ( rtx. clone ( ) ) ) . await . is_err ( ) {
637
644
error ! (
638
- "error sending RTX for id {} on receiver session {}" ,
645
+ "error sending RTX for id {} on session {}" ,
639
646
msg_id, session_id
640
647
) ;
641
648
}
@@ -663,34 +670,42 @@ async fn handle_failure(
663
670
664
671
match receiver. buffer . on_lost_message ( msg_id) {
665
672
Ok ( recv) => {
666
- for opt in recv {
667
- match opt {
668
- Some ( m) => {
669
- let info = Info :: from ( & m) ;
670
- let session_msg = SessionMessage :: new ( m, info) ;
671
- // send message to the app
672
- if send_app. send ( Ok ( session_msg) ) . await . is_err ( ) {
673
- error ! (
674
- "error sending packet to the gateway on session {}" ,
675
- session_id
676
- ) ;
677
- }
678
- }
679
- None => {
680
- warn ! ( "a message was definitely lost in session {}" , session_id) ;
681
- let _ = send_app
682
- . send ( Err ( SessionError :: MessageLost ( session_id. to_string ( ) ) ) )
683
- . await ;
684
- }
685
- }
686
- }
673
+ send_message_to_app ( recv, session_id, send_app) . await ;
687
674
}
688
675
Err ( e) => {
689
676
error ! ( "error adding message lost to the buffer: {}" , e. to_string( ) ) ;
690
677
}
691
678
} ;
692
679
}
693
680
681
+ async fn send_message_to_app (
682
+ messages : Vec < Option < Message > > ,
683
+ session_id : u32 ,
684
+ send_app : & mpsc:: Sender < Result < SessionMessage , SessionError > > ,
685
+ ) {
686
+ for opt in messages {
687
+ match opt {
688
+ Some ( m) => {
689
+ let info = Info :: from ( & m) ;
690
+ let session_msg = SessionMessage :: new ( m, info) ;
691
+ // send message to the app
692
+ if send_app. send ( Ok ( session_msg) ) . await . is_err ( ) {
693
+ error ! (
694
+ "error sending packet to the gateway on session {}" ,
695
+ session_id
696
+ ) ;
697
+ }
698
+ }
699
+ None => {
700
+ warn ! ( "a message was definitely lost in session {}" , session_id) ;
701
+ let _ = send_app
702
+ . send ( Err ( SessionError :: MessageLost ( session_id. to_string ( ) ) ) )
703
+ . await ;
704
+ }
705
+ }
706
+ }
707
+ }
708
+
694
709
#[ async_trait]
695
710
impl Session for Streaming {
696
711
async fn on_message (
0 commit comments