?? tcpip.c
字號(hào):
(gptConn->TcpStateFlags == cTCP_TIME_WAIT)){
goto found_unused_connection;
}
}
goto drop; // 沒有空閑的TCP聯(lián)接,進(jìn)入異常終止遠(yuǎn)端處理!
// 有空閑的TCP聯(lián)接,回應(yīng)遠(yuǎn)端的SYN請(qǐng)求
found_unused_connection:
// 設(shè)置初始TCP聯(lián)接事務(wù)狀態(tài)
gptConn->Timer = cTCP_RTO;
gptConn->NumRetran = 0;
gptConn->LocalPort = cptTcpHdrBuf->DestPort;
gptConn->RemotePort = cptTcpHdrBuf->SrcPort;
gptConn->RemoteIpAddr[0] = cptIpHdrBuf->SrcIpAddr[0];
gptConn->RemoteIpAddr[1] = cptIpHdrBuf->SrcIpAddr[1];
gptConn->TcpStateFlags = cTCP_SYN_RCVD|cTCP_OUTSTANDING;
//-------------------------
gptConn->SeqNum[0] = guwISN[0];
gptConn->SeqNum[1] = guwISN[1];
//-------------------------
gptConn->AckNum[0] = guwISN[0];
gptConn->AckNum[1] = guwISN[1];
if (++gptConn->AckNum[1] == 0){
++gptConn->AckNum[0];
}
//-------------------------
gptConn->RcvNum[0] = cptTcpHdrBuf->SeqNum[0];
gptConn->RcvNum[1] = cptTcpHdrBuf->SeqNum[1];
if (++gptConn->RcvNum[1] == 0){
++gptConn->RcvNum[0];
}
// 獲取遠(yuǎn)端TCP報(bào)文長(zhǎng)度。如果遠(yuǎn)端比本地小,就以遠(yuǎn)端為準(zhǔn)。
i = cptTcpHdrBuf->HdrLen;
if (i > cTCP_HDR_NOOPT){
i = (i - cTCP_HDR_NOOPT) << 1; // Convert 32bit number to 16bit number.
for (j = 0; j < i; j++){
if (cpTcpData[j] == 0x0204){
gptConn->MaxSegSize = cpTcpData[j + 1] > cTCP_MSS ? cTCP_MSS : cpTcpData[j + 1];
break;
}
}
}
// 發(fā)送 SYNACK 包
#if TCP_ACTIVE_OPEN == 1
tcp_send_synack:
cptTcpHdrBuf->Flags = cTCP_ACK;
tcp_send_syn:
cptTcpHdrBuf->Flags |= cTCP_SYN;
#else
tcp_send_synack:
cptTcpHdrBuf->Flags = cTCP_SYN|cTCP_ACK;
#endif
// 給 SYNACK 包配置TCP頭選項(xiàng)表
cpTcpData[0] = 0x0204; // 0x0204 表示最大報(bào)文段長(zhǎng)度前綴
cpTcpData[1] = cTCP_MSS; // 最大報(bào)文段長(zhǎng)度前綴
cpTcpData[2] = 0x0101; // 0x01表示無操作,0x00表示選項(xiàng)表結(jié)束
cpTcpData[3] = 0x0402; // 0x0402 表示 SACK 被允許
guwEthLen = 2*cIpHdrLen + (cTCP_HDR_OPT << 2);
cptTcpHdrBuf->HdrLen = cTCP_HDR_OPT;
goto tcp_send;
// 找到已經(jīng)存在的TCP聯(lián)接事物
found:
guwFlags = 0;
// 如果遠(yuǎn)端是RST包,就通知本地應(yīng)用層:當(dāng)前連接被遠(yuǎn)端異常終止!
if (cptTcpHdrBuf->Flags & cTCP_RST){
gptConn->TcpStateFlags = cTCP_CLOSED;
guwFlags = cTCP_ABORT;
msip_APPCALL();
goto drop;
}
// 如果沒有ACK標(biāo)識(shí),不響應(yīng)!
if (!(cptTcpHdrBuf->Flags & cTCP_ACK)){
goto drop;
}
// 計(jì)算TCP數(shù)據(jù)段字節(jié)長(zhǎng)度
guwEthLen -= ((cptIpHdrBuf->Vhl & 0x0f) << 2) + (cptTcpHdrBuf->HdrLen << 2);
// 檢驗(yàn)遠(yuǎn)端的ACK序號(hào)是否我們期待的.....
if ((cptTcpHdrBuf->AckNum[0] == gptConn->AckNum[0]) && (cptTcpHdrBuf->AckNum[1] == gptConn->AckNum[1])){
gptConn->SeqNum[0] = gptConn->AckNum[0];
gptConn->SeqNum[1] = gptConn->AckNum[1];
gptConn->TcpStateFlags &= ~cTCP_OUTSTANDING;
gptConn->Timer = cTCP_RTO;
gptConn->NumRetran = 0;
guwFlags = cTCP_ACKDATA;
} else {
goto drop;
}
// 根據(jù)不同的聯(lián)接狀態(tài)決定TCP狀態(tài)變遷,并通知應(yīng)用程序
switch (gptConn->TcpStateFlags & cTCP_TS_MASK){
// CLOSED和LISTEN狀態(tài)不在這里處理
// CLOSE_WAIT狀態(tài)同樣被忽略:因?yàn)橐坏┍镜厥盏紽IN,我們就強(qiáng)制應(yīng)用層關(guān)閉,即從ESTABLISH到LAST_ACK
case cTCP_SYN_RCVD:
// 在SYN_RCVD狀態(tài)下,我們收到遠(yuǎn)端ACK回應(yīng)
// 另一方面,如果已經(jīng)存在cTCP_ACKDATA標(biāo)識(shí),就進(jìn)入ESTABLISHED狀態(tài)
gptConn->TcpStateFlags = cTCP_ESTABLISHED;
guwFlags = cTCP_CONNECTED;
msip_APPCALL();
goto appsend;
#if TCP_ACTIVE_OPEN == 1
case cTCP_SYN_SENT:
// 在SYN_SENT狀態(tài),我們收到遠(yuǎn)端SYNACK響應(yīng),本地發(fā)送ACK后就進(jìn)入ESTABLISHED狀態(tài)
// 獲取遠(yuǎn)端TCP報(bào)文長(zhǎng)度。如果遠(yuǎn)端比本地小,就以遠(yuǎn)端為準(zhǔn)。
i = cptTcpHdrBuf->HdrLen;
if (i > cTCP_HDR_NOOPT){
i = (i - cTCP_HDR_NOOPT) << 1;
for (j = 0; j < i; j++){
if (cpTcpData[j] == 0x0204){
gptConn->MaxSegSize = cpTcpData[j + 1] > cTCP_MSS ? cTCP_MSS : cpTcpData[j + 1];
break;
}
}
}
gptConn->RcvNum[0] = cptTcpHdrBuf->SeqNum[0];
gptConn->RcvNum[1] = cptTcpHdrBuf->SeqNum[1];
if (++gptConn->RcvNum[1] == 0){
++gptConn->RcvNum[0];
}
gptConn->TcpStateFlags = cTCP_ESTABLISHED;
guwFlags = cTCP_CONNECTED;
msip_APPCALL();
goto appsend;
#endif
case cTCP_ESTABLISHED: // 應(yīng)用狀態(tài)標(biāo)識(shí)cTCP_ACKDATA被設(shè)置,允許應(yīng)用層發(fā)送TCP數(shù)據(jù)包
// 如果收到包含F(xiàn)IN標(biāo)識(shí)的包,協(xié)議層發(fā)送FIN并進(jìn)入LAST_ACK狀態(tài),并向應(yīng)用層發(fā)cTCP_CLOSE標(biāo)識(shí)
if (cptTcpHdrBuf->Flags & cTCP_FIN) {
i = 1 + guwEthLen;
if ((gptConn->RcvNum[1] += i) < i){
++gptConn->RcvNum[0];
}
guwFlags = cTCP_CLOSE;
msip_APPCALL();
if (++gptConn->AckNum[1] == 0){
++gptConn->AckNum[0];
}
gptConn->TcpStateFlags = cTCP_LAST_ACK|cTCP_OUTSTANDING;
tcp_send_finack: // 發(fā)送FINACK包:由TCP事務(wù)查詢重傳跳過來的.....
cptTcpHdrBuf->Flags = cTCP_FIN|cTCP_ACK;
goto tcp_send_nodata;
}
if (guwEthLen > 0){ // 收到的TCP包有數(shù)據(jù)段
if (gptConn->TcpStateFlags & cTCP_STOPPED){
// 1)如果有cTCP_STOPPED標(biāo)識(shí),表明應(yīng)用層沒有buffer處理,我們只能ACK回應(yīng)。
// guwFlags = cTCP_ACKDATA; // 已經(jīng)存在的,這里不需要重設(shè)
goto tcp_send_ack;
} else {
// 2)應(yīng)用層可以處理這個(gè)含數(shù)據(jù)段的TCP包,給應(yīng)用層發(fā)cTCP_NEWDATA標(biāo)識(shí)以替換cTCP_ACKDATA標(biāo)識(shí)
guwFlags = cTCP_NEWDATA;
if ((gptConn->RcvNum[1] += guwEthLen) < guwEthLen){
++gptConn->RcvNum[0];
}
}
}
// 協(xié)議層通知應(yīng)用層目前的狀態(tài):
msip_APPCALL();
appsend: // 根據(jù)應(yīng)用層的反饋標(biāo)識(shí)處理回應(yīng)遠(yuǎn)端
// 如果應(yīng)用層需要異常終止當(dāng)前連接,協(xié)議層就RSTACK遠(yuǎn)端,并清除這個(gè)TCP事務(wù)!
if (guwFlags & cTCP_ABORT){
gptConn->TcpStateFlags = cTCP_CLOSED;
cptTcpHdrBuf->Flags = cTCP_RST|cTCP_ACK;
guwEthLen = 0;
goto tcp_send_nodata;
}
// 如果應(yīng)用層需要正常關(guān)閉當(dāng)前連接,協(xié)議層就進(jìn)入等待FIN_WAIT_1狀態(tài),并向遠(yuǎn)端發(fā)送FINACK
if (guwFlags & cTCP_CLOSE){
if (++gptConn->AckNum[1] == 0){
++gptConn->AckNum[0];
}
gptConn->TcpStateFlags = cTCP_FIN_WAIT_1|cTCP_OUTSTANDING;
gptConn->NumRetran = 0;
cptTcpHdrBuf->Flags = cTCP_FIN|cTCP_ACK;
guwEthLen = 0;
goto tcp_send_nodata;
}
// 檢查應(yīng)用層是否有TCP數(shù)據(jù)包
if (guwEthLen > 0){ // 應(yīng)用層有TCP數(shù)據(jù)包
gptConn->TcpStateFlags |= cTCP_OUTSTANDING;
gptConn->NumRetran = 0;
if ((gptConn->AckNum[1] += guwEthLen) < guwEthLen){
++gptConn->AckNum[0];
}
// 重傳處理,當(dāng)然也要處理正常的ACK回應(yīng)。
apprexmit:
// 發(fā)送ACK確認(rèn),可能包含TCP數(shù)據(jù)
guwEthLen += 2*(cIpHdrLen + cTcpHdrLen);
// 設(shè)置PSHACK標(biāo)識(shí)
cptTcpHdrBuf->Flags = cTCP_ACK | cTCP_PSH;
// 進(jìn)入TCP封裝
goto tcp_send_noopts;
} else if (guwFlags & cTCP_NEWDATA){ // 應(yīng)用層沒有有TCP數(shù)據(jù)包。檢查遠(yuǎn)端是否等待本地的ACK回應(yīng)
goto tcp_send_ack;
}
goto drop; // 遠(yuǎn)端是沒有數(shù)據(jù)的ACK回應(yīng),并且應(yīng)用層也沒有數(shù)據(jù)要傳。
case cTCP_LAST_ACK:
// 如果收到遠(yuǎn)端ACK確認(rèn)本地FIN,協(xié)議層關(guān)閉連接。
if (guwFlags & cTCP_ACKDATA){
gptConn->TcpStateFlags = cTCP_CLOSED;
}
goto drop;
case cTCP_FIN_WAIT_1:
// 應(yīng)用層已經(jīng)關(guān)閉,但遠(yuǎn)端還沒有。本地協(xié)議層等待FIN
if (guwEthLen > 0){
if ((gptConn->RcvNum[1] += guwEthLen) < guwEthLen){
++gptConn->RcvNum[0];
}
}
if (cptTcpHdrBuf->Flags & cTCP_FIN){
if (guwFlags & cTCP_ACKDATA){
gptConn->TcpStateFlags = cTCP_TIME_WAIT;
gptConn->Timer = 0;
}
else{
gptConn->TcpStateFlags = cTCP_CLOSING|cTCP_OUTSTANDING;
}
if (++gptConn->RcvNum[1] == 0){
++gptConn->RcvNum[0];
}
goto tcp_send_ack;
}
else if (guwFlags & cTCP_ACKDATA){
gptConn->TcpStateFlags = cTCP_FIN_WAIT_2;
goto drop;
}
if (guwEthLen > 0){
goto tcp_send_ack;
}
goto drop;
case cTCP_FIN_WAIT_2:
if (guwEthLen > 0){
if ((gptConn->RcvNum[1] += guwEthLen) < guwEthLen){
++gptConn->RcvNum[0];
}
}
if (cptTcpHdrBuf->Flags & cTCP_FIN){
gptConn->TcpStateFlags = cTCP_TIME_WAIT;
gptConn->Timer = 0;
if (+gptConn->RcvNum[1] == 0){
++gptConn->RcvNum[0];
}
goto tcp_send_ack;
}
if(guwEthLen > 0){
goto tcp_send_ack;
}
goto drop;
case cTCP_TIME_WAIT:
goto tcp_send_ack;
case cTCP_CLOSING:
if (guwFlags & cTCP_ACKDATA){
gptConn->TcpStateFlags = cTCP_TIME_WAIT;
gptConn->Timer = 0;
}
}
goto drop;
// 封裝 TCP
tcp_send_ack:
cptTcpHdrBuf->Flags = cTCP_ACK;
tcp_send_nodata:
guwEthLen = 2*(cIpHdrLen + cTcpHdrLen);
tcp_send_noopts:
cptTcpHdrBuf->HdrLen = cTCP_HDR_NOOPT;
tcp_send: // 構(gòu)造TCP頭
cptTcpHdrBuf->AckNum[0] = gptConn->RcvNum[0];
cptTcpHdrBuf->AckNum[1] = gptConn->RcvNum[1];
cptTcpHdrBuf->SeqNum[0] = gptConn->SeqNum[0];
cptTcpHdrBuf->SeqNum[1] = gptConn->SeqNum[1];
cptTcpHdrBuf->SrcPort = gptConn->LocalPort;
cptTcpHdrBuf->DestPort = gptConn->RemotePort;
cptIpHdrBuf->SrcIpAddr[0] = guwIpAddr[0];
cptIpHdrBuf->SrcIpAddr[1] = guwIpAddr[1];
cptIpHdrBuf->DestIpAddr[0] = gptConn->RemoteIpAddr[0];
cptIpHdrBuf->DestIpAddr[1] = gptConn->RemoteIpAddr[1];
// 如果應(yīng)用層要求停止數(shù)據(jù),協(xié)議層凍結(jié)窗口
if (gptConn->TcpStateFlags & cTCP_STOPPED){
cptTcpHdrBuf->WndSize = 0;
}
else{
// 通知遠(yuǎn)端本地重新開放窗口。由于本地RAM小,所以是靜態(tài)窗口
cptTcpHdrBuf->WndSize = cTCP_WS;
}
tcp_send_noconn: // 構(gòu)造IP頭
cptIpHdrBuf->Vhl = cIP_VER_HLEN;
cptIpHdrBuf->Tos = 0;
cptIpHdrBuf->Len = guwEthLen;
cptIpHdrBuf->IpId = ++guwIpId;
cptIpHdrBuf->Flags = cIP_DF; // Do not Fragment!
cptIpHdrBuf->Offset = 0;
cptIpHdrBuf->Ttl = cIP_TTL;
cptIpHdrBuf->Proto = cIP_PROTO_TCP;
// Calculate IP checksums.
cptIpHdrBuf->IpChkSum = 0;
cptIpHdrBuf->IpChkSum = ~checksum(2*cIpHdrLen, cpIpHdrBuf);
// Calculate TCP checksums.
cptTcpHdrBuf->Reserve = 0;
cptTcpHdrBuf->TcpChkSum = 0;
cptTcpHdrBuf->TcpChkSum = ~msip_TcpChkSum();
send: // 發(fā)生送IP包
msip_Arp_Out(pARP);
drop: // 釋放緩沖區(qū)
guwEthLen = 0;
return;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -