@@ -14,55 +14,63 @@ import (
1414 "golang.org/x/sys/unix"
1515)
1616
17- func newConn (base net.Conn , getTime func () time.Time , timeout time.Duration ) conn {
18- return newConnFallback (base , getTime )
17+ type connLinux struct {
18+ base net.Conn
19+ udpConn * net.UDPConn
20+ msgBuf []byte
21+ ctrlBuf []byte
22+ getTime func () time.Time
1923}
2024
21- // enableHardwareTimestamps enables SO_TIMESTAMPNS on the UDP connection to
22- // get kernel-level receive timestamps with nanosecond precision.
23- func enableHardwareTimestamps (conn net.Conn ) error {
24- udpConn , ok := conn .(* net.UDPConn )
25+ func newConn (base net.Conn , opt * QueryOptions ) (conn , error ) {
26+ udpConn , ok := base .(* net.UDPConn )
2527 if ! ok {
26- return nil
28+ return newConnFallback ( base , opt )
2729 }
2830
2931 rawConn , err := udpConn .SyscallConn ()
3032 if err != nil {
31- return err
33+ return newConnFallback ( base , opt )
3234 }
3335
3436 var setErr error
3537 err = rawConn .Control (func (fd uintptr ) {
3638 setErr = unix .SetsockoptInt (int (fd ), unix .SOL_SOCKET , unix .SO_TIMESTAMPNS , 1 )
3739 })
38- if err != nil {
39- return err
40+ if err != nil || setErr != nil {
41+ return newConnFallback ( base , opt )
4042 }
41- return setErr
42- }
4343
44- // readWithTimestamp reads from the connection and returns both the data and
45- // the kernel-level receive timestamp (if available).
46- func readWithTimestamp (conn net.Conn , b , oob []byte , opt * QueryOptions ) (n int , recvTime time.Time , err error ) {
47- // If we don't have a UDP connection, fallback to imprecise time.
48- udpConn , ok := conn .(* net.UDPConn )
49- if ! ok {
50- n , err = conn .Read (b )
51- return n , opt .GetSystemTime (), err
44+ if err := applyOptions (base , opt ); err != nil {
45+ return newConnFallback (base , opt )
46+ }
47+
48+ conn := & connLinux {
49+ base : base ,
50+ udpConn : udpConn ,
51+ msgBuf : make ([]byte , 8192 ),
52+ ctrlBuf : make ([]byte , 128 ),
53+ getTime : opt .GetSystemTime ,
5254 }
55+ return conn , nil
56+ }
57+
58+ func (c * connLinux ) Close () error {
59+ return c .base .Close ()
60+ }
5361
54- // Read message with out-of-band control data.
55- n , on , _ , _ , err := udpConn .ReadMsgUDP (b , oob )
62+ func ( c * connLinux ) Read () ( b [] byte , recvTime time. Time , err error ) {
63+ n , cn , _ , _ , err := c . udpConn .ReadMsgUDP (c . msgBuf , c . ctrlBuf )
5664 if err != nil {
57- return n , opt . GetSystemTime () , err
65+ return nil , time. Time {} , err
5866 }
5967
60- // Get imprecise time in case we can't get a kernel timestamp.
61- recvTime = opt . GetSystemTime ()
68+ // Get imprecise time in case we can't get a hardware timestamp.
69+ recvTime = c . getTime ()
6270
6371 // Parse control messages to extract timestamp.
64- if on > 0 {
65- msgs , parseErr := unix .ParseSocketControlMessage (oob [: on ])
72+ if cn > 0 {
73+ msgs , parseErr := unix .ParseSocketControlMessage (c . ctrlBuf [: cn ])
6674 if parseErr == nil {
6775 for _ , m := range msgs {
6876 // Try nanosecond precision first.
@@ -84,5 +92,9 @@ func readWithTimestamp(conn net.Conn, b, oob []byte, opt *QueryOptions) (n int,
8492 }
8593 }
8694
87- return n , recvTime , nil
95+ return c .msgBuf [:n ], recvTime , nil
96+ }
97+
98+ func (c * connLinux ) Write (b []byte ) (n int , err error ) {
99+ return c .base .Write (b )
88100}
0 commit comments