forked from TrueCloudLab/neoneo-go
network: add ping pong processing
add pingInterval same as used in ref C# implementation with the same logic add pingTimeout which is used to check whether pong received. If not -- drop the peer. add pingLimit which is hardcoded to 4 in TCPPeer. It's limit for unsuccessful ping/pong calls (where pong wasn't received in pingTimeout interval)
This commit is contained in:
parent
7ba5267494
commit
4e6ed9021c
18 changed files with 195 additions and 3 deletions
|
@ -73,6 +73,8 @@ type (
|
||||||
Relay bool `yaml:"Relay"`
|
Relay bool `yaml:"Relay"`
|
||||||
DialTimeout time.Duration `yaml:"DialTimeout"`
|
DialTimeout time.Duration `yaml:"DialTimeout"`
|
||||||
ProtoTickInterval time.Duration `yaml:"ProtoTickInterval"`
|
ProtoTickInterval time.Duration `yaml:"ProtoTickInterval"`
|
||||||
|
PingInterval time.Duration `yaml:"PingInterval"`
|
||||||
|
PingTimeout time.Duration `yaml:"PingTimeout"`
|
||||||
MaxPeers int `yaml:"MaxPeers"`
|
MaxPeers int `yaml:"MaxPeers"`
|
||||||
AttemptConnPeers int `yaml:"AttemptConnPeers"`
|
AttemptConnPeers int `yaml:"AttemptConnPeers"`
|
||||||
MinPeers int `yaml:"MinPeers"`
|
MinPeers int `yaml:"MinPeers"`
|
||||||
|
|
|
@ -50,6 +50,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 100
|
MaxPeers: 100
|
||||||
AttemptConnPeers: 20
|
AttemptConnPeers: 20
|
||||||
MinPeers: 5
|
MinPeers: 5
|
||||||
|
|
|
@ -41,6 +41,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 3
|
MinPeers: 3
|
||||||
|
|
|
@ -41,6 +41,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 3
|
MinPeers: 3
|
||||||
|
|
|
@ -35,6 +35,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 0
|
MinPeers: 0
|
||||||
|
|
|
@ -41,6 +41,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 3
|
MinPeers: 3
|
||||||
|
|
|
@ -41,6 +41,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 3
|
MinPeers: 3
|
||||||
|
|
|
@ -41,6 +41,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 10
|
MaxPeers: 10
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 3
|
MinPeers: 3
|
||||||
|
|
|
@ -50,6 +50,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 100
|
MaxPeers: 100
|
||||||
AttemptConnPeers: 20
|
AttemptConnPeers: 20
|
||||||
MinPeers: 5
|
MinPeers: 5
|
||||||
|
|
|
@ -40,6 +40,8 @@ ApplicationConfiguration:
|
||||||
Relay: true
|
Relay: true
|
||||||
DialTimeout: 3
|
DialTimeout: 3
|
||||||
ProtoTickInterval: 2
|
ProtoTickInterval: 2
|
||||||
|
PingInterval: 60
|
||||||
|
PingTimeout: 60
|
||||||
MaxPeers: 50
|
MaxPeers: 50
|
||||||
AttemptConnPeers: 5
|
AttemptConnPeers: 5
|
||||||
MinPeers: 1
|
MinPeers: 1
|
||||||
|
|
|
@ -153,9 +153,11 @@ var defaultMessageHandler = func(t *testing.T, msg *Message) {}
|
||||||
type localPeer struct {
|
type localPeer struct {
|
||||||
netaddr net.TCPAddr
|
netaddr net.TCPAddr
|
||||||
version *payload.Version
|
version *payload.Version
|
||||||
|
lastBlockIndex uint32
|
||||||
handshaked bool
|
handshaked bool
|
||||||
t *testing.T
|
t *testing.T
|
||||||
messageHandler func(t *testing.T, msg *Message)
|
messageHandler func(t *testing.T, msg *Message)
|
||||||
|
pingSent int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLocalPeer(t *testing.T) *localPeer {
|
func newLocalPeer(t *testing.T) *localPeer {
|
||||||
|
@ -185,6 +187,12 @@ func (p *localPeer) Done() chan error {
|
||||||
func (p *localPeer) Version() *payload.Version {
|
func (p *localPeer) Version() *payload.Version {
|
||||||
return p.version
|
return p.version
|
||||||
}
|
}
|
||||||
|
func (p *localPeer) LastBlockIndex() uint32 {
|
||||||
|
return p.lastBlockIndex
|
||||||
|
}
|
||||||
|
func (p *localPeer) UpdateLastBlockIndex(newIndex uint32) {
|
||||||
|
p.lastBlockIndex = newIndex
|
||||||
|
}
|
||||||
func (p *localPeer) HandleVersion(v *payload.Version) error {
|
func (p *localPeer) HandleVersion(v *payload.Version) error {
|
||||||
p.version = v
|
p.version = v
|
||||||
return nil
|
return nil
|
||||||
|
@ -199,6 +207,12 @@ func (p *localPeer) HandleVersionAck() error {
|
||||||
p.handshaked = true
|
p.handshaked = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (p *localPeer) GetPingSent() int {
|
||||||
|
return p.pingSent
|
||||||
|
}
|
||||||
|
func (p *localPeer) UpdatePingSent(newValue int) {
|
||||||
|
p.pingSent = newValue
|
||||||
|
}
|
||||||
|
|
||||||
func (p *localPeer) Handshaked() bool {
|
func (p *localPeer) Handshaked() bool {
|
||||||
return p.handshaked
|
return p.handshaked
|
||||||
|
|
|
@ -197,6 +197,8 @@ func (m *Message) decodePayload(br *io.BinReader) error {
|
||||||
p = &transaction.Transaction{}
|
p = &transaction.Transaction{}
|
||||||
case CMDMerkleBlock:
|
case CMDMerkleBlock:
|
||||||
p = &payload.MerkleBlock{}
|
p = &payload.MerkleBlock{}
|
||||||
|
case CMDPing, CMDPong:
|
||||||
|
p = &payload.Ping{}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("can't decode command %s", cmdByteArrayToString(m.Command))
|
return fmt.Errorf("can't decode command %s", cmdByteArrayToString(m.Command))
|
||||||
}
|
}
|
||||||
|
|
40
pkg/network/payload/ping.go
Normal file
40
pkg/network/payload/ping.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ping payload for ping/pong payloads.
|
||||||
|
type Ping struct {
|
||||||
|
// Index of the last block.
|
||||||
|
LastBlockIndex uint32
|
||||||
|
// Timestamp.
|
||||||
|
Timestamp uint32
|
||||||
|
// Nonce of the server.
|
||||||
|
Nonce uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPing creates new Ping payload.
|
||||||
|
func NewPing(blockIndex uint32, nonce uint32) *Ping {
|
||||||
|
return &Ping{
|
||||||
|
LastBlockIndex: blockIndex,
|
||||||
|
Timestamp: uint32(time.Now().UTC().Unix()),
|
||||||
|
Nonce: nonce,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeBinary implements Serializable interface.
|
||||||
|
func (p *Ping) DecodeBinary(br *io.BinReader) {
|
||||||
|
p.LastBlockIndex = br.ReadU32LE()
|
||||||
|
p.Timestamp = br.ReadU32LE()
|
||||||
|
p.Nonce = br.ReadU32LE()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeBinary implements Serializable interface.
|
||||||
|
func (p *Ping) EncodeBinary(bw *io.BinWriter) {
|
||||||
|
bw.WriteU32LE(p.LastBlockIndex)
|
||||||
|
bw.WriteU32LE(p.Timestamp)
|
||||||
|
bw.WriteU32LE(p.Nonce)
|
||||||
|
}
|
25
pkg/network/payload/ping_test.go
Normal file
25
pkg/network/payload/ping_test.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/io"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncodeDecodeBinary(t *testing.T) {
|
||||||
|
payload := NewPing(uint32(1), uint32(2))
|
||||||
|
assert.NotEqual(t, 0, payload.Timestamp)
|
||||||
|
|
||||||
|
bufBinWriter := io.NewBufBinWriter()
|
||||||
|
payload.EncodeBinary(bufBinWriter.BinWriter)
|
||||||
|
assert.Nil(t, bufBinWriter.Err)
|
||||||
|
|
||||||
|
binReader := io.NewBinReaderFromBuf(bufBinWriter.Bytes())
|
||||||
|
decodedPing := &Ping{}
|
||||||
|
decodedPing.DecodeBinary(binReader)
|
||||||
|
assert.Nil(t, binReader.Err)
|
||||||
|
|
||||||
|
assert.Equal(t, uint32(1), decodedPing.LastBlockIndex)
|
||||||
|
assert.Equal(t, uint32(2), decodedPing.Nonce)
|
||||||
|
}
|
|
@ -21,9 +21,13 @@ type Peer interface {
|
||||||
WriteMsg(msg *Message) error
|
WriteMsg(msg *Message) error
|
||||||
Done() chan error
|
Done() chan error
|
||||||
Version() *payload.Version
|
Version() *payload.Version
|
||||||
|
LastBlockIndex() uint32
|
||||||
|
UpdateLastBlockIndex(lbIndex uint32)
|
||||||
Handshaked() bool
|
Handshaked() bool
|
||||||
SendVersion(*Message) error
|
SendVersion(*Message) error
|
||||||
SendVersionAck(*Message) error
|
SendVersionAck(*Message) error
|
||||||
HandleVersion(*payload.Version) error
|
HandleVersion(*payload.Version) error
|
||||||
HandleVersionAck() error
|
HandleVersionAck() error
|
||||||
|
GetPingSent() int
|
||||||
|
UpdatePingSent(int)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ const (
|
||||||
maxBlockBatch = 200
|
maxBlockBatch = 200
|
||||||
maxAddrsToSend = 200
|
maxAddrsToSend = 200
|
||||||
minPoolCount = 30
|
minPoolCount = 30
|
||||||
|
defaultPingLimit = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -314,7 +315,7 @@ func (s *Server) startProtocol(p Peer) {
|
||||||
zap.Uint32("id", p.Version().Nonce))
|
zap.Uint32("id", p.Version().Nonce))
|
||||||
|
|
||||||
s.discovery.RegisterGoodAddr(p.PeerAddr().String())
|
s.discovery.RegisterGoodAddr(p.PeerAddr().String())
|
||||||
if s.chain.HeaderHeight() < p.Version().StartHeight {
|
if s.chain.HeaderHeight() < p.LastBlockIndex() {
|
||||||
err = s.requestHeaders(p)
|
err = s.requestHeaders(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Disconnect(err)
|
p.Disconnect(err)
|
||||||
|
@ -323,6 +324,7 @@ func (s *Server) startProtocol(p Peer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.NewTimer(s.ProtoTickInterval)
|
timer := time.NewTimer(s.ProtoTickInterval)
|
||||||
|
pingTimer := time.NewTimer(s.PingTimeout)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case err = <-p.Done():
|
case err = <-p.Done():
|
||||||
|
@ -331,12 +333,31 @@ func (s *Server) startProtocol(p Peer) {
|
||||||
err = p.WriteMsg(m)
|
err = p.WriteMsg(m)
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
// Try to sync in headers and block with the peer if his block height is higher then ours.
|
// Try to sync in headers and block with the peer if his block height is higher then ours.
|
||||||
if p.Version().StartHeight > s.chain.BlockHeight() {
|
if p.LastBlockIndex() > s.chain.BlockHeight() {
|
||||||
err = s.requestBlocks(p)
|
err = s.requestBlocks(p)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
timer.Reset(s.ProtoTickInterval)
|
timer.Reset(s.ProtoTickInterval)
|
||||||
}
|
}
|
||||||
|
if s.chain.HeaderHeight() >= p.LastBlockIndex() {
|
||||||
|
block, errGetBlock := s.chain.GetBlock(s.chain.CurrentBlockHash())
|
||||||
|
if errGetBlock != nil {
|
||||||
|
err = errGetBlock
|
||||||
|
} else {
|
||||||
|
diff := uint32(time.Now().UTC().Unix()) - block.Timestamp
|
||||||
|
if diff > uint32(s.PingInterval/time.Second) {
|
||||||
|
p.UpdatePingSent(p.GetPingSent() + 1)
|
||||||
|
err = p.WriteMsg(NewMessage(s.Net, CMDPing, payload.NewPing(s.id, s.chain.HeaderHeight())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-pingTimer.C:
|
||||||
|
if p.GetPingSent() > defaultPingLimit {
|
||||||
|
err = errors.New("ping/pong timeout")
|
||||||
|
} else {
|
||||||
|
pingTimer.Reset(s.PingTimeout)
|
||||||
|
p.UpdatePingSent(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.unregister <- peerDrop{p, err}
|
s.unregister <- peerDrop{p, err}
|
||||||
|
@ -394,7 +415,7 @@ func (s *Server) handleHeadersCmd(p Peer, headers *payload.Headers) {
|
||||||
// The peer will respond with a maximum of 2000 headers in one batch.
|
// The peer will respond with a maximum of 2000 headers in one batch.
|
||||||
// We will ask one more batch here if needed. Eventually we will get synced
|
// We will ask one more batch here if needed. Eventually we will get synced
|
||||||
// due to the startProtocol routine that will ask headers every protoTick.
|
// due to the startProtocol routine that will ask headers every protoTick.
|
||||||
if s.chain.HeaderHeight() < p.Version().StartHeight {
|
if s.chain.HeaderHeight() < p.LastBlockIndex() {
|
||||||
s.requestHeaders(p)
|
s.requestHeaders(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,6 +425,25 @@ func (s *Server) handleBlockCmd(p Peer, block *core.Block) error {
|
||||||
return s.bQueue.putBlock(block)
|
return s.bQueue.putBlock(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handlePing processes ping request.
|
||||||
|
func (s *Server) handlePing(p Peer, ping *payload.Ping) error {
|
||||||
|
return p.WriteMsg(NewMessage(s.Net, CMDPong, payload.NewPing(s.id, s.chain.BlockHeight())))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePing processes pong request.
|
||||||
|
func (s *Server) handlePong(p Peer, pong *payload.Ping) error {
|
||||||
|
pingSent := p.GetPingSent()
|
||||||
|
if pingSent == 0 {
|
||||||
|
return errors.New("pong message wasn't expected")
|
||||||
|
}
|
||||||
|
p.UpdatePingSent(pingSent - 1)
|
||||||
|
p.UpdateLastBlockIndex(pong.LastBlockIndex)
|
||||||
|
if s.chain.HeaderHeight() < pong.LastBlockIndex {
|
||||||
|
return s.requestHeaders(p)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// handleInvCmd processes the received inventory.
|
// handleInvCmd processes the received inventory.
|
||||||
func (s *Server) handleInvCmd(p Peer, inv *payload.Inventory) error {
|
func (s *Server) handleInvCmd(p Peer, inv *payload.Inventory) error {
|
||||||
reqHashes := make([]util.Uint256, 0)
|
reqHashes := make([]util.Uint256, 0)
|
||||||
|
@ -640,6 +680,12 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error {
|
||||||
case CMDTX:
|
case CMDTX:
|
||||||
tx := msg.Payload.(*transaction.Transaction)
|
tx := msg.Payload.(*transaction.Transaction)
|
||||||
return s.handleTxCmd(tx)
|
return s.handleTxCmd(tx)
|
||||||
|
case CMDPing:
|
||||||
|
ping := msg.Payload.(*payload.Ping)
|
||||||
|
return s.handlePing(peer, ping)
|
||||||
|
case CMDPong:
|
||||||
|
pong := msg.Payload.(*payload.Ping)
|
||||||
|
return s.handlePong(peer, pong)
|
||||||
case CMDVersion, CMDVerack:
|
case CMDVersion, CMDVerack:
|
||||||
return fmt.Errorf("received '%s' after the handshake", msg.CommandType())
|
return fmt.Errorf("received '%s' after the handshake", msg.CommandType())
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,11 @@ type (
|
||||||
// When this is 0, the default interval of 5 seconds will be used.
|
// When this is 0, the default interval of 5 seconds will be used.
|
||||||
ProtoTickInterval time.Duration
|
ProtoTickInterval time.Duration
|
||||||
|
|
||||||
|
// Interval used in pinging mechanism for syncing blocks.
|
||||||
|
PingInterval time.Duration
|
||||||
|
// Time to wait for pong(response for sent ping request).
|
||||||
|
PingTimeout time.Duration
|
||||||
|
|
||||||
// Level of the internal logger.
|
// Level of the internal logger.
|
||||||
LogLevel zapcore.Level
|
LogLevel zapcore.Level
|
||||||
|
|
||||||
|
@ -83,6 +88,8 @@ func NewServerConfig(cfg config.Config) ServerConfig {
|
||||||
Seeds: protoConfig.SeedList,
|
Seeds: protoConfig.SeedList,
|
||||||
DialTimeout: appConfig.DialTimeout * time.Second,
|
DialTimeout: appConfig.DialTimeout * time.Second,
|
||||||
ProtoTickInterval: appConfig.ProtoTickInterval * time.Second,
|
ProtoTickInterval: appConfig.ProtoTickInterval * time.Second,
|
||||||
|
PingInterval: appConfig.PingInterval * time.Second,
|
||||||
|
PingTimeout: appConfig.PingTimeout * time.Second,
|
||||||
MaxPeers: appConfig.MaxPeers,
|
MaxPeers: appConfig.MaxPeers,
|
||||||
AttemptConnPeers: appConfig.AttemptConnPeers,
|
AttemptConnPeers: appConfig.AttemptConnPeers,
|
||||||
MinPeers: appConfig.MinPeers,
|
MinPeers: appConfig.MinPeers,
|
||||||
|
|
|
@ -31,6 +31,8 @@ type TCPPeer struct {
|
||||||
|
|
||||||
// The version of the peer.
|
// The version of the peer.
|
||||||
version *payload.Version
|
version *payload.Version
|
||||||
|
// Index of the last block.
|
||||||
|
lastBlockIndex uint32
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
handShake handShakeStage
|
handShake handShakeStage
|
||||||
|
@ -38,6 +40,9 @@ type TCPPeer struct {
|
||||||
done chan error
|
done chan error
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
|
// number of sent pings.
|
||||||
|
pingSent int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPPeer returns a TCPPeer structure based on the given connection.
|
// NewTCPPeer returns a TCPPeer structure based on the given connection.
|
||||||
|
@ -103,6 +108,7 @@ func (p *TCPPeer) HandleVersion(version *payload.Version) error {
|
||||||
return errors.New("invalid handshake: already received Version")
|
return errors.New("invalid handshake: already received Version")
|
||||||
}
|
}
|
||||||
p.version = version
|
p.version = version
|
||||||
|
p.lastBlockIndex = version.StartHeight
|
||||||
p.handShake |= versionReceived
|
p.handShake |= versionReceived
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -191,3 +197,31 @@ func (p *TCPPeer) Disconnect(err error) {
|
||||||
func (p *TCPPeer) Version() *payload.Version {
|
func (p *TCPPeer) Version() *payload.Version {
|
||||||
return p.version
|
return p.version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LastBlockIndex returns last block index.
|
||||||
|
func (p *TCPPeer) LastBlockIndex() uint32 {
|
||||||
|
p.lock.RLock()
|
||||||
|
defer p.lock.RUnlock()
|
||||||
|
return p.lastBlockIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLastBlockIndex updates last block index.
|
||||||
|
func (p *TCPPeer) UpdateLastBlockIndex(newIndex uint32) {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
p.lastBlockIndex = newIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPingSent returns flag whether ping was sent or not.
|
||||||
|
func (p *TCPPeer) GetPingSent() int {
|
||||||
|
p.lock.RLock()
|
||||||
|
defer p.lock.RUnlock()
|
||||||
|
return p.pingSent
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePingSent updates pingSent value.
|
||||||
|
func (p *TCPPeer) UpdatePingSent(newValue int) {
|
||||||
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
p.pingSent = newValue
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue