Connections: Introduce Redundant type to lower ping overhead.

This commit is contained in:
Kleissner
2021-03-01 03:41:26 +01:00
parent ce831b31b6
commit fec5644b9f
2 changed files with 50 additions and 18 deletions

View File

@@ -88,7 +88,7 @@ func (peer *PeerInfo) cmdChat(msg *packet2) {
const pingTime = 10
// connectionInvalidate is the threshold in seconds to invalidate formerly active connections that no longer receive incoming packets.
const connectionInvalidate = 20
const connectionInvalidate = 22
// connectionRemove is the threshold in seconds to remove inactive connections in case there is at least one active connection known.
const connectionRemove = 2 * 60
@@ -97,24 +97,29 @@ const connectionRemove = 2 * 60
func autoPingAll() {
for {
time.Sleep(time.Second)
thresholdInvalidate := time.Now().Add(-connectionInvalidate * time.Second)
thresholdPingOut := time.Now().Add(-pingTime * time.Second)
thresholdInvalidate1 := time.Now().Add(-connectionInvalidate * time.Second)
thresholdInvalidate2 := time.Now().Add(-connectionInvalidate * time.Second * 4)
thresholdPingOut1 := time.Now().Add(-pingTime * time.Second)
thresholdPingOut2 := time.Now().Add(-pingTime * time.Second * 4)
for _, peer := range PeerlistGet() {
// first handle active connections
for _, connection := range peer.GetConnections(true) {
// Check if no incoming packet for the last X seconds. Regularly sent pings should result in incoming packets.
if connection.LastPacketIn.Before(thresholdInvalidate) {
thresholdPing := thresholdPingOut1
thresholdInv := thresholdInvalidate1
if connection.Status == ConnectionRedundant {
thresholdPing = thresholdPingOut2
thresholdInv = thresholdInvalidate2
}
if connection.LastPacketIn.Before(thresholdInv) {
peer.invalidateActiveConnection(connection)
continue
}
// Send ping if none was sent recently and no incoming packet was received recently.
if connection.LastPacketIn.Before(thresholdPingOut) && connection.LastPingOut.Before(thresholdPingOut) {
if err := peer.sendConnection(&PacketRaw{Command: CommandPing}, connection); IsNetworkErrorFatal(err) {
peer.invalidateActiveConnection(connection)
}
connection.LastPingOut = time.Now()
if connection.LastPacketIn.Before(thresholdPing) && connection.LastPingOut.Before(thresholdPing) {
peer.sendPing(connection)
continue
}
}
@@ -128,15 +133,24 @@ func autoPingAll() {
}
// if no ping was sent recently, send one now
if connection.LastPingOut.Before(thresholdPingOut) {
peer.sendConnection(&PacketRaw{Command: CommandPing}, connection)
connection.LastPingOut = time.Now()
if connection.LastPingOut.Before(thresholdPingOut1) {
peer.sendPing(connection)
}
}
}
}
}
// sendPing sends a ping to the target peer
func (peer *PeerInfo) sendPing(connection *Connection) {
err := peer.sendConnection(&PacketRaw{Command: CommandPing}, connection)
connection.LastPingOut = time.Now()
if (connection.Status == ConnectionActive || connection.Status == ConnectionRedundant) && IsNetworkErrorFatal(err) {
peer.invalidateActiveConnection(connection)
}
}
// SendChatAll sends a text message to all peers
func SendChatAll(text string) {
for _, peer := range PeerlistGet() {

View File

@@ -24,7 +24,7 @@ type Connection struct {
LastPacketOut time.Time // Last time an outgoing packet was attempted to send.
LastPingOut time.Time // Last ping out.
Expires time.Time // Inactive connections only: Expiry date. If it does not become active by that date, it will be considered expired and removed.
Status int // 0 = Active established connection, 1 = Inactive, 2 = Removed
Status int // 0 = Active established connection, 1 = Inactive, 2 = Removed, 3 = Redundant
}
// Connection status
@@ -32,6 +32,7 @@ const (
ConnectionActive = iota
ConnectionInactive
ConnectionRemoved
ConnectionRedundant // Same as active. Incoming packets are accepted. Outgoing use only for redundancy. Reduces ping overhead.
)
// Equal checks if the connection was established other the same network adapter using the same IP address. Port is intentionally not checked.
@@ -64,7 +65,8 @@ func (peer *PeerInfo) registerConnection(incoming *Connection) (result *Connecti
connection.Address.Port = incoming.Address.Port
}
peer.connectionLatest = connection
connection.Status = ConnectionActive
peer.setConnectionLatest(connection)
return connection
}
}
@@ -78,8 +80,8 @@ func (peer *PeerInfo) registerConnection(incoming *Connection) (result *Connecti
// elevate by adding to active and mark as latest active
connection.Status = ConnectionActive
peer.connectionLatest = connection
peer.connectionActive = append(peer.connectionActive, connection)
peer.setConnectionLatest(connection)
// remove from inactive
inactiveNew := peer.connectionInactive[:n]
@@ -94,11 +96,27 @@ func (peer *PeerInfo) registerConnection(incoming *Connection) (result *Connecti
// otherwise it is a new connection!
peer.connectionActive = append(peer.connectionActive, incoming)
peer.connectionLatest = incoming
peer.setConnectionLatest(incoming)
return incoming
}
// setConnectionLatest updates the latest valid connection to use for sending. All other connections will be changed to redundant, which reduces ping overhead.
func (peer *PeerInfo) setConnectionLatest(latest *Connection) {
if peer.connectionLatest == latest {
return
}
peer.connectionLatest = latest
for _, connection := range peer.connectionActive {
if connection == latest {
continue
}
connection.Status = ConnectionRedundant
}
}
// invalidateActiveConnection invalidates an active connection
func (peer *PeerInfo) invalidateActiveConnection(input *Connection) {
peer.Lock()