kaspad/protocol/protocol.go
Ori Newman 433cdb6006
[NOD-1126] implement block relay flow (#786)
* [NOD-1126] Implement block relay flow

* [NOD-1126] Add StartGetRelayBlocksListener

* [NOD-1126] Implement block relay flow

* [NOD-1126] Integrate with new interface

* [NOD-1126] Fix comments

* [NOD-1126] Refactor protocol.go

* [NOD-1126] Split long lines

* [NOD-1126] Fix comment

* [NOD-1126] move sharedRequestedBlocks to a separate file

* [NOD-1126] Fix error message

* [NOD-1126] Move handleInv to StartBlockRelay

* [NOD-1126] Create hashesQueueSet type

* [NOD-1126] Make deleteFromRequestedBlocks a method

* [NOD-1126] Fix comment

* [NOD-1126] Add block logger

* [NOD-1126] Rename advertisedProtoVer->advertisedProtocolVer

* [NOD-1126] Fix comment and an error message

* [NOD-1126] Remove redundant loop

* [NOD-1126] Move requestBlocks upper

* [NOD-1126] Remove exiting blocks in requestedBlocks from hashesToRequest

* [NOD-1126] Change comment

* [NOD-1126] Rename stallResponseTimeout->timeout

* [NOD-1126] Use switch inside readMsgBlock

* [NOD-1126] Fix error message and remove redundant log

* [NOD-1126] Rename pacakge names

* [NOD-1126] Fix comment

* [NOD-1126] Change file names

* [NOD-1126] Convert block to partial if needed

* [NOD-1126] Remove function redeclaration

* [NOD-1126] continue instead of return

* [NOD-1126] Rename LogBlockBlueScore->LogBlock

* [NOD-1126] Add minimum functions to utils

* [NOD-1126] Flip condition on readInv

* [NOD-1126] Rename utilMath->mathUtil

* [NOD-1126] Fix comment
2020-07-12 16:11:42 +03:00

112 lines
2.9 KiB
Go

package protocol
import (
"github.com/kaspanet/kaspad/blockdag"
"github.com/kaspanet/kaspad/netadapter"
"github.com/kaspanet/kaspad/protocol/handlerelayblockrequests"
"github.com/kaspanet/kaspad/protocol/handlerelayinvs"
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
"github.com/kaspanet/kaspad/wire"
"sync/atomic"
)
// Manager manages the p2p protocol
type Manager struct {
netAdapter *netadapter.NetAdapter
}
// NewManager creates a new instance of the p2p protocol manager
func NewManager(listeningAddrs []string, dag *blockdag.BlockDAG) (*Manager, error) {
netAdapter, err := netadapter.NewNetAdapter(listeningAddrs)
if err != nil {
return nil, err
}
routerInitializer := newRouterInitializer(netAdapter, dag)
netAdapter.SetRouterInitializer(routerInitializer)
manager := Manager{
netAdapter: netAdapter,
}
return &manager, nil
}
// Start starts the p2p protocol
func (p *Manager) Start() error {
return p.netAdapter.Start()
}
// Stop stops the p2p protocol
func (p *Manager) Stop() error {
return p.netAdapter.Stop()
}
func newRouterInitializer(netAdapter *netadapter.NetAdapter, dag *blockdag.BlockDAG) netadapter.RouterInitializer {
return func() (*netadapter.Router, error) {
router := netadapter.NewRouter()
spawn(func() {
err := startFlows(netAdapter, router, dag)
if err != nil {
// TODO(libp2p) Ban peer
}
})
return router, nil
}
}
func startFlows(netAdapter *netadapter.NetAdapter, router *netadapter.Router, dag *blockdag.BlockDAG) error {
stop := make(chan error)
stopped := uint32(0)
peer := new(peerpkg.Peer)
addFlow("HandleRelayInvs", router, []string{wire.CmdInvRelayBlock, wire.CmdBlock}, &stopped, stop,
func(ch chan wire.Message) error {
return handlerelayinvs.HandleRelayInvs(ch, peer, netAdapter, router, dag)
},
)
addFlow("HandleRelayBlockRequests", router, []string{wire.CmdGetRelayBlocks}, &stopped, stop,
func(ch chan wire.Message) error {
return handlerelayblockrequests.HandleRelayBlockRequests(ch, peer, router, dag)
},
)
// TODO(libp2p): Remove this and change it with a real Ping-Pong flow.
addFlow("PingPong", router, []string{wire.CmdPing, wire.CmdPong}, &stopped, stop,
func(ch chan wire.Message) error {
router.WriteOutgoingMessage(wire.NewMsgPing(666))
for message := range ch {
log.Infof("Got message: %+v", message.Command())
if message.Command() == "ping" {
router.WriteOutgoingMessage(wire.NewMsgPong(666))
}
}
return nil
},
)
err := <-stop
return err
}
func addFlow(name string, router *netadapter.Router, messageTypes []string, stopped *uint32,
stopChan chan error, flow func(ch chan wire.Message) error) {
ch := make(chan wire.Message)
err := router.AddRoute(messageTypes, ch)
if err != nil {
panic(err)
}
spawn(func() {
err := flow(ch)
if err != nil {
log.Errorf("error from %s flow: %s", name, err)
}
if atomic.AddUint32(stopped, 1) == 1 {
stopChan <- err
}
})
}