11 type Listener struct {
18 addr2peer map[string]cltPeer
19 id2peer map[PeerID]cltPeer
23 // Listen listens for packets on conn until it is closed.
24 func Listen(conn net.PacketConn) *Listener {
28 clts: make(chan cltPeer),
29 errs: make(chan error),
31 addr2peer: make(map[string]cltPeer),
32 id2peer: make(map[PeerID]cltPeer),
35 pkts := make(chan netPkt)
36 go readNetPkts(l.conn, pkts, l.errs)
38 for pkt := range pkts {
39 if err := l.processNetPkt(pkt); err != nil {
46 for _, clt := range l.addr2peer {
54 // Accept waits for and returns a connecting Peer.
55 // You should keep calling this until it returns ErrClosed
56 // so it doesn't leak a goroutine.
57 func (l *Listener) Accept() (*Peer, error) {
59 case clt, ok := <-l.clts:
75 // Addr returns the net.PacketConn the Listener is listening on.
76 func (l *Listener) Conn() net.PacketConn { return l.conn }
78 var ErrOutOfPeerIDs = errors.New("out of peer ids")
83 accepted chan struct{} // close-only
86 func (l *Listener) processNetPkt(pkt netPkt) error {
90 addrstr := pkt.SrcAddr.String()
92 clt, ok := l.addr2peer[addrstr]
95 for l.id2peer[l.peerid].Peer != nil || l.peerid < PeerIDCltMin {
96 if l.peerid == prev-1 {
97 return ErrOutOfPeerIDs
102 pkts := make(chan netPkt, 256)
105 Peer: newPeer(l.conn, pkt.SrcAddr, l.peerid, PeerIDSrv),
107 accepted: make(chan struct{}),
110 l.addr2peer[addrstr] = clt
111 l.id2peer[clt.ID()] = clt
113 data := make([]byte, 1+1+2)
114 data[0] = uint8(rawTypeCtl)
115 data[1] = uint8(ctlSetPeerID)
116 binary.BigEndian.PutUint16(data[2:4], uint16(clt.ID()))
117 if _, err := clt.sendRaw(rawPkt{Data: data}); err != nil {
118 return fmt.Errorf("can't set client peer id: %w", err)
127 clt.processNetPkts(pkts)
135 delete(l.addr2peer, addrstr)
136 delete(l.id2peer, clt.ID())
146 case clt.pkts <- pkt:
148 return fmt.Errorf("ignoring net pkt from %s because buf is full", addrstr)