github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/p2p/discover/mdns/lan_discover.go (about) 1 package mdns 2 3 import ( 4 "net" 5 "sync/atomic" 6 "time" 7 8 log "github.com/sirupsen/logrus" 9 10 "github.com/bytom/bytom/event" 11 ) 12 13 const ( 14 logModule = "p2p/mdns" 15 registerServiceCycle = 10 * time.Minute 16 registerServiceDelay = 2 * time.Second 17 ) 18 19 // LANPeerEvent represent LAN peer ip and port. 20 type LANPeerEvent struct { 21 IP []net.IP 22 Port int 23 } 24 25 // mDNSProtocol mdns protocol interface. 26 type mDNSProtocol interface { 27 registerService(port int) error 28 registerResolver(event chan LANPeerEvent) error 29 stopService() 30 stopResolver() 31 } 32 33 // LANDiscover responsible for finding the related services registered LAN nodes. 34 type LANDiscover struct { 35 protocol mDNSProtocol 36 resolving uint32 37 servicePort int //service port 38 entries chan LANPeerEvent 39 eventDispatcher *event.Dispatcher 40 quite chan struct{} 41 } 42 43 // NewLANDiscover create a new LAN node discover. 44 func NewLANDiscover(protocol mDNSProtocol, port int) *LANDiscover { 45 ld := &LANDiscover{ 46 protocol: protocol, 47 servicePort: port, 48 entries: make(chan LANPeerEvent, 1024), 49 eventDispatcher: event.NewDispatcher(), 50 quite: make(chan struct{}), 51 } 52 // register service 53 go ld.registerServiceRoutine() 54 go ld.getLANPeerLoop() 55 return ld 56 } 57 58 // Stop stop LAN discover. 59 func (ld *LANDiscover) Stop() { 60 close(ld.quite) 61 ld.protocol.stopResolver() 62 ld.protocol.stopService() 63 ld.eventDispatcher.Stop() 64 } 65 66 // Subscribe used to subscribe for LANPeerEvent. 67 func (ld *LANDiscover) Subscribe() (*event.Subscription, error) { 68 //subscribe LANPeerEvent. 69 sub, err := ld.eventDispatcher.Subscribe(LANPeerEvent{}) 70 if err != nil { 71 return nil, err 72 } 73 74 //need to register the parser once. 75 if atomic.CompareAndSwapUint32(&ld.resolving, 0, 1) { 76 if err = ld.protocol.registerResolver(ld.entries); err != nil { 77 return nil, err 78 } 79 } 80 81 return sub, nil 82 } 83 84 // register service routine, will be re-registered periodically 85 // for the stability of node discovery. 86 func (ld *LANDiscover) registerServiceRoutine() { 87 time.Sleep(registerServiceDelay) 88 if err := ld.protocol.registerService(ld.servicePort); err != nil { 89 log.WithFields(log.Fields{"module": logModule, "err": err}).Error("mdns service register error") 90 return 91 } 92 93 ticker := time.NewTicker(registerServiceCycle) 94 defer ticker.Stop() 95 for { 96 select { 97 case <-ticker.C: 98 ld.protocol.stopService() 99 if err := ld.protocol.registerService(ld.servicePort); err != nil { 100 log.WithFields(log.Fields{"module": logModule, "err": err}).Error("mdns service register error") 101 return 102 } 103 case <-ld.quite: 104 return 105 } 106 } 107 } 108 109 // obtain the lan peer event from the specific protocol 110 // and distribute it to the subscriber. 111 func (ld *LANDiscover) getLANPeerLoop() { 112 for { 113 select { 114 case entry := <-ld.entries: 115 if err := ld.eventDispatcher.Post(entry); err != nil { 116 log.WithFields(log.Fields{"module": logModule, "err": err}).Error("event dispatch error") 117 } 118 case <-ld.quite: 119 return 120 } 121 } 122 }