📄 tcp.c
字号:
/*
+FHDR------------------------------------------------------------------
Copyright (c),
Tony Yang –51,AVR,ARM firmware developer
Contact:qq 292942278 e-mail:tony_yang123@sina.com.cn
Abstract:
$Id: tcp.c,v 1.10 2006/12/31 16:05:32 tony Exp $
-FHDR-------------------------------------------------------------------
*/
#include "config.h"
#include "tcp_ip_cfg.h"
#include "hardware.h"
#include "ethernet.h"
#include "uart0\uart0.h"
#include "icmp.h"
#include "arp.h"
#include "udp.h"
#include "ip.h"
#include "socket.h"
SOCKET TCP_Socket[MAX_TCP_LINKS];
/*本地TCP监听端口表*/
u16 TCP_PORT_Listening[MAX_TCP_Listening_Ports];
/*本地端口分配表*/
u16 Local_PORT_Pool[MAX_Local_PORT_Pool_SIZE];
struct TCP_Header *TCP_Header;
/****************************************************************************
* 名称:CHECK_Port_Can_be_Used()
* 功能:检查一个端口是否可用?
* 入口:PORT_NUM--端口号
* 出口: SUCC-可以使用;FAIL-禁止使用
****************************************************************************/
u8 CHECK_Port_Can_be_Used(u16 PORT_MUN)
{
u16 i;
for(i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
{
if(Local_PORT_Pool[i] == PORT_MUN)
return(FAIL);
}
return(SUCC);
}
/****************************************************************************
* 名称:Free_a_LOCAL_Port(u16 PORT_MUN)
* 功能:释放的一个本地端口
* 入口:PORT_NUM--端口号
* 出口: SUCC-释放成功;FAIL-端口可用,无需释放
****************************************************************************/
u8 Free_a_LOCAL_Port(u16 PORT_MUN)
{
u16 i;
for(i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
{
if(Local_PORT_Pool[i] == PORT_MUN)
{
Local_PORT_Pool[i] = 0;
return(SUCC);
}
}
return(FAIL);
}
/****************************************************************************
* 名称:Allocate_A_LOCAL_Port()
* 功能:为客户端分配一个本地端口,用于连接至服务器
* 入口:无
* 出口: 0xffff-分配错误,正常为分配的端口号
****************************************************************************/
u16 Allocate_A_LOCAL_Port(void)
{
u16 i,j;
for(i = 0x410;i < (0x410 + MAX_Local_PORT_Pool_SIZE);i++)
{
if(CHECK_Port_Can_be_Used(i) == SUCC)
{
/*寻找一个空位,把PORT i写到本地端口分配表*/
for(j = 0;j < MAX_Local_PORT_Pool_SIZE;j++)
if(Local_PORT_Pool[j] == 0)
{
Local_PORT_Pool[j] = i;
break;
}
if(j >= MAX_Local_PORT_Pool_SIZE)
return(0xffff);
else
return(i);
}
}
return(0xffff);
}
/****************************************************************************
* 名称:TCP_initial
* 功能:检查端口是否工作为监听状态?
* 入口:PortNUM-端口号
* 出口: SUCC FAIL
****************************************************************************/
u8 TCP_check_port_listening(u16 PortNUM)
{
u16 i;
for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
if(TCP_PORT_Listening[i] == PortNUM)
{
return(SUCC);
}
return(FAIL);
}
/****************************************************************************
* 名称:enable_a_port_listen
* 功能:触发一个端口工作为监听状态?
* 入口:PortNUM-端口号
* 出口: SUCC FAIL
****************************************************************************/
u8 TCP_enable_a_port_listen(u16 PortNUM)
{
u16 i;
if(TCP_check_port_listening(PortNUM) == SUCC)
return(FAIL);
for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
if(TCP_PORT_Listening[i] == 0)
{
TCP_PORT_Listening[i] = PortNUM;
return(SUCC);
}
return(FAIL);
}
/****************************************************************************
* 名称:TCP_Seek_4_elements
* 功能:查找四元组,一个四无组表示一个服务器与客户器连接
* 入口:pkt-TCP数据报的首地址,
* index-UDP_Socket的索引
* IP-源/目的首地址
* 出口: 无
****************************************************************************/
u8 TCP_Seek_4_elements(u8 * pkt,u16 * index,u8 *IP)
{
u16 i,j,flag;
for(i = 0 ;i < MAX_TCP_LINKS ;i++)
{
if(!TCP_Socket[i].EN)
continue;
/*检查PKT的源端口*/
if(pkt[0] != TCP_Socket[i].DEST_Port[1] || pkt[1] != TCP_Socket[i].DEST_Port[0])
continue;
if(pkt[2] != TCP_Socket[i].SRC_Port[1] || pkt[3] != TCP_Socket[i].SRC_Port[0])
continue;
/*检查PKT的目的地址*/
flag = SUCC;
for(j = 0;j < 4;j++)
{
if(IP[j] != TCP_Socket[i].DEST_IP_Address[j] )
{
flag = FAIL;
break;
}
}
if(flag == SUCC)
{
for(j = 0;j < 4;j++)
{
if(IP[j+4] != TCP_Socket[i].SRC_IP_Address[j] )
{
flag = FAIL;
break;
}
}
if(flag == SUCC)
{
*index = i;
return(SUCC);
}
}
}
return(FAIL);
}
/****************************************************************************
* 名称:TCP_Write_4_element
* 功能:写一个四元组,表示一个服务器与客户器连接
* 入口:pkt-TCP数据报的首地址,
* index-UDP_Socket的索引
* IP-源/目的首地址
* 出口: 无
****************************************************************************/
void TCP_Write_4_element(u8 * pkt,u16 index,u8 *IP)
{
u16 i;
TCP_Socket[index].EN = 1;
for(i = 0;i < 4;i++)
{
TCP_Socket[index].DEST_IP_Address[i] = IP[i];
TCP_Socket[index].SRC_IP_Address[i] = IP[4+i];
}
TCP_Socket[index].DEST_Port[0] = pkt[1];
TCP_Socket[index].DEST_Port[1] = pkt[0];
TCP_Socket[index].SRC_Port [0] = pkt[3];
TCP_Socket[index].SRC_Port [1] = pkt[2];
TCP_Socket[index].SRC_SN[0] = pkt[11];
TCP_Socket[index].SRC_SN[1] = pkt[10];
TCP_Socket[index].SRC_SN[2] = pkt[9];
TCP_Socket[index].SRC_SN[3] = pkt[8];
TCP_Socket[index].DEST_SN[0] = pkt[7];
TCP_Socket[index].DEST_SN[1] = pkt[6];
TCP_Socket[index].DEST_SN[2] = pkt[5];
TCP_Socket[index].DEST_SN[3] = pkt[4];
TCP_Socket[index].SRC_WIN[0] = MAX_TCP_UDP_DATA_link_buf_len >> 8;
TCP_Socket[index].SRC_WIN[1] = MAX_TCP_UDP_DATA_link_buf_len & 0xff;
TCP_Socket[index].DEST_WIN[0] = pkt[15];
TCP_Socket[index].DEST_WIN[1] = pkt[14];
}
/****************************************************************************
* 名称:UDP_initial
* 功能:初始化TCP模块
* 入口:无
* 出口: 无
****************************************************************************/
void TCP_initial(void)
{
u16 i;
u8 j;
for(i = 0;i < MAX_TCP_LINKS;i++)
{
TCP_Socket[i].DEST_Port[0] = 0;
TCP_Socket[i].DEST_Port[1] = 0;
TCP_Socket[i].SRC_Port[0] = 0;
TCP_Socket[i].SRC_Port[1] = 0;
for(j = 0;j < 4;j++)
{
TCP_Socket[i].DEST_IP_Address[j] =0x0;
TCP_Socket[i].SRC_IP_Address[j] = 0x0;
}
TCP_Socket[i].Queue_Rear = 0;
TCP_Socket[i].Queue_Front = 0;
TCP_Socket[i].Queue_Full = 0;
TCP_Socket[i].EN = 0;
TCP_Socket[i].SRC_SN[0] = 0x0;
TCP_Socket[i].SRC_SN[1] = 0x0;
TCP_Socket[i].SRC_SN[2] = 0x43;
TCP_Socket[i].SRC_SN[3] = 0x21;
TCP_Socket[i].DEST_SN[0] = 0;
TCP_Socket[i].DEST_SN[1] = 0;
TCP_Socket[i].DEST_SN[2] = 0;
TCP_Socket[i].DEST_SN[3] = 0;
TCP_Socket[i].SRC_WIN[0] = MAX_TCP_UDP_DATA_link_buf_len >> 8;
TCP_Socket[i].SRC_WIN[1] = MAX_TCP_UDP_DATA_link_buf_len & 0xff;
TCP_Socket[i].DEST_WIN[0] = 0;
TCP_Socket[i].DEST_WIN[1] = 0;
TCP_Socket[i].status = Closed;
TCP_Socket[i].ACK_Unsended = 0;;
TCP_Socket[i].last_pkt_len = 0;
TCP_Socket[i].timeout_ack = 0;
TCP_Socket[i].type = NOT_Listening;
}
for(i = 0 ;i < MAX_TCP_Listening_Ports ;i++)
TCP_PORT_Listening[i] = 0;
for( i = 0;i < MAX_Local_PORT_Pool_SIZE;i++)
Local_PORT_Pool[i] = 0;
}
/****************************************************************************
* 名称: Send_TCP_PKT
* 功能:发送一个TCP数据报
* 入口:TxdData--需发送数据的指针,
* dest_ip_add:目的IP地址
* 出口: 无
****************************************************************************/
void Send_TCP_PKT(struct _pkst *TxdData,u8 *dest_ip_add)
{
Send_IP_PKT(TxdData,dest_ip_add,TCP);
}
/****************************************************************************
* 名称: bigEND_u32_add_1
* 功能:对大端模式的32位整数据加1
* 入口:data1-数据的首地址
*
* 出口: 无
****************************************************************************/
void bigEND_u32_add_1(u8 * data1)
{
if(data1[3] !=0xff)
{
data1[3]++;
}
else if(data1[2] != 0xff)
{ data1[3] = 0;
data1[2]++;
}
else if(data1[1] != 0xff)
{data1[2] = 0;
data1[1]++;
}
else if(data1[0] != 0xff)
{ data1[1] = 0;
data1[0] ++;
}
else
data1[0] = 0;
}
/****************************************************************************
* 名称: littleEND_u32_add_1
* 功能:对小端模式的两个32位整数据相加
* 入口:data1-数据的首地址
*
* 出口: 无
****************************************************************************/
void littleEND_u32_add(u8 * data1,u8 * data2)
{
s8 i;
u16 temp,temp1;
temp1 = 0;
for(i = 0;i < 4;i++)
{
temp = data1[i] + data2[i] + temp1;
if(temp > 255)
temp1 = 1;
else
temp1 = 0;
data1[i] = temp & 0xff;
}
}
/****************************************************************************
* 名称:Send_TCP_ACK()
* 功能:发送ACK数据报
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -