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