public Rrep(Rrep rrep)
 {
     R                         = rrep.R;
     A                         = rrep.A;
     PrefixSize                = rrep.PrefixSize;
     HopCount                  = rrep.HopCount;
     DestinationAddress        = rrep.DestinationAddress;
     DestinationSequenceNumber = rrep.DestinationSequenceNumber;
     OriginatorAddress         = rrep.OriginatorAddress;
     Lifetime                  = rrep.Lifetime;
 }
        /// <summary>
        /// Handles an incoming RREQ packet.
        /// </summary>
        /// <param name="incomingPacket"></param>
        private void HandleRreq(Message incomingPacket)
        {
            //Processing RREQ according to section 6.5
            var rreq = (Rreq)incomingPacket.Payload; //Cast message to right type

            //Check that received RREQ has not been received and processed before
            if (_aodvHelper.RreqAttemptExist(rreq.DestinationAddress, rreq.OriginatorAddress))
            {
                _logger.WriteLine("Incoming RREQ from " + rreq.OriginatorAddress + " discarded, since it has been processed before.");
                return; //Discard RREQ
            }

            //RREQ not received before, place in buffer with 0 as attempt number
            _aodvHelper.AddBufferedRreqAttempt(new BufferedRreqAttempt(0, rreq, _conf.AodvConfiguration.PathDiscoveryTime));

            //First, create/update route to previous hop. If route to previous hop exists, update lifetime
            if (_aodvHelper.RoutingTable.ActiveRouteExists(incomingPacket.PreviousHop))
            {
                var prevRoute = _aodvHelper.RoutingTable.GetEntry(incomingPacket.PreviousHop);
                prevRoute.Valid          = true;
                prevRoute.HopCount       = 1;
                prevRoute.NextHop        = incomingPacket.PreviousHop;
                prevRoute.ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout);

                _logger.WriteLine("RREQ handler: Updating route to previous hop: " + incomingPacket.PreviousHop + " for RREQ #" + rreq.RouteRequestId);
                _aodvHelper.RoutingTable.UpdateEntry(prevRoute);
            }
            else //Route did not exist, so create it
            {
                var prevHopEntry = new AodvTableEntry
                {
                    Valid = true,
                    DestinationAddress                 = incomingPacket.PreviousHop,
                    DestinationSequenceNumber          = 0,
                    ValidDestinationSequenceNumberFlag = false, //(He's my neighbour, so even though I dont know his sequence number, I know that he's there)
                    HopCount       = 1,                         //Only 1 hop to previous neighbour (duh)
                    NextHop        = incomingPacket.PreviousHop,
                    ExpirationTime = _time.GetFutureTime(_aodvParameters.ActiveRouteTimeout)
                };

                _logger.WriteLine("RREQ handler: Adding route to previous hop: " + incomingPacket.PreviousHop + " for RREQ #" + rreq.RouteRequestId);
                _aodvHelper.RoutingTable.AddEntry(prevHopEntry);
            }

            //RREQ has not been seen before or was not sent by me, continue to process it.
            rreq.HopCount = rreq.HopCount + 1; //Increment HopCount in RREQ, since me receiving it, was one hop more

            //Create or update reverse route to RREQ Originator
            var oldEntry        = _aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress);
            var minimalLifetime = _aodvParameters.MinimalLifetime(rreq.HopCount);

            //No route to originator exists, create it
            if (oldEntry == null)
            {
                var originatorRoute = new AodvTableEntry
                {
                    DestinationAddress                 = rreq.OriginatorAddress,
                    DestinationSequenceNumber          = rreq.OriginatorSequenceNumber,
                    ValidDestinationSequenceNumberFlag = true,
                    HopCount       = rreq.HopCount,
                    Valid          = true,
                    NextHop        = incomingPacket.PreviousHop,
                    ExpirationTime = minimalLifetime
                };

                _logger.WriteLine("RREQ handler: Adding route to originator: " + rreq.OriginatorAddress + " for RREQ #" + rreq.RouteRequestId);
                _aodvHelper.RoutingTable.AddEntry(originatorRoute);
            }
            else //Route exists, update existing entry
            {
                var originatorRoute = new AodvTableEntry
                {
                    DestinationAddress                 = rreq.OriginatorAddress,
                    DestinationSequenceNumber          = rreq.OriginatorSequenceNumber > oldEntry.DestinationSequenceNumber ? rreq.OriginatorSequenceNumber : oldEntry.DestinationSequenceNumber, //See section 6.5, action 1.
                    ValidDestinationSequenceNumberFlag = true,
                    HopCount       = rreq.HopCount,
                    Valid          = true,
                    NextHop        = incomingPacket.PreviousHop,
                    ExpirationTime = oldEntry.ExpirationTime > minimalLifetime ? oldEntry.ExpirationTime : minimalLifetime
                };

                _logger.WriteLine("RREQ handler: Updating route to originator: " + rreq.OriginatorAddress + " for RREQ #" + rreq.RouteRequestId);
                _aodvHelper.RoutingTable.UpdateEntry(originatorRoute); //And now we have a route towards the originator that can be used. neat-o.
            }

            //If I am the destination specified in RREQ
            if (rreq.DestinationAddress == _localAddress) //Section 6.6 (i) and section 6.6.1
            {
                //Increment my sequence number, if DSN in RREQ is 1 larger per secton 6.6.1
                if (rreq.DestinationSequenceNumber == _aodvHelper.RoutingTable.SequenceNumber + 1)
                {
                    _aodvHelper.RoutingTable.IncrementSequenceNumber();
                }

                var rrep = new Rrep
                {
                    OriginatorAddress         = rreq.OriginatorAddress,
                    DestinationAddress        = rreq.DestinationAddress,
                    DestinationSequenceNumber = _aodvHelper.RoutingTable.SequenceNumber,
                    HopCount = 0,
                    Lifetime = _time.GetFutureTime(_aodvParameters.MyRouteTimeout) //Section 6.6.1, see also section 10.
                };

                var responseMsg = new Message(rrep, rreq.OriginatorAddress, _localAddress, _conf.MessageTtlValue);
                SendAodvMessage(responseMsg, incomingPacket.PreviousHop); //Send RREP to previous hop, which is where I received the RREQ from
            }
            //If I have an active route to destination, which upholds requirements in section 6.6 (ii), see section 6.6.2
            else if (_aodvHelper.RoutingTable.ActiveRouteExists(rreq.DestinationAddress) && //If I have an active route
                     _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress).ValidDestinationSequenceNumberFlag && //and the route has a valid dsn
                     _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress).DestinationSequenceNumber >= rreq.DestinationSequenceNumber && //and route dsn is >= rreq.dsn
                     !rreq.D) //and rreq must NOT only be answered by destination
            {
                var forwardRoute = _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress);
                var rrep         = new Rrep
                {
                    OriginatorAddress         = rreq.OriginatorAddress,
                    DestinationAddress        = rreq.DestinationAddress,
                    DestinationSequenceNumber = forwardRoute.DestinationSequenceNumber,
                    HopCount = forwardRoute.HopCount,
                    Lifetime = _time.GetFutureTime((forwardRoute.ExpirationTime - _time.CurrentTime).TotalSeconds) //6.6.2, "subtract current time from expiration time in route table entry"
                };

                //Add previous hop of incoming message to precursor list of destination
                _aodvHelper.RoutingTable.AddPrecursorToEntry(rreq.DestinationAddress, incomingPacket.PreviousHop);

                //Add next-hop of forward route to precursor list of originator
                _aodvHelper.RoutingTable.AddPrecursorToEntry(rreq.OriginatorAddress, forwardRoute.NextHop);

                //Place RREP in outbox
                var responseMsg = new Message(rrep, rreq.OriginatorAddress, _localAddress, _conf.MessageTtlValue);
                SendAodvMessage(responseMsg, incomingPacket.PreviousHop); //Send RREP to previous hop, which is where I received the RREQ from

                //Send gratuitous RREP if required in RREQ, specified in section 6.6.3. Dont send it, if path to destination goes through previousHop
                if (rreq.G)
                {
                    var gratuitousRrep = new Rrep
                    {
                        HopCount                  = _aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress).HopCount,
                        DestinationAddress        = rreq.OriginatorAddress,
                        DestinationSequenceNumber = rreq.OriginatorSequenceNumber,
                        OriginatorAddress         = rreq.DestinationAddress,
                        Lifetime                  = _time.GetFutureTime((_aodvHelper.RoutingTable.GetEntry(rreq.OriginatorAddress).ExpirationTime - _time.CurrentTime).TotalSeconds) //"Remaining lifetime of route towards RREQ originator, as known by intermediate node" (expiration time - current time = remaining time)
                    };

                    var gratuitousMsg = new Message(gratuitousRrep, rreq.DestinationAddress, _localAddress, _conf.MessageTtlValue);
                    SendAodvMessage(gratuitousMsg, forwardRoute.NextHop); //Gratuitous RREP sent forward
                }
            }
            //Else, I have no active route and am not the destination
            else
            {
                var outMsg = new Message(incomingPacket);

                rreq.DestinationSequenceNumber = Math.Max(rreq.DestinationSequenceNumber, _aodvHelper.RoutingTable.GetEntry(rreq.DestinationAddress)?.DestinationSequenceNumber ?? -1); //Set DSN to max of rreq.dsn or table[destination].dsn
                outMsg.Payload            = new Rreq(rreq);
                outMsg.DestinationAddress = SimulationConstants.BroadcastAddress;

                SendAodvMessage(outMsg, SimulationConstants.BroadcastAddress);
            }
        }