www.pudn.com > TCPmodbushy.rar > P2P.c


/****************************************************************************** 
 * Project     : t_box 
 * Module Name : p2p.C 
 * CPU Type    : C8051F340 
 * 
 * Description : 
 * 
 * History        Author     Version       Comment 
 * 2006.11.15       HY       V0.0         Original version 
 * 
 * Copyright (C) 2006 HY. All rights reserved. 
 ******************************************************************************/ 
#include   "o:\sysdef.h" 
#include   "modbus.h" 
#include  
#define BumpPack_serve1_num		land_sever1_num 
#define BumpPack_serve2_num		land_sever2_num 
ulong idata sever1_ip,sever2_ip; 
uint idata sever1_port,sever2_port; 
uchar data land_sever1_flag; 
uchar data land_sever2_flag; 
uchar data net_type; 
uchar idata net_group_type; 
bit	  send_net_type_flag; 
bit	  bumppack_flag; 
bit   extend_trans_flag; 
uchar data bumppack_times; 
uint idata land_sever1_num,land_sever2_num; 
/************************************************************************* 
p2p function:when receive right command,process p2p command 
*************************************************************************/ 
void  p2p_cmdOK_process(uchar subop,uchar xdata *pd) 
{ 
	switch(subop) 
	{ 
		case LAND_ANSWER: 
			land_answer_process(pd); 
		break; 
		case NET_TYPE_ANSWER: 
			send_net_type_flag = NO; 
		break; 
		case BUMPPACK_ANSWER: 
			if(BumpPack_serve1_num == MAKE_WORD( *pd, *(pd+1) )) 
				BumpPack_serve1_num = 0; 
			if(BumpPack_serve2_num == MAKE_WORD( *pd, *(pd+1) )) 
				BumpPack_serve2_num = 0; 
			/*two bump pack's reply have received */ 
			if(BumpPack_serve2_num == 0 && BumpPack_serve2_num == 0) 
			{ 
				bumppack_flag = YES; 
				bumppack_times = 0; 
			} 
		break; 
		default:break; 
	} 
} 
 
/************************************************************************ 
p2p function:when receive error command,process p2p command 
************************************************************************/ 
void  p2p_cmdERR_process(uchar subop) 
{ 
	switch(subop) 
	{ 
		case LAND_ANSWER: 
			land_sever1_flag = LAND_SEVER; 
			land_sever1_flag = LAND_SEVER; 
			land_sever1_num = 0; 
			land_sever2_num = 0; 
		break; 
		case NET_TYPE_ANSWER: 
			send_net_type_flag = YES; 
			net_type_function(1); 
			net_type_function(2); 
		break; 
		default:break; 
	} 
} 
 
/*********************************************************************** 
when receive the reply of the land command,process this reply 
************************************************************************/ 
void land_answer_process(uchar xdata *pd) 
{ 
	if(land_sever1_flag == LAND_SEVER_END && land_sever1_num == MAKE_WORD( *pd, *(pd+1) ) ) 
	{ 
		sever1_ip = MAKE_LONG( MAKE_WORD( *(pd+9), *(pd+10) ), MAKE_WORD( *(pd+11), *(pd+12) ) ); 
		sever1_port = MAKE_WORD( *(pd+13), *(pd+14) ); 
		land_sever1_flag = LAND_SEVER_SUCCESS; 
	} 
	if(land_sever2_flag == LAND_SEVER_END && land_sever2_num == MAKE_WORD( *pd, *(pd+1) ) ) 
	{ 
		sever2_ip = MAKE_LONG( MAKE_WORD( *(pd+9), *(pd+10) ), MAKE_WORD( *(pd+11), *(pd+12) ) ); 
		sever2_port = MAKE_WORD( *(pd+13), *(pd+14) ); 
		land_sever2_flag = LAND_SEVER_SUCCESS; 
	} 
	if(land_sever1_flag == LAND_SEVER_SUCCESS && land_sever2_flag == LAND_SEVER_SUCCESS) 
		judge_net_type(); 
} 
 
