diff options
Diffstat (limited to 'eth/downloader/peer.go')
-rw-r--r-- | eth/downloader/peer.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go new file mode 100644 index 000000000..f66e5afd8 --- /dev/null +++ b/eth/downloader/peer.go @@ -0,0 +1,97 @@ +package downloader + +import ( + "errors" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum/common" +) + +const ( + workingState = 2 + idleState = 4 +) + +type hashFetcherFn func(common.Hash) error +type blockFetcherFn func([]common.Hash) error + +// XXX make threadsafe!!!! +type peers map[string]*peer + +func (p peers) get(state int) []*peer { + var peers []*peer + for _, peer := range p { + peer.mu.RLock() + if peer.state == state { + peers = append(peers, peer) + } + peer.mu.RUnlock() + } + + return peers +} + +func (p peers) setState(id string, state int) { + if peer, exist := p[id]; exist { + peer.mu.Lock() + defer peer.mu.Unlock() + peer.state = state + } +} + +func (p peers) getPeer(id string) *peer { + return p[id] +} + +func (p peers) bestPeer() *peer { + var peer *peer + for _, cp := range p { + if peer == nil || cp.td.Cmp(peer.td) > 0 { + peer = cp + } + } + return peer +} + +// peer represents an active peer +type peer struct { + state int // Peer state (working, idle) + rep int // TODO peer reputation + + mu sync.RWMutex + id string + td *big.Int + recentHash common.Hash + + getHashes hashFetcherFn + getBlocks blockFetcherFn +} + +// create a new peer +func newPeer(id string, td *big.Int, hash common.Hash, getHashes hashFetcherFn, getBlocks blockFetcherFn) *peer { + return &peer{id: id, td: td, recentHash: hash, getHashes: getHashes, getBlocks: getBlocks, state: idleState} +} + +// fetch a chunk using the peer +func (p *peer) fetch(chunk *chunk) error { + p.mu.Lock() + defer p.mu.Unlock() + + if p.state == workingState { + return errors.New("peer already fetching chunk") + } + + // set working state + p.state = workingState + // convert the set to a fetchable slice + hashes, i := make([]common.Hash, chunk.hashes.Size()), 0 + chunk.hashes.Each(func(v interface{}) bool { + hashes[i] = v.(common.Hash) + i++ + return true + }) + p.getBlocks(hashes) + + return nil +} |