📄 tcp.c
字号:
TcpHead[14] = (v16 >> 8); TcpHead[15] = (uint8)v16;
v32 = This->Seq; // 序列号
TcpHead[16] = (v32 >> 24); TcpHead[17] = (v32 >> 16);
TcpHead[18] = (v32 >> 8); TcpHead[19] = (uint8)v32;
v32 = This->Ack; // 确认号
TcpHead[20] = (v32 >> 24); TcpHead[21] = (v32 >> 16);
TcpHead[22] = (v32 >> 8); TcpHead[23] = (uint8)v32;
TcpHead[24] = ((20 + OLength) << 2) & 0xf0; // 头部长
TcpHead[25] = 0x00 | (Flag & 0x3f); // 代码位
/*
if(This->hook != NULL)
{
//v16 = 1460;
//v16 = 3072;
v16 = 4096;
//v16 = 8192;
}
else
{
v16 = This->RxWindow.Size; // 窗口
}*/
#if TCP_RXWINDOW_SIZE > 0
v16 = This->RxWindow.Size;
#else
v16 = 4096;
#endif
TcpHead[26] = (v16 >> 8); TcpHead[27] = (uint8)v16;
TcpHead[28] = 0; TcpHead[29] = 0; // 校验和
TcpHead[30] = 0; TcpHead[31] = 0; // 紧急指针
// 计算校验和
v16 = ~TcpCheckSum(&Head);
TcpHead[28] = (uint8)v16; TcpHead[29] = (v16 >> 8);
// 丢开伪头部,发送数据包
Head.Data = TcpHead + 12;
Head.Length = 20;
//Head.Next = &Opt;
NetLayer.SendPacket(IPF_TCP,This->DestAddr,&Head);
}
/********************************************************************************************
*** 函数名称: TcpHeadProcess
*** 函数描述: TCP 头部处理:主要是根据收到的确认号进行状态转换
*** 入 口: Socket:接口指针 Head:头部指针 DataLength:数据段长度
*** 出 口: 1:TCP包包含新数据, 0:TCP包不包含新数据
********************************************************************************************/
static uint8 TcpHeadProcess(TCP_SOCKET *Socket,uint8 *Head,uint16 DataLength)
{
uint32 Ack = 0,Tmp = 0,Seq = 0;
uint8 *ptr,len,dat;
uint16 v16;
uint8 Flag;
// 提取对方窗口大小
v16 = Head[14]; v16 <<= 8;
v16 |= Head[15];
Socket->DestSize = v16;
// 提取TCP包序列号 Seq
Tmp = Head[4]; Tmp <<= 24; Seq |= Tmp;
Tmp = Head[5]; Tmp <<= 16; Seq |= Tmp;
Tmp = Head[6]; Tmp <<= 8; Seq |= Tmp;
Tmp = Head[7]; Seq |= Tmp;
// 提取FLAG 标志
Flag = Head[13] & 0x3f;
// 设置确认号
if(Flag & TCPFLAG_SYN) Socket->Ack = Seq + DataLength + 1;
else Socket->Ack = Seq + DataLength;
// 为发送通道产生状态迁移
if(Flag & TCPFLAG_ACK)
{
// 提取TCP包确认号 Ack
Tmp = Head[ 8]; Tmp <<= 24; Ack |= Tmp;
Tmp = Head[ 9]; Tmp <<= 16; Ack |= Tmp;
Tmp = Head[10]; Tmp <<= 8; Ack |= Tmp;
Tmp = Head[11]; Ack |= Tmp;
// 设置序列号
Socket->Seq = Ack;
switch(Socket->TXS)
{
case SOCKS_TXSYN:
Socket->TXS = SOCKS_SYNACK;
break;
case SOCKS_SENDING:
if(Socket->LastRcvAck > Ack)
{
v16 = Ack + (0xffffffff - Socket->LastRcvAck);
}
else
{
v16 = Ack - Socket->LastRcvAck;
}
WindowDel(&Socket->TxWindow,v16);
Socket->TXS = SOCKS_SENDACK;
break;
case SOCKS_TXFIN:
Socket->TXS = SOCKS_FINACK;
break;
default: break;
}
}
// 为接收通道状态机产生状态迁移
if(Flag & TCPFLAG_SYN)
{
Socket->RXS = SOCKS_RXSYN;
// 接收到 SYN ,记录对方的MRU到本地的MTU
ptr = Head + 20;
len = (Head[12] & 0xf0) >> 2;
len = len - 20;
while(len--)
{
dat = *ptr++;
switch(dat)
{
case 0x02:
dat = *ptr++;
if(dat != 0x04) break;
v16 = *ptr++;
v16 <<= 8;
v16 = v16 | *ptr++;
Socket->MTU = v16;
len = 0;
break;
case 0x01: break;
case 0x03: ptr = ptr + 3; break;
case 0x04: ptr++; break;
default: break;
}
}
}
if(Flag & TCPFLAG_FIN)
{
if(Socket->RXS != SOCKS_CLOSED)
{
Socket->RXS = SOCKS_RXFIN;
}
}
if(Flag & TCPFLAG_RST)
{
TcpSendPacket(Socket,NULL,0,(TCPFLAG_RST|TCPFLAG_ACK),0);
/*
Socket->RXS = SOCKS_CLOSED;
Socket->TXS = SOCKS_CLOSED;
*/
Socket->RXS = SOCKS_CLOSED;
//Socket->TXS = SOCKS_RESET;
Socket->TXS = SOCKS_CLOSED;
//Printf("[Connection is reseted:TOT=%d]\r\n",Socket->TOT);
}
Socket->LastRcvAck = Ack;
if(Seq == Socket->LastRcvSeq) return 0;
Socket->LastRcvSeq = Seq; return 1;
}
#endif
/********************************************************************************************
*** 函数名称: TcpReceiveTask
*** 函数描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
void TcpReceiveTask(void)
{
#if MAX_TCP_SOCKETS > 0
TCP_SOCKET *Socket;
uint8 *TcpData;
uint16 TcpDataLength;
uint16 DestPort;
uint16 SourcePort;
uint8 SourceIp[4];
uint8 TcpHeadLength;
TcpHeadLength = *NetLayer.Rxd;
TcpHeadLength = (TcpHeadLength & 0x0f) << 2;// 获取IP 包头部长度
TcpData = NetLayer.Rxd + TcpHeadLength; // 指向TCP包
// 计算TCP包数据段总长
TcpDataLength = NetLayer.Rxd[2]; // 获取IP包总长
TcpDataLength <<= 8;
TcpDataLength |= NetLayer.Rxd[3];
TcpDataLength -= TcpHeadLength; // 减去IP头部长
TcpHeadLength = (TcpData[12] & 0xf0) >> 2;// 获取TCP头部长度
TcpDataLength -= TcpHeadLength; // 减去TCP头部长
// 取 IP 包源地址
SourceIp[0] = NetLayer.Rxd[12];
SourceIp[1] = NetLayer.Rxd[13];
SourceIp[2] = NetLayer.Rxd[14];
SourceIp[3] = NetLayer.Rxd[15];
// 取 TCP 包源端口
SourcePort = TcpData[0];
SourcePort <<= 8;
SourcePort |= TcpData[1];
// 取 TCP 包目的端口
DestPort = TcpData[2];
DestPort <<= 8;
DestPort |= TcpData[3];
// 搜索匹配的TCP连接
Socket = TcpFirstSocket;
while(Socket != NULL)
{
if( (DestPort == Socket->LocalPort) // IP包目的端口与Socket的源端口匹配
&& (SourcePort == Socket->DestPort) // IP包的源端口与Socket目的端口匹配
&& (InetMemCmp(SourceIp,Socket->DestAddr,4)) // IP包的源地址与Socket目的地址匹配
)
{
// TCP数据包过滤规则 Added by Yan Zhangjian(C) @ 2008-05-24
/*
if(Socket->TXS == SOCKS_CLOSED && Socket->RXS == SOCKS_CLOSED)
{
}*/
TcpHeadProcess(Socket,TcpData,TcpDataLength);
if(TcpDataLength)
{
TcpData = TcpData + TcpHeadLength;
#if TCP_RXWINDOW_SIZE > 0
WindowPush(&Socket->RxWindow,TcpData,TcpDataLength);
#endif
Socket->Rxd = TcpData;
Socket->Rxl = TcpDataLength;
if(Socket->hook != NULL)
{
Socket->hook(Socket);
}
TcpSendPacket(Socket,NULL,0,TCPFLAG_ACK,0);
}
break;
}
Socket = Socket->Next;
}
#endif
}
/********************************************************************************************
*** 函数名称: TcpFsmTask
*** 函数描述: TCP有限状态机处理任务
*** 入 口: 无
*** 出 口: 无
********************************************************************************************/
void TcpFsmTask(void)
{
#if MAX_TCP_SOCKETS > 0
TCP_SOCKET *Socket;
uint32 time;
int32 DIFF;
if(LinkLayer.State != PPPS_OPENED) return;
Socket = TcpFirstSocket;
while(Socket != NULL)
{
#ifdef USE_TCP_DEBUGER
{
static uint8 RXS = SOCKS_CLOSED;
static uint8 TXS = SOCKS_CLOSED;
if(RXS != Socket->RXS || TXS != Socket->TXS)
{
RXS = Socket->RXS;
TXS = Socket->TXS;
Printf("[RXS=0x%02x,TXS=0x%02x]\r\n",RXS,TXS);
}
}
#endif
time = NET_TICK_COUNTER; // 采样当前时间
if(time < Socket->Time)
{
time = time + NET_TICK_LIMITED;
}
// 超时服务、采样RTT
switch(Socket->TXS)
{
case SOCKS_TXSYN:
if((time - Socket->Time) > Socket->Timeout)
{ // 同步超时服务
if(Socket->TOT <= 3)
{ // 超时不超过3次,重新请求
Socket->TXS = SOCKS_CONNREQ;
Socket->TOT = Socket->TOT + 1;
}
else
{ // 超时大于3次返回关闭状态
//Printf("[TOT=%d]\r\n",Socket->TOT);
Socket->TXS = SOCKS_CLOSED;
Socket->RXS = SOCKS_CLOSED;
Socket->TOT = 0;
}
}
break;
case SOCKS_SENDREQ:
if( ((time - Socket->Time) > Socket->RTT)
|| (Socket->TxWindow.DatLen > 500)
)
{ // 填充数据字节数大于500或者填充数据后时间超过RTT
Socket->TXS = SOCKS_SENDSTART;
Socket->TOT = 0;
}
break;
case SOCKS_SENDING:
if((time - Socket->Time) > Socket->Timeout)
{ // 发送超时服务
if(Socket->TOT < 10)
{ // 超时不超过10次,重新请求
Socket->TXS = SOCKS_SENDSTART;
Socket->TOT = Socket->TOT + 1;
}
else
{ // 超时大于10次返回关闭状态
//Printf("[TOT=%d]\r\n",Socket->TOT);
Socket->TXS = SOCKS_CLOSED;
Socket->RXS = SOCKS_CLOSED;
Socket->TOT = 0;
TcpSendPacket(Socket,NULL,0,(TCPFLAG_RST|TCPFLAG_ACK),0);
}
}
break;
case SOCKS_TXFIN:
if((time - Socket->Time) > Socket->Timeout)
{ // 关闭超时服务
if(Socket->TOT <= 3)
{ // 超时不超过3次,重新请求
Socket->TXS = SOCKS_CLOSEREQ;
Socket->TOT = Socket->TOT + 1;
}
else
{ // 超时大于3次返回关闭状态
Socket->TXS = SOCKS_CLOSED;
Socket->TOT = 0;
}
}
break;
case SOCKS_RESTART: // Added by Yan Zhangjian(C) @ 2008-05-24
if((time - Socket->Time) > 10)
{
Socket->TXS = SOCKS_CLOSED;
}
break;
default:break;
}// end of switch(Socket->TXS)
// 发送通道状态迁移
switch(Socket->TXS)
{
case SOCKS_CLOSED:
if(Socket->UREQ == UREQ_CONN)
{
Socket->UREQ = UREQ_NONE;
Socket->TXS = SOCKS_CONNREQ;
}
//Socket->TOT = 0;
break;
case SOCKS_CONNREQ:
{
uint8 Option[4] = {0x02,0x04,0x00,0x00};
Option[2] = Socket->MRU >> 8;
Option[3] = Socket->MRU;
TcpSendPacket(Socket,Option,4,TCPFLAG_SYN,0);
}
Socket->Time = NET_TICK_COUNTER;
Socket->TXS = SOCKS_TXSYN;
break;
case SOCKS_SYNACK:
Socket->TXS = SOCKS_OPENED;
//Socket->TOT = 0;
break;
case SOCKS_OPENED:
if(Socket->UREQ == UREQ_SEND)
{
Socket->UREQ = UREQ_NONE;
Socket->TXS = SOCKS_SENDREQ;
}
else if(Socket->UREQ == UREQ_CLOSE)
{
Socket->UREQ = UREQ_NONE;
Socket->TXS = SOCKS_CLOSEREQ;
}
//Socket->TOT = 0;
break;
case SOCKS_SENDSTART: // 开始发送
Socket->SampRTT = NET_TICK_COUNTER; // 开始采样RTT
TcpSendPacket(Socket,NULL,0,(TCPFLAG_ACK|TCPFLAG_PSH),1);
Socket->Time = NET_TICK_COUNTER;
Socket->TXS = SOCKS_SENDING;
break;
case SOCKS_SENDACK:
time = NET_TICK_COUNTER; // 结束采样RTT
if(time < Socket->Time)
{
time += NET_TICK_LIMITED;
}
Socket->SampRTT = time - Socket->SampRTT;
if(Socket->SampRTT < 1) // RTT下限:1ms
{
Socket->SampRTT = 1;
}
if(Socket->SampRTT > 10000) // RTT上限:10s
{
Socket->SampRTT = 10000;
}
DIFF = Socket->SampRTT - Socket->RTT;
Socket->RTT = Socket->RTT + 0.125 * DIFF;
Socket->DEV = Socket->DEV + 0.25 * (abs(DIFF) - Socket->DEV);
Socket->Timeout = Socket->RTT + 3 * Socket->DEV;
Socket->TXS = SOCKS_OPENED;
//Socket->TOT = 0;
break;
case SOCKS_CLOSEREQ:
TcpSendPacket(Socket,NULL,0,TCPFLAG_FIN,1);
Socket->Time = NET_TICK_COUNTER;
Socket->TXS = SOCKS_TXFIN;
break;
case SOCKS_RESET: // Added by Yan Zhangjian(C) @ 2008-05-24
Socket->Time = NET_TICK_COUNTER;
Socket->TXS = SOCKS_RESTART;
break;
default: break;
}// end of switch(Socket->TXS)
// 接收通道状态迁移
switch(Socket->RXS)
{
case SOCKS_RXSYN:
if(Socket->TXS == SOCKS_OPENED)
{
TcpSendPacket(Socket,NULL,0,TCPFLAG_ACK,0);
}
else
{
TcpSendPacket(Socket,NULL,0,(TCPFLAG_SYN|TCPFLAG_ACK),0);
}
Socket->RXS = SOCKS_OPENED;
break;
case SOCKS_RXFIN:
TcpSendPacket(Socket,NULL,0,TCPFLAG_ACK,0);
TcpSendPacket(Socket,NULL,0,TCPFLAG_FIN|TCPFLAG_ACK,0);
Socket->RXS = SOCKS_CLOSED;
//Socket->TXS = SOCKS_CLOSED; // added by Yan Zhangjian(C) @ 2008-04-08 18:27
break;
default: break;
}// end of switch(Socket->RXS)
if((Socket->TxWindow.DatLen == 0) && (Socket->UREQ == UREQ_SEND))
{
Socket->UREQ = UREQ_NONE;
}
if(Socket->TxWindow.DatLen > 0)
{
if(Socket->TXS == SOCKS_CLOSED)
{
//Socket->UREQ = UREQ_CONN;
}
if(Socket->TXS == SOCKS_OPENED)
{
Socket->UREQ = UREQ_SEND;
}
}
if( (Socket->RXS == SOCKS_CLOSED)
&& (Socket->TXS == SOCKS_OPENED)
&& (Socket->TxWindow.DatLen == 0))
{
TcpSendPacket(Socket,NULL,0,(TCPFLAG_RST|TCPFLAG_ACK),0);
Socket->TXS = SOCKS_CLOSED;
}
Socket = Socket->Next;
}// end of while(Socket != NULL)
#endif
}
/********************************************************************************************
*** 函数名称:
*** 函数描述:
*** 入 口:
*** 出 口:
********************************************************************************************/
void TcpInitial(void)
{
#if MAX_TCP_SOCKETS > 0
TcpFirstSocket = NULL;
#endif
}
/********************************************************************************************
*** 文件结束 ***
********************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -