/// <summary> /// Handle incoming packets related to connection setup /// </summary> /// <param name="message">The message to handle</param> /// <returns>A PacketResponse indicating if the message was consumed</returns> public PacketResponse HandlePacket(Message message) { switch (message.MessageType) { case MessageType.HeartbeatRequest: var msg = new Message(MessageType.Heartbeat, message.Sender) { DataAsString = Dns.GetHostName() }; Outbox.SendUnencryptedMessage(msg); if (!ConnectedPeers.ContainsKey(message.Sender)) { ConnectedPeers.Add(message.Sender, message.DataAsString); } return(PacketResponse.Accept); case MessageType.Heartbeat: if (!ConnectedPeers.ContainsKey(message.Sender)) { ConnectedPeers.Add(message.Sender, message.DataAsString); } return(PacketResponse.Accept); case MessageType.EncryptionPacket: SecurityManager.GetInstance().SetKeysFromPacket(message.Data); Inbox.GetInstance().UseEncryption = true; ConnectionDone = true; return(PacketResponse.AcceptAndFinish); default: return(PacketResponse.Decline); } }
/// <summary> /// Handles a PingRequest packet by creating a <see cref="PongListener">PongListener</see> and sending a ping to the suspect /// </summary> /// <param name="pingRequest">The received PingRequest object</param> /// <returns>Accept or Decline depending on what type of packet was received</returns> public PacketResponse HandlePacket(Message pingRequest) { if (pingRequest.MessageType != MessageType.PingRequest) { return(PacketResponse.Decline); } IPAddress peerToPing; var valid = IPAddress.TryParse(pingRequest.DataAsString, out peerToPing); if (!valid) { pingRequest.DeemInvalid(); return(PacketResponse.Decline); } var pongListener = new PongListener(pingRequest.Sender, peerToPing); networkListener.RegisterHandler(pongListener, PongListener.Timeout); var ping = new Message(MessageType.Ping, peerToPing); Outbox.SendMessage(ping); return(PacketResponse.Accept); }
/// <summary> /// Recieves a voting number and reports to it's own database /// that the person with that specific voting number has voted. /// </summary> /// <param name="message">The Message-object containing the voting number /// of the person who has been given a voting card</param> /// <returns></returns> /// Author: Michael Oliver Urhøj Mortensen public PacketResponse HandlePacket(Message message) { if (message.MessageType != MessageType.Vote) { return(PacketResponse.Decline); } try { var voterNumber = Convert.ToUInt64(message.DataAsString); if (!localVoteListener.Peers.ContainsKey(message.Sender)) //Error in sender - kill'im { var response = new Message(MessageType.PeerDead, message.Sender) { DataAsString = message.Sender.ToString() }; Outbox.SendMessage(response); } else { var response = new Message(MessageType.VoteOk, message.Sender) { Data = message.Data }; Outbox.SendMessage(response); Database.GetInstance.SetVoted(voterNumber, true); } } catch (Exception) { message.DeemInvalid(); return(PacketResponse.Decline); } return(PacketResponse.Accept); }
/// <summary> /// The pong listener times out when it doesn't receive a pong. This will be reported to the initiator /// </summary> public void TimedOut() { Message pingFailed = new Message(MessageType.PingFailed, initiator) { DataAsString = suspect.ToString() }; Outbox.SendMessage(pingFailed); }
/// <summary> /// Broadcasts a heartbeat to the entire network /// </summary> public void BroadcastHeartbeatRequest() { var msg = new Message(MessageType.HeartbeatRequest) { DataAsString = Dns.GetHostName() }; Outbox.SendUnencryptedMessage(msg); }
/// <summary> /// Handle an incomping Pong packet /// </summary> /// <param name="message">The ping message to process</param> /// <returns>Accept if it's a ping message, Decline otherwise</returns> public PacketResponse HandlePacket(Message message) { if (message.MessageType != MessageType.Pong || !message.Sender.Equals(suspect)) { return(PacketResponse.Decline); } var pingOK = new Message(MessageType.PingOk, initiator) { DataAsString = suspect.ToString() }; Outbox.SendMessage(pingOK); return(PacketResponse.AcceptAndFinish); }
/// <summary> /// Send the generated key and IV directly to the discovered peers /// </summary> public void SendKey() { if (ConnectedPeers.Count < Program.MinimumPeerCount) { throw new NotEnoughPeersException(ConnectedPeers.Count); } foreach (var ipaddress in ConnectedPeers) { var keymsg = new Message(MessageType.EncryptionPacket, ipaddress.Key); keymsg.Data = SecurityManager.GetInstance().GetKeysAsPacket(); Outbox.SendUnencryptedMessage(keymsg); } Inbox.GetInstance().UseEncryption = true; ConnectionDone = true; }
/// <summary> /// Creates a new PingRequestResponseListener and sends out a new PingRequest /// message to each of the peers that has not yet replied in the VoteReplyList. /// </summary> public void TimedOut() { var prrl = new PingRequestResponseListener(networkListener, vote); networkListener.RegisterHandler(prrl, PingRequestResponseListener.Timeout); foreach (var peer in vote.VoteReplyList) { if (!peer.Value) { var pingRequest = new Message(MessageType.PingRequest) { DataAsString = peer.Key.ToString() }; Outbox.SendMessage(pingRequest); } } }
/// <summary> /// Handles the Message: /// If the MessageType is of any other type than "VoteOK" it ignores the Message. /// If it is of the type "VoteOK" the following scenarios may happen: /// - If the sender is not in the VoteReplyList, then that sender is considered dead /// and a reply is send out to the sender to notify it about this. The sender dies. /// - Notifies the vote object that a peer has replied "VoteOK". /// </summary> /// <param name="message">The Message that is broadcasted.</param> /// <returns> /// PacketResponse.AcceptAndFinish if all the peers have replied "VoteOK", /// PacketResponse.Accept if not. /// </returns> public PacketResponse HandlePacket(Message message) { if (message.MessageType != MessageType.VoteOk) { return(PacketResponse.Decline); } if (!vote.VoteReplyList.ContainsKey(message.Sender)) //Error in sender - kill'im { var response = new Message(MessageType.PeerDead, message.Sender) { DataAsString = message.Sender.ToString() }; Outbox.SendMessage(response); } else { vote.Replied(message.Sender); } return(vote.IsAcknowledged() ? PacketResponse.AcceptAndFinish : PacketResponse.Accept); }
/// <summary> /// The PRRL timed out. /// All peers that did not respond are registered as non-responding, and a new PRRL is created from the peer list /// </summary> public void TimedOut() { foreach (var nonRespondingPeer in nonRespondingPeers) { vote.SetPeerState(nonRespondingPeer.Key, PeerState.MaybeDead); } if (retries + 1 >= networkStabilityTreshold) { throw new NotEnoughPeersException(0); } var prrl = new PingRequestResponseListener(networkListener, vote, retries + 1); networkListener.RegisterHandler(prrl, Timeout); foreach (var peer in nonRespondingPeers) { var pingRequest = new Message(MessageType.PingRequest) { DataAsString = peer.Key.ToString() }; Outbox.SendMessage(pingRequest); } }
/// <summary> /// Update the list of responses from an incoming packet /// </summary> /// <param name="nonRespondingPeer">The unresponsive peer that has new data</param> /// <param name="sender">The sender of the new data</param> /// <param name="type">The message type that was received</param> private void UpdateResponses(IPAddress nonRespondingPeer, IPAddress sender, MessageType type) { if (type == MessageType.PingOk) { nonRespondingPeers.Remove(nonRespondingPeer); vote.SetPeerState(nonRespondingPeer, PeerState.Alive); } else { nonRespondingPeers[nonRespondingPeer][sender] = PingRequestResponse.No; //If all living peers answered No, broadcast that the peer must be dead. if (nonRespondingPeers[nonRespondingPeer].All(responder => responder.Value == PingRequestResponse.No)) { nonRespondingPeers.Remove(nonRespondingPeer); vote.SetPeerState(nonRespondingPeer, PeerState.Dead); var msg = new Message(MessageType.PeerDead) { DataAsString = nonRespondingPeer.ToString() }; Outbox.SendMessage(msg); } } }