9 func tryClose(ch chan struct{}) (ok bool) {
10 defer func() { recover() }()
23 func (c *udpClt) mkConn() {
24 conn := newConn(c, c.id, PeerIDSrv)
29 conn.sendRaw(func(buf []byte) int {
30 buf[0] = uint8(rawCtl)
31 buf[1] = uint8(ctlSetPeerID)
32 be.PutUint16(buf[2:4], uint16(conn.ID()))
36 case c.l.conns <- conn:
42 func (c *udpClt) Write(pkt []byte) (int, error) {
45 return 0, net.ErrClosed
49 return c.l.pc.WriteTo(pkt, c.addr)
52 func (c *udpClt) recvUDP() ([]byte, error) {
57 return nil, net.ErrClosed
61 func (c *udpClt) Close() error {
62 if !tryClose(c.closed) {
70 delete(c.l.clts, c.addr.String())
75 func (c *udpClt) LocalAddr() net.Addr { return c.l.pc.LocalAddr() }
76 func (c *udpClt) RemoteAddr() net.Addr { return c.addr }
78 // All Listener's methods are safe for concurrent use.
79 type Listener struct {
90 clts map[string]*udpClt
93 // Listen listens for connections on pc, pc is closed once the returned Listener
94 // and all Conns connected through it are closed.
95 func Listen(pc net.PacketConn) *Listener {
99 conns: make(chan *Conn),
100 closed: make(chan struct{}),
102 ids: make(map[PeerID]bool),
103 clts: make(map[string]*udpClt),
108 if err := l.processNetPkt(); err != nil {
109 if errors.Is(err, net.ErrClosed) {
123 // Accept waits for and returns the next incoming Conn or an error.
124 func (l *Listener) Accept() (*Conn, error) {
128 case err := <-l.errs:
131 return nil, net.ErrClosed
135 // Close makes the Listener stop listening for new Conns.
136 // Blocked Accept calls will return net.ErrClosed.
137 // Already Accepted Conns are not closed.
138 func (l *Listener) Close() error {
139 if !tryClose(l.closed) {
151 // Addr returns the Listener's network address.
152 func (l *Listener) Addr() net.Addr { return l.pc.LocalAddr() }
154 var ErrOutOfPeerIDs = errors.New("out of peer ids")
156 func (l *Listener) processNetPkt() error {
157 buf := make([]byte, maxUDPPktSize)
158 n, addr, err := l.pc.ReadFrom(buf)
164 clt, ok := l.clts[addr.String()]
173 clt, err = l.add(addr)
180 case clt.pkts <- buf[:n]:
187 func (l *Listener) add(addr net.Addr) (*udpClt, error) {
193 for l.peerID < PeerIDCltMin || l.ids[l.peerID] {
194 if l.peerID == start {
195 return nil, ErrOutOfPeerIDs
199 l.ids[l.peerID] = true
205 pkts: make(chan []byte),
206 closed: make(chan struct{}),
208 l.clts[addr.String()] = clt