/// <summary> /// Generates a new Message, containing a RREQ for the wanted destination. /// Implemented according to Section 6.3: Generating Route Requests (RREQ) in the RFC. /// /// Method also handles buffering of RREQ, to avoid sending a duplicate in next iteration. /// </summary> /// <param name="destination">String representation of the destination address.</param> /// <returns>A Message with the RREQ enclosed. Includes destination address set to broadcast, and TTL adjusted according to the RFC.</returns> public Message GenerateInitialRreqMessage(string destination) { //If RREQ has been sent for this destination by me, and has not yet timed out, dont send a new one if (RreqAttemptExist(destination, _localAddress) && _time.CurrentTime < GetBufferedRreqAttempt(destination, _localAddress).ExpirationTime) { _logger.WriteLine("RREQ has been sent for this destination, and has not yet timed out, so dont send a new one."); return(null); } //Else, no RREQ for this destination waiting for response, send a new one RoutingTable.IncrementSequenceNumber(); //Must be incremented before sending a RREQ, per section 6.1 and 6.3 var knownEntry = RoutingTable.GetEntry(destination); //Get stale entry if it exists var rreq = new Rreq { G = _conf.AODV_UseGratuitousRREPs, D = _conf.AODV_DestinationRespondOnlyFlag, U = knownEntry == null, //True if no current DSN is known, per section 6.3 HopCount = 0, RouteRequestId = RoutingTable.NextRouteRequestId, DestinationAddress = destination, DestinationSequenceNumber = knownEntry?.DestinationSequenceNumber ?? 0, //Known DSN and U=false, or unknown DSN=0 and U=true OriginatorAddress = _localAddress, OriginatorSequenceNumber = RoutingTable.SequenceNumber }; //Any stale routing table entry waiting for a RREP (because of the newly generated RREQ) should not be expunged before current_time + 2 * NET_TRAVERSAL_TIME if (knownEntry != null) { knownEntry.ExpirationTime = _time.GetFutureTime(2 * _aodvParameters.NetTraversalTime); } //Create Message to send RREQ in, and adjust RREQ var msg = new Message(rreq, SimulationConstants.BroadcastAddress, _localAddress, _conf.MessageTtlValue); msg.Ttl = knownEntry?.HopCount + _aodvParameters.TtlIncrement ?? _aodvParameters.TtlStart; //Per section 6.4, use last known hopcount as initial TTL + TTL_INCREMENT //Buffer RREQ ID and Originator address, pr. section 6.3 (taken from rreq) var rreqAttempt = new BufferedRreqAttempt(0, rreq, _conf.AodvConfiguration.PathDiscoveryTime); rreqAttempt.ExpirationTime = _time.GetFutureTime(_aodvParameters.PathDiscoveryTime); AddBufferedRreqAttempt(rreqAttempt); return(msg); }