mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00

* [NOD-1162] [FIX] Connection manager should run the moment it adds a request * [NOD-1162] [FIX] Set peerID on handshake * [NOD-1162] [FIX] Broadcast should send to outgoing route, not incoming * [NOD-1162] [FIX] Add CmdInvRelayBlock to MakeEmptyMessage * [NOD-1162] [FIX] Initialize Hash before decoding MsgInvRelayBlock * [NOD-1162] [FIX] Invert condition * [NOD-1162] [FIX] Fixes to encoding of MsgGetRelayBlocks * [NOD-1162] [FIX] Add MsgGetRelayBlocks to MakeEmptyMessage * [NOD-1162] Add comment
114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
package connmanager
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
minRetryDuration = 30 * time.Second
|
|
maxRetryDuration = 10 * time.Minute
|
|
)
|
|
|
|
func nextRetryDuration(previousDuration time.Duration) time.Duration {
|
|
if previousDuration < minRetryDuration {
|
|
return minRetryDuration
|
|
}
|
|
if previousDuration*2 > maxRetryDuration {
|
|
return maxRetryDuration
|
|
}
|
|
return previousDuration * 2
|
|
}
|
|
|
|
// checkRequestedConnections checks that all activeRequested are still active, and initiates connections
|
|
// for pendingRequested.
|
|
// While doing so, it filters out of connSet all connections that were initiated as a connectionRequest
|
|
func (c *ConnectionManager) checkRequestedConnections(connSet connectionSet) {
|
|
c.connectionRequestsLock.Lock()
|
|
defer c.connectionRequestsLock.Unlock()
|
|
|
|
now := time.Now()
|
|
|
|
for address, connReq := range c.activeRequested {
|
|
connection, ok := connSet.get(address)
|
|
if !ok { // a requested connection was disconnected
|
|
delete(c.activeRequested, address)
|
|
|
|
if connReq.isPermanent { // if is one-try - ignore. If permanent - add to pending list to retry
|
|
connReq.nextAttempt = now
|
|
connReq.retryDuration = 0
|
|
c.pendingRequested[address] = connReq
|
|
}
|
|
continue
|
|
}
|
|
|
|
connSet.remove(connection)
|
|
}
|
|
|
|
for address, connReq := range c.pendingRequested {
|
|
if connReq.nextAttempt.After(now) { // ignore connection requests which are still waiting for retry
|
|
continue
|
|
}
|
|
|
|
connection, ok := connSet.get(address)
|
|
// The pending connection request has already connected - move it to active
|
|
// This can happen in rare cases such as when the other side has connected to our node
|
|
// while it has been pending on our side.
|
|
if ok {
|
|
delete(c.pendingRequested, address)
|
|
c.pendingRequested[address] = connReq
|
|
|
|
connSet.remove(connection)
|
|
|
|
continue
|
|
}
|
|
|
|
// try to initiate connection
|
|
err := c.initiateConnection(connReq.address)
|
|
if err != nil {
|
|
log.Infof("Couldn't connect to %s: %s", address, err)
|
|
// if connection request is one try - remove from pending and ignore failure
|
|
if !connReq.isPermanent {
|
|
delete(c.pendingRequested, address)
|
|
continue
|
|
}
|
|
// if connection request is permanent - keep in pending, and increase retry time
|
|
connReq.retryDuration = nextRetryDuration(connReq.retryDuration)
|
|
connReq.nextAttempt = now.Add(connReq.retryDuration)
|
|
log.Debugf("Retrying permanent connection to %s in %s", address, connReq.retryDuration)
|
|
continue
|
|
}
|
|
|
|
// if connected successfully - move from pending to active
|
|
delete(c.pendingRequested, address)
|
|
c.activeRequested[address] = connReq
|
|
}
|
|
}
|
|
|
|
// AddConnectionRequest adds the given address to list of pending connection requests
|
|
func (c *ConnectionManager) AddConnectionRequest(address string, isPermanent bool) {
|
|
// spawn goroutine so that caller doesn't wait in case connectionManager is in the midst of handling
|
|
// connection requests
|
|
spawn("ConnectionManager.AddConnectionRequest", func() {
|
|
c.connectionRequestsLock.Lock()
|
|
defer c.connectionRequestsLock.Unlock()
|
|
|
|
if _, ok := c.activeRequested[address]; ok {
|
|
return
|
|
}
|
|
|
|
c.pendingRequested[address] = &connectionRequest{
|
|
address: address,
|
|
isPermanent: isPermanent,
|
|
}
|
|
|
|
c.run()
|
|
})
|
|
}
|
|
|
|
// RemoveConnection disconnects the connection for the given address
|
|
// and removes it entirely from the connection manager.
|
|
func (c *ConnectionManager) RemoveConnection(address string) {
|
|
// TODO(libp2p): unimplemented
|
|
panic("unimplemented")
|
|
}
|