@@ -1535,3 +1535,105 @@ pub fn test_vsock() {
1535
1535
close ( s1) . unwrap ( ) ;
1536
1536
thr. join ( ) . unwrap ( ) ;
1537
1537
}
1538
+
1539
+ #[ cfg( all( target_os = "linux" , any( target_arch = "x86_64" , target_arch = "x86" ) , target_env = "gnu" ) ) ]
1540
+ #[ test]
1541
+ fn test_recvmsg_timestampns ( ) {
1542
+ use nix:: sys:: socket:: * ;
1543
+ use nix:: sys:: uio:: IoVec ;
1544
+ use nix:: sys:: time:: * ;
1545
+ use std:: time:: * ;
1546
+
1547
+ // Set up
1548
+ let message = "Ohayō!" . as_bytes ( ) ;
1549
+ let in_socket = socket (
1550
+ AddressFamily :: Inet ,
1551
+ SockType :: Datagram ,
1552
+ SockFlag :: empty ( ) ,
1553
+ None ) . unwrap ( ) ;
1554
+ setsockopt ( in_socket, sockopt:: ReceiveTimestampNs , & true ) . unwrap ( ) ;
1555
+ let localhost = InetAddr :: new ( IpAddr :: new_v4 ( 127 , 0 , 0 , 1 ) , 0 ) ;
1556
+ bind ( in_socket, & SockAddr :: new_inet ( localhost) ) . unwrap ( ) ;
1557
+ let address = getsockname ( in_socket) . unwrap ( ) ;
1558
+ // Get initial time
1559
+ let time0 = SystemTime :: now ( ) ;
1560
+ // Send the message
1561
+ let iov = [ IoVec :: from_slice ( message) ] ;
1562
+ let flags = MsgFlags :: empty ( ) ;
1563
+ let l = sendmsg ( in_socket, & iov, & [ ] , flags, Some ( & address) ) . unwrap ( ) ;
1564
+ assert_eq ! ( message. len( ) , l) ;
1565
+ // Receive the message
1566
+ let mut buffer = vec ! [ 0u8 ; message. len( ) ] ;
1567
+ let mut cmsgspace = nix:: cmsg_space!( TimeSpec ) ;
1568
+ let iov = [ IoVec :: from_mut_slice ( & mut buffer) ] ;
1569
+ let r = recvmsg ( in_socket, & iov, Some ( & mut cmsgspace) , flags) . unwrap ( ) ;
1570
+ let rtime = match r. cmsgs ( ) . next ( ) {
1571
+ Some ( ControlMessageOwned :: ScmTimestampNs ( rtime) ) => rtime,
1572
+ Some ( _) => panic ! ( "Unexpected control message" ) ,
1573
+ None => panic ! ( "No control message" )
1574
+ } ;
1575
+ // Check the final time
1576
+ let time1 = SystemTime :: now ( ) ;
1577
+ // the packet's received timestamp should lie in-between the two system
1578
+ // times, unless the system clock was adjusted in the meantime.
1579
+ let rduration = Duration :: new ( rtime. tv_sec ( ) as u64 ,
1580
+ rtime. tv_nsec ( ) as u32 ) ;
1581
+ assert ! ( time0. duration_since( UNIX_EPOCH ) . unwrap( ) <= rduration) ;
1582
+ assert ! ( rduration <= time1. duration_since( UNIX_EPOCH ) . unwrap( ) ) ;
1583
+ // Close socket
1584
+ nix:: unistd:: close ( in_socket) . unwrap ( ) ;
1585
+ }
1586
+
1587
+ #[ cfg( all( target_os = "linux" , any( target_arch = "x86_64" , target_arch = "x86" ) , target_env = "gnu" ) ) ]
1588
+ #[ test]
1589
+ fn test_recvmmsg_timestampns ( ) {
1590
+ use nix:: sys:: socket:: * ;
1591
+ use nix:: sys:: uio:: IoVec ;
1592
+ use nix:: sys:: time:: * ;
1593
+ use std:: time:: * ;
1594
+
1595
+ // Set up
1596
+ let message = "Ohayō!" . as_bytes ( ) ;
1597
+ let in_socket = socket (
1598
+ AddressFamily :: Inet ,
1599
+ SockType :: Datagram ,
1600
+ SockFlag :: empty ( ) ,
1601
+ None ) . unwrap ( ) ;
1602
+ setsockopt ( in_socket, sockopt:: ReceiveTimestampNs , & true ) . unwrap ( ) ;
1603
+ let localhost = InetAddr :: new ( IpAddr :: new_v4 ( 127 , 0 , 0 , 1 ) , 0 ) ;
1604
+ bind ( in_socket, & SockAddr :: new_inet ( localhost) ) . unwrap ( ) ;
1605
+ let address = getsockname ( in_socket) . unwrap ( ) ;
1606
+ // Get initial time
1607
+ let time0 = SystemTime :: now ( ) ;
1608
+ // Send the message
1609
+ let iov = [ IoVec :: from_slice ( message) ] ;
1610
+ let flags = MsgFlags :: empty ( ) ;
1611
+ let l = sendmsg ( in_socket, & iov, & [ ] , flags, Some ( & address) ) . unwrap ( ) ;
1612
+ assert_eq ! ( message. len( ) , l) ;
1613
+ // Receive the message
1614
+ let mut buffer = vec ! [ 0u8 ; message. len( ) ] ;
1615
+ let mut cmsgspace = nix:: cmsg_space!( TimeSpec ) ;
1616
+ let iov = [ IoVec :: from_mut_slice ( & mut buffer) ] ;
1617
+ let mut data = vec ! [
1618
+ RecvMmsgData {
1619
+ iov,
1620
+ cmsg_buffer: Some ( & mut cmsgspace) ,
1621
+ } ,
1622
+ ] ;
1623
+ let r = recvmmsg ( in_socket, & mut data, flags, None ) . unwrap ( ) ;
1624
+ let rtime = match r[ 0 ] . cmsgs ( ) . next ( ) {
1625
+ Some ( ControlMessageOwned :: ScmTimestampNs ( rtime) ) => rtime,
1626
+ Some ( _) => panic ! ( "Unexpected control message" ) ,
1627
+ None => panic ! ( "No control message" )
1628
+ } ;
1629
+ // Check the final time
1630
+ let time1 = SystemTime :: now ( ) ;
1631
+ // the packet's received timestamp should lie in-between the two system
1632
+ // times, unless the system clock was adjusted in the meantime.
1633
+ let rduration = Duration :: new ( rtime. tv_sec ( ) as u64 ,
1634
+ rtime. tv_nsec ( ) as u32 ) ;
1635
+ assert ! ( time0. duration_since( UNIX_EPOCH ) . unwrap( ) <= rduration) ;
1636
+ assert ! ( rduration <= time1. duration_since( UNIX_EPOCH ) . unwrap( ) ) ;
1637
+ // Close socket
1638
+ nix:: unistd:: close ( in_socket) . unwrap ( ) ;
1639
+ }
0 commit comments