⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsr_routing_layer.pr.c

📁 afit的ad hoc路由协议源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
	while ((reply_route.route[i]!=my_dsr_address)&&(i<reply_route.size_route));
			
	// if the node is still there: it was not in a loop and the reply packet can be sent
	if (i<reply_route.size_route)
		{
		// assign the first relay on the reply packet's route
		relay_dsr_address=reply_route.route[i-1];

		// set the Seg_Left field of the reply
		seg_left=i-1;
		op_pk_nfd_set(reply_pk_ptr,"IP_TTL",seg_left);
		
		if (DEBUG != 0)
			{
			printf("Reply from Relay route with seg_left=%d: ",seg_left);
			printf("%d...",request_source_dsr_address);	
			}
		// copy the reply_route in the Node_i fields of the packet
		for (i=1;i<reply_route.size_route;i++)
			{
			if (DEBUG != 0)
				{
				printf("%d...",reply_route.route[i]);
				}
			sprintf(field,"Node_%d",i-1);
			op_pk_nfd_set(reply_pk_ptr,field,reply_route.route[i]);
			}
		if (DEBUG != 0)
			{
			printf("end\n");
			}
		
		// set the Opt_Data_Len field of the reply = size_route minus source node
		op_pk_nfd_set(reply_pk_ptr,"Opt_Data_Len",reply_route.size_route-1);
		
		// set the TR_source field for the Transmission range purpose
		op_pk_nfd_set(reply_pk_ptr,"TR_source",my_node_objid);
		
		// since I am the reply transmitter I will not have to process it in the future
		//dsr_reply_already_seen(my_dsr_address,request_source_dsr_address,sequence_number);
		dsr_reply_already_seen(request_source_dsr_address,request_destination_dsr_address,sequence_number);
			
		// init the delay_reply distribution
		delay_reply_dist=op_dist_load("uniform",0.0,1.0);
		// calculate the delay that the node must wait before sending its reply
		delay=op_dist_outcome(delay_reply_dist);
		delay=HOP_DELAY*((double)(reply_route.size_route-2)+delay);
			
		// prepare the code (destination and source coded in one integer) associated (in the fifo) with the reply information 
		intPtr=(int*)op_prg_mem_alloc(sizeof(int));
		*intPtr=request_destination_dsr_address*OPTION+request_source_dsr_address;
		
		// check if a reply for the same route is still scheduled by looking in the fifo for its information
		reply=fifo_multiplex_extract(&reply_fifo,*intPtr);
		// if some information about a scheduled reply are found
		if (reply!=NULL)
			{
			// cancel the intrpt associated with this previous scheduled reply 
			if (complex_intrpt_cancel(my_complex_intrpt_ptr,reply->evt))
				{
				// "replies" statistic calculation if success
				++total_canceled_replies;
				op_stat_write(stat_total_canceled_replies,total_canceled_replies);
				}
			else
				{
				// error since the intrpt must be valid and active
				op_sim_end("Amazing error: reply should be valid and active","","","");
				}
			// destroy the information about this reply 
			op_pk_destroy(reply->pk);
			op_prg_mem_free(reply);
			}

		// memory allocation for structure containing information about the new reply
		reply=(sReply*)op_prg_mem_alloc(sizeof(sReply));
		// store in it the reply packet
		reply->pk=reply_pk_ptr;
		// and its sequence number
		reply->sequence_number=sequence_number;
		// schedule an intrpt that will "say" when to send the reply and store the associated event in the reply information structure 
		reply->evt=complex_intrpt_schedule_self(my_complex_intrpt_ptr,op_sim_time()+delay,SEND_REPLY_CODE,intPtr);
		// save the scheduled reply in a multiplexed Fifo
		fifo_multiplex_insert(&reply_fifo,reply,*intPtr);
		
		sprintf(message,"I plan to send a reply to %d for the route reaching %d in %f seconds (size_route=%d)\n",request_source_dsr_address,request_destination_dsr_address,delay,reply_route.size_route);
		dsr_message(message);
		}
	// if the current node was in a loop, its dsr address is not the reply_route anymore so the packet can't be sent back to the request source
	else
		{
		dsr_message("Proper route not found\n");
		// Check all cached routes to this destination for nodes in the request packet's route thus far
		// If any are found, then those nodes can no longer be used to reach this destination
		for (i=0; i<MAX_CACHED_ROUTES; i++)
			{
			j = 0;
			node_found = 0;
			do
				{
				if (route_cache[request_destination_dsr_address].node_route[i].route[j]==request_source_dsr_address)
					{
					dsr_route_init(route_cache,request_destination_dsr_address,i);
					node_found = 1;
					}
				j++;
				}
			while (j<MAX_SIZE_ROUTE && node_found == 0);
			}
		dsr_swap_route(route_cache,request_destination_dsr_address);
		
		op_pk_destroy(reply_pk_ptr);
		return (0);
		}
	}