/**************************************************************************************** 
function:judge net type 
****************************************************************************************/ 
void  judge_net_type(void) 
{ 
	if(sever1_ip == sever2_ip) 
	{ 
		if(sever1_port == sever2_port) 
		{ 
			if( (sever1_ip == netif->ip_addr.addr)&&(sever1_port == UDP_LOCAL_PORT) ) 
				net_type = PUBLIC; 
			else 
				net_type = CONE; 
		} 
		else if(abs(sever1_port - sever2_port) == 1) 
		{ 
			net_type = SYMMETRIC; 
		} 
		else 
			net_type = NO_SYMMETRIC; 
	} 
	else 
		net_type = NO_SYMMETRIC; 
	send_net_type_flag = YES; 
	net_type_function(1); 
	net_type_function(2); 
} 
 
/**************************************************************************** 
send net type function 
****************************************************************************/ 
void net_type_function(uchar serve_num) 
{ 
	uchar head; 
	uchar NameAddLen,PasswordLen; 
	MEMB xdata *pd; 
 
	NameAddLen = GetWordLen( USE_NAME_ADDRESS ); 
	PasswordLen = GetWordLen( USE_PASSWORD_ADDRESS ); 
	head = apply_memb( TCPMODBUS_LEN+1+1+1+1 + NameAddLen + PasswordLen); 
	if(head != MEMORY_EER) 
	{ 
		uchar offset; 
		pd = &memory[head]; 
		/* Prepare TcpModbus Head */ 
		PrepareHostSenderTcpModbusHead( &memory[head], (1+1+1+1 + NameAddLen + PasswordLen) ); 
		/* device NO */ 
		memory[head].space[6] = 0x00; 
		/* CMD */ 
		memory[head].space[7] = LAND_FUNCTION; 
		/* SubCMD */ 
		memory[head].space[8] = REGISTER_NET_TYPE; 
		offset = 9; 
		pd = WriteMembFromFlash( pd, &offset, USE_NAME_ADDRESS, NameAddLen ); 
		pd = WriteMembFromFlash( pd, &offset, USE_PASSWORD_ADDRESS, PasswordLen ); 
		/*net type*/ 
		pd->space[offset] = net_type; 
		if(serve_num == 1) 
			send_to_serve1(head); 
		else 
			send_to_serve2(head);	 
		send_net_type_flag = NO; 
	} 
} 
 
/************************************************************************************* 
function:process land function and connect serve1 
*************************************************************************************/ 
void land_function(void) 
{ 
	/*land sever1*/ 
	if( land_sever1_flag == LAND_SEVER ) 
	{ 
		land_sever1_num = land_sever1(); 
	} 
	/*land sever2*/ 
	if( land_sever2_flag == LAND_SEVER ) 
	{ 
		land_sever2_num = land_sever2(); 
	} 
	if(land_sever1_flag == LAND_SEVER_END || land_sever2_flag == LAND_SEVER_END) 
	{ 
		if(landTIME == 0 ) 
		{ 
			/*reply land command outtime,land again*/ 
			land_sever1_flag = LAND_SEVER; 
			land_sever2_flag = LAND_SEVER; 
		} 
	} 
	if(land_sever1_flag == LAND_SEVER_SUCCESS && land_sever2_flag == LAND_SEVER_SUCCESS) 
	{ 
		if(landTIME == 0 ) 
		{ 
			/*send BUMPPACK*/ 
			if(!bumppack_flag) 
			{ 
				/*not receive the reply of bump pack*/ 
				if(	bumppack_times == BUMPPACK_COUNT) 
				{ 
					/*connect to serve is cut ,so must again land*/ 
					land_sever1_flag = LAND_SEVER; 
					land_sever2_flag = LAND_SEVER; 
				} 
				else 
				{ 
					BumpPack_serve1_num = send_bumppack(1); 
					BumpPack_serve2_num = send_bumppack(2); 
				} 
			} 
			else 
			{ 
				BumpPack_serve1_num =send_bumppack(1); 
				BumpPack_serve2_num =send_bumppack(2); 
			} 
			if( BumpPack_serve1_num !=MEMORY_EER && BumpPack_serve2_num !=MEMORY_EER ) 
			{ 
				landTIME = LANDTIME; 
				bumppack_flag = NO; 
				bumppack_times++; 
			} 
		} 
	} 
} 
 
