diff options
Diffstat (limited to 'swarm/network/protocol.go')
-rw-r--r-- | swarm/network/protocol.go | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/swarm/network/protocol.go b/swarm/network/protocol.go deleted file mode 100644 index dd8a86c0b..000000000 --- a/swarm/network/protocol.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. - -package network - -import ( - "context" - "errors" - "fmt" - "math/rand" - "sync" - "time" - - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/protocols" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/swarm/log" - "github.com/ethereum/go-ethereum/swarm/state" -) - -const ( - DefaultNetworkID = 4 - // timeout for waiting - bzzHandshakeTimeout = 3000 * time.Millisecond -) - -var DefaultTestNetworkID = rand.Uint64() - -// BzzSpec is the spec of the generic swarm handshake -var BzzSpec = &protocols.Spec{ - Name: "bzz", - Version: 9, - MaxMsgSize: 10 * 1024 * 1024, - Messages: []interface{}{ - HandshakeMsg{}, - }, -} - -// DiscoverySpec is the spec for the bzz discovery subprotocols -var DiscoverySpec = &protocols.Spec{ - Name: "hive", - Version: 8, - MaxMsgSize: 10 * 1024 * 1024, - Messages: []interface{}{ - peersMsg{}, - subPeersMsg{}, - }, -} - -// BzzConfig captures the config params used by the hive -type BzzConfig struct { - OverlayAddr []byte // base address of the overlay network - UnderlayAddr []byte // node's underlay address - HiveParams *HiveParams - NetworkID uint64 - LightNode bool - BootnodeMode bool -} - -// Bzz is the swarm protocol bundle -type Bzz struct { - *Hive - NetworkID uint64 - LightNode bool - localAddr *BzzAddr - mtx sync.Mutex - handshakes map[enode.ID]*HandshakeMsg - streamerSpec *protocols.Spec - streamerRun func(*BzzPeer) error -} - -// NewBzz is the swarm protocol constructor -// arguments -// * bzz config -// * overlay driver -// * peer store -func NewBzz(config *BzzConfig, kad *Kademlia, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz { - bzz := &Bzz{ - Hive: NewHive(config.HiveParams, kad, store), - NetworkID: config.NetworkID, - LightNode: config.LightNode, - localAddr: &BzzAddr{config.OverlayAddr, config.UnderlayAddr}, - handshakes: make(map[enode.ID]*HandshakeMsg), - streamerRun: streamerRun, - streamerSpec: streamerSpec, - } - - if config.BootnodeMode { - bzz.streamerRun = nil - bzz.streamerSpec = nil - } - - return bzz -} - -// UpdateLocalAddr updates underlayaddress of the running node -func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr { - b.localAddr = b.localAddr.Update(&BzzAddr{ - UAddr: byteaddr, - OAddr: b.localAddr.OAddr, - }) - return b.localAddr -} - -// NodeInfo returns the node's overlay address -func (b *Bzz) NodeInfo() interface{} { - return b.localAddr.Address() -} - -// Protocols return the protocols swarm offers -// Bzz implements the node.Service interface -// * handshake/hive -// * discovery -func (b *Bzz) Protocols() []p2p.Protocol { - protocol := []p2p.Protocol{ - { - Name: BzzSpec.Name, - Version: BzzSpec.Version, - Length: BzzSpec.Length(), - Run: b.runBzz, - NodeInfo: b.NodeInfo, - }, - { - Name: DiscoverySpec.Name, - Version: DiscoverySpec.Version, - Length: DiscoverySpec.Length(), - Run: b.RunProtocol(DiscoverySpec, b.Hive.Run), - NodeInfo: b.Hive.NodeInfo, - PeerInfo: b.Hive.PeerInfo, - }, - } - if b.streamerSpec != nil && b.streamerRun != nil { - protocol = append(protocol, p2p.Protocol{ - Name: b.streamerSpec.Name, - Version: b.streamerSpec.Version, - Length: b.streamerSpec.Length(), - Run: b.RunProtocol(b.streamerSpec, b.streamerRun), - }) - } - return protocol -} - -// APIs returns the APIs offered by bzz -// * hive -// Bzz implements the node.Service interface -func (b *Bzz) APIs() []rpc.API { - return []rpc.API{{ - Namespace: "hive", - Version: "3.0", - Service: b.Hive, - }} -} - -// RunProtocol is a wrapper for swarm subprotocols -// returns a p2p protocol run function that can be assigned to p2p.Protocol#Run field -// arguments: -// * p2p protocol spec -// * run function taking BzzPeer as argument -// this run function is meant to block for the duration of the protocol session -// on return the session is terminated and the peer is disconnected -// the protocol waits for the bzz handshake is negotiated -// the overlay address on the BzzPeer is set from the remote handshake -func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error { - return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - // wait for the bzz protocol to perform the handshake - handshake, _ := b.GetOrCreateHandshake(p.ID()) - defer b.removeHandshake(p.ID()) - select { - case <-handshake.done: - case <-time.After(bzzHandshakeTimeout): - return fmt.Errorf("%08x: %s protocol timeout waiting for handshake on %08x", b.BaseAddr()[:4], spec.Name, p.ID().Bytes()[:4]) - } - if handshake.err != nil { - return fmt.Errorf("%08x: %s protocol closed: %v", b.BaseAddr()[:4], spec.Name, handshake.err) - } - // the handshake has succeeded so construct the BzzPeer and run the protocol - peer := &BzzPeer{ - Peer: protocols.NewPeer(p, rw, spec), - BzzAddr: handshake.peerAddr, - lastActive: time.Now(), - LightNode: handshake.LightNode, - } - - log.Debug("peer created", "addr", handshake.peerAddr.String()) - - return run(peer) - } -} - -// performHandshake implements the negotiation of the bzz handshake -// shared among swarm subprotocols -func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error { - ctx, cancel := context.WithTimeout(context.Background(), bzzHandshakeTimeout) - defer func() { - close(handshake.done) - cancel() - }() - rsh, err := p.Handshake(ctx, handshake, b.checkHandshake) - if err != nil { - handshake.err = err - return err - } - handshake.peerAddr = rsh.(*HandshakeMsg).Addr - handshake.LightNode = rsh.(*HandshakeMsg).LightNode - return nil -} - -// runBzz is the p2p protocol run function for the bzz base protocol -// that negotiates the bzz handshake -func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { - handshake, _ := b.GetOrCreateHandshake(p.ID()) - if !<-handshake.init { - return fmt.Errorf("%08x: bzz already started on peer %08x", b.localAddr.Over()[:4], p.ID().Bytes()[:4]) - } - close(handshake.init) - defer b.removeHandshake(p.ID()) - peer := protocols.NewPeer(p, rw, BzzSpec) - err := b.performHandshake(peer, handshake) - if err != nil { - log.Warn(fmt.Sprintf("%08x: handshake failed with remote peer %08x: %v", b.localAddr.Over()[:4], p.ID().Bytes()[:4], err)) - - return err - } - // fail if we get another handshake - msg, err := rw.ReadMsg() - if err != nil { - return err - } - msg.Discard() - return errors.New("received multiple handshakes") -} - -// BzzPeer is the bzz protocol view of a protocols.Peer (itself an extension of p2p.Peer) -// implements the Peer interface and all interfaces Peer implements: Addr, OverlayPeer -type BzzPeer struct { - *protocols.Peer // represents the connection for online peers - *BzzAddr // remote address -> implements Addr interface = protocols.Peer - lastActive time.Time // time is updated whenever mutexes are releasing - LightNode bool -} - -func NewBzzPeer(p *protocols.Peer) *BzzPeer { - return &BzzPeer{Peer: p, BzzAddr: NewAddr(p.Node())} -} - -// ID returns the peer's underlay node identifier. -func (p *BzzPeer) ID() enode.ID { - // This is here to resolve a method tie: both protocols.Peer and BzzAddr are embedded - // into the struct and provide ID(). The protocols.Peer version is faster, ensure it - // gets used. - return p.Peer.ID() -} - -/* - Handshake - -* Version: 8 byte integer version of the protocol -* NetworkID: 8 byte integer network identifier -* Addr: the address advertised by the node including underlay and overlay connecctions -*/ -type HandshakeMsg struct { - Version uint64 - NetworkID uint64 - Addr *BzzAddr - LightNode bool - - // peerAddr is the address received in the peer handshake - peerAddr *BzzAddr - - init chan bool - done chan struct{} - err error -} - -// String pretty prints the handshake -func (bh *HandshakeMsg) String() string { - return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v, LightNode: %v, peerAddr: %v", bh.Version, bh.NetworkID, bh.Addr, bh.LightNode, bh.peerAddr) -} - -// Perform initiates the handshake and validates the remote handshake message -func (b *Bzz) checkHandshake(hs interface{}) error { - rhs := hs.(*HandshakeMsg) - if rhs.NetworkID != b.NetworkID { - return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, b.NetworkID) - } - if rhs.Version != uint64(BzzSpec.Version) { - return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, BzzSpec.Version) - } - return nil -} - -// removeHandshake removes handshake for peer with peerID -// from the bzz handshake store -func (b *Bzz) removeHandshake(peerID enode.ID) { - b.mtx.Lock() - defer b.mtx.Unlock() - delete(b.handshakes, peerID) -} - -// GetHandshake returns the bzz handhake that the remote peer with peerID sent -func (b *Bzz) GetOrCreateHandshake(peerID enode.ID) (*HandshakeMsg, bool) { - b.mtx.Lock() - defer b.mtx.Unlock() - handshake, found := b.handshakes[peerID] - if !found { - handshake = &HandshakeMsg{ - Version: uint64(BzzSpec.Version), - NetworkID: b.NetworkID, - Addr: b.localAddr, - LightNode: b.LightNode, - init: make(chan bool, 1), - done: make(chan struct{}), - } - // when handhsake is first created for a remote peer - // it is initialised with the init - handshake.init <- true - b.handshakes[peerID] = handshake - } - - return handshake, found -} |