📄 tcp.c
字号:
if ( partialMatch == INVALID_SOCKET )
return UNKNOWN_SOCKET;
else
return INVALID_SOCKET;
}
/*********************************************************************
* Function: static void SwapTCPHeader(TCP_HEADER* header)
*
* PreCondition: None
*
* Input: header - TCP Header to be swapped.
*
* Output: Given header is swapped.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
static void SwapTCPHeader(TCP_HEADER* header)
{
header->SourcePort = swaps(header->SourcePort);
header->DestPort = swaps(header->DestPort);
header->SeqNumber = swapl(header->SeqNumber);
header->AckNumber = swapl(header->AckNumber);
header->Window = swaps(header->Window);
header->Checksum = swaps(header->Checksum);
header->UrgentPointer = swaps(header->UrgentPointer);
}
/*********************************************************************
* Function: static void CloseSocket(SOCKET_INFO* ps)
*
* PreCondition: TCPInit() is already called
*
* Input: ps - Pointer to a socket info that is to be
* closed.
*
* Output: Given socket information is reset and any
* buffer held by this socket is discarded.
*
* Side Effects: None
*
* Overview: None
*
* Note: None
********************************************************************/
static void CloseSocket(SOCKET_INFO* ps)
{
if ( ps->TxBuffer != INVALID_BUFFER )
{
MACDiscardTx(ps->TxBuffer);
ps->TxBuffer = INVALID_BUFFER;
ps->Flags.bIsPutReady = TRUE;
}
ps->remote.IPAddr.Val = 0x00;
ps->remotePort = 0x00;
if ( ps->Flags.bIsGetReady )
{
MACDiscardRx();
}
ps->Flags.bIsGetReady = FALSE;
ps->Flags.bACKValid = FALSE;
ps->TimeOut = TCP_START_TIMEOUT_VAL;
ps->Flags.bIsTxInProgress = FALSE;
if ( ps->Flags.bServer )
{
ps->smState = TCP_LISTEN;
}
else
{
ps->smState = TCP_CLOSED;
}
return;
}
/*********************************************************************
* Function: static void HandleTCPSeg(TCP_SOCKET s,
* NODE_INFO *remote,
* TCP_HEADER* h,
* WORD len)
*
* PreCondition: TCPInit() is already called AND
* TCPProcess() is the caller.
*
* Input: s - Socket that owns this segment
* remote - Remote node info
* 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 s,
NODE_INFO *remote,
TCP_HEADER *h,
WORD len)
{
DWORD ack;
DWORD seq;
DWORD prevAck, prevSeq;
SOCKET_INFO *ps;
BYTE flags;
flags = 0x00;
ps = &TCB[s];
// When you use TCPConnect() to connect to a remote socket, the
// SND_ACK socket parameter needs to be initialized to the first
// sequence number returned by the remote node.
if(!ps->Flags.bACKValid)
{
ps->SND_ACK = h->SeqNumber;
ps->Flags.bACKValid = TRUE;
}
/*
* Remember current seq and ack for our connection so that if
* we have to silently discard this packet, we can go back to
* previous ack and seq numbers.
*/
prevAck = ps->SND_ACK;
prevSeq = ps->SND_SEQ;
ack = h->SeqNumber;
ack += (DWORD)len;
seq = ps->SND_SEQ;
/*
* Clear retry counts and timeout tick counter.
*/
ps->RetryCount = 0;
ps->startTick = TickGet();
ps->TimeOut = TCP_START_TIMEOUT_VAL;
// Handle listening condition
if ( ps->smState == TCP_LISTEN )
{
MACDiscardRx();
ps->SND_SEQ = ++ISS;
ps->SND_ACK = ++ack;
seq = ps->SND_SEQ;
++ps->SND_SEQ;
if ( h->Flags.bits.flagSYN )
{
/*
* This socket has received connection request.
* Remember calling node, assign next segment seq. number
* for this potential connection.
*/
memcpy((void*)&ps->remote, (const void*)remote, sizeof(*remote));
ps->remotePort = h->SourcePort;
/*
* Grant connection request.
*/
flags = SYN | ACK;
ps->smState = TCP_SYN_RCVD;
}
else
{
/*
* Anything other than connection request is ignored in
* LISTEN state.
*/
flags = RST;
seq = ack;
ack = h->SeqNumber;
ps->remote.IPAddr.Val = 0x00;
}
}
// State is something other than TCP_LISTEN, handle it.
else
{
/*
* Reset FSM, if RST is received.
*/
if ( h->Flags.bits.flagRST )
{
MACDiscardRx();
CloseSocket(ps);
return;
}
// Check to see if the incomming sequence number is what
// we expect (last transmitted ACK value). Throw this packet
// away if it is wrong.
else if ( h->SeqNumber == prevAck )
{
// After receiving a SYNchronization request, we expect an
// ACK to our transmitted SYN
if ( ps->smState == TCP_SYN_RCVD )
{
if ( h->Flags.bits.flagACK )
{
// ACK received as expected, this connection is
// now established
ps->SND_ACK = ack;
ps->RetryCount = 0;
ps->startTick = TickGet();
ps->smState = TCP_EST;
// Check if this first packet has application data
// in it. Make it available if so.
if ( len > 0 )
{
ps->Flags.bIsGetReady = TRUE;
ps->RxCount = len;
ps->Flags.bFirstRead = TRUE;
}
else
MACDiscardRx();
}
else // No ACK to our SYN
{
MACDiscardRx();
}
}
#ifdef STACK_CLIENT_MODE
// The TCP_SYN_SENT state occurs when an application
// calls TCPConnect(). After an initial SYN is sent,
// we expect a SYN + ACK before establishing the
// connection.
else if ( ps->smState == TCP_SYN_SENT )
{
// Check if this is a SYN packet
if ( h->Flags.bits.flagSYN )
{
ps->SND_ACK = ++ack;
// Check if this is a ACK packet, and if so,
// establish the connection
if ( h->Flags.bits.flagACK )
{
flags = ACK;
ps->smState = TCP_EST;
}
// No ACK received yet, expect it next time.
else
{
// Send another SYNchronization request
flags = SYN | ACK;
ps->smState = TCP_SYN_RCVD;
ps->SND_SEQ = ++seq;
}
// Check for application data and make it
// available, if present
if ( len > 0 )
{
ps->Flags.bIsGetReady = TRUE;
ps->RxCount = len;
ps->Flags.bFirstRead = TRUE;
}
else // No application data in this packet
MACDiscardRx();
}
// No use for (unexpected) non-SYN packets, so discard
else
{
MACDiscardRx();
}
}
#endif
// Connection is established, closing, or otherwise
else
{
// Save the seq+len value of the packet for our future
// ACK transmission, and so out of sequence packets
// can be detected in the future.
ps->SND_ACK = ack;
// Handle packets received while connection established.
if ( ps->smState == TCP_EST )
{
// If this packet has the ACK set, mark all
// previous TX packets as no longer needed for
// possible retransmission.
if ( h->Flags.bits.flagACK )
{
if ( ps->TxBuffer != INVALID_BUFFER )
{
MACDiscardTx(ps->TxBuffer);
ps->TxBuffer = INVALID_BUFFER;
ps->Flags.bIsPutReady = TRUE;
}
}
// Check if the remote node is closing the connection
if ( h->Flags.bits.flagFIN )
{
flags = FIN | ACK;
seq = ps->SND_SEQ++;
ack = ++ps->SND_ACK;
ps->smState = TCP_LAST_ACK;
}
// Check if there is any application data in
// this packet.
if ( len > 0 )
{
// There is data. Make it available if we
// don't already have data available.
if ( !ps->Flags.bIsGetReady )
{
ps->Flags.bIsGetReady = TRUE;
ps->RxCount = len;
ps->Flags.bFirstRead = TRUE;
// 4/1/02
flags = ACK;
}
// There is data, but we cannot handle it at this time.
else
{
/*
* Since we cannot accept this packet,
* restore to previous seq and ack.
* and do not send anything back.
* Host has to resend this packet when
* we are ready.
*/
flags = 0x00;
ps->SND_SEQ = prevSeq;
ps->SND_ACK = prevAck;
MACDiscardRx();
}
}
// There is no data in this packet, and thus it
// can be thrown away.
else
{
MACDiscardRx();
}
}
// Connection is not established; check if we've sent
// a FIN and expect our last ACK
else if ( ps->smState == TCP_LAST_ACK )
{
MACDiscardRx();
if ( h->Flags.bits.flagACK )
{
CloseSocket(ps);
}
}
else if ( ps->smState == TCP_FIN_WAIT_1 )
{
MACDiscardRx();
if ( h->Flags.bits.flagFIN )
{
flags = ACK;
ack = ++ps->SND_ACK;
if ( h->Flags.bits.flagACK )
{
CloseSocket(ps);
}
else
{
ps->smState = TCP_CLOSING;
}
}
}
else if ( ps->smState == TCP_CLOSING )
{
MACDiscardRx();
if ( h->Flags.bits.flagACK )
{
CloseSocket(ps);
}
}
}
}
// This packet's sequence number does not match what we were
// expecting (the last value we ACKed). Throw this packet
// away. This may happen if packets are delivered out of order.
// Not enough memory is available on our PIC or Ethernet
// controller to implement a robust stream reconstruction
// buffer. As a result, the remote node will just have to
// retransmit its packets starting with the proper sequence number.
else
{
MACDiscardRx();
// Send a new ACK out in case if the previous one was lost
// (ACKs aren't ACKed). This is required to prevent an
// unlikely but possible situation which would cause the
// connection to time out if the ACK was lost and the
// remote node keeps sending us older data than we are
// expecting.
flags = ACK;
ack = prevAck;
}
}
if ( flags > 0x00 )
{
SendTCP(remote,
h->DestPort,
h->SourcePort,
seq,
ack,
flags);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -