📄 tcp.c
字号:
ps->Flags.bTimerEnabled = FALSE;
ps->remoteHash.Val = MyTCB.localPort.Val;
ps->txTail = ps->bufferTxStart;
ps->txHead = ps->bufferTxStart;
ps->rxTail = ps->bufferRxStart;
ps->rxHead = ps->bufferRxStart;
MyTCB.txUnackedTail = ps->bufferTxStart;
((DWORD_VAL*)(&MyTCB.MySEQ))->w[0] = rand();
((DWORD_VAL*)(&MyTCB.MySEQ))->w[1] = rand();
}
/*********************************************************************
* Function: static void HandleTCPSeg(TCP_SOCKET s,
* TCP_HEADER* h,
* WORD len)
*
* PreCondition: TCPInit() is already called AND
* TCPProcess() is the caller.
*
* Input: hTCP - Socket that owns this segment
* h - TCP Header
* len - Total buffer length.
*
* Output: TCP FSM is executed on given socket with
* given TCP segment.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
static void HandleTCPSeg(TCP_SOCKET hTCP,
TCP_HEADER *h,
WORD len)
{
DWORD dwTemp;
WORD wTemp;
TCB_STUB *ps;
BYTE flags;
ps = &TCBStubs[hTCP];
flags = 0x00;
// Reset FSM, if RST is received.
if(h->Flags.bits.flagRST)
{
SendTCP(hTCP, RST);
CloseSocket(hTCP);
MACDiscardRx();
return;
}
if ( h->SeqNumber == 751 )
h->SeqNumber = 751;
// Update the local stored copy of the RemoteWindow
MyTCB.remoteWindow = h->Window;
switch(ps->smState)
{
case TCP_LISTEN:
if(!h->Flags.bits.flagSYN)
{
SendTCP(hTCP, RST);
CloseSocket(hTCP);
break;
}
flags = SYN | ACK;
ps->smState = TCP_SYN_RECEIVED;
// Clear timeout info
MyTCB.retryCount = 0;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
ps->Flags.bTimerEnabled = TRUE;
// We now have a sequence number for the remote node
MyTCB.RemoteSEQ = h->SeqNumber + 1;
break;
case TCP_SYN_SENT:
if(!h->Flags.bits.flagSYN)
break;
if(h->Flags.bits.flagACK)
{
// If SYN+ACK, we may need to go to TCP_ESTABLISHED state
if(h->AckNumber == MyTCB.MySEQ)
{
flags = ACK;
ps->smState = TCP_ESTABLISHED;
ps->Flags.bTimerEnabled = FALSE;
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
}
else
{
// ACK number incorrect: ignore this packet
flags = RST;
break;
}
}
else
{
// Got SYN without ACK, need to go to TCP_SYN_RECEIVED state
flags = SYN | ACK;
ps->smState = TCP_SYN_RECEIVED;
// Clear timeout info
MyTCB.retryCount = 0;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
}
// We now have a sequence number for the remote node
MyTCB.RemoteSEQ = h->SeqNumber + 1;
break;
case TCP_SYN_RECEIVED:
if(h->Flags.bits.flagACK && (h->AckNumber == MyTCB.MySEQ))
{
ps->smState = TCP_ESTABLISHED;
ps->Flags.bTimerEnabled = FALSE;
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
}
break;
case TCP_ESTABLISHED:
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
// Handle any requests to close the connection
if(h->Flags.bits.flagFIN)
{
MyTCB.RemoteSEQ++;
if(len == 0u)
{
flags = FIN | ACK;
MyTCB.MySEQ++;
ps->smState = TCP_LAST_ACK;
}
else
{
// Don't send a FIN back immediately. The application
// may want to send a little bit more data before closing
// the socket.
flags = ACK;
ps->smState = TCP_CLOSE_WAIT;
}
// Clear timeout info
MyTCB.retryCount = 0;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
ps->Flags.bTimerEnabled = TRUE;
}
break;
case TCP_FIN_WAIT_1:
if(h->Flags.bits.flagFIN && h->Flags.bits.flagACK && (h->AckNumber == MyTCB.MySEQ))
{
MyTCB.RemoteSEQ++;
flags = ACK;
ps->smState = TCP_TIME_WAIT;
ps->eventTime = TickGet() + TCP_TIME_WAIT_TIMEOUT_VAL;
}
else if(h->Flags.bits.flagACK && (h->AckNumber == MyTCB.MySEQ))
{
ps->smState = TCP_FIN_WAIT_2;
}
else if(h->Flags.bits.flagFIN)
{
MyTCB.RemoteSEQ++;
flags = ACK;
ps->smState = TCP_CLOSING;
// Clear timeout info
MyTCB.retryCount = 0;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
}
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
break;
case TCP_FIN_WAIT_2:
if(h->Flags.bits.flagFIN)
{
MyTCB.RemoteSEQ++;
flags = ACK;
ps->smState = TCP_TIME_WAIT;
ps->eventTime = TickGet() + TCP_TIME_WAIT_TIMEOUT_VAL;
}
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
break;
case TCP_CLOSING:
if(h->Flags.bits.flagACK && (h->AckNumber == MyTCB.MySEQ))
{
ps->smState = TCP_TIME_WAIT;
ps->eventTime = TickGet() + TCP_TIME_WAIT_TIMEOUT_VAL;
}
// Check for application data and make it
// available, if present
if(len)
{
dwTemp = MyTCB.RemoteSEQ - h->SeqNumber;
if(((LONG)dwTemp >= 0) && ((LONG)((DWORD)len - dwTemp) > 0))
{
len -= (WORD)dwTemp;
// Calculate the lesser of RX buffer space and new packet data length
if(ps->rxHead >= ps->rxTail)
wTemp = (ps->bufferEnd - ps->bufferRxStart) - (ps->rxHead - ps->rxTail);
else
wTemp = ps->rxTail - ps->rxHead - 1;
if(wTemp < len)
len = wTemp;
if(len)
{
// Position packet read pointer to start of useful data area.
IPSetRxBuffer((h->DataOffset.Val << 2) + (WORD)dwTemp);
flags |= ACK;
// See if we need a two part copy (spans bufferEnd->bufferRxStart)
if(ps->rxHead + len > ps->bufferEnd)
{
wTemp = ps->bufferEnd - ps->rxHead + 1;
MACMemCopyAsync(ps->rxHead, -1, wTemp);
len -= wTemp;
MyTCB.RemoteSEQ += wTemp;
ps->rxHead = ps->bufferRxStart;
}
MACMemCopyAsync(ps->rxHead, -1, len);
ps->rxHead += len;
MyTCB.RemoteSEQ += (DWORD)len;
}
}
}
break;
case TCP_CLOSE_WAIT:
flags = ACK;
break;
case TCP_LAST_ACK:
if(h->Flags.bits.flagACK && (h->AckNumber == MyTCB.MySEQ))
{
CloseSocket(hTCP);
}
break;
case TCP_TIME_WAIT:
flags = RST;
break;
}
// Throw away all ACKnowledged TX data
if(h->Flags.bits.flagACK && ps->smState != TCP_CLOSED && ps->smState != TCP_LISTEN)
{
// Calculate what the last acknowledged sequence number was
dwTemp = MyTCB.MySEQ - (LONG)(SHORT)(MyTCB.txUnackedTail - ps->txTail);
if(MyTCB.txUnackedTail < ps->txTail)
dwTemp -= ps->bufferRxStart - ps->bufferTxStart;
dwTemp = h->AckNumber - dwTemp;
if((LONG)(dwTemp) > 0)
{
ps->txTail += dwTemp;
if(ps->txTail >= ps->bufferRxStart)
{
ps->txTail -= ps->bufferRxStart - ps->bufferTxStart;
}
}
}
while(!MACIsMemCopyDone());
MACDiscardRx();
if(flags)
SendTCP(hTCP, flags);
}
#endif //#if defined(STACK_USE_TCP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -