📄 tcp.c
字号:
ps = &TCBStubs[hTCP];
LoadTCB(hTCP);
if(ps->txHead != MyTCB.txUnackedTail)
{
SendTCP(hTCP, PSH | ACK);
// Clear timeout info
MyTCB.retryCount = 0;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
ps->eventTime = TickGet() + TCP_START_TIMEOUT_VAL;
ps->Flags.bTimerEnabled = TRUE;
}
SaveTCB(hTCP);
}
/*********************************************************************
* Function: WORD TCPIsPutReady(TCP_SOCKET hTCP)
*
* PreCondition: TCPInit() is already called.
*
* Input: hTCP: handle of socket to test
*
* Output: Number of bytes that can be immediately placed
* in the transmit buffer.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPIsPutReady(TCP_SOCKET hTCP)
{
TCB_STUB *ps;
ps = &TCBStubs[hTCP];
if(ps->txHead >= ps->txTail)
return (ps->bufferRxStart - ps->bufferTxStart - 1) - (ps->txHead - ps->txTail);
else
return ps->txTail - ps->txHead - 1;
}
/*********************************************************************
* Function: BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
*
* PreCondition: TCPIsPutReady(s) != 0
*
* Input: hTCP: socket handle to use
* byte: a data byte to send
*
* Output: TRUE if given byte was put in transmit buffer
* FALSE if transmit buffer is full.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
{
TCB_STUB *ps;
WORD wFreeTXSpace;
ps = &TCBStubs[hTCP];
wFreeTXSpace = TCPIsPutReady(hTCP);
if(!wFreeTXSpace)
{
TCPFlush(hTCP);
return FALSE;
}
/***
if(wFreeTXSpace == 0u)
return FALSE;
else if(wFreeTXSpace == 1u) // About to run out of space, lets transmit so the remote node might send an ACK back faster
TCPFlush(hTCP);
***/
MACSetWritePtr(ps->txHead);
MACPut(byte);
if(++ps->txHead >= ps->bufferRxStart)
ps->txHead = ps->bufferTxStart;
// Send the last byte as a separate packet (likely will make the remote node send back ACK faster)
if(wFreeTXSpace == 1u)
TCPFlush(hTCP);
return TRUE;
}
/*********************************************************************
* Function: WORD TCPPutArray(TCP_SOCKET hTCP, BYTE *data, WORD len)
*
* PreCondition: None
*
* Input: hTCP - Socket handle to use
* data - Pointer to data to put
* len - Count of bytes to put
*
* Output: Count of bytes actually placed in the TX buffer
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPPutArray(TCP_SOCKET hTCP, BYTE *data, WORD len)
{
WORD wActualLen;
WORD wFreeTXSpace;
WORD wRightLen = 0;
TCB_STUB *ps;
ps = &TCBStubs[hTCP];
wFreeTXSpace = TCPIsPutReady(hTCP);
if(wFreeTXSpace == 0u)
{
TCPFlush(hTCP);
return 0;
}
wActualLen = wFreeTXSpace;
if(wFreeTXSpace > len)
wActualLen = len;
// See if we need a two part put
if(ps->txHead + wActualLen >= ps->bufferRxStart)
{
wRightLen = ps->bufferRxStart-ps->txHead;
MACSetWritePtr(ps->txHead);
MACPutArray(data, wRightLen);
data += wRightLen;
wActualLen -= wRightLen;
ps->txHead = ps->bufferTxStart;
}
MACSetWritePtr(ps->txHead);
MACPutArray(data, wActualLen);
ps->txHead += wActualLen;
// Send these bytes right now if we are out of TX buffer space
if(wFreeTXSpace <= len)
TCPFlush(hTCP);
return wActualLen + wRightLen;
}
// Note: This function is slow. Performance could be enhanced
// if the array was copied into RAM and then TCPPutArray() was
// called instead.
WORD TCPPutROMArray(TCP_SOCKET hTCP, ROM BYTE *data, WORD len)
{
WORD wActualLen;
wActualLen = TCPIsPutReady(hTCP);
if(wActualLen > len)
wActualLen = len;
len = wActualLen;
while(len--)
{
TCPPut(hTCP, *data++);
}
return wActualLen;
}
/*********************************************************************
* Function: WORD TCPPutString(TCP_SOCKET hTCP, BYTE *data)
*
* PreCondition: None
*
* Input: hTCP - Socket handle to use
* data - Pointer to null terminated string to put
*
* Output: Count of bytes actually placed in the TX buffer
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPPutString(TCP_SOCKET hTCP, BYTE *data)
{
return TCPPutArray(hTCP, data, strlen(data));
}
// Note: This function is slow. Performance could be enhanced
// if the string was copied into RAM and then TCPPutString() was
// called instead.
WORD TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE *data)
{
WORD len = 0;
while(*data)
{
if(TCPPut(hTCP, *data++))
len++;
else
break;
}
return len;
}
/*********************************************************************
* Function: void TCPDiscard(TCP_SOCKET hTCP)
*
* PreCondition: TCPInit() is already called.
*
* Input: hTCP - socket handle
*
* Output: None
*
* Side Effects: None
*
* Overview: Removes all pending data from the socket's RX
* buffer.
*
* Note: None
********************************************************************/
void TCPDiscard(TCP_SOCKET hTCP)
{
TCB_STUB *ps;
ps = &TCBStubs[hTCP];
LoadTCB(hTCP);
// Delete all data in the RX buffer
ps->rxTail = ps->rxHead;
// Send a Window update message to the remote node
SendTCP(hTCP, ACK);
SaveTCB(hTCP);
}
/*********************************************************************
* Function: WORD TCPIsGetReady(TCP_SOCKET hTCP)
*
* PreCondition: TCPInit() is already called.
*
* Input: hTCP - socket to test
*
* Output: Number of bytes that are available in socket 'hTCP'
* for immediate retrieval
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPIsGetReady(TCP_SOCKET hTCP)
{
TCB_STUB *ps;
ps = &TCBStubs[hTCP];
if(ps->rxHead == ps->rxTail)
return 0;
else if(ps->rxHead > ps->rxTail)
return ps->rxHead - ps->rxTail;
else
return (ps->bufferEnd - ps->rxTail + 1) + (ps->rxHead - ps->bufferRxStart);
}
/*********************************************************************
* Function: BOOL TCPGet(TCP_SOCKET hTCP, BYTE *byte)
*
* PreCondition: TCPInit() is already called
*
* Input: hTCP - socket
* byte - Pointer to a byte.
*
* Output: TRUE if a byte was read.
* FALSE if byte was not read.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
BOOL TCPGet(TCP_SOCKET hTCP, BYTE *byte)
{
TCB_STUB *ps;
WORD GetReadyCount;
GetReadyCount = TCPIsGetReady(hTCP);
if(GetReadyCount == 0u)
return FALSE;
ps = &TCBStubs[hTCP];
MACSetReadPtr(ps->rxTail);
*byte = MACGet();
if(++ps->rxTail > ps->bufferEnd)
ps->rxTail = ps->bufferRxStart;
// Send a window update if we've run out of data
if(GetReadyCount == 1u)
{
LoadTCB(hTCP);
SendTCP(hTCP, ACK);
SaveTCB(hTCP);
}
return TRUE;
}
/*********************************************************************
* Function: WORD TCPGetArray(TCP_SOCKET hTCP, BYTE *buffer,
* WORD len)
*
* PreCondition: TCPInit() is already called
*
* Input: hTCP - socket handle
* buffer - Buffer to hold received data.
* len - Buffer length
*
* Output: Number of bytes loaded into buffer.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPGetArray(TCP_SOCKET hTCP, BYTE *buffer, WORD len)
{
WORD ActualLen;
WORD RightLen = 0;
TCB_STUB *ps;
ps = &TCBStubs[hTCP];
ActualLen = TCPIsGetReady(hTCP);
if(ActualLen > len)
ActualLen = len;
// See if we need a two part get
if(ps->rxTail + ActualLen > ps->bufferEnd)
{
RightLen = ps->bufferEnd - ps->rxTail + 1;
MACSetReadPtr(ps->rxTail);
MACGetArray(buffer, RightLen);
buffer += RightLen;
ActualLen -= RightLen;
ps->rxTail = ps->bufferRxStart;
}
MACSetReadPtr(ps->rxTail);
MACGetArray(buffer, ActualLen);
ps->rxTail += ActualLen;
return ActualLen + RightLen;
}
/*********************************************************************
* Function: WORD TCPGetString(TCP_SOCKET hTCP, BYTE *buffer,
* WORD len)
*
* PreCondition: TCPInit() is already called
*
* Input: hTCP - socket handle
* buffer - Buffer to hold received data.
* len - Buffer length
*
* Output: Number of bytes loaded into buffer, not including the null terminator
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
WORD TCPGetString(TCP_SOCKET hTCP, BYTE *buffer, WORD len)
{
WORD ActualLen = 0;
TCPGet(hTCP, buffer);
while(*buffer)
{
ActualLen++;
TCPGet(hTCP, ++buffer);
}
return ActualLen;
}
/*********************************************************************
* Function: void TCPTick(void)
*
* PreCondition: TCPInit() is already called.
*
* Input: None
*
* Output: Each socket FSM is executed for any timeout
* situation.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
void TCPTick(void)
{
TCP_SOCKET hTCP;
TCB_STUB *ps;
DWORD SEQSave;
// Periodically all "not closed" sockets must perform timed operations
for(hTCP = 0; hTCP < MAX_TCP_SOCKETS; hTCP++)
{
ps = &TCBStubs[hTCP];
// The TCP_CLOSED, TCP_LISTEN, and sometimes the TCP_ESTABLISHED
// state don't need any timeout events
if(!ps->Flags.bTimerEnabled)
continue;
// If timeout has not occured, do not do anything.
if((signed)(TickGet() - ps->eventTime) < 0)
continue;
// Load up extended MyTCB information
LoadTCB(hTCP);
// This will be one more attempt.
MyTCB.retryCount++;
// Update timeout value if there is need to wait longer.
MyTCB.retryInterval <<= 1;
// Restart timeout reference.
ps->eventTime = TickGet() + MyTCB.retryInterval;
// A timeout has occured. Respond to this timeout condition
// depending on what state this socket is in.
switch(ps->smState)
{
case TCP_SYN_SENT:
// Keep sending SYN until we hear from remote node.
// This may be for infinite time, in that case
// caller must detect it and do something.
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
MyTCB.retryCount = 0;
SendTCP(hTCP, SYN);
break;
case TCP_SYN_RECEIVED:
// We must receive ACK before timeout expires.
// If not, resend SYN+ACK.
// Abort, if maximum attempts counts are reached.
if(MyTCB.retryCount <= MAX_RETRY_COUNTS)
{
SendTCP(hTCP, SYN | ACK);
}
else
{
if(ps->Flags.bServer)
{
SendTCP(hTCP, RST);
CloseSocket(hTCP);
}
else
{
ps->smState = TCP_SYN_SENT;
MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
MyTCB.retryCount = 0;
SendTCP(hTCP, SYN);
}
}
break;
case TCP_ESTABLISHED:
// Retransmit any unacknowledged data
if(MyTCB.retryCount <= MAX_RETRY_COUNTS)
{
SEQSave = MyTCB.MySEQ;
// Roll back unacknowledged TX tail pointer
MyTCB.MySEQ -= (LONG)(SHORT)(MyTCB.txUnackedTail - ps->txTail);
if(MyTCB.txUnackedTail < ps->txTail)
MyTCB.MySEQ -= (LONG)(SHORT)(ps->bufferRxStart - ps->bufferTxStart);
MyTCB.txUnackedTail = ps->txTail;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -