-
Notifications
You must be signed in to change notification settings - Fork 103
/
server.go
118 lines (100 loc) · 3.23 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* @file
* @copyright defined in go-seele/LICENSE
*/
package light
import (
rand2 "math/rand"
"time"
"github.com/seeleteam/go-seele/common"
"github.com/seeleteam/go-seele/core/types"
"github.com/seeleteam/go-seele/event"
"github.com/seeleteam/go-seele/log"
"github.com/seeleteam/go-seele/node"
"github.com/seeleteam/go-seele/p2p"
"github.com/seeleteam/go-seele/rpc"
"github.com/seeleteam/go-seele/seele"
)
// ServiceServer implements light server service.
type ServiceServer struct {
p2pServer *p2p.Server
seeleProtocol *LightProtocol
log *log.SeeleLog
shard uint
}
// NewServiceServer create ServiceServer
func NewServiceServer(service *seele.SeeleService, conf *node.Config, log *log.SeeleLog, shard uint) (*ServiceServer, error) {
seeleProtocol, err := NewLightProtocol(conf.P2PConfig.NetworkID, service.TxPool(), service.DebtPool(), service.BlockChain(), true, nil, log, shard)
if err != nil {
return nil, err
}
s := &ServiceServer{
log: log,
seeleProtocol: seeleProtocol,
}
rand2.Seed(time.Now().UnixNano())
s.log.Info("Light server started")
return s, nil
}
// Protocols implements node.Service, returning all the currently configured
// network protocols to start.
func (s *ServiceServer) Protocols() (protos []p2p.Protocol) {
return append(protos, s.seeleProtocol.Protocol)
}
// Start implements node.Service, starting goroutines needed by ServiceServer.
func (s *ServiceServer) Start(srvr *p2p.Server) error {
s.p2pServer = srvr
s.seeleProtocol.Start()
go s.seeleProtocol.blockLoop()
return nil
}
// Stop implements node.Service, terminating all internal goroutines.
func (s *ServiceServer) Stop() error {
s.seeleProtocol.Stop()
return nil
}
// APIs implements node.Service, returning the collection of RPC services the seele package offers.
func (s *ServiceServer) APIs() (apis []rpc.API) {
return
}
func (pm *LightProtocol) chainHeaderChanged(e event.Event) {
newBlock := e.(*types.Block)
if newBlock == nil || newBlock.HeaderHash.IsEmpty() {
return
}
pm.chainHeaderChangeCh <- newBlock.HeaderHash
}
// as light node server, when this node's chain header has changed, broadcast it to all light node client peers
func (pm *LightProtocol) blockLoop() {
pm.wg.Add(1)
defer pm.wg.Done()
pm.chainHeaderChangeCh = make(chan common.Hash, 1)
event.ChainHeaderChangedEventMananger.AddAsyncListener(pm.chainHeaderChanged)
needQuit:
for {
select {
case <-pm.chainHeaderChangeCh:
magic := rand2.Uint32()
peers := pm.peerSet.getPeers()
for _, p := range peers {
if p != nil {
if lastTime, ok := pm.peerSet.peerLastAnnounceTimeMap[p]; ok && (time.Now().Unix()-lastTime < 5 ) {
pm.log.Debug("blockLoop sendAnnounce cancelled,magic:%d,peer:%s",magic,p.peerStrID)
continue
}
pm.peerSet.peerLastAnnounceTimeMap[p] = time.Now().Unix()
pm.log.Debug("blockLoop sendAnnounce,magic:%d,peer:%s",magic,p.peerStrID)
err := p.sendAnnounce(magic, uint64(0), uint64(0))
if err != nil {
pm.log.Debug("blockLoop sendAnnounce err=%s", err)
}
}
}
pm.log.Debug("blockLoop head changed. ")
case <-pm.quitCh:
break needQuit
}
}
event.ChainHeaderChangedEventMananger.RemoveListener(pm.chainHeaderChanged)
close(pm.chainHeaderChangeCh)
}