/************************************************************************************** 
land serve1 
**************************************************************************************/ 
uint  land_sever1( void ) 
{ 
	ulong xdata ip; 
	uint xdata port; 
	uint idata num; 
	/*land sever1*/ 
	ReadBytesFromFlash( SEVER1_IP_ADDRESS, SEVER1_IP_LEN, (uchar xdata *)&ip); 
	ReadBytesFromFlash( SEVER1_PORT_ADDRESS, SEVER1_PORT_LEN, (uchar xdata *)&port); 
	if(land_apply(ip,port,(uchar idata *)&num)) 
	{ 
		land_sever1_flag = LAND_SEVER_END; 
		landTIME = LANDTIME; 
		return(num); 
	} 
} 
 
/************************************************************************************** 
land serve2 
**************************************************************************************/ 
uint  land_sever2( void ) 
{ 
	ulong xdata ip; 
	uint xdata port; 
	uint idata num; 
	/*land sever1*/ 
	ReadBytesFromFlash( SEVER2_IP_ADDRESS, SEVER2_IP_LEN, (uchar xdata *)&ip); 
	ReadBytesFromFlash( SEVER2_PORT_ADDRESS, SEVER2_PORT_LEN, (uchar xdata *)&port); 
	if(land_apply(ip,port,(uchar idata *)&num)) 
	{ 
		land_sever2_flag = LAND_SEVER_END; 
		landTIME = LANDTIME; 
		return(num); 
	} 
} 
 
/************************************************************************************* 
send bumppack command 
*************************************************************************************/ 
uint send_bumppack(uchar sever_num) 
{ 
	uchar head; 
 
	head = apply_memb( TCPMODBUS_LEN+1+1+1 ); 
	if(head != MEMORY_EER) 
	{ 
		PrepareHostSenderTcpModbusHead( &memory[head], 3 );	 
		/* device NO */ 
		memory[head].space[6] = 0x00; 
		/* CMD */ 
		memory[head].space[7] = LAND_FUNCTION; 
		/* SubCMD */ 
		memory[head].space[8] = BUMPPACK; 
		if(sever_num == 1) 
		{ 
			BumpPack_serve1_num = MAKE_WORD( memory[head].space[0], memory[head].space[1] ); 
			send_to_serve1(head); 
			return(BumpPack_serve1_num); 
		} 
		else 
		{ 
			BumpPack_serve2_num = MAKE_WORD( memory[head].space[0], memory[head].space[1] ); 
			send_to_serve2(head); 
			return(BumpPack_serve2_num); 
		} 
	} 
} 
 