// destroy the request packet
op_pk_destroy(pk_ptr);

// breakpoints for debugging purpose
if (1)
	{
	op_prg_odb_bkpt("transmit_reply");
	op_prg_odb_bkpt("transmit_reply_from_relay");
	}

return (1);
}

/*************************************************************/
/*                    DSR_HANDLE_REPLY                       */
/*************************************************************/
/* This function handle any reply packet received by the node*/
/*															 */
/* Packet* pk_ptr: a pointer to the reply packet to process  */
/*************************************************************/
void  dsr_handle_reply(Packet* pk_ptr)
{
int reply_source_dsr_address;
int destination_dsr_address;
int sequence_number;
int intended_relay_dsr_address;
int route_source_dsr_address;
int route_destination_dsr_address;
int size_route;
int seg_left;
int node_dsr_address;
int current_node_index;
Packet* data_pk_ptr;
int from_target;
char field[10];
int i;
char message[255];
int error_in_relay_reply_route;

// extract usefull information from the reply packet
op_pk_nfd_get (pk_ptr,"SRC",&reply_source_dsr_address);
op_pk_nfd_get (pk_ptr,"DEST",&route_source_dsr_address); 
op_pk_nfd_get (pk_ptr,"Identification",&sequence_number);
op_pk_nfd_get (pk_ptr,"Reply_From_Target",&from_target);
op_pk_nfd_get(pk_ptr,"Opt_Data_Len",&size_route);

// add source node to size_route
size_route = size_route + 1;
sprintf(field,"Node_%d",size_route - 2);
op_pk_nfd_get (pk_ptr,field,&route_destination_dsr_address);
op_pk_nfd_get(pk_ptr,"IP_TTL",&seg_left);


// obtain the address of the intended relay node
if (seg_left > 0)
	{
	sprintf(field,"Node_%d",seg_left-1);
	op_pk_nfd_get(pk_ptr,field,&intended_relay_dsr_address);
	}
else 
	{
	intended_relay_dsr_address = route_source_dsr_address;
	}

if (DEBUG > 0)
{
sprintf(message,"Relay address for Reply packet from node %d with seq# %d back to %d = %d\n",
	reply_source_dsr_address,sequence_number,route_source_dsr_address,intended_relay_dsr_address);
dsr_message(message);
}

// Check if I am the intended reply relay node or the destination of the reply packet
if (my_dsr_address == route_source_dsr_address || my_dsr_address == intended_relay_dsr_address)
	{
	dsr_insert_reply_route_in_cache(pk_ptr);
	}

// Check to see if this reply packet has already been seen
if  (((!dsr_reply_already_seen(route_source_dsr_address,route_destination_dsr_address,sequence_number))||
	 (sequence_number==-1)))
	{

	// if the reply packet is destinated to the current node
	if (my_dsr_address==route_source_dsr_address)
		{
			if (request_sent[route_destination_dsr_address].waiting_time!=0)
				{
				// cancel the intrpt associated with this request expiration time
				//if (complex_intrpt_cancel(my_complex_intrpt_ptr,request_sent[source_dsr_address].evt))
				if (complex_intrpt_cancel(my_complex_intrpt_ptr,request_sent[route_destination_dsr_address].evt))
					{
					//printf("well done for the path !\n");
					
					// re-init the request_sent table since the reply has been received
					request_sent[route_destination_dsr_address].scheduling_time = 0.0;
					request_sent[route_destination_dsr_address].waiting_time = 0.0;
					request_sent[route_destination_dsr_address].sequence_number = -1;
					}
				else
					{
					// error since the intrpt must be valid and active
					op_sim_end("Amazing error: request intrpt should be valid and active","","","");
					op_stat_write(stat_amazing_errors,++amazing_errors);
					}
				}
			
			// try to extract the first packet to send on the new route (=> packet destined to the reply source)
			data_pk_ptr=dsr_extract_buffer(route_destination_dsr_address);
			// if a packet was found in the buffer
			if (data_pk_ptr!=OPC_NIL)
				{
				dsr_transmit_data(data_pk_ptr,route_destination_dsr_address,1);
				}
		// destroy the reply packet
		op_pk_destroy(pk_ptr);
		}
	// if the node is the relay of the reply packet
	else if (my_dsr_address==intended_relay_dsr_address)
		{
			// if the promiscuous reply mode is activated
			dsr_promiscuous_reply(pk_ptr);
			/* forward reply */
			dsr_forward_reply(pk_ptr);
		}	
	// if we are not concerned by the reply packet
	else if (sequence_number!=-1)
		{
		// if the promiscuous reply mode is activated
		dsr_promiscuous_reply(pk_ptr);
		// destroy the reply packet
		i=0;
		current_node_index=-1;
		// check if the current node is in the reply path
		do
			{
			sprintf(field,"Node_%d",i);
			op_pk_nfd_get(pk_ptr,field,&node_dsr_address);
			if (node_dsr_address==my_dsr_address)
				{
				current_node_index=i;
				}
			else 
				{ 
				i++;
				}
			}
		while ((current_node_index==-1)&&(i<seg_left));

		// if the node is in the path then there is a shorter path than the one used by the reply packet
		if (current_node_index!=-1)
			{
			// "calculate" and set the reply packet route with this shorter path
			for (i=0;i<size_route-(seg_left+1);i++)
				{
				sprintf(field,"Node_%d",i+seg_left);
				op_pk_nfd_get(pk_ptr,field,&node_dsr_address);
				sprintf(field,"Node_%d",i+current_node_index+1);
				op_pk_nfd_set(pk_ptr,field,node_dsr_address);
				}
			// and update the Size_Route and Seg_left of the reply packet
			op_pk_nfd_set(pk_ptr,"Opt_Data_Len",size_route-(seg_left-current_node_index));
			op_pk_nfd_set(pk_ptr,"IP_TTL",current_node_index+1);
			dsr_message("I have just found a shorter path for the reply\n");
			dsr_forward_reply(pk_ptr);
			}
		else
			{
			dsr_message("I am not concerned by the reply thus I am destroying it\n");
			op_pk_destroy(pk_ptr);
			}
		}
	}

// if the reply has already been received by the node
else
	{
	dsr_promiscuous_reply(pk_ptr);

	// it is destroyed
	op_pk_destroy(pk_ptr);
	}

// breakpoints for debugging purpose
if (1)
	{
	op_prg_odb_bkpt("handle_reply");
   	}
if (sequence_number==-1)
	{
	op_prg_odb_bkpt("handle_gratuitous_reply");
	}
}

/*************************************************************/
/*                 DSR_REPLY_ALREADY_SEEN                    */
/*************************************************************/
/* This function checks if the reply identified by its source,
/* its destination and its sequence_number has been already 
/* seen and consequently handled
/*
/* int source_dsr_address: the dsr address of the reply source
/* int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -