tcpin.c
来自「代码在ti的c67系列单片机上实现了完整的TCPIP协议栈」· C语言 代码 · 共 1,084 行 · 第 1/3 页
C
1,084 行
// Set the new socket state to LISTEN
pt->t_state = TSTATE_LISTEN;
AbortSpawnSocket = 1;
}
else
{
normal_resolve:
// Send to existing socket
hSock = SockPcbResolve( SOCKPROT_TCP, dwIPDst, (uint)pTcpHdr->DstPort,
dwIPSrc, (uint)pTcpHdr->SrcPort, SOCK_RESOLVE_EXACT );
if( !hSock )
goto dropwithreset;
pt = (TCPPROT *)SockGetTP( hSock );
if( !pt )
goto dropwithresetfatal;
}
//
// We now have a valid TCPROT* in pt, and a valid SOCK in hSock.
//
// If the state is closed, perform silent drop
if( pt->t_state == TSTATE_CLOSED )
goto drop;
// Since segment received, reset IDLE and KEEPALIVE
pt->t_tidle = 0;
pt->dwTicksKeep = TCPTV_KEEP_IDLE;
// Process Options
if( OptLen > 0 )
{
int i = 0;
INT8 opt,olen;
uint mss;
for( ; i < OptLen; i+=olen )
{
opt = pTcpHdr->Options[i];
if( opt == TCPOPT_EOL )
break;
if( opt == TCPOPT_NOP )
olen = 1;
else
{
olen = (INT8) pTcpHdr->Options[i+1];
if( opt == TCPOPT_MAXSEG )
{
if( olen == TCPOLEN_MAXSEG && (TcpFlags & TCP_SYN) )
{
// Get the MSS and notify our metrics routine
mss = pTcpHdr->Options[i+3]+pTcpHdr->Options[i+2]*256;
TcpValidateMetrics( pt, mss );
}
}
}
}
}
// Calc our receive window
win = SBGetSpace( pt->hSBRx );
if( win < 0 )
win = 0;
if( win < (INT32)(pt->rcv_adv - pt->rcv_nxt) )
win = (INT32)(pt->rcv_adv - pt->rcv_nxt);
//
// Handle LISTEN and SYNSENT special
//
if( pt->t_state == TSTATE_LISTEN )
{
//
// Socket is listening for a new connection
//
if( TcpFlags & TCP_RST )
goto drop;
if( TcpFlags & TCP_ACK )
goto dropwithreset;
if( !(TcpFlags & TCP_SYN) )
goto drop;
// RFC1122 - Discard SYN pkts sent via BCAST
if( PktGetFlags( hPkt ) & (FLG_PKT_MACBCAST | FLG_PKT_MACMCAST) )
goto drop;
// Initialize ISS
if( tmpseq )
pt->iss = tmpseq;
else
pt->iss = tcp_iss;
tcp_iss += TCP_ISSINCR / 2;
pt->snd_una = pt->snd_nxt = pt->snd_max = pt->snd_up = pt->iss;
// Initialize IRS
pt->irs = seq;
pt->rcv_adv = pt->rcv_nxt = pt->irs+1;
// Initialize the send window
pt->snd_wnd = (INT32)pTcpHdr->WindowSize;
// Set the new state
pt->t_flags |= TF_ACKNOW;
pt->t_state = TSTATE_SYNRCVD;
pt->dwTicksKeep = TCPTV_KEEP_INIT;
// Bump Stats
tcps.dwAccepts++;
// Try and get a route for this socket
TcpValidateMetrics( pt, 0 );
// Don't drop the (possibly) newly spawned socket
AbortSpawnSocket = 0;
goto continueSYN;
}
else if( pt->t_state == TSTATE_SYNSENT )
{
//
// Socket is connecting
//
// Check for an illegal ACK
if( (TcpFlags & TCP_ACK) &&
(SEQ_LEQ(ack, pt->iss) || SEQ_GT(ack, pt->snd_max)) )
goto dropwithreset;
// Check for refused connection
if( TcpFlags & TCP_RST )
{
// If ACK set (we know its OK at this point), send
// Connection Refused. Else we just drop the segment
if( TcpFlags & TCP_ACK )
TcpDrop( pt, ECONNREFUSED );
goto drop;
}
// Check for no SYN
if( !(TcpFlags & TCP_SYN) )
goto drop;
// Initialize IRS
pt->irs = seq;
pt->rcv_adv = pt->rcv_nxt = pt->irs+1;
// We ack the SYN no matter what...
pt->t_flags |= TF_ACKNOW;
// See if sender is ACK'ing. If not, enter the SYNRCVD state
if( !(TcpFlags & TCP_ACK) )
pt->t_state = TSTATE_SYNRCVD;
else
{
// We're connected
tcps.dwConnects++;
// Update ACK'd data
pt->snd_una = ack;
// Turn off retransmit timer
pt->dwTicksRexmt = 0;
// Set state
pt->t_state = TSTATE_ESTAB;
// Notify Socket
SockNotify( pt->hSock, SOCK_NOTIFY_CONNECT );
}
continueSYN:
// Force a window update (snd_wl1 will be < seq)
pt->snd_wl1 = seq;
// Advance Seq to account for the SYN
seq++;
// Trim data for fit our window
if( len > win )
{
len = win;
// If we trim, we can't have a FIN (we trimmed it!)
TcpFlags &= ~TCP_FIN;
}
// Init urgent data sequence number
pt->rcv_up = seq;
goto continueALL;
}
//
// The state is other than LISTEN or SYNSENT
//
//
// Drop duplicate data
//
todrop = pt->rcv_nxt - seq;
if( todrop > 0 )
{
// If there's a SYN, its one less byte to drop
if( TcpFlags & TCP_SYN )
{
// Skip SYN (we've already seen it)
TcpFlags &= ~TCP_SYN;
// Adjust seq to reflect elimination of SYN
seq++;
// Also adjust URG
if( TcpFlags & TCP_URG )
{
if( pTcpHdr->UrgPtr > 1 )
pTcpHdr->UrgPtr--;
else
TcpFlags &= ~TCP_URG;
}
// Now we don't drop as much
todrop--;
}
// See if entire packet is redundant
if( todrop > len ||
(todrop == len && !(TcpFlags & TCP_FIN)) )
{
//
// Duplicate packet
//
tcps.dwRcvDupPack++;
tcps.dwRcvDupByte += (UINT32)len;
// Set todrop to entire packet
todrop = len;
// Drop any DUP FIN
TcpFlags &= ~TCP_FIN;
// ACK now to resynch
pt->t_flags |= TF_ACKNOW;
}
else
{
// Partial dup packet
tcps.dwRcvPartDupPack++;
tcps.dwRcvPartDupByte += (UINT32)todrop;
}
// Now adjust the packet
seq += todrop;
len -= todrop;
Offset += (uint)todrop;
// Also adjust URG
if( TcpFlags & TCP_URG )
{
if( pTcpHdr->UrgPtr > (UINT16)todrop )
pTcpHdr->UrgPtr -= (UINT16)todrop;
else
TcpFlags &= ~TCP_URG;
}
}
//
// Can't receive data on a closed segment
//
if( pt->t_state > TSTATE_ESTAB && len &&
pt->t_state != TSTATE_FINWAIT1 && pt->t_state != TSTATE_FINWAIT2 )
{
TcpClose( pt );
tcps.dwRcvAfterClose++;
goto dropwithreset;
}
//
// Trim data to our window size
//
todrop = (seq + (UINT32)len) - (pt->rcv_nxt + win);
if( todrop > 0 )
{
tcps.dwRcvAfterWinPack++;
if( todrop < len )
tcps.dwRcvAfterWinByte += (UINT32)todrop;
else
{
// If this is a SYN request and we are in TIMEWAIT,
// we can close now and restart
if( (TcpFlags & TCP_SYN) &&
pt->t_state == TSTATE_TIMEWAIT &&
SEQ_GT( seq, pt->rcv_nxt ) )
{
tmpseq = pt->rcv_nxt + TCP_ISSINCR;
TcpClose( pt );
goto findpcb;
}
// If our window is closed and this is a single
// byte, then it is a probe. ACK it now.
if( !win && seq == pt->rcv_nxt )
{
pt->t_flags |= TF_ACKNOW;
tcps.dwRcvWinProbe++;
}
else
{
// This is simply bad data we send a RST
// unless the RST flag is set in this segment
goto dropafterack;
}
}
// Drop data past window
len -= todrop;
// Ignore PSH, and we must have trimmed off any FIN
TcpFlags &= ~(TCP_PSH|TCP_FIN);
}
//
// Process a RST
//
if( TcpFlags & TCP_RST )
{
// What we do is state dependent
// 1. Set error as required
// 2. Bump the Drops stat as needed
// 3. Proceed directly to CLOSED without passing GO
// 4. Drop the packet
switch( pt->t_state )
{
case TSTATE_SYNRCVD:
case TSTATE_ESTAB:
case TSTATE_FINWAIT1:
case TSTATE_FINWAIT2:
case TSTATE_CLOSEWAIT:
if( pt->t_state == TSTATE_SYNRCVD )
SockSetError( pt->hSock, ECONNREFUSED );
else
SockSetError( pt->hSock, ECONNRESET );
tcps.dwDrops++;
case TSTATE_CLOSING:
case TSTATE_LASTACK:
case TSTATE_TIMEWAIT:
TcpClose( pt );
goto drop;
}
}
//
// If we still have a SYN (i.e.: wasn't removed as a dup),
// then we've got problems
//
if( TcpFlags & TCP_SYN )
{
TcpDrop( pt, ECONNRESET );
goto dropwithreset;
}
//
// If the ACK bit isn't set at this point, then its an illegal packet
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?