// Ping the Peer every second. func (pr *Peer) heartbeat() { pr.HeartbeatTicker = time.NewTicker(time.Second) for { <-pr.HeartbeatTicker.C // Check For Defib if time.Now().After(pr.LastHeartbeat.Add(5 * time.Second)) { pr.Logger.Warn("Peer", "%02X: Peer Defib (no response for >5 seconds)", pr.ServerNetworkNode.ID) pr.State = PeerStateDefib } switch pr.State { case PeerStateConnected: err := pr.SendPacket(packets.NewPacket(packets.CMD_HEARTBEAT, nil)) if err != nil { pr.Logger.Error("Peer", "%02X: Error Sending Heartbeat, disconnecting", pr.ServerNetworkNode.ID) pr.Disconnect() return } case PeerStateDefib: if time.Now().After(pr.LastHeartbeat.Add(10 * time.Second)) { pr.Logger.Warn("Peer", "%02X: Peer DOA (Defib for 5 seconds, disconnecting)", pr.ServerNetworkNode.ID) pr.Disconnect() return } } } }
func (svr *TLSServer) SetKey(key string, value []byte, flags int16, expiry *time.Time) { keymd5 := ch.NewMD5Key(key) nodes := svr.ServerNode.GetNodesFor(keymd5, 3) svr.Logger.Debug("Server", "SetKey: %d peers for key %02X", len(nodes), keymd5) for _, node := range nodes { if node.ID == svr.ServerNode.ID { svr.Logger.Debug("Server", "SetKey: Peer for key %02X -> %02X (Local)", keymd5, node.ID) // Local set. svr.KVStore.Set(key, value, flags, expiry) } else { svr.Logger.Debug("Server", "SetKey: Peer for key %02X -> %02X (Remote)", keymd5, node.ID) peer := svr.Connections[node.ID] if peer.State != PeerStateConnected { svr.Logger.Warn("Server", "SetKey: Peer for key %02X -> %02X (Remote) Unavailable", keymd5, node.ID) continue } // Remote Set. payload := packets.KVStorePacket{ Command: packets.CMD_KVSTORE_SET, Key: key, KeyHash: keymd5, Data: value, ExpiresAt: expiry, Flags: flags, TargetID: node.ID, } packet := packets.NewPacket(packets.CMD_KVSTORE, payload) peer.SendPacketWaitReply(packet, 5*time.Second) } } }
func (svr *TLSServer) NotifyNewPeer(newPeer *Peer) { for id, peer := range svr.Connections { if peer.ServerNetworkNode.ID != newPeer.ServerNetworkNode.ID && peer.Incoming { svr.Logger.Info("Server", "Notifying Existing Peer %02X of new Peer %02X (%s)", id, newPeer.ServerNetworkNode.ID, newPeer.ServerNetworkNode.HostAddr) payload := packets.PeerListPacket{} payload[newPeer.ServerNetworkNode.ID] = newPeer.ServerNetworkNode.HostAddr peer.SendPacket(packets.NewPacket(packets.CMD_PEERLIST, payload)) } } }
func (svr *TLSServer) GetKey(key string) ([]byte, int16, bool) { keymd5 := ch.NewMD5Key(key) nodes := svr.ServerNode.GetNodesFor(keymd5, 3) for _, node := range nodes { if node.ID == svr.ServerNode.ID { svr.Logger.Debug("Server", "GetKey: Peer for key %02X -> %02X (Local)", keymd5, node.ID) // Local set. return svr.KVStore.Get(key) } else { svr.Logger.Debug("Server", "GetKey: Peer for key %02X -> %02X (Remote)", keymd5, node.ID) peer := svr.Connections[node.ID] if peer.State != PeerStateConnected { svr.Logger.Warn("Server", "GetKey: Peer for key %02X -> %02X (Remote) Unavailable", keymd5, node.ID) continue } // Remote Set. payload := packets.KVStorePacket{ Command: packets.CMD_KVSTORE_GET, Key: key, KeyHash: keymd5, TargetID: node.ID, } packet := packets.NewPacket(packets.CMD_KVSTORE, payload) reply, err := peer.SendPacketWaitReply(packet, 5*time.Second) // Process reply or timeout if err == nil { switch reply.Command { case packets.CMD_KVSTORE_ACK: kvpacket := reply.Payload.(packets.KVStorePacket) svr.Logger.Debug("Server", "GetKey: Reply from Remote %s = %s", key, kvpacket.Data) return kvpacket.Data, kvpacket.Flags, true case packets.CMD_KVSTORE_NOT_FOUND: svr.Logger.Debug("Server", "GetKey: Reply from Remote %s Not Found", key) return []byte{}, 0, false default: svr.Logger.Warn("Server", "GetKey: Unknown Reply Command %d", reply.Command) } } else { svr.Logger.Warn("Server", "GetKey: Reply Timeout") } } } return []byte{}, 0, false }
func (svr *TLSServer) DeleteKey(key string) bool { keymd5 := ch.NewMD5Key(key) node := svr.ServerNode.GetNodeFor(keymd5) if node.ID == svr.ServerNode.ID { svr.Logger.Debug("Server", "DeleteKey: Peer for key %02X -> %02X (Local)", keymd5, node.ID) // Local set. return svr.KVStore.Delete(key) } else { svr.Logger.Debug("Server", "DeleteKey: Peer for key %02X -> %02X (Remote)", keymd5, node.ID) // Remote Set. payload := packets.KVStorePacket{ Command: packets.CMD_KVSTORE_DELETE, Key: key, KeyHash: keymd5, TargetID: node.ID, } packet := packets.NewPacket(packets.CMD_KVSTORE, payload) reply, err := svr.Connections[node.ID].SendPacketWaitReply(packet, 5*time.Second) // Process reply or timeout if err == nil { switch reply.Command { case packets.CMD_KVSTORE_ACK: svr.Logger.Debug("Server", "DeleteKey: Reply from Remote %s Deleted", key) return true case packets.CMD_KVSTORE_NOT_FOUND: svr.Logger.Debug("Server", "DeleteKey: Reply from Remote %s Not Found", key) return false default: svr.Logger.Warn("Server", "DeleteKey: Unknown Reply Command %d", reply.Command) } } else { svr.Logger.Warn("Server", "DeleteKey: Reply Timeout") } } return false }
func (pr *Peer) SendDistribution() error { packet := packets.NewPacket(packets.CMD_DISTRIBUTION, pr.Server.ServerNode.ServerNetworkNode) pr.SendPacket(packet) return nil }