/********************************************************************************* 
function: process the message that receive serve transfer 
**********************************************************************************/ 
void serve_trans_message_process(uchar head) 
{ 
	uchar function,subop; 
	uchar xdata *pd; 
	function = memory[head].space[TCPMODBUS_LEN+1+TRANS_COMMAND_LEN];  
	subop = memory[head].space[TCPMODBUS_LEN+1+TRANS_COMMAND_LEN+1]; 
	switch(function) 
	{ 
		case LAND_FUNCTION: 
			if(subop == P2PTRANSH) 
				P2Ptransh_process(head); 
		break; 
		case PARAMETER_FUN: 
			extend_trans_flag = YES; 
			switch(subop) 
			{ 
				case PARAMETER_QUERY: 
					pd = &(memory[head].space[TCPMODBUS_LEN+TRANS_COMMAND_LEN]); 
					if( ( (*(pd+3) == (!(CurWorkState & MASTER_NOT_SLAVE)) || *(pd+3) == ALL_TBOX) ) 
							&& (!(CurWorkState & MASTER_NOT_SLAVE)) ) 
					{ 
						pd = &(memory[head].space[0]); 
						slave_replay_parameter(pd); 
					} 
					if(	( (*(pd+3) == ( !(CurWorkState & MASTER_NOT_SLAVE )) || *(pd+3) == ALL_TBOX) ) 
						&& ( CurWorkState & MASTER_NOT_SLAVE ) ) 
					{ 
						pd = &(memory[head].space[0]); 
						master_reply_parameter(pd); 
					} 
				break; 
				case READ_PARA: 
					pd = &(memory[head].space[0]); 
					if(ERR_chk(pd)) 
						reply_read_OK( head ); 
					else 
						reply_read_ERR(pd); 
				break; 
				case WRITE_PARA: 
					pd = &(memory[head].space[0]); 
					if(*(pd+21) == (!(CurWorkState & MASTER_NOT_SLAVE)) || *(pd+21) == ALL_TBOX) 
					{ 
					 	if(ERR_chk(pd)) 
					 		reply_write_OK(head); 
					 	else 
							reply_write_ERR(pd); 
					} 
				break; 
				case ERASURE_FUN: 
					reply_erasure(&(memory[head].space[0])); 
				break; 
				case PARA_AFFIRM: 
					affirm_para(&(memory[head].space[0])); 
				break; 
				default:break; 
			} 
		break; 
		default: 
			//if( !(CurWorkState & SETPARA_NOT_WORK) ) 
			UART_transmitted( head );			/* normal modbus function */ 
			return;									// Queeue space free in 'UART_transmitted()' 
	} 
	free_memb( &(memory[head]) );	 
	extend_trans_flag = NO; 
} 
 
/*************************************************************************** 
function: reply P2Ptransh command 
***************************************************************************/ 
void answer_P2Ptransh_to_serve(ulong dst_ip,uint dst_port, uchar xdata *DATA,uint self_port) 
{ 
	uchar head,offset; 
 
	offset = TCPMODBUS_LEN+1+1+1+ TRANS_COMMAND_LEN ; 
	head = apply_memb( offset ); 
	if(head != MEMORY_EER) 
	{	 
		PrepareReplyTransHead( head,( offset - TCPMODBUS_LEN ),DATA); 
		offset = TRANS_COMMAND_LEN+TCPMODBUS_LEN+1; 
		memory[head].space[offset] = LAND_FUNCTION; 
		memory[head].space[offset+1] = P2PTRANSH_ACK; 
		UDP_send_data(head,dst_ip,dst_port,self_port); 
	}	 
} 
 
