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

📄 igmp_host_state.c

📁 路由器协议平台igmp协议设计实现源码。
💻 C
字号:
/*
 $Log:: /OEM Source Code/igmp/igmp_host_state.c                                                    $
 * 
 * 1     4/23/98 9:53p Release Engineer
 * Initial release
 * IGMP v4.1.0
 */
/************************************************************************/
/*  Copyright (C) 1997-1998 RouterWare, Inc.                            */
/*  Unpublished - rights reserved under the Copyright Laws of the       */
/*  United States.  Use, duplication, or disclosure by the              */
/*  Government is subject to restrictions as set forth in               */
/*  subparagraph (c)(1)(ii) of the Rights in Technical Data and         */
/*  Computer Software clause at 252.227-7013.                           */
/*  RouterWare, Inc., 3961 MacArthur Blvd. Suite 212, Newport Beach, CA */
/************************************************************************/
#include <stdlib.h>
#include "igmp.h"
/********************************************************************************************/
void igmp_process_host_group_state_transition (UINT port, ULONG group_ip_address,enum IGMP_HOST_GROUP_EVENT event)
{
	enum IGMP_HOST_GROUP_STATE state;
	enum IGMP_HOST_GROUP_STATE next_state;
	IGMP_GROUP_CLASS *sptr_matching_group_node;
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u for state transition on event %s.\n",
			convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port,
			igmp_host_group_event_string [event]);

		return;
		}

	state = sptr_matching_group_node->host_group.state;

	next_state = igmp_host_group_state_transition_table[state][event].next_state;

	if (igmp_host_group_state_is_valid (next_state) == FALSE)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Event %s would force group %s on port %u from current state %s to INVALID_STATE.\n",
			igmp_host_group_event_string [event],
			convert_ip_address_to_dot_format (&ip_address[0], group_ip_address),
			port, igmp_host_group_state_string [state]);

		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: No actions will be taken. State will not be changed.\n");

		return ;
		}

	IGMP_PROTOCOL_TRACE (IGMP_TRACE, "IGMP Host: Processing state transition for group %s on port %u. Event: %s Current state: %s Next state: %s\n",
		convert_ip_address_to_dot_format (&ip_address[0],group_ip_address), port,
		igmp_host_group_event_string [event],igmp_host_group_state_string [state],
		igmp_host_group_state_string [next_state]);

	if (igmp_host_group_state_transition_table[state][event].fptr_action_1 != NULL)
		{
		igmp_host_group_state_transition_table[state][event].fptr_action_1 (port,group_ip_address);
		}


	if (igmp_host_group_state_transition_table[state][event].fptr_action_2 != NULL)
		{
		igmp_host_group_state_transition_table[state][event].fptr_action_2 (port,group_ip_address);
		}


	if (igmp_host_group_state_transition_table[state][event].fptr_action_3 != NULL)
		{
		igmp_host_group_state_transition_table[state][event].fptr_action_3 (port,group_ip_address);
		}

	sptr_matching_group_node->host_group.state = next_state;
}
/********************************************************************************************/
void igmp_host_send_join_report_message (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_group_node;
	enum IGMP_MESSAGE_TYPE message_type;
	
	sptr_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP HOST: Unable to locate group %s on port %u for sending join report.\n",
			convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	sptr_group_node->host_group.this_host_was_last_reporter = TRUE;

	if ((igmp.port_table[port].host_port.v1_router_present == TRUE) || (igmp.port_table[port].version == IGMP_VERSION_1))
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Sending out V1 membership report for group %s on port %u.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		message_type = IGMP_V1_MEMBERSHIP_REPORT;
		}
	else
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Sending out V2 membership report for group %s on port %u.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);
		
		message_type = IGMP_V2_MEMBERSHIP_REPORT;
		}

	igmp_transmit_message (port, group_ip_address, message_type, /* copy_to_router */ TRUE, /* copy_to_host */ FALSE);
		
	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_send_leave_if_this_host_last_repoter (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_group_node;

	sptr_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP HOST: Unable to locate group %s on port %u for sending leave report.\n",
			convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	if (sptr_group_node->host_group.this_host_was_last_reporter == FALSE)
		{
		return /*(TRUE)*/;
		}


	/* Note we could check and NOT send out the leave report if the querier on this port is V1. But we would
		send out a Leave report anywayz. Thats to support any V2 routers that may be out there! */

	IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP HOST: Sending leave report for group %s on port %u.\n",
		convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

	igmp_transmit_message (port, group_ip_address, IGMP_LEAVE_GROUP, /* copy_to_router */ TRUE, /* copy_to_host */ FALSE);

	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_start_report_delay_timer (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_matching_group_node;
	UINT report_delay_timeout;

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u to start the report delay timer.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Starting report delay timer for group %s on port %u.\n",
		convert_ip_address_to_dot_format (&ip_address[0],group_ip_address), port);
	
	srand (igmp.port_table[port].max_response_time_from_most_recent_query);

	/*
	Note that the random number generated will be greater than igmp.port_table[port].max_response_time_from_most_recent_query.
	But, a number between (0, igmp.port_table[port].max_response_time_from_most_recent_query] is needed for this timer. The
	following step ensures that.
	*/
	report_delay_timeout = (UINT) rand () % igmp.port_table[port].max_response_time_from_most_recent_query;

	igmp_enable_timer (&sptr_matching_group_node->host_group.report_delay_timer, report_delay_timeout);

	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_stop_report_delay_timer (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_matching_group_node;

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u to stop the report delay timer.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	IGMP_PROTOCOL_TRACE (IGMP_TRACE, "IGMP Host: Stopping report delay timer for group %s on port %u.\n",
		convert_ip_address_to_dot_format (&ip_address[0],group_ip_address), port);

	igmp_initialize_timer (&sptr_matching_group_node->host_group.report_delay_timer);

	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_check_and_reset_report_delay_timer (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_matching_group_node;
	UINT report_delay_timeout;

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u to reset the report delay timer.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	if (sptr_matching_group_node->host_group.this_host_was_last_reporter == FALSE)
		{
		return /*(TRUE)*/;
		}

	IGMP_PROTOCOL_TRACE (IGMP_TRACE, "IGMP Host: Restarting report delay timer for group %s on port %u.\n",
		convert_ip_address_to_dot_format (&ip_address[0],group_ip_address), port);

	srand (igmp.port_table[port].max_response_time_from_most_recent_query);

	/*
	Note that the random number generated will be greater than igmp.port_table[port].max_response_time_from_most_recent_query.
	But, a number between (0, igmp.port_table[port].max_response_time_from_most_recent_query] is needed for this timer. The
	following step ensures that.
	*/
	report_delay_timeout = (UINT) rand () % igmp.port_table[port].max_response_time_from_most_recent_query;

	igmp_enable_timer (&sptr_matching_group_node->host_group.report_delay_timer, report_delay_timeout);

	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_set_this_host_as_last_reporter (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_matching_group_node;

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u to set this host as last reporter.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	IGMP_PROTOCOL_TRACE (IGMP_TRACE, "IGMP HOST: Setting this host as last reporter for group %s on port %u\n",
		convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

	sptr_matching_group_node->ip_address_of_last_reporter = igmp.port_table[port].ip_address_of_port;

	sptr_matching_group_node->igmpCacheEntry.igmpCacheLastReporter = sptr_matching_group_node->ip_address_of_last_reporter;

	sptr_matching_group_node->host_group.this_host_was_last_reporter = TRUE;

	return /*(PASS)*/;
}
/********************************************************************************************/
void igmp_host_clear_last_reporter (UINT port, ULONG group_ip_address)
{
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];
	IGMP_GROUP_CLASS *sptr_matching_group_node;

	sptr_matching_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_matching_group_node == NULL)
		{
		IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Host: Unable to locate group %s on port %u to clear last reporter.\n",
				convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

		return /*(FAIL)*/;
		}

	IGMP_PROTOCOL_TRACE (IGMP_TRACE, "IGMP HOST: Clearing this host as last reporter for group %s on port %u\n",
		convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

	sptr_matching_group_node->ip_address_of_last_reporter = 0x00000000L;
	
	sptr_matching_group_node->igmpCacheEntry.igmpCacheLastReporter = 0x00000000L;

	sptr_matching_group_node->host_group.this_host_was_last_reporter = FALSE;

	return /*(PASS)*/;
}
/********************************************************************************************/
enum BOOLEAN igmp_host_group_state_is_valid (enum IGMP_HOST_GROUP_STATE state)
{
	if ((state == IGMP_HOST_GROUP_NON_MEMBER_STATE) || (state == IGMP_HOST_GROUP_DELAYING_MEMBER_STATE) ||
		(state == IGMP_HOST_GROUP_IDLE_MEMBER_STATE))
		{
		return (TRUE);
		}

	return (FALSE);
}

⌨️ 快捷键说明

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