@@ -333,6 +333,41 @@ impl<'a> Socket<'a> {
333333 self . rx_waker . wake ( ) ;
334334 }
335335
336+ pub ( crate ) fn dispatch < F , E > ( & mut self , cx : & mut Context , emit : F ) -> Result < ( ) , E >
337+ where
338+ F : FnOnce ( & mut Context , ( EthernetRepr , & [ u8 ] ) ) -> Result < ( ) , E > ,
339+ {
340+ let ethertype = self . ethertype ;
341+ let res = self . tx_buffer . dequeue_with ( |& mut ( ) , buffer| {
342+ #[ allow( clippy:: useless_asref) ]
343+ let frame = match EthernetFrame :: new_checked ( buffer. as_ref ( ) ) {
344+ Ok ( x) => x,
345+ Err ( _) => {
346+ net_trace ! ( "eth: malformed ethernet frame in queue, dropping." ) ;
347+ return Ok ( ( ) ) ;
348+ }
349+ } ;
350+ let eth_repr = match EthernetRepr :: parse ( & frame) {
351+ Ok ( r) => r,
352+ Err ( _) => {
353+ net_trace ! ( "eth: malformed ethernet frame in queue, dropping." ) ;
354+ return Ok ( ( ) ) ;
355+ }
356+ } ;
357+ net_trace ! ( "eth:{}: sending" , ethertype. unwrap_or( 0 ) ) ;
358+ emit ( cx, ( eth_repr, frame. payload ( ) ) )
359+ } ) ;
360+ match res {
361+ Err ( Empty ) => Ok ( ( ) ) ,
362+ Ok ( Err ( e) ) => Err ( e) ,
363+ Ok ( Ok ( ( ) ) ) => {
364+ #[ cfg( feature = "async" ) ]
365+ self . tx_waker . wake ( ) ;
366+ Ok ( ( ) )
367+ }
368+ }
369+ }
370+
336371 pub ( crate ) fn poll_at ( & self , _cx : & mut Context ) -> PollAt {
337372 if self . tx_buffer . is_empty ( ) {
338373 PollAt :: Ingress
@@ -342,4 +377,62 @@ impl<'a> Socket<'a> {
342377 }
343378}
344379
380+ #[ cfg( test) ]
381+ mod test {
382+ use super :: * ;
383+
384+ use crate :: phy:: Medium ;
385+ use crate :: tests:: setup;
386+ use crate :: wire:: ethernet:: EtherType ;
387+
388+ fn buffer ( packets : usize ) -> PacketBuffer < ' static > {
389+ PacketBuffer :: new ( vec ! [ PacketMetadata :: EMPTY ; packets] , vec ! [ 0 ; 48 * packets] )
390+ }
391+
392+ const ETHER_TYPE : u16 = 0x1234 ;
393+
394+ fn socket (
395+ rx_buffer : PacketBuffer < ' static > ,
396+ tx_buffer : PacketBuffer < ' static > ,
397+ ) -> Socket < ' static > {
398+ Socket :: new ( Some ( ETHER_TYPE ) , rx_buffer, tx_buffer)
399+ }
345400
401+ #[ rustfmt:: skip]
402+ pub const PACKET_BYTES : [ u8 ; 18 ] = [
403+ 0xaa , 0xbb , 0xcc , 0x12 , 0x34 , 0x56 ,
404+ 0xaa , 0xbb , 0xcc , 0x78 , 0x90 , 0x12 ,
405+ 0x12 , 0x34 ,
406+ 0xaa , 0x00 , 0x00 , 0xff ,
407+ ] ;
408+ pub const PACKET_PAYLOAD : [ u8 ; 4 ] = [ 0xaa , 0x00 , 0x00 , 0xff ] ;
409+
410+ #[ test]
411+ fn test_send ( ) {
412+ let ( mut iface, _, _) = setup ( Medium :: Ethernet ) ;
413+ let cx = iface. context ( ) ;
414+ let mut socket = socket ( buffer ( 1 ) , buffer ( 1 ) ) ;
415+ assert ! ( socket. can_send( ) ) ;
416+ assert_eq ! ( socket. send_slice( & PACKET_BYTES [ ..] ) , Ok ( ( ) ) ) ;
417+ assert_eq ! ( socket. send_slice( b"" ) , Err ( SendError :: BufferFull ) ) ;
418+ assert ! ( !socket. can_send( ) ) ;
419+ assert_eq ! (
420+ socket. dispatch( cx, |_, ( eth_repr, eth_payload) | {
421+ assert_eq!( eth_repr. ethertype, EtherType :: from( ETHER_TYPE ) ) ;
422+ assert_eq!( eth_payload, PACKET_PAYLOAD ) ;
423+ Err ( ( ) )
424+ } ) ,
425+ Err ( ( ) )
426+ ) ;
427+ assert ! ( !socket. can_send( ) ) ;
428+ assert_eq ! (
429+ socket. dispatch( cx, |_, ( eth_repr, eth_payload) | {
430+ assert_eq!( eth_repr. ethertype, EtherType :: from( ETHER_TYPE ) ) ;
431+ assert_eq!( eth_payload, PACKET_PAYLOAD ) ;
432+ Ok :: <_, ( ) >( ( ) )
433+ } ) ,
434+ Ok ( ( ) )
435+ ) ;
436+ assert ! ( socket. can_send( ) ) ;
437+ }
438+ }
0 commit comments