/********************************************************************************* 
function:process P2Ptransh 
*********************************************************************************/ 
void P2Ptransh_process(uchar head) 
{ 
	/*judge net type group*/ 
	uchar dst_net_type; 
	ulong dst_ip; 
	uint  dst_port,flag_num; 
	/*get destination net type*/ 
	dst_net_type = get_trans_net_type( head); 
	dst_ip = get_trans_ip( head); 
	dst_port = get_trans_port( head); 
	flag_num = MAKE_WORD( memory[head].space[0], memory[head].space[1] ); 
	if(net_type == CONE) 
	{ 
		if(dst_net_type == PUBLIC) 
		{ 
			net_group_type = CONE_PUBLIC; 
			answer_P2Ptransh(dst_ip,dst_port, flag_num,UDP_LOCAL_PORT); 
		} 
		else if(dst_net_type == CONE) 
		{ 
			net_group_type = CONE_CONE; 
			answer_P2Ptransh(dst_ip,dst_port, flag_num,UDP_LOCAL_PORT); 
		} 
		else 
		{ 
			net_group_type = CONE_SYMMETRIC; 
			answer_P2Ptransh(dst_ip,(dst_port+1), flag_num,UDP_LOCAL_PORT); 
		} 
	} 
	else if(net_type == SYMMETRIC || net_type == NO_SYMMETRIC) 
	{ 
		if(dst_net_type == CONE) 
			net_group_type = SYMMETRIC_CONE; 
		else if(dst_net_type == SYMMETRIC || dst_net_type == NO_SYMMETRIC) 
				net_group_type = SYMMETRIC_SYMMETRIC; 
		else //if(dst_net_type == PUBLIC) 
		{ 
			net_group_type = SYMMETRIC_PUBLIC; 
			answer_P2Ptransh(dst_ip,dst_port, flag_num,UDP_LOCAL_PORT); 
		} 
		if(net_group_type == SYMMETRIC_CONE || net_group_type == SYMMETRIC_SYMMETRIC) 
		{ 
			uint new_port; 
			new_port = NewPortForP2P(); 
			/*use new port ,send to master */ 
			//dst_ip = get_trans_ip(head); 
		//	dst_port = get_trans_port(head); 
			if(net_group_type == SYMMETRIC_SYMMETRIC) 
				dst_port++; 
			answer_P2Ptransh(dst_ip,dst_port,flag_num, new_port ); 
			/*use new port,send to serve*/ 
			ReadBytesFromFlash( SEVER1_IP_ADDRESS, SEVER1_IP_LEN, (uchar xdata *)&dst_ip); 
			ReadBytesFromFlash( SEVER1_PORT_ADDRESS, SEVER1_PORT_LEN, (uchar xdata *)&dst_port); 
			answer_P2Ptransh_to_serve(dst_ip,dst_port,&(memory[head].space[0]), new_port ); 
		} 
	} 
} 
 
/*************************************************************************** 
function: reply P2Ptransh command 
***************************************************************************/ 
void answer_P2Ptransh(ulong dst_ip,uint dst_port,uint number,uint self_port) 
{ 
	uchar head; 
	head = apply_memb( TCPMODBUS_LEN+1+1+1 ); 
	if(head != MEMORY_EER) 
	{ 
		memory[head].space[0] = HIGH_BYTE( number ); 
		memory[head].space[1] = LOW_BYTE( number); 
		memory[head].space[2] = 0; 
		memory[head].space[3] = 0; 
		memory[head].space[4] = 0; 
		memory[head].space[5] = 0x03; 
		memory[head].space[6] = 0; 
		memory[head].space[7] = LAND_FUNCTION; 
		memory[head].space[8] = P2PTRANSH_ACK; 
		UDP_send_data(head,dst_ip,dst_port,self_port); 
	}	 
} 
 
/********************************************************************** 
function:get transfer ip 
*********************************************************************/ 
ulong get_trans_ip(uchar head) 
{ 
	ulong ip; 
	ip = MAKE_LONG( MAKE_WORD( memory[head].space[TCPMODBUS_LEN+3], memory[head].space[TCPMODBUS_LEN+4] ),  
					MAKE_WORD( memory[head].space[TCPMODBUS_LEN+5], memory[head].space[TCPMODBUS_LEN+6] ) ); 
	return(ip); 
} 
 
/********************************************************************** 
function:get transfer port 
*********************************************************************/ 
uint get_trans_port(uchar head) 
{ 
	uint port; 
	port = MAKE_WORD( memory[head].space[TCPMODBUS_LEN+7], memory[head].space[TCPMODBUS_LEN+8] ); 
	return(port); 
} 
 
/********************************************************************** 
function:get transfer net type 
*********************************************************************/ 
uchar get_trans_net_type(uchar head) 
{ 
	uchar net_tmp; 
	net_tmp = memory[head].space[TCPMODBUS_LEN+9]; 
	return(net_tmp); 
} 
 
/********************************************************************** 
function:Prepare head for reply transfer command 
*********************************************************************/ 
void PrepareReplyTransHead(uchar head,uint Len,uchar xdata *pd) 
{ 
	uchar i; 
	for(i = 0;i