// Deadlined socket read/write. https://github.com/golang/go/issues/16100 package godlighty import ( "net" "time" ) type DeadlinedConn struct { net.Conn ReadTimeout time.Duration WriteTimeout time.Duration ReadThreshold int64 WriteThreshold int64 BytesReadFromDeadline int64 BytesWrittenFromDeadline int64 } func (c *DeadlinedConn) Read(b []byte) (n int, err error) { if c.BytesReadFromDeadline > c.ReadThreshold { c.BytesReadFromDeadline = 0 err = c.Conn.SetDeadline(time.Now().Add(c.ReadTimeout)) if err != nil { return } } n, err = c.Conn.Read(b) c.BytesReadFromDeadline += int64(n) return } func (c *DeadlinedConn) Write(b []byte) (n int, err error) { if c.BytesWrittenFromDeadline > c.WriteThreshold { c.BytesWrittenFromDeadline = 0 err = c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout)) if err != nil { return } } n, err = c.Conn.Write(b) c.BytesWrittenFromDeadline += int64(n) return } type DeadlinedListener struct { net.Listener ReadTimeout time.Duration WriteTimeout time.Duration } func (l *DeadlinedListener) Accept() (net.Conn, error) { c, err := l.Listener.Accept() if err != nil { return nil, err } return &DeadlinedConn{ Conn: c, ReadTimeout: l.ReadTimeout, WriteTimeout: l.WriteTimeout, ReadThreshold: int64((l.ReadTimeout * 1024) / time.Second), WriteThreshold: int64((l.WriteTimeout * 1024) / time.Second), }, nil } func DeadlinedListen( network, addr string, readTimeout, writeTimeout time.Duration, ) (net.Listener, error) { l, err := net.Listen(network, addr) if err != nil { return nil, err } return &DeadlinedListener{ Listener: l, ReadTimeout: readTimeout, WriteTimeout: writeTimeout, }, nil }