github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/swarm/network/protocol.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package network
    18  
    19  /*
    20  bzz implements the swarm wire protocol [bzz] (sister of vnt and shh)
    21  the protocol instance is launched on each peer by the network layer if the
    22  bzz protocol handler is registered on the p2p server.
    23  
    24  The bzz protocol component speaks the bzz protocol
    25  * handle the protocol handshake
    26  * register peers in the KΛÐΞMLIΛ table via the hive logistic manager
    27  * dispatch to hive for handling the DHT logic
    28  * encode and decode requests for storage and retrieval
    29  * handle sync protocol messages via the syncer
    30  * talks the SWAP payment protocol (swap accounting is done within NetStore)
    31  */
    32  
    33  import (
    34  	"errors"
    35  	"fmt"
    36  	"math/big"
    37  	"net"
    38  	"strconv"
    39  	"time"
    40  
    41  	"github.com/vntchain/go-vnt/contracts/chequebook"
    42  	"github.com/vntchain/go-vnt/log"
    43  	"github.com/vntchain/go-vnt/metrics"
    44  	bzzswap "github.com/vntchain/go-vnt/swarm/services/swap"
    45  	"github.com/vntchain/go-vnt/swarm/services/swap/swap"
    46  	"github.com/vntchain/go-vnt/swarm/storage"
    47  	"github.com/vntchain/go-vnt/vntp2p"
    48  )
    49  
    50  //metrics variables
    51  var (
    52  	storeRequestMsgCounter    = metrics.NewRegisteredCounter("network.protocol.msg.storerequest.count", nil)
    53  	retrieveRequestMsgCounter = metrics.NewRegisteredCounter("network.protocol.msg.retrieverequest.count", nil)
    54  	peersMsgCounter           = metrics.NewRegisteredCounter("network.protocol.msg.peers.count", nil)
    55  	syncRequestMsgCounter     = metrics.NewRegisteredCounter("network.protocol.msg.syncrequest.count", nil)
    56  	unsyncedKeysMsgCounter    = metrics.NewRegisteredCounter("network.protocol.msg.unsyncedkeys.count", nil)
    57  	deliverRequestMsgCounter  = metrics.NewRegisteredCounter("network.protocol.msg.deliverrequest.count", nil)
    58  	paymentMsgCounter         = metrics.NewRegisteredCounter("network.protocol.msg.payment.count", nil)
    59  	invalidMsgCounter         = metrics.NewRegisteredCounter("network.protocol.msg.invalid.count", nil)
    60  	handleStatusMsgCounter    = metrics.NewRegisteredCounter("network.protocol.msg.handlestatus.count", nil)
    61  )
    62  
    63  const (
    64  	Version            = 0
    65  	ProtocolLength     = uint64(8)
    66  	ProtocolMaxMsgSize = 10 * 1024 * 1024
    67  	NetworkId          = 3
    68  )
    69  
    70  // bzz represents the swarm wire protocol
    71  // an instance is running on each peer
    72  type bzz struct {
    73  	storage    StorageHandler       // handler storage/retrieval related requests coming via the bzz wire protocol
    74  	hive       *Hive                // the logistic manager, peerPool, routing service and peer handler
    75  	dbAccess   *DbAccess            // access to db storage counter and iterator for syncing
    76  	requestDb  *storage.LDBDatabase // db to persist backlog of deliveries to aid syncing
    77  	remoteAddr *peerAddr            // remote peers address
    78  	peer       *vntp2p.Peer         // the p2p peer object
    79  	rw         vntp2p.MsgReadWriter // messageReadWriter to send messages to
    80  	backend    chequebook.Backend
    81  	lastActive time.Time
    82  	NetworkId  uint64
    83  
    84  	swap        *swap.Swap          // swap instance for the peer connection
    85  	swapParams  *bzzswap.SwapParams // swap settings both local and remote
    86  	swapEnabled bool                // flag to enable SWAP (will be set via Caps in handshake)
    87  	syncEnabled bool                // flag to enable SYNC (will be set via Caps in handshake)
    88  	syncer      *syncer             // syncer instance for the peer connection
    89  	syncParams  *SyncParams         // syncer params
    90  	syncState   *syncState          // outgoing syncronisation state (contains reference to remote peers db counter)
    91  }
    92  
    93  // interface type for handler of storage/retrieval related requests coming
    94  // via the bzz wire protocol
    95  // messages: UnsyncedKeys, DeliveryRequest, StoreRequest, RetrieveRequest
    96  type StorageHandler interface {
    97  	HandleUnsyncedKeysMsg(req *unsyncedKeysMsgData, p *peer) error
    98  	HandleDeliveryRequestMsg(req *deliveryRequestMsgData, p *peer) error
    99  	HandleStoreRequestMsg(req *storeRequestMsgData, p *peer)
   100  	HandleRetrieveRequestMsg(req *retrieveRequestMsgData, p *peer)
   101  }
   102  
   103  /*
   104  main entrypoint, wrappers starting a server that will run the bzz protocol
   105  use this constructor to attach the protocol ("class") to server caps
   106  This is done by node.Node#Register(func(node.ServiceContext) (Service, error))
   107  Service implements Protocols() which is an array of protocol constructors
   108  at node startup the protocols are initialised
   109  the Dev p2p layer then calls Run(p *p2p.Peer, rw p2p.MsgReadWriter) error
   110  on each peer connection
   111  The Run function of the Bzz protocol class creates a bzz instance
   112  which will represent the peer for the swarm hive and all peer-aware components
   113  */
   114  func Bzz(cloud StorageHandler, backend chequebook.Backend, hive *Hive, dbaccess *DbAccess, sp *bzzswap.SwapParams, sy *SyncParams, networkId uint64) (vntp2p.Protocol, error) {
   115  
   116  	// a single global request db is created for all peer connections
   117  	// this is to persist delivery backlog and aid syncronisation
   118  	requestDb, err := storage.NewLDBDatabase(sy.RequestDbPath)
   119  	if err != nil {
   120  		return vntp2p.Protocol{}, fmt.Errorf("error setting up request db: %v", err)
   121  	}
   122  	fmt.Println(requestDb)
   123  	if networkId == 0 {
   124  		networkId = NetworkId
   125  	}
   126  	return vntp2p.Protocol{
   127  		Name:    "bzz",
   128  		Version: Version,
   129  		Length:  ProtocolLength,
   130  		Run: func(p *vntp2p.Peer, rw vntp2p.MsgReadWriter) error {
   131  			return run(requestDb, cloud, backend, hive, dbaccess, sp, sy, networkId, p, rw)
   132  		},
   133  	}, nil
   134  }
   135  
   136  /*
   137  the main protocol loop that
   138   * does the handshake by exchanging statusMsg
   139   * if peer is valid and accepted, registers with the hive
   140   * then enters into a forever loop handling incoming messages
   141   * storage and retrieval related queries coming via bzz are dispatched to StorageHandler
   142   * peer-related messages are dispatched to the hive
   143   * payment related messages are relayed to SWAP service
   144   * on disconnect, unregister the peer in the hive (note RemovePeer in the post-disconnect hook)
   145   * whenever the loop terminates, the peer will disconnect with Subprotocol error
   146   * whenever handlers return an error the loop terminates
   147  */
   148  func run(requestDb *storage.LDBDatabase, depo StorageHandler, backend chequebook.Backend, hive *Hive, dbaccess *DbAccess, sp *bzzswap.SwapParams, sy *SyncParams, networkId uint64, p *vntp2p.Peer, rw vntp2p.MsgReadWriter) (err error) {
   149  
   150  	self := &bzz{
   151  		storage:     depo,
   152  		backend:     backend,
   153  		hive:        hive,
   154  		dbAccess:    dbaccess,
   155  		requestDb:   requestDb,
   156  		peer:        p,
   157  		rw:          rw,
   158  		swapParams:  sp,
   159  		syncParams:  sy,
   160  		swapEnabled: hive.swapEnabled,
   161  		syncEnabled: true,
   162  		NetworkId:   networkId,
   163  	}
   164  
   165  	// handle handshake
   166  	err = self.handleStatus()
   167  	if err != nil {
   168  		return err
   169  	}
   170  	defer func() {
   171  		// if the handler loop exits, the peer is disconnecting
   172  		// deregister the peer in the hive
   173  		self.hive.removePeer(&peer{bzz: self})
   174  		if self.syncer != nil {
   175  			self.syncer.stop() // quits request db and delivery loops, save requests
   176  		}
   177  		if self.swap != nil {
   178  			self.swap.Stop() // quits chequebox autocash etc
   179  		}
   180  	}()
   181  
   182  	// the main forever loop that handles incoming requests
   183  	for {
   184  		if self.hive.blockRead {
   185  			log.Warn(fmt.Sprintf("Cannot read network"))
   186  			time.Sleep(100 * time.Millisecond)
   187  			continue
   188  		}
   189  		err = self.handle()
   190  		if err != nil {
   191  			return
   192  		}
   193  	}
   194  }
   195  
   196  // TODO: may need to implement protocol drop only? don't want to kick off the peer
   197  // if they are useful for other protocols
   198  func (self *bzz) Drop() {
   199  	self.peer.Disconnect(vntp2p.DiscSubprotocolError)
   200  }
   201  
   202  // one cycle of the main forever loop that handles and dispatches incoming messages
   203  func (self *bzz) handle() error {
   204  	msg, err := self.rw.ReadMsg()
   205  	log.Debug(fmt.Sprintf("<- %v", msg))
   206  	if err != nil {
   207  		return err
   208  	}
   209  	size := msg.GetBodySize()
   210  	if size > ProtocolMaxMsgSize {
   211  		return fmt.Errorf("message too long: %v > %v", size, ProtocolMaxMsgSize)
   212  	}
   213  
   214  	// make sure that the payload has been fully consumed
   215  	// 按理说,新版的协议处理方式,不会有残留数据得不到处理
   216  	// defer msg.Discard()
   217  
   218  	switch msg.Body.Type {
   219  
   220  	case statusMsg:
   221  		// no extra status message allowed. The one needed already handled by
   222  		// handleStatus
   223  		log.Debug(fmt.Sprintf("Status message: %v", msg))
   224  		return errors.New("extra status message")
   225  
   226  	case storeRequestMsg:
   227  		// store requests are dispatched to netStore
   228  		storeRequestMsgCounter.Inc(1)
   229  		var req storeRequestMsgData
   230  		if err := msg.Decode(&req); err != nil {
   231  			return fmt.Errorf("<- %v: %v", msg, err)
   232  		}
   233  		if n := len(req.SData); n < 9 {
   234  			return fmt.Errorf("<- %v: Data too short (%v)", msg, n)
   235  		}
   236  		// last Active time is set only when receiving chunks
   237  		self.lastActive = time.Now()
   238  		log.Trace(fmt.Sprintf("incoming store request: %s", req.String()))
   239  		// swap accounting is done within forwarding
   240  		self.storage.HandleStoreRequestMsg(&req, &peer{bzz: self})
   241  
   242  	case retrieveRequestMsg:
   243  		// retrieve Requests are dispatched to netStore
   244  		retrieveRequestMsgCounter.Inc(1)
   245  		var req retrieveRequestMsgData
   246  		if err := msg.Decode(&req); err != nil {
   247  			return fmt.Errorf("<- %v: %v", msg, err)
   248  		}
   249  		req.from = &peer{bzz: self}
   250  		// if request is lookup and not to be delivered
   251  		if req.isLookup() {
   252  			log.Trace(fmt.Sprintf("self lookup for %v: responding with peers only...", req.from))
   253  		} else if req.Key == nil {
   254  			return fmt.Errorf("protocol handler: req.Key == nil || req.Timeout == nil")
   255  		} else {
   256  			// swap accounting is done within netStore
   257  			self.storage.HandleRetrieveRequestMsg(&req, &peer{bzz: self})
   258  		}
   259  		// direct response with peers, TODO: sort this out
   260  		self.hive.peers(&req)
   261  
   262  	case peersMsg:
   263  		// response to lookups and immediate response to retrieve requests
   264  		// dispatches new peer data to the hive that adds them to KADDB
   265  		peersMsgCounter.Inc(1)
   266  		var req peersMsgData
   267  		if err := msg.Decode(&req); err != nil {
   268  			return fmt.Errorf("<- %v: %v", msg, err)
   269  		}
   270  		req.from = &peer{bzz: self}
   271  		log.Trace(fmt.Sprintf("<- peer addresses: %v", req))
   272  		self.hive.HandlePeersMsg(&req, &peer{bzz: self})
   273  
   274  	case syncRequestMsg:
   275  		syncRequestMsgCounter.Inc(1)
   276  		var req syncRequestMsgData
   277  		if err := msg.Decode(&req); err != nil {
   278  			return fmt.Errorf("<- %v: %v", msg, err)
   279  		}
   280  		log.Debug(fmt.Sprintf("<- sync request: %v", req))
   281  		self.lastActive = time.Now()
   282  		self.sync(req.SyncState)
   283  
   284  	case unsyncedKeysMsg:
   285  		// coming from parent node offering
   286  		unsyncedKeysMsgCounter.Inc(1)
   287  		var req unsyncedKeysMsgData
   288  		if err := msg.Decode(&req); err != nil {
   289  			return fmt.Errorf("<- %v: %v", msg, err)
   290  		}
   291  		log.Debug(fmt.Sprintf("<- unsynced keys : %s", req.String()))
   292  		err := self.storage.HandleUnsyncedKeysMsg(&req, &peer{bzz: self})
   293  		self.lastActive = time.Now()
   294  		if err != nil {
   295  			return fmt.Errorf("<- %v: %v", msg, err)
   296  		}
   297  
   298  	case deliveryRequestMsg:
   299  		// response to syncKeysMsg hashes filtered not existing in db
   300  		// also relays the last synced state to the source
   301  		deliverRequestMsgCounter.Inc(1)
   302  		var req deliveryRequestMsgData
   303  		if err := msg.Decode(&req); err != nil {
   304  			return fmt.Errorf("<-msg %v: %v", msg, err)
   305  		}
   306  		log.Debug(fmt.Sprintf("<- delivery request: %s", req.String()))
   307  		err := self.storage.HandleDeliveryRequestMsg(&req, &peer{bzz: self})
   308  		self.lastActive = time.Now()
   309  		if err != nil {
   310  			return fmt.Errorf("<- %v: %v", msg, err)
   311  		}
   312  
   313  	case paymentMsg:
   314  		// swap protocol message for payment, Units paid for, Cheque paid with
   315  		paymentMsgCounter.Inc(1)
   316  		if self.swapEnabled {
   317  			var req paymentMsgData
   318  			if err := msg.Decode(&req); err != nil {
   319  				return fmt.Errorf("<- %v: %v", msg, err)
   320  			}
   321  			log.Debug(fmt.Sprintf("<- payment: %s", req.String()))
   322  			self.swap.Receive(int(req.Units), req.Promise)
   323  		}
   324  
   325  	default:
   326  		// no other message is allowed
   327  		invalidMsgCounter.Inc(1)
   328  		return fmt.Errorf("invalid message code: %v", msg.Body.Type)
   329  	}
   330  	return nil
   331  }
   332  
   333  func (self *bzz) handleStatus() (err error) {
   334  
   335  	handshake := &statusMsgData{
   336  		Version:   uint64(Version),
   337  		ID:        "honey",
   338  		Addr:      self.selfAddr(),
   339  		NetworkId: self.NetworkId,
   340  		Swap: &bzzswap.SwapProfile{
   341  			Profile:    self.swapParams.Profile,
   342  			PayProfile: self.swapParams.PayProfile,
   343  		},
   344  	}
   345  
   346  	err = vntp2p.Send(self.rw, "bzz", statusMsg, handshake)
   347  	if err != nil {
   348  		return err
   349  	}
   350  
   351  	// read and handle remote status
   352  	var msg vntp2p.Msg
   353  	msg, err = self.rw.ReadMsg()
   354  	if err != nil {
   355  		return err
   356  	}
   357  
   358  	if msg.Body.Type != statusMsg {
   359  		return fmt.Errorf("first msg has code %x (!= %x)", msg.Body.Type, statusMsg)
   360  	}
   361  
   362  	handleStatusMsgCounter.Inc(1)
   363  
   364  	size := msg.GetBodySize()
   365  	if size > ProtocolMaxMsgSize {
   366  		return fmt.Errorf("message too long: %v > %v", size, ProtocolMaxMsgSize)
   367  	}
   368  
   369  	var status statusMsgData
   370  	if err := msg.Decode(&status); err != nil {
   371  		return fmt.Errorf("<- %v: %v", msg, err)
   372  	}
   373  
   374  	if status.NetworkId != self.NetworkId {
   375  		return fmt.Errorf("network id mismatch: %d (!= %d)", status.NetworkId, self.NetworkId)
   376  	}
   377  
   378  	if Version != status.Version {
   379  		return fmt.Errorf("protocol version mismatch: %d (!= %d)", status.Version, Version)
   380  	}
   381  
   382  	self.remoteAddr = self.peerAddr(status.Addr)
   383  	log.Trace(fmt.Sprintf("self: advertised IP: %v, peer advertised: %v, local address: %v\npeer: advertised IP: %v, remote address: %v\n", self.selfAddr(), self.remoteAddr, self.peer.LocalAddr(), status.Addr.IP, self.peer.RemoteAddr()))
   384  
   385  	if self.swapEnabled {
   386  		// set remote profile for accounting
   387  		self.swap, err = bzzswap.NewSwap(big.NewInt(int64(self.NetworkId)), self.swapParams, status.Swap, self.backend, self)
   388  		if err != nil {
   389  			return err
   390  		}
   391  	}
   392  
   393  	log.Info(fmt.Sprintf("Peer %08x is capable (%d/%d)", self.remoteAddr.Addr[:4], status.Version, status.NetworkId))
   394  	err = self.hive.addPeer(&peer{bzz: self})
   395  	if err != nil {
   396  		return err
   397  	}
   398  
   399  	// hive sets syncstate so sync should start after node added
   400  	log.Info(fmt.Sprintf("syncronisation request sent with %v", self.syncState))
   401  	self.syncRequest()
   402  
   403  	return nil
   404  }
   405  
   406  func (self *bzz) sync(state *syncState) error {
   407  	// syncer setup
   408  	if self.syncer != nil {
   409  		return errors.New("sync request can only be sent once")
   410  	}
   411  
   412  	cnt := self.dbAccess.counter()
   413  	remoteaddr := self.remoteAddr.Addr
   414  	start, stop := self.hive.kad.KeyRange(remoteaddr)
   415  
   416  	// an explicitly received nil syncstate disables syncronisation
   417  	if state == nil {
   418  		self.syncEnabled = false
   419  		log.Warn(fmt.Sprintf("syncronisation disabled for peer %v", self))
   420  		state = &syncState{DbSyncState: &storage.DbSyncState{}, Synced: true}
   421  	} else {
   422  		state.synced = make(chan bool)
   423  		state.SessionAt = cnt
   424  		if storage.IsZeroKey(state.Stop) && state.Synced {
   425  			state.Start = storage.Key(start[:])
   426  			state.Stop = storage.Key(stop[:])
   427  		}
   428  		log.Debug(fmt.Sprintf("syncronisation requested by peer %v at state %v", self, state))
   429  	}
   430  	var err error
   431  	self.syncer, err = newSyncer(
   432  		self.requestDb,
   433  		storage.Key(remoteaddr[:]),
   434  		self.dbAccess,
   435  		self.unsyncedKeys, self.store,
   436  		self.syncParams, state, func() bool { return self.syncEnabled },
   437  	)
   438  	if err != nil {
   439  		return nil
   440  	}
   441  	log.Trace(fmt.Sprintf("syncer set for peer %v", self))
   442  	return nil
   443  }
   444  
   445  func (self *bzz) String() string {
   446  	return self.remoteAddr.String()
   447  }
   448  
   449  // repair reported address if IP missing
   450  func (self *bzz) peerAddr(base *peerAddr) *peerAddr {
   451  	if base.IP.IsUnspecified() {
   452  		host, _, _ := net.SplitHostPort(self.peer.RemoteAddr().String())
   453  		base.IP = net.ParseIP(host)
   454  	}
   455  	return base
   456  }
   457  
   458  // returns self advertised node connection info (listening address w vnodes)
   459  // IP will get repaired on the other end if missing
   460  // or resolved via ID by discovery at dialout
   461  func (self *bzz) selfAddr() *peerAddr {
   462  	id := self.hive.id
   463  	host, port, _ := net.SplitHostPort(self.hive.listenAddr())
   464  	intport, _ := strconv.Atoi(port)
   465  	addr := &peerAddr{
   466  		Addr: self.hive.addr,
   467  		ID:   id[:],
   468  		IP:   net.ParseIP(host),
   469  		Port: uint16(intport),
   470  	}
   471  	return addr
   472  }
   473  
   474  // outgoing messages
   475  // send retrieveRequestMsg
   476  func (self *bzz) retrieve(req *retrieveRequestMsgData) error {
   477  	return self.send(retrieveRequestMsg, req)
   478  }
   479  
   480  // send storeRequestMsg
   481  func (self *bzz) store(req *storeRequestMsgData) error {
   482  	return self.send(storeRequestMsg, req)
   483  }
   484  
   485  func (self *bzz) syncRequest() error {
   486  	req := &syncRequestMsgData{}
   487  	if self.hive.syncEnabled {
   488  		log.Debug(fmt.Sprintf("syncronisation request to peer %v at state %v", self, self.syncState))
   489  		req.SyncState = self.syncState
   490  	}
   491  	if self.syncState == nil {
   492  		log.Warn(fmt.Sprintf("syncronisation disabled for peer %v at state %v", self, self.syncState))
   493  	}
   494  	return self.send(syncRequestMsg, req)
   495  }
   496  
   497  // queue storeRequestMsg in request db
   498  func (self *bzz) deliveryRequest(reqs []*syncRequest) error {
   499  	req := &deliveryRequestMsgData{
   500  		Deliver: reqs,
   501  	}
   502  	return self.send(deliveryRequestMsg, req)
   503  }
   504  
   505  // batch of syncRequests to send off
   506  func (self *bzz) unsyncedKeys(reqs []*syncRequest, state *syncState) error {
   507  	req := &unsyncedKeysMsgData{
   508  		Unsynced: reqs,
   509  		State:    state,
   510  	}
   511  	return self.send(unsyncedKeysMsg, req)
   512  }
   513  
   514  // send paymentMsg
   515  func (self *bzz) Pay(units int, promise swap.Promise) {
   516  	req := &paymentMsgData{uint(units), promise.(*chequebook.Cheque)}
   517  	self.payment(req)
   518  }
   519  
   520  // send paymentMsg
   521  func (self *bzz) payment(req *paymentMsgData) error {
   522  	return self.send(paymentMsg, req)
   523  }
   524  
   525  // sends peersMsg
   526  func (self *bzz) peers(req *peersMsgData) error {
   527  	return self.send(peersMsg, req)
   528  }
   529  
   530  func (self *bzz) send(msg vntp2p.MessageType, data interface{}) error {
   531  	if self.hive.blockWrite {
   532  		return fmt.Errorf("network write blocked")
   533  	}
   534  	log.Trace(fmt.Sprintf("-> %v: %v (%T) to %v", msg, data, data, self))
   535  	err := vntp2p.Send(self.rw, "bzz", msg, data)
   536  	if err != nil {
   537  		self.Drop()
   538  	}
   539  	return err
   540  }