mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
177 lines
3.5 KiB
Go
177 lines
3.5 KiB
Go
package network
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
// "github.com/ethereum/go-ethereum/p2p/adapters"
|
|
// "github.com/ethereum/go-ethereum/p2p/discover"
|
|
"github.com/ethereum/go-ethereum/logger/glog"
|
|
)
|
|
|
|
const orders = 8
|
|
|
|
type testOverlay struct {
|
|
mu sync.Mutex
|
|
addr []byte
|
|
pos [][]*testPeerAddr
|
|
posMap map[string]*testPeerAddr
|
|
}
|
|
|
|
type testPeerAddr struct {
|
|
PeerAddr
|
|
Peer Peer
|
|
}
|
|
|
|
func (self *testOverlay) Register(nas ...PeerAddr) error {
|
|
self.mu.Lock()
|
|
defer self.mu.Unlock()
|
|
return self.register(nas...)
|
|
}
|
|
|
|
func (self *testOverlay) register(nas ...PeerAddr) error {
|
|
for _, na := range nas {
|
|
tna := &testPeerAddr{PeerAddr: na}
|
|
addr := na.OverlayAddr()
|
|
if self.posMap[string(addr)] != nil {
|
|
continue
|
|
}
|
|
self.posMap[string(addr)] = tna
|
|
o := order(addr)
|
|
glog.V(6).Infof("PO: %v, orders: %v", o, orders)
|
|
self.pos[o] = append(self.pos[o], tna)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func order(addr []byte) int {
|
|
return int(addr[0]) / 32
|
|
}
|
|
|
|
func (self *testOverlay) On(n Peer) {
|
|
self.mu.Lock()
|
|
defer self.mu.Unlock()
|
|
addr := n.OverlayAddr()
|
|
na := self.posMap[string(addr)]
|
|
if na == nil {
|
|
self.register(n)
|
|
na = self.posMap[string(addr)]
|
|
} else if na.Peer != nil {
|
|
return
|
|
}
|
|
glog.V(6).Infof("Online: %v", fmt.Sprintf("%x", addr[:4]))
|
|
na.Peer = n
|
|
return
|
|
}
|
|
|
|
func (self *testOverlay) Off(n Peer) {
|
|
self.mu.Lock()
|
|
defer self.mu.Unlock()
|
|
addr := n.OverlayAddr()
|
|
na := self.posMap[string(addr)]
|
|
if na == nil {
|
|
return
|
|
}
|
|
delete(self.posMap, string(addr))
|
|
na.Peer = nil
|
|
}
|
|
|
|
// caller must hold the lock
|
|
func (self *testOverlay) on(po []*testPeerAddr) (nodes []Peer) {
|
|
for _, na := range po {
|
|
if na.Peer != nil {
|
|
nodes = append(nodes, na.Peer)
|
|
}
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
// caller must hold the lock
|
|
func (self *testOverlay) off(po []*testPeerAddr) (nas []PeerAddr) {
|
|
for _, na := range po {
|
|
if na.Peer == nil {
|
|
nas = append(nas, PeerAddr(na))
|
|
}
|
|
}
|
|
return nas
|
|
}
|
|
|
|
func (self *testOverlay) EachLivePeer(base []byte, o int, f func(Peer, int) bool) {
|
|
if base == nil {
|
|
base = self.addr
|
|
}
|
|
for i := o; i < len(self.pos); i++ {
|
|
for _, na := range self.pos[i] {
|
|
if na.Peer != nil {
|
|
if !f(na.Peer, o) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (self *testOverlay) EachPeer(base []byte, o int, f func(PeerAddr, int) bool) {
|
|
if base == nil {
|
|
base = self.addr
|
|
}
|
|
for i := o; i < len(self.pos); i++ {
|
|
for _, na := range self.pos[i] {
|
|
if !f(na, i) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (self *testOverlay) SuggestPeer() (PeerAddr, int, bool) {
|
|
self.mu.Lock()
|
|
defer self.mu.Unlock()
|
|
for i, po := range self.pos {
|
|
ons := self.on(po)
|
|
if len(ons) < 2 {
|
|
offs := self.off(po)
|
|
if len(offs) > 0 {
|
|
glog.V(6).Infof("node %v is off", offs[0])
|
|
return offs[0], i, true
|
|
}
|
|
}
|
|
}
|
|
return nil, 0, true
|
|
}
|
|
|
|
func (self *testOverlay) String() string {
|
|
self.mu.Lock()
|
|
defer self.mu.Unlock()
|
|
var t []string
|
|
var ons, offs int
|
|
var ns []Peer
|
|
var nas []PeerAddr
|
|
for o, po := range self.pos {
|
|
var row []string
|
|
ns = self.on(po)
|
|
nas = self.off(po)
|
|
ons = len(ns)
|
|
for _, n := range ns {
|
|
addr := n.OverlayAddr()
|
|
row = append(row, fmt.Sprintf("%x", addr[:4]))
|
|
}
|
|
row = append(row, "|")
|
|
offs = len(nas)
|
|
for _, na := range nas {
|
|
addr := na.OverlayAddr()
|
|
row = append(row, fmt.Sprintf("%x", addr[:4]))
|
|
}
|
|
t = append(t, fmt.Sprintf("%v: (%v/%v) %v", o, ons, offs, strings.Join(row, " ")))
|
|
}
|
|
return strings.Join(t, "\n")
|
|
}
|
|
|
|
func NewTestOverlay(addr []byte) *testOverlay {
|
|
return &testOverlay{
|
|
addr: addr,
|
|
posMap: make(map[string]*testPeerAddr),
|
|
pos: make([][]*testPeerAddr, orders),
|
|
}
|
|
}
|