mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-18 11:17:49 +01:00
New function IsNetworkErrorFatal to invalidate connections on fatal network errors. Use connection.Expires field to trigger removal of inactive connections after a while.
This commit is contained in:
11
Commands.go
11
Commands.go
@@ -98,7 +98,6 @@ func autoPingAll() {
|
||||
for {
|
||||
time.Sleep(time.Second)
|
||||
thresholdInvalidate := time.Now().Add(-connectionInvalidate * time.Second)
|
||||
thresholdRemove := time.Now().Add(-(connectionRemove + connectionInvalidate) * time.Second)
|
||||
thresholdPingOut := time.Now().Add(-pingTime * time.Second)
|
||||
|
||||
for _, peer := range PeerlistGet() {
|
||||
@@ -107,19 +106,23 @@ func autoPingAll() {
|
||||
// Check if no incoming packet for the last X seconds. Regularly sent pings should result in incoming packets.
|
||||
if connection.LastPacketIn.Before(thresholdInvalidate) {
|
||||
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) {
|
||||
peer.sendConnection(&PacketRaw{Command: CommandPing}, connection)
|
||||
if err := peer.sendConnection(&PacketRaw{Command: CommandPing}, connection); IsNetworkErrorFatal(err) {
|
||||
peer.invalidateActiveConnection(connection)
|
||||
}
|
||||
connection.LastPingOut = time.Now()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// handle inactive connections
|
||||
for _, connection := range peer.GetConnections(false) {
|
||||
// Remove connections that have been inactive for a long time; only if there is at least an active connection, or at least two other inactive ones.
|
||||
if connection.LastPacketIn.Before(thresholdRemove) && (len(peer.connectionActive) >= 1 || len(peer.connectionInactive) > 2) {
|
||||
// If the inactive connection is expired, remove it; although only if there is at least one active connection, or two other inactive ones.
|
||||
if (len(peer.connectionActive) >= 1 || len(peer.connectionInactive) > 2) && connection.Expires.Before(time.Now()) {
|
||||
peer.removeInactiveConnection(connection)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type Connection struct {
|
||||
LastPacketIn time.Time // Last time an incoming packet was received.
|
||||
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.
|
||||
}
|
||||
|
||||
// Equal checks if the connection was established other the same network adapter using the same IP address. Port is intentionally not checked.
|
||||
@@ -94,6 +95,9 @@ func (peer *PeerInfo) invalidateActiveConnection(input *Connection) {
|
||||
peer.Lock()
|
||||
defer peer.Unlock()
|
||||
|
||||
// Change the status to inactive and start the expiration. If the connection does not become valid by that date, it will be removed.
|
||||
input.Expires = time.Now().Add(connectionRemove * time.Second)
|
||||
|
||||
// remove from connectionLatest if selected so it won't be used by standard send function
|
||||
if peer.connectionLatest == input {
|
||||
peer.connectionLatest = nil
|
||||
@@ -111,7 +115,7 @@ func (peer *PeerInfo) invalidateActiveConnection(input *Connection) {
|
||||
}
|
||||
peer.connectionActive = activeNew
|
||||
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +170,9 @@ func (peer *PeerInfo) send(packet *PacketRaw) (err error) {
|
||||
|
||||
// Invalid connection, immediately invalidate. Fallback to broadcast to all other active ones.
|
||||
// Windows: A common error when the network adapter is disabled is "wsasendto: The requested address is not valid in its context".
|
||||
peer.invalidateActiveConnection(c)
|
||||
if IsNetworkErrorFatal(err) {
|
||||
peer.invalidateActiveConnection(c)
|
||||
}
|
||||
}
|
||||
|
||||
// If no latest connection available, broadcast on all available connections.
|
||||
|
||||
@@ -6,7 +6,10 @@ Author: Peter Kleissner
|
||||
|
||||
package core
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FindInterfaceByIP finds an interface based on the IP. The IP must be available at the interface.
|
||||
func FindInterfaceByIP(ip net.IP) (iface *net.Interface, ipnet *net.IPNet) {
|
||||
@@ -69,3 +72,18 @@ func IsIPv4(IP net.IP) bool {
|
||||
func IsIPv6(IP net.IP) bool {
|
||||
return IP.To4() == nil && IP.To16() != nil
|
||||
}
|
||||
|
||||
// IsNetworkErrorFatal checks if a network error indicates a broken connection.
|
||||
// Not every network error indicates a broken connection. This function prevents from over-dropping connections.
|
||||
func IsNetworkErrorFatal(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Windows: A common error when the network adapter is disabled is "wsasendto: The requested address is not valid in its context".
|
||||
if strings.Contains(err.Error(), "requested address is not valid in its context") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user