mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 06:36:46 +00:00
[NOD-1148] P2P stabilization (#798)
* [NOD-1148] Add lock around route's close operation * [NOD-1148] Added tracing of incoming and outgoing messages * [NOD-1148] Cast to MsgPing should have been to MsgPong * [NOD-1148] Check for NeedMoreAddresses before sending GetAddr message and invert condition
This commit is contained in:
parent
b9a25c1141
commit
aa5bc34280
@ -1,9 +1,11 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/wire"
|
"github.com/kaspanet/kaspad/wire"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -20,7 +22,10 @@ type onCapacityReachedHandler func()
|
|||||||
// Route represents an incoming or outgoing Router route
|
// Route represents an incoming or outgoing Router route
|
||||||
type Route struct {
|
type Route struct {
|
||||||
channel chan wire.Message
|
channel chan wire.Message
|
||||||
|
// closed and closeLock are used to protect us from writing to a closed channel
|
||||||
|
// reads use the channel's built-in mechanism to check if the channel is closed
|
||||||
closed bool
|
closed bool
|
||||||
|
closeLock sync.Mutex
|
||||||
|
|
||||||
onCapacityReachedHandler onCapacityReachedHandler
|
onCapacityReachedHandler onCapacityReachedHandler
|
||||||
}
|
}
|
||||||
@ -35,6 +40,9 @@ func NewRoute() *Route {
|
|||||||
|
|
||||||
// Enqueue enqueues a message to the Route
|
// Enqueue enqueues a message to the Route
|
||||||
func (r *Route) Enqueue(message wire.Message) (isOpen bool) {
|
func (r *Route) Enqueue(message wire.Message) (isOpen bool) {
|
||||||
|
r.closeLock.Lock()
|
||||||
|
defer r.closeLock.Unlock()
|
||||||
|
|
||||||
if r.closed {
|
if r.closed {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -45,17 +53,12 @@ func (r *Route) Enqueue(message wire.Message) (isOpen bool) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dequeue dequeues a message from the Route
|
|
||||||
func (r *Route) Dequeue() (message wire.Message, isOpen bool) {
|
|
||||||
if r.closed {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return <-r.channel, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnqueueWithTimeout attempts to enqueue a message to the Route
|
// EnqueueWithTimeout attempts to enqueue a message to the Route
|
||||||
// and returns an error if the given timeout expires first.
|
// and returns an error if the given timeout expires first.
|
||||||
func (r *Route) EnqueueWithTimeout(message wire.Message, timeout time.Duration) (isOpen bool, err error) {
|
func (r *Route) EnqueueWithTimeout(message wire.Message, timeout time.Duration) (isOpen bool, err error) {
|
||||||
|
r.closeLock.Lock()
|
||||||
|
defer r.closeLock.Unlock()
|
||||||
|
|
||||||
if r.closed {
|
if r.closed {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -70,17 +73,20 @@ func (r *Route) EnqueueWithTimeout(message wire.Message, timeout time.Duration)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dequeue dequeues a message from the Route
|
||||||
|
func (r *Route) Dequeue() (message wire.Message, isOpen bool) {
|
||||||
|
message, isOpen = <-r.channel
|
||||||
|
return message, isOpen
|
||||||
|
}
|
||||||
|
|
||||||
// DequeueWithTimeout attempts to dequeue a message from the Route
|
// DequeueWithTimeout attempts to dequeue a message from the Route
|
||||||
// and returns an error if the given timeout expires first.
|
// and returns an error if the given timeout expires first.
|
||||||
func (r *Route) DequeueWithTimeout(timeout time.Duration) (message wire.Message, isOpen bool, err error) {
|
func (r *Route) DequeueWithTimeout(timeout time.Duration) (message wire.Message, isOpen bool, err error) {
|
||||||
if r.closed {
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
select {
|
select {
|
||||||
case <-time.After(timeout):
|
case <-time.After(timeout):
|
||||||
return nil, false, errors.Wrapf(ErrTimeout, "got timeout after %s", timeout)
|
return nil, false, errors.Wrapf(ErrTimeout, "got timeout after %s", timeout)
|
||||||
case message := <-r.channel:
|
case message, isOpen = <-r.channel:
|
||||||
return message, true, nil
|
return message, isOpen, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +96,9 @@ func (r *Route) setOnCapacityReachedHandler(onCapacityReachedHandler onCapacityR
|
|||||||
|
|
||||||
// Close closes this route
|
// Close closes this route
|
||||||
func (r *Route) Close() error {
|
func (r *Route) Close() error {
|
||||||
|
r.closeLock.Lock()
|
||||||
|
defer r.closeLock.Unlock()
|
||||||
|
|
||||||
r.closed = true
|
r.closed = true
|
||||||
close(r.channel)
|
close(r.channel)
|
||||||
return nil
|
return nil
|
||||||
|
@ -3,6 +3,9 @@ package grpcserver
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/kaspanet/kaspad/logger"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/netadapter/server/grpcserver/protowire"
|
"github.com/kaspanet/kaspad/netadapter/server/grpcserver/protowire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +36,11 @@ func (c *gRPCConnection) sendLoop() error {
|
|||||||
if !isOpen {
|
if !isOpen {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Tracef("outgoing '%s' message to %s: %s", message.Command(), c, logger.NewLogClosure(func() string {
|
||||||
|
return spew.Sdump(message)
|
||||||
|
}))
|
||||||
|
|
||||||
messageProto, err := protowire.FromWireMessage(message)
|
messageProto, err := protowire.FromWireMessage(message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -60,6 +68,11 @@ func (c *gRPCConnection) receiveLoop() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Tracef("incoming '%s' message from %s: %s", message.Command(), c, logger.NewLogClosure(func() string {
|
||||||
|
return spew.Sdump(message)
|
||||||
|
}))
|
||||||
|
|
||||||
isOpen, err := c.router.EnqueueIncomingMessage(message)
|
isOpen, err := c.router.EnqueueIncomingMessage(message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -22,6 +22,10 @@ func ReceiveAddresses(incomingRoute *router.Route, outgoingRoute *router.Route,
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !addressManager.NeedMoreAddresses() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
msgGetAddresses := wire.NewMsgGetAddresses(false, subnetworkID)
|
msgGetAddresses := wire.NewMsgGetAddresses(false, subnetworkID)
|
||||||
isOpen, err := outgoingRoute.EnqueueWithTimeout(msgGetAddresses, timeout)
|
isOpen, err := outgoingRoute.EnqueueWithTimeout(msgGetAddresses, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -31,10 +35,6 @@ func ReceiveAddresses(incomingRoute *router.Route, outgoingRoute *router.Route,
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if addressManager.NeedMoreAddresses() {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
message, isOpen, err := incomingRoute.DequeueWithTimeout(timeout)
|
message, isOpen, err := incomingRoute.DequeueWithTimeout(timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package ping
|
package ping
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/netadapter/router"
|
"github.com/kaspanet/kaspad/netadapter/router"
|
||||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/util/random"
|
"github.com/kaspanet/kaspad/util/random"
|
||||||
"github.com/kaspanet/kaspad/wire"
|
"github.com/kaspanet/kaspad/wire"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const pingTimeout = 30 * time.Second
|
const pingTimeout = 30 * time.Second
|
||||||
@ -63,7 +64,7 @@ func SendPings(incomingRoute *router.Route, outgoingRoute *router.Route, peer *p
|
|||||||
if !isOpen {
|
if !isOpen {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
pongMessage := message.(*wire.MsgPing)
|
pongMessage := message.(*wire.MsgPong)
|
||||||
if pongMessage.Nonce != pingMessage.Nonce {
|
if pongMessage.Nonce != pingMessage.Nonce {
|
||||||
return protocolerrors.New(true, "nonce mismatch between ping and pong")
|
return protocolerrors.New(true, "nonce mismatch between ping and pong")
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/protocol/flows/handshake"
|
"github.com/kaspanet/kaspad/protocol/flows/handshake"
|
||||||
@ -17,6 +16,7 @@ import (
|
|||||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/wire"
|
"github.com/kaspanet/kaspad/wire"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initializes the p2p protocol
|
// Init initializes the p2p protocol
|
||||||
|
@ -7,9 +7,10 @@ package wire
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/util/daghash"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -65,8 +66,8 @@ const (
|
|||||||
var messageCommandToString = map[MessageCommand]string{
|
var messageCommandToString = map[MessageCommand]string{
|
||||||
CmdVersion: "Version",
|
CmdVersion: "Version",
|
||||||
CmdVerAck: "VerAck",
|
CmdVerAck: "VerAck",
|
||||||
CmdGetAddresses: "GetAddr",
|
CmdGetAddresses: "GetAddress",
|
||||||
CmdAddress: "Addr",
|
CmdAddress: "Address",
|
||||||
CmdGetBlockInvs: "GetBlockInvs",
|
CmdGetBlockInvs: "GetBlockInvs",
|
||||||
CmdInv: "Inv",
|
CmdInv: "Inv",
|
||||||
CmdGetData: "GetData",
|
CmdGetData: "GetData",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user