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);
            }
        }
Exemple #5
0
        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");
            }
        }
Exemple #7
0
        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);
 }
Exemple #11
0
 protected virtual void OnMessageReceived(ExtendedPacketInformation e)
 {
     MessageReceived?.Invoke(this, e);
 }