1package daemon
 2
 3import (
 4	"context"
 5	"net"
 6	"time"
 7)
 8
 9type serverConn struct {
10	net.Conn
11
12	idleTimeout   time.Duration
13	maxDeadline   time.Time
14	closeCanceler context.CancelFunc
15}
16
17func (c *serverConn) Write(p []byte) (n int, err error) {
18	c.updateDeadline()
19	n, err = c.Conn.Write(p)
20	if _, isNetErr := err.(net.Error); isNetErr && c.closeCanceler != nil {
21		c.closeCanceler()
22	}
23	return
24}
25
26func (c *serverConn) Read(b []byte) (n int, err error) {
27	c.updateDeadline()
28	n, err = c.Conn.Read(b)
29	if _, isNetErr := err.(net.Error); isNetErr && c.closeCanceler != nil {
30		c.closeCanceler()
31	}
32	return
33}
34
35func (c *serverConn) Close() (err error) {
36	err = c.Conn.Close()
37	if c.closeCanceler != nil {
38		c.closeCanceler()
39	}
40	return
41}
42
43func (c *serverConn) updateDeadline() {
44	switch {
45	case c.idleTimeout > 0:
46		idleDeadline := time.Now().Add(c.idleTimeout)
47		if idleDeadline.Unix() < c.maxDeadline.Unix() || c.maxDeadline.IsZero() {
48			c.Conn.SetDeadline(idleDeadline)
49			return
50		}
51		fallthrough
52	default:
53		c.Conn.SetDeadline(c.maxDeadline)
54	}
55}