whisper: process incoming packets

This commit is contained in:
Guillaume Ballet 2018-03-14 20:36:04 +01:00
parent 9483cfb1e8
commit 57d7b21a14
2 changed files with 85 additions and 26 deletions

View file

@ -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
} }

View file

@ -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
} }