private void RemoveFromReceiveQueueAndUpdateSeqNo(ExtendedPacketInformation receivedPacket, ExtendedPacketInformation extendedPacketInformation) { //Remove Packet from Recieve Queue _guranteedDelivery.RemoveMessageFromReceiveQueueAsync(extendedPacketInformation.Id).Start(); //Update Client UpdateIngoingSequence(receivedPacket.SenderClient, extendedPacketInformation.Packet.SeqNo); }
private void SendGarbageCollectMessage(ExtendedPacketInformation extendedPacketInformation) { var msg = new UdpMessage { SeqNo = extendedPacketInformation.Packet.SeqNo, ReturnPort = Setup.Port }; _guranteedDelivery.SendUdpMessage(msg, UdpMessageType.GarbageCollect, extendedPacketInformation.Ip, extendedPacketInformation.Port); }
private void SendDelayedAckResponse(ExtendedPacketInformation extendedPacketInformation, bool inOrder) { var msg = new UdpMessage { SeqNo = extendedPacketInformation.Packet.SeqNo, ReturnPort = Setup.Port, MessageId = extendedPacketInformation.Packet.Id, InOrder = inOrder }; _guranteedDelivery.SendUdpMessage(msg, UdpMessageType.DelayedAckResponse, extendedPacketInformation.Ip, extendedPacketInformation.Port); }
private void HandleMessage(ExtendedPacketInformation receivedPacket) { //Cancel any recurring resendrequests //Todo: Cancel task based on clintid and seqno _schedular.CancelTask(receivedPacket.Packet.Id, receivedPacket.SenderClient, receivedPacket.Packet.SeqNo); //Debug.WriteLine("Packet received SeqNo: " + receivedPacket.Packet.SeqNo); //Check Order, dont publish event if its out of order var packetsToPublish = GetPacketsToPublish(receivedPacket); //PublishPackage all events in order foreach (var extendedPacketInformation in packetsToPublish) { // Send ack after a set number of messages if (extendedPacketInformation.Packet.SeqNo % Setup.AckAfterNumber == 0) { SendGarbageCollectMessage(extendedPacketInformation); } if (extendedPacketInformation.UdpMessageType == UdpMessageType.DelayedAck) { //Send garbagecollect mesage SendGarbageCollectMessage(extendedPacketInformation); RemoveFromReceiveQueueAndUpdateSeqNo(receivedPacket, extendedPacketInformation); //Dont publish the delayedAck continue; } if (extendedPacketInformation.Packet.Type == PacketType.AdminitrationMessages) { PublishEventToApplicationLayer(new MessageReceivedEventArgs { AdministrationMessage = extendedPacketInformation.Packet.AdministrationMessage, IpAddress = extendedPacketInformation.Ip, Port = extendedPacketInformation.Port, Type = extendedPacketInformation.UdpMessageType }); } else { PublishPacketToApplicationLayer(new PublishPacketReceivedEventArgs { Packet = extendedPacketInformation.Packet, Port = extendedPacketInformation.Packet.ReturnPort, IpAddress = extendedPacketInformation.Ip }); } RemoveFromReceiveQueueAndUpdateSeqNo(receivedPacket, extendedPacketInformation); } }
public void Send(ExtendedPacketInformation msg) { var sendMsg = new SenderMessage { Body = MessagePackSerializer.Serialize(msg.Packet), Type = msg.UdpMessageType }; lock (_harakaDb.GetLock(Setup.OutgoingMessagesCS)) { var messages = _harakaDb.GetObjects <ExtendedPacketInformation>(Setup.OutgoingMessagesCS); messages.Add(msg); _harakaDb.StoreObject(Setup.OutgoingMessagesCS, messages); } _sender.SendMsg(sendMsg, msg.Ip, msg.Port); }
public void HandleRecievedMessage(ExtendedPacketInformation receivedPacket) { switch (receivedPacket.UdpMessageType) { case UdpMessageType.Packet: HandleMessage(receivedPacket); break; case UdpMessageType.DelayedAckResponse: _schedular.CancelTask(receivedPacket.UdpMessage.MessageId.Value); if (receivedPacket.UdpMessage.InOrder) { _guranteedDelivery.RemoveMessagesFromSendQueueAsync(receivedPacket.SenderClient, receivedPacket.UdpMessage.SeqNo).Start(); } break; case UdpMessageType.DelayedAck: var client = GetClient(receivedPacket.Ip, receivedPacket.Port); //Debug.WriteLine("Received Delayed ack: " + receivedPacket.Packet.Id); if (client.IngoingSeqNo + 1 == receivedPacket.Packet.SeqNo) { //Inorder SendDelayedAckResponse(receivedPacket, true); UpdateIngoingSequence(receivedPacket.SenderClient, receivedPacket.Packet.SeqNo); _guranteedDelivery.RemoveMessageFromReceiveQueueAsync(receivedPacket.Id).Start(); } else { //OutOfOrder SendDelayedAckResponse(receivedPacket, false); HandleMessage(receivedPacket); } break; case UdpMessageType.GarbageCollect: _guranteedDelivery.RemoveMessagesFromSendQueueAsync(receivedPacket.SenderClient, receivedPacket.UdpMessage.SeqNo).Start(); break; default: throw new ArgumentException("Couldnt handle message"); } }
public void HandleExtendedMessageInformation(UdpReceiveResult result) { ExtendedPacketInformation extendedMsg; var deserializedUdpMessage = MessagePackSerializer.Deserialize <SenderMessage>(result.Buffer); switch (deserializedUdpMessage.Type) { case UdpMessageType.DelayedAck: case UdpMessageType.Packet: var message = MessagePackSerializer.Deserialize <Packet>(deserializedUdpMessage.Body); if (_idempotentReceiver.VerifyPacket(message)) { lock (_harakaDb.GetLock(Setup.IngoingMessagesCS)) { extendedMsg = new ExtendedPacketInformation(message, deserializedUdpMessage.Type, result.RemoteEndPoint.Address.ToString()); { var messages = _harakaDb.GetObjects <ExtendedPacketInformation>(Setup.IngoingMessagesCS); messages.Add(extendedMsg); _harakaDb.StoreObject(Setup.IngoingMessagesCS, messages); } OnMessageReceived(extendedMsg); } } break; case UdpMessageType.ResendRequest: var resendMessage = MessagePackSerializer.Deserialize <UdpMessage>(deserializedUdpMessage.Body); ReSend(result.RemoteEndPoint.Address.ToString() + resendMessage.ReturnPort, resendMessage.SeqNo); break; case UdpMessageType.DelayedAckResponse: case UdpMessageType.GarbageCollect: var udpMessage = MessagePackSerializer.Deserialize <UdpMessage>(deserializedUdpMessage.Body); extendedMsg = new ExtendedPacketInformation(udpMessage, deserializedUdpMessage.Type, result.RemoteEndPoint.Address.ToString()); OnMessageReceived(extendedMsg); break; default: throw new NotImplementedException(); } }
private IEnumerable <ExtendedPacketInformation> GetPacketsToPublish(ExtendedPacketInformation receivedPacket) { var packetsToPublish = new Queue <ExtendedPacketInformation>(); var client = GetClient(receivedPacket.Ip, receivedPacket.Packet.ReturnPort); //Add Client to dictionary if it does not exist if (!DictionaryWithSortedMessages.ContainsKey(client.Id)) { DictionaryWithSortedMessages.Add(client.Id, new SortedList <int, ExtendedPacketInformation>()); } if (client.IngoingSeqNo + 1 == receivedPacket.Packet.SeqNo) // +1 because ingoingSeqNo represents the last recieved { GetSortedPacketsInOrder(receivedPacket, packetsToPublish); } else { DictionaryWithSortedMessages[receivedPacket.SenderClient].Add(receivedPacket.Packet.SeqNo, receivedPacket); _schedular.ScheduleRecurringResend(100, receivedPacket.Ip, receivedPacket.Port, client.IngoingSeqNo + 1, SendResendRequest); } return(packetsToPublish); }
private void GetSortedPacketsInOrder(ExtendedPacketInformation receivedPacket, Queue <ExtendedPacketInformation> packetsToPublish) { packetsToPublish.Enqueue(receivedPacket); var count = DictionaryWithSortedMessages[receivedPacket.SenderClient].Count; for (var i = 0; i < count; i++) { //Find The next message inorder // It is always Keys[0] because it has the lowest seqNo always, it will adjsut when elements on the list gets removed. // It is receivedPacket.Packet.SeqNo + i + 1. Example: ingoing message is 4, now we have to find 5 = 4 + 0 + 1 = 5 if (DictionaryWithSortedMessages[receivedPacket.SenderClient].Keys[0] == receivedPacket.Packet.SeqNo + i + 1) { packetsToPublish.Enqueue(DictionaryWithSortedMessages[receivedPacket.SenderClient].Values[0]); //Remove the message from the sorted list DictionaryWithSortedMessages[receivedPacket.SenderClient].Remove(DictionaryWithSortedMessages[receivedPacket.SenderClient].Keys[0]); } //Messages are not in order anymore then stop iterating else { _schedular.ScheduleRecurringResend(100, receivedPacket.Ip, receivedPacket.Port, receivedPacket.Packet.SeqNo + i + 1, SendResendRequest); break; } } }
private void OnMessageReceived(object sender, ExtendedPacketInformation e) { HandleRecievedMessage(e); }
protected virtual void OnMessageReceived(ExtendedPacketInformation e) { MessageReceived?.Invoke(this, e); }