@@ -618,28 +618,18 @@ impl ActiveRelayActor {
618
618
& mut send_datagrams_buf,
619
619
SEND_DATAGRAM_BATCH_SIZE ,
620
620
) => {
621
- use std:: sync:: atomic:: Ordering :: Relaxed ;
622
-
623
621
if count == 0 {
624
622
warn!( "Datagram inbox closed, shutdown" ) ;
625
623
break Ok ( ( ) ) ;
626
624
} ;
627
625
self . reset_inactive_timeout( ) ;
628
626
// TODO(frando): can we avoid the clone here?
629
627
let metrics = self . metrics. clone( ) ;
630
- let max_segments = self . max_receive_segments. load( Relaxed ) ;
631
- let packet_iter = send_datagrams_buf. drain( ..) . flat_map( |item| {
632
- let metrics = metrics. clone( ) ;
633
- let dst_node_id = item. remote_node;
634
- DatagramFragmenter {
635
- max_segments,
636
- datagram: item. datagrams,
637
- } . map( move |datagrams| {
638
- metrics. send_relay. inc_by( datagrams. contents. len( ) as _) ;
639
- Ok ( ClientToRelayMsg :: Datagrams {
640
- dst_node_id,
641
- datagrams
642
- } )
628
+ let packet_iter = send_datagrams_buf. drain( ..) . map( |item| {
629
+ metrics. send_relay. inc_by( item. datagrams. contents. len( ) as _) ;
630
+ Ok ( ClientToRelayMsg :: Datagrams {
631
+ dst_node_id: item. remote_node,
632
+ datagrams: item. datagrams,
643
633
} )
644
634
} ) ;
645
635
let mut packet_stream = n0_future:: stream:: iter( packet_iter) ;
@@ -693,12 +683,28 @@ impl ActiveRelayActor {
693
683
state. last_packet_src = Some ( remote_node_id) ;
694
684
state. nodes_present . insert ( remote_node_id) ;
695
685
}
696
- if let Err ( err) = self . relay_datagrams_recv . try_send ( RelayRecvDatagram {
697
- url : self . url . clone ( ) ,
698
- src : remote_node_id,
686
+
687
+ let max_segments = self
688
+ . max_receive_segments
689
+ . load ( std:: sync:: atomic:: Ordering :: Relaxed ) ;
690
+ // We might receive a datagram batch that's bigger than our magic socket's
691
+ // `AsyncUdpSocket::max_receive_segments`, if the other endpoint behind the relay
692
+ // has a higher `AsyncUdpSocket::max_transmit_segments` than we do.
693
+ // This happens e.g. when a linux machine (max transmit segments is usually 64)
694
+ // talks to a windows machine or a macos machine (max transmit segments is usually 1).
695
+ let re_batched = DatagramReBatcher {
696
+ max_segments,
699
697
datagrams,
700
- } ) {
701
- warn ! ( "Dropping received relay packet: {err:#}" ) ;
698
+ } ;
699
+ for datagrams in re_batched {
700
+ if let Err ( err) = self . relay_datagrams_recv . try_send ( RelayRecvDatagram {
701
+ url : self . url . clone ( ) ,
702
+ src : remote_node_id,
703
+ datagrams,
704
+ } ) {
705
+ warn ! ( "Dropping received relay packet: {err:#}" ) ;
706
+ break ; // No need to hot-loop in that case.
707
+ }
702
708
}
703
709
}
704
710
RelayToClientMsg :: NodeGone ( node_id) => {
@@ -1243,16 +1249,19 @@ pub(crate) struct RelayRecvDatagram {
1243
1249
pub ( crate ) datagrams : Datagrams ,
1244
1250
}
1245
1251
1246
- struct DatagramFragmenter {
1252
+ /// Turns a datagrams batch into multiple datagram batches of maximum `max_segments` size.
1253
+ ///
1254
+ /// If the given datagram isn't batched, it just returns that datagram once.
1255
+ struct DatagramReBatcher {
1247
1256
max_segments : usize ,
1248
- datagram : Datagrams ,
1257
+ datagrams : Datagrams ,
1249
1258
}
1250
1259
1251
- impl Iterator for DatagramFragmenter {
1260
+ impl Iterator for DatagramReBatcher {
1252
1261
type Item = Datagrams ;
1253
1262
1254
1263
fn next ( & mut self ) -> Option < Self :: Item > {
1255
- self . datagram . take_segments ( self . max_segments )
1264
+ self . datagrams . take_segments ( self . max_segments )
1256
1265
}
1257
1266
}
1258
1267
0 commit comments