|
@@ -54,7 +54,10 @@ const (
|
|
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-var errTooManyInvalidRequest = errors.New("too many invalid requests made")
|
|
|
|
|
|
|
+var (
|
|
|
|
|
+ errTooManyInvalidRequest = errors.New("too many invalid requests made")
|
|
|
|
|
+ errFullClientPool = errors.New("client pool is full")
|
|
|
|
|
+)
|
|
|
|
|
|
|
|
// serverHandler is responsible for serving light client and process
|
|
// serverHandler is responsible for serving light client and process
|
|
|
// all incoming light requests.
|
|
// all incoming light requests.
|
|
@@ -124,23 +127,26 @@ func (h *serverHandler) handle(p *peer) error {
|
|
|
}
|
|
}
|
|
|
defer p.fcClient.Disconnect()
|
|
defer p.fcClient.Disconnect()
|
|
|
|
|
|
|
|
|
|
+ // Disconnect the inbound peer if it's rejected by clientPool
|
|
|
|
|
+ if !h.server.clientPool.connect(p, 0) {
|
|
|
|
|
+ p.Log().Debug("Light Ethereum peer registration failed", "err", errFullClientPool)
|
|
|
|
|
+ return errFullClientPool
|
|
|
|
|
+ }
|
|
|
// Register the peer locally
|
|
// Register the peer locally
|
|
|
if err := h.server.peers.Register(p); err != nil {
|
|
if err := h.server.peers.Register(p); err != nil {
|
|
|
|
|
+ h.server.clientPool.disconnect(p)
|
|
|
p.Log().Error("Light Ethereum peer registration failed", "err", err)
|
|
p.Log().Error("Light Ethereum peer registration failed", "err", err)
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len()))
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len()))
|
|
|
|
|
|
|
|
- // add dummy balance tracker for tests
|
|
|
|
|
- if p.balanceTracker == nil {
|
|
|
|
|
- p.balanceTracker = &balanceTracker{}
|
|
|
|
|
- p.balanceTracker.init(&mclock.System{}, 1)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ var wg sync.WaitGroup // Wait group used to track all in-flight task routines.
|
|
|
|
|
|
|
|
connectedAt := mclock.Now()
|
|
connectedAt := mclock.Now()
|
|
|
defer func() {
|
|
defer func() {
|
|
|
- p.balanceTracker = nil
|
|
|
|
|
|
|
+ wg.Wait() // Ensure all background task routines have exited.
|
|
|
h.server.peers.Unregister(p.id)
|
|
h.server.peers.Unregister(p.id)
|
|
|
|
|
+ h.server.clientPool.disconnect(p)
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len()))
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len()))
|
|
|
connectionTimer.Update(time.Duration(mclock.Now() - connectedAt))
|
|
connectionTimer.Update(time.Duration(mclock.Now() - connectedAt))
|
|
|
}()
|
|
}()
|
|
@@ -153,7 +159,7 @@ func (h *serverHandler) handle(p *peer) error {
|
|
|
return err
|
|
return err
|
|
|
default:
|
|
default:
|
|
|
}
|
|
}
|
|
|
- if err := h.handleMsg(p); err != nil {
|
|
|
|
|
|
|
+ if err := h.handleMsg(p, &wg); err != nil {
|
|
|
p.Log().Debug("Light Ethereum message handling failed", "err", err)
|
|
p.Log().Debug("Light Ethereum message handling failed", "err", err)
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
@@ -162,7 +168,7 @@ func (h *serverHandler) handle(p *peer) error {
|
|
|
|
|
|
|
|
// handleMsg is invoked whenever an inbound message is received from a remote
|
|
// handleMsg is invoked whenever an inbound message is received from a remote
|
|
|
// peer. The remote connection is torn down upon returning any error.
|
|
// peer. The remote connection is torn down upon returning any error.
|
|
|
-func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
|
|
|
|
+func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error {
|
|
|
// Read the next message from the remote peer, and ensure it's fully consumed
|
|
// Read the next message from the remote peer, and ensure it's fully consumed
|
|
|
msg, err := p.rw.ReadMsg()
|
|
msg, err := p.rw.ReadMsg()
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -243,7 +249,7 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
// Feed cost tracker request serving statistic.
|
|
// Feed cost tracker request serving statistic.
|
|
|
h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost)
|
|
h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost)
|
|
|
// Reduce priority "balance" for the specific peer.
|
|
// Reduce priority "balance" for the specific peer.
|
|
|
- p.balanceTracker.requestCost(realCost)
|
|
|
|
|
|
|
+ h.server.clientPool.requestCost(p, realCost)
|
|
|
}
|
|
}
|
|
|
if reply != nil {
|
|
if reply != nil {
|
|
|
p.queueSend(func() {
|
|
p.queueSend(func() {
|
|
@@ -273,7 +279,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
}
|
|
}
|
|
|
query := req.Query
|
|
query := req.Query
|
|
|
if accept(req.ReqID, query.Amount, MaxHeaderFetch) {
|
|
if accept(req.ReqID, query.Amount, MaxHeaderFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
hashMode := query.Origin.Hash != (common.Hash{})
|
|
hashMode := query.Origin.Hash != (common.Hash{})
|
|
|
first := true
|
|
first := true
|
|
|
maxNonCanonical := uint64(100)
|
|
maxNonCanonical := uint64(100)
|
|
@@ -387,7 +395,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
)
|
|
)
|
|
|
reqCnt := len(req.Hashes)
|
|
reqCnt := len(req.Hashes)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
for i, hash := range req.Hashes {
|
|
for i, hash := range req.Hashes {
|
|
|
if i != 0 && !task.waitOrStop() {
|
|
if i != 0 && !task.waitOrStop() {
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
@@ -433,7 +443,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
)
|
|
)
|
|
|
reqCnt := len(req.Reqs)
|
|
reqCnt := len(req.Reqs)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
for i, request := range req.Reqs {
|
|
for i, request := range req.Reqs {
|
|
|
if i != 0 && !task.waitOrStop() {
|
|
if i != 0 && !task.waitOrStop() {
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
@@ -502,7 +514,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
)
|
|
)
|
|
|
reqCnt := len(req.Hashes)
|
|
reqCnt := len(req.Hashes)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
for i, hash := range req.Hashes {
|
|
for i, hash := range req.Hashes {
|
|
|
if i != 0 && !task.waitOrStop() {
|
|
if i != 0 && !task.waitOrStop() {
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime)
|
|
@@ -557,7 +571,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
)
|
|
)
|
|
|
reqCnt := len(req.Reqs)
|
|
reqCnt := len(req.Reqs)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
nodes := light.NewNodeSet()
|
|
nodes := light.NewNodeSet()
|
|
|
|
|
|
|
|
for i, request := range req.Reqs {
|
|
for i, request := range req.Reqs {
|
|
@@ -658,7 +674,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
)
|
|
)
|
|
|
reqCnt := len(req.Reqs)
|
|
reqCnt := len(req.Reqs)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
var (
|
|
var (
|
|
|
lastIdx uint64
|
|
lastIdx uint64
|
|
|
lastType uint
|
|
lastType uint
|
|
@@ -725,7 +743,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
}
|
|
}
|
|
|
reqCnt := len(req.Txs)
|
|
reqCnt := len(req.Txs)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxSend) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxSend) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
stats := make([]light.TxStatus, len(req.Txs))
|
|
stats := make([]light.TxStatus, len(req.Txs))
|
|
|
for i, tx := range req.Txs {
|
|
for i, tx := range req.Txs {
|
|
|
if i != 0 && !task.waitOrStop() {
|
|
if i != 0 && !task.waitOrStop() {
|
|
@@ -771,7 +791,9 @@ func (h *serverHandler) handleMsg(p *peer) error {
|
|
|
}
|
|
}
|
|
|
reqCnt := len(req.Hashes)
|
|
reqCnt := len(req.Hashes)
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) {
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) {
|
|
|
|
|
+ wg.Add(1)
|
|
|
go func() {
|
|
go func() {
|
|
|
|
|
+ defer wg.Done()
|
|
|
stats := make([]light.TxStatus, len(req.Hashes))
|
|
stats := make([]light.TxStatus, len(req.Hashes))
|
|
|
for i, hash := range req.Hashes {
|
|
for i, hash := range req.Hashes {
|
|
|
if i != 0 && !task.waitOrStop() {
|
|
if i != 0 && !task.waitOrStop() {
|