/* File Name: Commands.go Copyright: 2021 Peernet s.r.o. Author: Peter Kleissner */ package core import ( "fmt" "time" ) // cmdAnouncement handles an incoming announcement func (peer *PeerInfo) cmdAnouncement(msg *MessageAnnouncement) { if peer == nil { peer, added := PeerlistAdd(msg.SenderPublicKey, msg.connection) fmt.Printf("Incoming initial announcement from %s\n", msg.connection.Address.String()) // send the Response if added { peer.send(&PacketRaw{Command: CommandResponse}) } return } fmt.Printf("Incoming secondary announcement from %s\n", msg.connection.Address.String()) // Announcement from existing peer means the peer most likely restarted peer.send(&PacketRaw{Command: CommandResponse}) } // cmdResponse handles the response to the announcement func (peer *PeerInfo) cmdResponse(msg *MessageResponse) { if peer == nil { peer, _ = PeerlistAdd(msg.SenderPublicKey, msg.connection) fmt.Printf("Incoming initial response from %s\n", msg.connection.Address.String()) return } fmt.Printf("Incoming response from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String()) } // cmdPing handles an incoming ping message func (peer *PeerInfo) cmdPing(msg *MessageRaw) { if peer == nil { // Unexpected incoming ping, reply with announce message // TODO return } peer.send(&PacketRaw{Command: CommandPong}) //fmt.Printf("Incoming ping from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String()) } // cmdPong handles an incoming pong message func (peer *PeerInfo) cmdPong(msg *MessageRaw) { //fmt.Printf("Incoming pong from %s on %s\n", msg.connection.Address.String(), msg.connection.Address.String()) } // cmdChat handles a chat message [debug] func (peer *PeerInfo) cmdChat(msg *MessageRaw) { fmt.Printf("Chat from '%s': %s\n", msg.connection.Address.String(), string(msg.PacketRaw.Payload)) } // pingTime is the time in seconds to send out ping messages const pingTime = 10 // connectionInvalidate is the threshold in seconds to invalidate formerly active connections that no longer receive incoming packets. 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 // autoPingAll sends out regular ping messages to all connections of all peers. This allows to detect invalid connections and eventually drop them. func autoPingAll() { for { time.Sleep(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) { thresholdPing := thresholdPingOut1 thresholdInv := thresholdInvalidate1 if connection.Status == ConnectionRedundant { thresholdPing = thresholdPingOut2 thresholdInv = thresholdInvalidate2 } if connection.LastPacketIn.Before(thresholdInv) { peer.invalidateActiveConnection(connection) continue } if connection.LastPacketIn.Before(thresholdPing) && connection.LastPingOut.Before(thresholdPing) { peer.pingConnection(connection) continue } } // handle inactive connections for _, connection := range peer.GetConnections(false) { // 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 } // if no ping was sent recently, send one now if connection.LastPingOut.Before(thresholdPingOut1) { peer.pingConnection(connection) } } } } } // SendChatAll sends a text message to all peers func SendChatAll(text string) { for _, peer := range PeerlistGet() { peer.Chat(text) } }