@@ -333,6 +333,41 @@ impl<'a> Socket<'a> {
333
333
self . rx_waker . wake ( ) ;
334
334
}
335
335
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
+
336
371
pub ( crate ) fn poll_at ( & self , _cx : & mut Context ) -> PollAt {
337
372
if self . tx_buffer . is_empty ( ) {
338
373
PollAt :: Ingress
@@ -342,4 +377,62 @@ impl<'a> Socket<'a> {
342
377
}
343
378
}
344
379
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
+ }
345
400
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 mut 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( & mut 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( & mut 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