mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00

* [NOD-1120] Removed closure in NetAdapter.onConnectedHanlder * [NOD-1120] Implement all connection manager methods * [NOD-1120] Integrated connmanager into kaspad + added call for dnsseeder * [NOD-1120] Allow buffer to not be bytes.Buffer * [NOD-1120] Added timeout to connect * [NOD-1120] Don't enter connections to add loop if none needed * [NOD-1120] Add call for addressManager.Good * [NOD-1120] Minor bug fixes * [NOD-1120] Remove errChan from grpcConnection * [NOD-1120] Add comments to exported methods * [NOD-1120] cancel the context for DialContext in gRPCServer.Connect * [NOD-1120] Don't try to remove from connSet a connection that doesn't exist * [NOD-1120] add ok bool to connectionSet.get * [NOD-1120] Remove overuse of if-else in checkConnectionRequests * [NOD-1120] Made some order in ConnectionManager * [NOD-1120] Moved checkIncomingConnections to it's own file * [NOD-1120] cleanup in checkOutgoingConnections * [NOD-1120] Cleanup in SeedDNS, and move call outside of connection manager * [NOD-1120] Add check that both --connect and --addpeer aren't used * [NOD-1120] Move dial timeout to constant * [NOD-1120] Enhance comment * [NOD-1120] Log connection failure out of initiateConnection * [NOD-1148] Reshuffle checkRequestedConnections to make more sense * [NOD-1120] Move continue to correct place + reshuffle logging code * [NOD-1120] Don't expose server.Connection outside netAdapter - expose a wrapper instead * [NOD-1120] Add comments * [NOD-1120] Don't return the connection from netAdapter.Connect() * [NOD-1120] Use .Address as key for connectionSet * [NOD-1120] Fix minRetryDuration usage * [NOD-1120] Remove the correct number of incoming connections * [NOD-1120] Add comment * [NOD-1120] Rename connSet -> incomingConnectionSet * [NOD-1120] fix grammar
105 lines
3.1 KiB
Go
105 lines
3.1 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(func() {
|
|
c.connectionRequestsLock.Lock()
|
|
defer c.connectionRequestsLock.Unlock()
|
|
|
|
if _, ok := c.activeRequested[address]; ok {
|
|
return
|
|
}
|
|
|
|
c.pendingRequested[address] = &connectionRequest{
|
|
address: address,
|
|
isPermanent: isPermanent,
|
|
}
|
|
})
|
|
}
|