mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
whisper: process incoming packets
This commit is contained in:
parent
9483cfb1e8
commit
57d7b21a14
2 changed files with 85 additions and 26 deletions
|
|
@ -30,6 +30,7 @@ import (
|
||||||
inet "github.com/libp2p/go-libp2p-net"
|
inet "github.com/libp2p/go-libp2p-net"
|
||||||
peer "github.com/libp2p/go-libp2p-peer"
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
set "gopkg.in/fatih/set.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LibP2PStream is a wrapper used to implement the MsgReadWriter
|
// LibP2PStream is a wrapper used to implement the MsgReadWriter
|
||||||
|
|
@ -116,25 +117,73 @@ func (stream *LibP2PStream) WriteMsg(msg p2p.Msg) error {
|
||||||
|
|
||||||
// LibP2PPeer implements Peer for libp2p
|
// LibP2PPeer implements Peer for libp2p
|
||||||
type LibP2PPeer struct {
|
type LibP2PPeer struct {
|
||||||
PeerBase
|
*PeerBase
|
||||||
|
|
||||||
id peer.ID
|
id peer.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newLibP2PPeer(w *Whisper, pid peer.ID, rw p2p.MsgReadWriter) Peer {
|
||||||
|
return &LibP2PPeer{
|
||||||
|
&PeerBase{
|
||||||
|
host: w,
|
||||||
|
ws: rw,
|
||||||
|
trusted: false,
|
||||||
|
powRequirement: 0.0,
|
||||||
|
known: set.New(),
|
||||||
|
quit: make(chan struct{}),
|
||||||
|
bloomFilter: makeFullNodeBloom(),
|
||||||
|
fullNode: true,
|
||||||
|
},
|
||||||
|
pid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ID returns the id of the peer
|
// ID returns the id of the peer
|
||||||
func (p *LibP2PPeer) ID() string {
|
func (p *LibP2PPeer) ID() string {
|
||||||
return p.id.String()
|
return p.id.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *LibP2PPeer) handshake() error {
|
||||||
|
err := p.handshakeBase()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("peer [%x] %s", p.ID(), err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// LibP2PWhisperServer implements WhisperServer for libp2p.
|
// LibP2PWhisperServer implements WhisperServer for libp2p.
|
||||||
type LibP2PWhisperServer struct {
|
type LibP2PWhisperServer struct {
|
||||||
Host host.Host
|
Host host.Host
|
||||||
|
|
||||||
Peers []LibP2PPeer
|
Peers []*LibP2PPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the server
|
// Start starts the server
|
||||||
func (server *LibP2PWhisperServer) Start() error {
|
func (server *LibP2PWhisperServer) Start() error {
|
||||||
|
server.Host.SetStreamHandler(WhisperProtocolString, func (stream inet.Stream) {
|
||||||
|
defer stream.Close()
|
||||||
|
|
||||||
|
pid := stream.Conn().RemotePeer()
|
||||||
|
var peer Peer
|
||||||
|
for _, p := range server.Peers {
|
||||||
|
if p.id == pid {
|
||||||
|
peer = p
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
whisper := server.Peers[0].host
|
||||||
|
lps := &LibP2PStream{stream}
|
||||||
|
|
||||||
|
// Unknown peer
|
||||||
|
if peer == nil {
|
||||||
|
peer = newLibP2PPeer(whisper, pid, lps)
|
||||||
|
// TODO check critical section
|
||||||
|
server.Peers = append(server.Peers, peer.(*LibP2PPeer))
|
||||||
|
}
|
||||||
|
|
||||||
|
whisper.runMessageLoop(peer, lps)
|
||||||
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,5 +228,7 @@ func NewLibP2PWhisperServer() (WhisperServer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error setting up the libp2p network: %s", err)
|
return nil, fmt.Errorf("Error setting up the libp2p network: %s", err)
|
||||||
}
|
}
|
||||||
return &LibP2PWhisperServer{h, []LibP2PPeer{}}, nil
|
|
||||||
|
server := &LibP2PWhisperServer{h, []*LibP2PPeer{}}
|
||||||
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,20 +95,28 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) Peer {
|
||||||
|
|
||||||
// start initiates the peer updater, periodically broadcasting the whisper packets
|
// start initiates the peer updater, periodically broadcasting the whisper packets
|
||||||
// into the network.
|
// into the network.
|
||||||
func (peer *DevP2PPeer) start() {
|
func (peer *PeerBase) start() {
|
||||||
go peer.update()
|
go peer.update()
|
||||||
log.Trace("start", "peer", peer.ID())
|
// log.Trace("start", "peer", peer.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop terminates the peer updater, stopping message forwarding to it.
|
// stop terminates the peer updater, stopping message forwarding to it.
|
||||||
func (peer *DevP2PPeer) stop() {
|
func (peer *PeerBase) stop() {
|
||||||
close(peer.quit)
|
close(peer.quit)
|
||||||
log.Trace("stop", "peer", peer.ID())
|
// log.Trace("stop", "peer", peer.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// handshake sends the protocol initiation status message to the remote peer and
|
// handshake sends the protocol initiation status message to the remote peer and
|
||||||
// verifies the remote status too.
|
// verifies the remote status too.
|
||||||
func (peer *DevP2PPeer) handshake() error {
|
func (peer *DevP2PPeer) handshake() error {
|
||||||
|
err := peer.handshakeBase()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("peer [%x] %s", peer.ID(), err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (peer *PeerBase) handshakeBase() error {
|
||||||
// Send the handshake status message asynchronously
|
// Send the handshake status message asynchronously
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -124,19 +132,19 @@ func (peer *DevP2PPeer) handshake() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if packet.Code != statusCode {
|
if packet.Code != statusCode {
|
||||||
return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
|
return fmt.Errorf("peer [%s] sent packet %x before status packet", peer.ID(), packet.Code)
|
||||||
}
|
}
|
||||||
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
|
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
|
||||||
_, err = s.List()
|
_, err = s.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
|
return fmt.Errorf("peer [%s] sent bad status message: %v", peer.ID(), err)
|
||||||
}
|
}
|
||||||
peerVersion, err := s.Uint()
|
peerVersion, err := s.Uint()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("peer [%x] sent bad status message (unable to decode version): %v", peer.ID(), err)
|
return fmt.Errorf("peer [%s] sent bad status message (unable to decode version): %v", peer.ID(), err)
|
||||||
}
|
}
|
||||||
if peerVersion != ProtocolVersion {
|
if peerVersion != ProtocolVersion {
|
||||||
return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
|
return fmt.Errorf("peer [%s]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// only version is mandatory, subsequent parameters are optional
|
// only version is mandatory, subsequent parameters are optional
|
||||||
|
|
@ -144,7 +152,7 @@ func (peer *DevP2PPeer) handshake() error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
pow := math.Float64frombits(powRaw)
|
pow := math.Float64frombits(powRaw)
|
||||||
if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 {
|
if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 {
|
||||||
return fmt.Errorf("peer [%x] sent bad status message: invalid pow", peer.ID())
|
return fmt.Errorf("peer [%s] sent bad status message: invalid pow", peer.ID())
|
||||||
}
|
}
|
||||||
peer.powRequirement = pow
|
peer.powRequirement = pow
|
||||||
|
|
||||||
|
|
@ -153,14 +161,14 @@ func (peer *DevP2PPeer) handshake() error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
sz := len(bloom)
|
sz := len(bloom)
|
||||||
if sz != BloomFilterSize && sz != 0 {
|
if sz != BloomFilterSize && sz != 0 {
|
||||||
return fmt.Errorf("peer [%x] sent bad status message: wrong bloom filter size %d", peer.ID(), sz)
|
return fmt.Errorf("peer [%s] sent bad status message: wrong bloom filter size %d", peer.ID(), sz)
|
||||||
}
|
}
|
||||||
peer.setBloomFilter(bloom)
|
peer.setBloomFilter(bloom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := <-errc; err != nil {
|
if err := <-errc; err != nil {
|
||||||
return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
|
return fmt.Errorf("peer [%s] failed to send status packet: %v", peer.ID(), err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -191,18 +199,18 @@ func (peer *DevP2PPeer) update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark marks an envelope known to the peer so that it won't be sent back.
|
// mark marks an envelope known to the peer so that it won't be sent back.
|
||||||
func (peer *DevP2PPeer) mark(envelope *Envelope) {
|
func (peer *PeerBase) mark(envelope *Envelope) {
|
||||||
peer.known.Add(envelope.Hash())
|
peer.known.Add(envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// marked checks if an envelope is already known to the remote peer.
|
// marked checks if an envelope is already known to the remote peer.
|
||||||
func (peer *DevP2PPeer) marked(envelope *Envelope) bool {
|
func (peer *PeerBase) marked(envelope *Envelope) bool {
|
||||||
return peer.known.Has(envelope.Hash())
|
return peer.known.Has(envelope.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// expire iterates over all the known envelopes in the host and removes all
|
// expire iterates over all the known envelopes in the host and removes all
|
||||||
// expired (unknown) ones from the known list.
|
// expired (unknown) ones from the known list.
|
||||||
func (peer *DevP2PPeer) expire() {
|
func (peer *PeerBase) expire() {
|
||||||
unmark := make(map[common.Hash]struct{})
|
unmark := make(map[common.Hash]struct{})
|
||||||
peer.known.Each(func(v interface{}) bool {
|
peer.known.Each(func(v interface{}) bool {
|
||||||
if !peer.host.isEnvelopeCached(v.(common.Hash)) {
|
if !peer.host.isEnvelopeCached(v.(common.Hash)) {
|
||||||
|
|
@ -218,7 +226,7 @@ func (peer *DevP2PPeer) expire() {
|
||||||
|
|
||||||
// broadcast iterates over the collection of envelopes and transmits yet unknown
|
// broadcast iterates over the collection of envelopes and transmits yet unknown
|
||||||
// ones over the network.
|
// ones over the network.
|
||||||
func (peer *DevP2PPeer) broadcast() error {
|
func (peer *PeerBase) broadcast() error {
|
||||||
envelopes := peer.host.Envelopes()
|
envelopes := peer.host.Envelopes()
|
||||||
bundle := make([]*Envelope, 0, len(envelopes))
|
bundle := make([]*Envelope, 0, len(envelopes))
|
||||||
for _, envelope := range envelopes {
|
for _, envelope := range envelopes {
|
||||||
|
|
@ -248,22 +256,22 @@ func (peer *DevP2PPeer) ID() string {
|
||||||
return peer.peer.ID().String()
|
return peer.peer.ID().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) notifyAboutPowRequirementChange(pow float64) error {
|
func (peer *PeerBase) notifyAboutPowRequirementChange(pow float64) error {
|
||||||
i := math.Float64bits(pow)
|
i := math.Float64bits(pow)
|
||||||
return p2p.Send(peer.ws, powRequirementCode, i)
|
return p2p.Send(peer.ws, powRequirementCode, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) notifyAboutBloomFilterChange(bloom []byte) error {
|
func (peer *PeerBase) notifyAboutBloomFilterChange(bloom []byte) error {
|
||||||
return p2p.Send(peer.ws, bloomFilterExCode, bloom)
|
return p2p.Send(peer.ws, bloomFilterExCode, bloom)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) bloomMatch(env *Envelope) bool {
|
func (peer *PeerBase) bloomMatch(env *Envelope) bool {
|
||||||
peer.bloomMu.Lock()
|
peer.bloomMu.Lock()
|
||||||
defer peer.bloomMu.Unlock()
|
defer peer.bloomMu.Unlock()
|
||||||
return peer.fullNode || BloomFilterMatch(peer.bloomFilter, env.Bloom())
|
return peer.fullNode || BloomFilterMatch(peer.bloomFilter, env.Bloom())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) setBloomFilter(bloom []byte) {
|
func (peer *PeerBase) setBloomFilter(bloom []byte) {
|
||||||
peer.bloomMu.Lock()
|
peer.bloomMu.Lock()
|
||||||
defer peer.bloomMu.Unlock()
|
defer peer.bloomMu.Unlock()
|
||||||
peer.bloomFilter = bloom
|
peer.bloomFilter = bloom
|
||||||
|
|
@ -273,19 +281,19 @@ func (peer *DevP2PPeer) setBloomFilter(bloom []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) isTrusted() bool {
|
func (peer *PeerBase) isTrusted() bool {
|
||||||
return peer.trusted
|
return peer.trusted
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) setTrusted(t bool) {
|
func (peer *PeerBase) setTrusted(t bool) {
|
||||||
peer.trusted = t
|
peer.trusted = t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) setPoWRequirement(r float64) {
|
func (peer *PeerBase) setPoWRequirement(r float64) {
|
||||||
peer.powRequirement = r
|
peer.powRequirement = r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *DevP2PPeer) stream() p2p.MsgReadWriter {
|
func (peer *PeerBase) stream() p2p.MsgReadWriter {
|
||||||
return peer.ws
|
return peer.ws
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue