📄 tcpout.c
字号:
tcps.dwSndRexmitByte+=len; // Retransmit bytes
}
else
{
tcps.dwSndPack++; // Send packets
tcps.dwSndByte+=len; // Send bytes
}
// Copy in the payload (with PEEK flag set to "1")
SBRead( pt->hSBTx, len, off, pPayload, 0, 0, 1 );
// If sending the last bit of data, set the PSH flag
if( (len+off) == TxbTotal )
flags |= TCP_PSH;
}
else
{
//
// We're Not Sending Data
//
// Update the send type stats
if( pt->t_flags & TF_ACKNOW )
tcps.dwSndAcks++; // Peek ACKS sent
else if( flags & (TCP_SYN | TCP_FIN | TCP_RST) )
tcps.dwSndCtrl++; // Control packets sent
else if( SEQ_GT( pt->snd_up, pt->snd_una ) )
tcps.dwSndUrg++; // URG only packets else
else
tcps.dwSndWinUp++; // Window update packets
}
//
// Fill in TCP Header
//
// Set some TCP header stuff
pTcpHdr->HdrLen = (UINT8)(((TCPHDR_SIZE+optlen)>>2)<<4);
pTcpHdr->SrcPort = SockGetLPort(pt->hSock);
pTcpHdr->DstPort = SockGetFPort(pt->hSock);
//
// Fill in Sequence Numbers
//
// If resending a FIN make sure to use to old sequence number
if((flags&TCP_FIN) && (pt->t_flags&TF_SENTFIN) && (pt->snd_nxt==pt->snd_max))
pt->snd_nxt--;
// Since we may have resent data, snd_nxt can be less than snd_max. If
// we're sending data or SYN/FIN flag, we'll use snd_nxt. For status
// updates, we use snd_max.
if( len || (flags&(TCP_SYN|TCP_FIN)) )
dwTmp = HNC32(pt->snd_nxt);
else
dwTmp = HNC32(pt->snd_max);
WrNet32( &pTcpHdr->dwSeq, dwTmp );
#ifdef TCP_DEBUG
printf("Send %04X, F=%04X, S=%08lX, ",(int)pt,flags,HNC32(dwTmp));
printf("A=%08lX, ",pt->rcv_nxt);
#endif
dwTmp = HNC32(pt->rcv_nxt);
WrNet32( &pTcpHdr->dwAck, dwTmp );
// Copy in TCP header options
if( optlen )
mmCopy( pTcpHdr->Options, opt, (uint)optlen );
// Calculate Window Size
//
// If less than 25% free and can't take a full segent, close window
if( (win < SBGetMax(pt->hSBRx)/4) && (win < mss) )
win = 0;
// Don't shrink the window that's already been advertised
if( win < (INT32)(pt->rcv_adv - pt->rcv_nxt) )
win = (INT32)(pt->rcv_adv - pt->rcv_nxt);
pTcpHdr->WindowSize = HNC16(((uint)win));
#ifdef TCP_DEBUG
printf("L=%ld, W=%ld\n",len,win);
#endif
// Check for Urgent data
if( SEQ_GT( pt->snd_up, pt->snd_nxt ) )
{
dwTmp = pt->snd_up - pt->snd_nxt;
pTcpHdr->UrgPtr = HNC16(((uint)dwTmp));
flags |= TCP_URG;
}
else
{
// Keep "up" bumped over to the far left
pt->snd_up = pt->snd_una;
pTcpHdr->UrgPtr = 0;
}
// Now we can set flags
pTcpHdr->Flags = flags;
// Fixup packet frag info
dwTmp = len+TCPHDR_SIZE+optlen;
dwTmp = (UINT32)(HNC16(((uint)dwTmp)));
// Checksum Header
tpseudo.dwIPSrc = SockGetLIP(pt->hSock);
tpseudo.dwIPDst = SockGetFIP(pt->hSock);
tpseudo.Null = 0;
tpseudo.Protocol = 6;
tpseudo.Length = (UINT16)dwTmp;
TcpChecksum( pTcpHdr );
//
// The packet is all set to go, but we need to update some of
// our sequences and timers.
//
// If in persist state, just update snd_max
if( pt->t_flags & TF_PERSIST )
{
// Length is always 1
if( SEQ_GT( pt->snd_nxt+len, pt->snd_max ) )
pt->snd_max = pt->snd_nxt+len;
}
else
{
//
// Update sequences and timers
//
dwTmp = pt->snd_nxt; // Save this for later
// Advance snd_nxt
//
// SYN and FIN count as a squence byte
if( flags & TCP_SYN )
pt->snd_nxt++;
if( flags & TCP_FIN )
{
pt->snd_nxt++;
pt->t_flags |= TF_SENTFIN;
}
// Count actual payload bytes
pt->snd_nxt += len;
// If sending new data, bump snd_max, and potentially time
// segment
if( SEQ_GT( pt->snd_nxt, pt->snd_max ) )
{
pt->snd_max = pt->snd_nxt;
// If timer isn't going, time this sequence
if( !pt->t_trtt )
{
pt->t_trtt = 1;
pt->t_rttseq = dwTmp;
tcps.dwSegsTimed++;
}
}
// Set the Retransmit timer if not already set, unless we don't
// expect an ACK (snd_nxt == snd_una)
if( !pt->dwTicksRexmt && (pt->snd_nxt != pt->snd_una) )
{
pt->dwTicksRexmt = pt->t_trtx;
// Since we just sent a packet, we don't "persist"
if( pt->dwTicksPersist )
{
pt->dwTicksPersist = 0;
pt->t_rtxindex = 0;
}
}
}
// If we've advertised a larger window, remember it
if( win > 0 && SEQ_GT( pt->rcv_nxt + win, pt->rcv_adv ) )
pt->rcv_adv = pt->rcv_nxt + win;
// Clear ACK related flags
pt->t_flags &= ~(TF_NEEDOUTPUT|TF_ACKNOW|TF_DELACK|TF_PERSIST);
// Indicate the preferred route
PktSetRoute( hPkt, SockGetRoute( pt->hSock ) );
// Count it
tcps.dwSndTotal++;
// Send the packet
error = IPTxPacket( hPkt,
SockGetOptionFlags(pt->hSock) & FLG_IPTX_SOSUPPORTED );
// Handle error cases
if( error )
{
if( (error == EHOSTUNREACH || error == EHOSTDOWN) &&
pt->t_state >= TSTATE_SYNRCVD )
{
pt->t_softerror = error;
return( 0 );
}
return( error );
}
if( sendmore )
goto sendagain;
return(0);
}
//--------------------------------------------------------------------
// TcpGenPacket()
//
// Called to send quick and dirty TCP packets
//--------------------------------------------------------------------
void TcpGenPacket
(
TCPPROT *pt,
IPN dwIPDst,
uint PortDst,
IPN dwIPSrc,
uint PortSrc,
UINT32 ack,
UINT32 seq,
int flags
)
{
HANDLE hPkt,hFrag;
uint Offset,IPHdrLen,win;
UINT8 *pb;
TCPHDR *pTcpHdr;
IPHDR *pIpHdr;
if( !pt )
hPkt = SockCreatePacket( 0, 0, TCPHDR_SIZE);
else
hPkt = SockCreatePacket( pt->hSock, 0, TCPHDR_SIZE);
if( !hPkt )
return;
// Get the frag
hFrag = PktGetFrag( hPkt );
// Get the buffer parameters
pb = FragGetBufParams( hFrag, 0, 0, &Offset );
// Get the IP header len
IPHdrLen = PktGetSizeNet( hPkt );
// Assign an IP header pointer
pIpHdr = (IPHDR *)(pb + Offset);
// Assign a UDP header pointer
pTcpHdr = (TCPHDR *)(pb + Offset + IPHdrLen);
//
// Fill in TCP/IP Header
//
// Override some IP header stuff
pIpHdr->Protocol = 6;
WrNet32( &pIpHdr->dwIPSrc, dwIPSrc );
WrNet32( &pIpHdr->dwIPDst, dwIPDst );
// Set some TCP header stuff
pTcpHdr->HdrLen = TCPHDR_SIZE*4;
pTcpHdr->SrcPort = PortSrc;
pTcpHdr->DstPort = PortDst;
pTcpHdr->UrgPtr = 0;
seq = HNC32(seq);
WrNet32( &pTcpHdr->dwSeq, seq );
ack = HNC32(ack);
WrNet32( &pTcpHdr->dwAck, ack );
// Setup the window size we wish to advertise
// This is the space we have left in the RX buffer
if( !pt )
pTcpHdr->WindowSize = 0;
else
{
win = (uint)SBGetSpace(pt->hSBRx);
pTcpHdr->WindowSize = HNC16(win);
}
// Set flags
pTcpHdr->Flags = flags;
// Checksum Header
tpseudo.dwIPSrc = dwIPSrc;
tpseudo.dwIPDst = dwIPDst;
tpseudo.Null = 0;
tpseudo.Protocol = 6;
tpseudo.Length = HNC16(TCPHDR_SIZE);
TcpChecksum( pTcpHdr );
// Count it
tcps.dwSndTotal++;
// Send the packet
if( pt )
IPTxPacket( hPkt, SockGetOptionFlags(pt->hSock)&FLG_IPTX_SOSUPPORTED );
else
IPTxPacket( hPkt, 0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -