tcpin.c
来自「代码在ti的c67系列单片机上实现了完整的TCPIP协议栈」· C语言 代码 · 共 1,084 行 · 第 1/3 页
C
1,084 行
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// TCPIN.C
//
// TCP In Functions
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "tcp.h"
//--------------------------------------------------------------------
// TcpAssembly()
//
// Assembled TCP Packets into the SB
//--------------------------------------------------------------------
static int TcpAssembly( TCPPROT *pt, HANDLE hFrag, UINT8 *pb )
{
UINT32 seq,eseq,off,len,seqT,eatseq,eatflag;
UINT8 *pbT;
HANDLE hFragT,hFragB;
seq = *(UINT32 *)pb;
eseq = *(UINT32 *)(pb+4);
off = *(UINT32 *)(pb+8);
eatflag = *(UINT32 *)(pb+12);
eatseq = *(UINT32 *)(pb+16);
len = eseq - seq;
// We shouldn't get here if the data is old, but check anyway.
if( SEQ_GEQ(pt->rcv_nxt, eseq) )
{
tcps.dwRcvDupPack++;
tcps.dwRcvDupByte += (eseq - seq);
// We don't want this Frag
return( 0 );
}
// If the seq is beyond us, we KNOW we can't assemble
// anything!
if( SEQ_GT(seq, pt->rcv_nxt) )
{
// Track out of order packets
tcps.dwRcvOOPack++;
tcps.dwRcvOOByte += len;
// We'll put it in order so we can reassemble accurately
if( !(hFragT = pt->hFrag) )
{
// Easy case - no other frags
pt->hFrag = hFrag;
}
else
{
hFragB = 0;
for(;;)
{
pbT = FragGetBufParams( hFrag, 0, 0, 0 );
seqT = *(UINT32 *)pbT;
if( SEQ_LT( seq, seqT ) )
break;
if( !FragGetNext(hFragT) )
break;
hFragB = hFragT;
hFragT = FragGetNext(hFragB);
}
if( SEQ_LEQ( seqT, seq ) )
{
// We go after this frag
FragSetNext( hFrag, FragGetNext(hFragT) );
FragSetNext( hFragT, hFrag );
}
else
{
// We go before hFragT and after hFragB, but we must
// trim our data to hFragT's seq since if there is
// an overlap, hFragT's data is older
if( SEQ_GT( eseq, seqT ) )
*(UINT32 *)(pb+4) = seqT; // eseq
FragSetNext( hFrag, hFragT );
if( !hFragB )
pt->hFrag = hFrag;
else
FragSetNext( hFragB, hFrag );
}
}
// We want this Frag
return( 1 );
}
else
{
// This frag contains data we want. Note it may also contain
// data duplicated in a held Frag. First, we'll trim it to
// any held frag
if( (hFragT = pt->hFrag) )
{
pbT = FragGetBufParams( hFragT, 0, 0, 0 );
seqT = *(UINT32 *)pbT;
if( SEQ_GT( eseq, seqT ) )
{
len -= ( eseq - seqT );
eseq = seqT;
}
}
for(;;)
{
//
// Now process our verified data
//
// Trim off leading data if necessary
if( SEQ_LT(seq, pt->rcv_nxt) )
{
off += (pt->rcv_nxt - seq);
len -= (pt->rcv_nxt - seq);
seq = pt->rcv_nxt;
// If we trimmed the eatseq, then the offset is really
// one byte "back".
if( eatflag && SEQ_GT(seq, eatseq) )
off--;
}
// Now ready to "receive"
tcps.dwRcvPack++;
tcps.dwRcvByte += len;
pt->rcv_nxt += len;
pt->t_flags |= TF_DELACK;
// If this frag contains an eatseq, then adjust the length
if( eatflag && SEQ_LEQ( seq, eatseq ) && SEQ_LEQ( eatseq, eseq ) )
len--;
// If any length left, copy the data to the SB
if( len )
SBWrite( pt->hSBRx, (INT32)len, pb+off, hFrag );
else
FragFree( hFrag );
// We will notify the socket at the end. Now, we'll search the
// frag list for data we can use - and always reset to the start
// if we will holes.
assemblyLoop:
// If no next frag to look at, break
if( !hFragT )
break;
// If not yet ready for this frag, break
if( SEQ_GT(seqT, pt->rcv_nxt) )
break;
// At this point, we KNOW we will consume the frag
// Get data on this frag
hFrag = hFragT;
pb = pbT;
seq = seqT;
eseq = *(UINT32 *)(pb+4);
off = *(UINT32 *)(pb+8);
eatflag = *(UINT32 *)(pb+12);
eatseq = *(UINT32 *)(pb+16);
len = eseq - seq;
// Get initial data on next frag
hFragT = pt->hFrag = FragGetNext( hFrag );
FragSetNext( hFrag, 0 );
if( hFragT )
{
pbT = FragGetBufParams( hFrag, 0, 0, 0 );
seqT = *(UINT32 *)pbT;
}
// Its possible (if not the first time though the loop) that
// this data is not needed
if( SEQ_GEQ(pt->rcv_nxt, eseq) )
{
tcps.dwRcvDupPack++;
tcps.dwRcvDupByte += (eseq - seq);
// We don't want this Frag (and neither does anyone else)
FragFree( hFrag );
// We keep trying though...
goto assemblyLoop;
}
// If we get this far, there's data to be appended.
// We'll loop back to the top of the loop to handle it
}
// When we get here, its time to nofity Socket
SockNotify( pt->hSock, SOCK_NOTIFY_RCVDATA );
// We consumed the Frag that was passed-in
return(1);
}
}
//--------------------------------------------------------------------
// TcpEnterTimeWait()
//
// TCP Connection enters TimeWait state
//--------------------------------------------------------------------
static void TcpEnterTimeWait( TCPPROT *pt )
{
pt->dwTicksRexmt = 0;
pt->dwTicksPersist = 0;
pt->dwTicksKeep = 0;
pt->dwTicksWait2 = 2 * TCPTV_MSL;
pt->t_state = TSTATE_TIMEWAIT;
SBFlush( pt->hSBTx, 1 );
SockNotify( pt->hSock, SOCK_NOTIFY_DISCONNECT );
}
//--------------------------------------------------------------------
// TcpInput()
//
// Rx TCP Packet
//--------------------------------------------------------------------
void TcpInput( HANDLE hPkt )
{
TCPPROT *pt;
HANDLE hFrag,hSock;
uint w,Offset,Valid,IPHdrLen,TCPLen;
IPN dwIPSrc,dwIPDst;
UINT8 *pb,TcpFlags;
IPHDR *pIpHdr;
TCPHDR *pTcpHdr;
int OptLen;
UINT32 ack,seq,tmpseq,eatseq,eatflag=0;
UINT32 *pVal;
INT32 len,win,todrop;
int AbortSpawnSocket = 0; // Set to abort spawned socket
int CallOutput = 0; // Set to force call to TcpOutput
int FinAcked = 0; // Set if our FIN was ACK'd
if( !(hFrag = PktGetFrag( hPkt )) )
{
DbgPrintf(DBG_ERROR,"TcpInput: No frag data");
PktFree( hPkt );
return;
}
// Get the size of the IP Header and pointer to our data
w = PktGetFlags( hPkt );
if( !(w & FLG_PKT_IP_VALID) || (w & FLG_PKT_LLC_VALID) )
{
DbgPrintf(DBG_ERROR,"TcpInput: Bad packet");
PktFree( hPkt );
return;
}
// Get the IP header len
IPHdrLen = PktGetSizeNet( hPkt );
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, &Valid, &Offset );
// Assign an IP header pointer
pIpHdr = (IPHDR *)(pb + Offset);
// Assign a TCP header pointer
pTcpHdr = (TCPHDR *)(pb + Offset + IPHdrLen);
// Count the total number of packets in
tcps.dwRcvTotal++;
// Get the total length of the TCP message
TCPLen = (uint)(HNC16( pIpHdr->TotalLen )) - IPHdrLen;
// Check for packet too small
if( TCPLen < TCPHDR_SIZE )
{
tcps.dwRcvShort++;
PktFree( hPkt );
return;
}
// Check for bad HdrLen
w = (pTcpHdr->HdrLen >> 4) << 2;
OptLen = (int)w - TCPHDR_SIZE; // Set OptLen = TCP Option Length
len = (INT32)(TCPLen - w); // Set len = TCP Payload Length
if( w < TCPHDR_SIZE || w > TCPLen )
{
tcps.dwRcvHdrSize++;
PktFree( hPkt );
return;
}
// We need some stuff for the pseudo header
//
// Get source and destination
dwIPSrc = RdNet32(&pIpHdr->dwIPSrc);
dwIPDst = RdNet32(&pIpHdr->dwIPDst);
// Save TCP Flags
TcpFlags = pTcpHdr->Flags;
// Record the Transport Header Size
PktSetSizeTP( hPkt, TCPLen );
PktSetFlagsSet( hPkt, FLG_PKT_TP_VALID );
// Init pseudo header for checksum
tpseudo.dwIPSrc = dwIPSrc;
tpseudo.dwIPDst = dwIPDst;
tpseudo.Null = 0;
tpseudo.Protocol = 6;
tpseudo.Length = HNC16(TCPLen);
// TCPLen is now the TCP header length
TCPLen = w;
// Verify checksum
w = (uint)pTcpHdr->TCPChecksum;
TcpChecksum( pTcpHdr );
if( w != (uint)pTcpHdr->TCPChecksum )
{
tcps.dwRcvBadSum++;
PktFree( hPkt );
return;
}
// Get readable seq and ack values
seq = RdNet32(&pTcpHdr->dwSeq);
seq = HNC32(seq);
ack = RdNet32(&pTcpHdr->dwAck);
ack = HNC32(ack);
// Convert 16 bit header values right in the header
pTcpHdr->WindowSize = HNC16(pTcpHdr->WindowSize);
pTcpHdr->UrgPtr = HNC16(pTcpHdr->UrgPtr);
tmpseq = 0; // This may get reset in another loop
findpcb:
//
// If this is a new SYN request, then we'll need to spawn a
// socket to accomodate it (assuming we're listening). Otherwise,
// we must have an exact match for this connection.
//
if( (TcpFlags & (TCP_SYN|TCP_ACK)) == TCP_SYN )
{
// New Connection Attempt
hSock = SockPcbResolve( SOCKPROT_TCP, dwIPDst, (uint)pTcpHdr->DstPort,
dwIPSrc, (uint)pTcpHdr->SrcPort, SOCK_RESOLVE_SPAWN );
// There's a chance that our first ACK was lost, so the sender may
// send another SYN. If this is the case, the SPAWN will fail, but
// the standard resolve will succeed
if( !hSock )
goto normal_resolve;
pt = (TCPPROT *)SockGetTP( hSock );
if( !pt )
goto dropwithresetfatal;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?