10 // A Conn is a connection to a client or server.
11 // All Conn's methods are safe for concurrent use.
30 chans [ChannelCount]pktChan // read/write
33 // ID returns the PeerID of the Conn.
34 func (c *Conn) ID() PeerID { return c.id }
36 // IsSrv reports whether the Conn is a connection to a server.
37 func (c *Conn) IsSrv() bool { return c.ID() == PeerIDSrv }
39 // Closed returns a channel which is closed when the Conn is closed.
40 func (c *Conn) Closed() <-chan struct{} { return c.closed }
42 // WhyClosed returns the error that caused the Conn to be closed or nil
43 // if the Conn was closed using the Close method or by the peer.
44 // WhyClosed returns nil if the Conn is not closed.
45 func (c *Conn) WhyClosed() error {
54 // LocalAddr returns the local network address.
55 func (c *Conn) LocalAddr() net.Addr { return c.udpConn.LocalAddr() }
57 // RemoteAddr returns the remote network address.
58 func (c *Conn) RemoteAddr() net.Addr { return c.udpConn.RemoteAddr() }
61 // Only accessed by Conn.recvUDPPkts goroutine.
62 inRels *[0x8000][]byte
64 sendAck func() (<-chan struct{}, error)
67 inSplitsMu sync.RWMutex
68 inSplits map[seqnum]*inSplit
70 ackChans sync.Map // map[seqnum]chan struct{}
86 // Close closes the Conn.
87 // Any blocked Send or Recv calls will return net.ErrClosed.
88 func (c *Conn) Close() error {
89 return c.closeDisco(nil)
92 func (c *Conn) closeDisco(err error) error {
93 c.sendRaw(func(buf []byte) int {
94 buf[0] = uint8(rawCtl)
95 buf[1] = uint8(ctlDisco)
97 }, PktInfo{Unrel: true})()
102 func (c *Conn) close(err error) error {
103 if atomic.SwapUint32(&c.closing, 1) == 1 {
111 defer close(c.closed)
113 return c.udpConn.Close()
116 func newConn(uc udpConn, id, remoteID PeerID) *Conn {
123 pkts: make(chan Pkt),
124 errs: make(chan error),
126 timeout: time.AfterFunc(ConnTimeout, func() {
127 c.closeDisco(ErrTimedOut)
129 ping: time.NewTicker(PingTimeout),
131 closed: make(chan struct{}),
136 for i := range c.chans {
137 c.chans[i] = pktChan{
138 inRels: new([0x8000][]byte),
141 inSplits: make(map[seqnum]*inSplit),
143 outSplitSN: initSeqnum,
145 outRelSN: initSeqnum,
146 outRelWin: initSeqnum,
152 go c.sendPings(c.ping.C)
158 func (c *Conn) sendPings(ping <-chan time.Time) {
159 send := c.sendRaw(func(buf []byte) int {
160 buf[0] = uint8(rawCtl)
161 buf[1] = uint8(ctlPing)