📄 pctcp.c
字号:
break;
case tcp_StateESTAB:
case tcp_StateESTCL:
case tcp_StateCLOSWT:
/* handle lost SYN */
if ((flags & tcp_FlagSYN) && (flags & tcp_FlagACK)) {
tcp_send( s, __LINE__ );
return;
}
if ( !(flags & tcp_FlagACK)) return; /* must ack somthing */
#ifdef NOTUSED // S. Lawson - above two IFs make this impossible
if ( flags & tcp_FlagSYN ) {
tcp_rst( ip , tp );
return;
}
#endif
s->timeout = 0l; /* we do not timeout at this point */
/* process ack value in packet - but only if it falls
* within current window */
ldiff = intel( tp->acknum ) - s->seqnum;
diff = (int) ldiff;
if ( ldiff >= 0 && diff <= s->datalen ) {
s->datalen -= diff;
s->unacked -= diff;
if (s->datalen < 0) s->datalen = 0; /* remote proto error */
if ( s->queuelen ) {
s->queue += diff;
s->queuelen -= diff;
} else
movmem(s->data + diff, s->data, s->datalen );
s->seqnum += ldiff;
} else {
#ifdef DEBUG
if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
#endif// DEBUG
s->unacked = 0;
}
if (s->unacked < 0) s->unacked = 0;
s->flags = tcp_FlagACK;
tcp_ProcessData(s, tp, len, &ph, &flags); // S. Lawson
#ifdef NOTUSED
// S. Lawson - this chokes on some stacks. (data+fin) comes in, the
// FIN isn't ACK'd and they resend the whole segment rather than
// just the FIN (getting us back to not ACKing FIN on (data+fin)
if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
&& ( s->acknum == intel( tp->seqnum ))) {
#else
if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
&& s->frag[0]==0L) {
#endif
s->acknum ++;
if ( ! s->err_msg ) s->err_msg = "Connection closed";
s->state = tcp_StateCLOSWT;
tcp_send( s, __LINE__ );
s->timeout = set_timeout( LASTACK_TIMEOUT ); // Added AGW 6 Jan 2001
s->state = tcp_StateLASTACK;
s->flags |= tcp_FlagFIN;
s->unhappy = true;
}
/* S. Lawson - added per below
* Eliminate the spurious ACK messages bug.
* For the window update, the length should be the
* data length only, so exclude the TCP header size
* -- Joe <jdhagen@itis.com> (this helped alot -gv)
*/
len -= tcp_GetDataOffset(tp) << 2;
// S. Lawson - don't send on ACK unless there's more to send
// if ( diff > 0 || len > 0 ) {
if ( (diff > 0 && s->datalen) || len > 0 ) { // S. Lawson
/* need to update window, but how urgent ??? */
// S. Lawson if ( diff > 0 || (len > (s->mss >> 1))) {
if (s->frag[0] || (diff > 0 && s->datalen) || (len > (s->mss >> 1))) { // S. Lawson
tcp_send( s, __LINE__ );
} else
tcp_sendsoon( s );
}
if ( s->state == tcp_StateESTCL )
tcp_close( s );
return;
case tcp_StateFINWT1:
/* They have not necessarily read all the data yet, we must
still supply it as requested */
ldiff = intel( tp->acknum ) - s->seqnum;
diff = (int) ldiff;
if ( ldiff >= 0 && diff <= s->datalen ) {
s->datalen -= diff;
s->unacked -= diff;
if (s->datalen < 0) s->datalen = 0;
if ( s->queuelen ) {
s->queue += diff;
s->queuelen -= diff;
} else
movmem(s->data + diff, s->data, s->datalen );
s->seqnum += ldiff;
if (ldiff == 0 || s->unacked < 0) s->unacked = 0;
}
/* they may still be transmitting data, we must read it */
tcp_ProcessData(s, tp, len, &ph, &flags); // S. Lawson
/* check if other tcp has acked all sent data and is ready
to change states */
// S. Lawson if ( (flags & (tcp_FlagFIN|tcp_FlagACK) ) == (tcp_FlagFIN|tcp_FlagACK)) {
if ( s->frag[0]==0L && (flags & (tcp_FlagFIN|tcp_FlagACK) ) ==
(tcp_FlagFIN|tcp_FlagACK)) { // S. Lawson
#ifdef NOTUSED // S. Lawson - below is untrue, misses a condition, and moves
// to the wrong state anyway
/* trying to do similtaneous close */
if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
( intel( tp->seqnum) == s->acknum )) {
s->seqnum++;
// we shouldn't be inc'ing the ack
// s->acknum++;
s->flags = tcp_FlagACK;
tcp_send( s, __LINE__ );
s->unhappy = false;
s->timeout = set_timeout( 2 );
s->state = tcp_StateCLOSED;
}
#else
if ( intel( tp->seqnum) == s->acknum ) {
word next_state;
s->acknum++; // we must ACK their FIN!
if (( intel( tp->acknum ) >= s->seqnum + 1 )) {
// Not simultaneous close (they've ACKed our FIN)
// We need to ACK their FIN and move to TIME_WAIT
s->seqnum++;
next_state=tcp_StateTIMEWT;
} else {
// Simultaneous close (haven't ACKed our FIN yet)
// We need to ACK their FIN and move to CLOSING
next_state=tcp_StateCLOSING;
}
s->flags = tcp_FlagACK;
tcp_send( s, __LINE__ );
s->unhappy = false;
if ((s->state = next_state) == tcp_StateTIMEWT)
s->timeout = set_timeout( TW_TO );
else
s->timeout = set_timeout( tcp_TIMEOUT );
}
#endif
} else if ( flags & tcp_FlagACK ) {
/* other side is legitimately acking our fin */
if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
( intel( tp->seqnum ) == s->acknum ) &&
( s->datalen == 0 )) {
s->seqnum++;
// they are just acking our seq num, not sending more data for us to ack
// s->acknum++;
s->state = tcp_StateFINWT2;
s->timeout = set_timeout( tcp_TIMEOUT ); // S. Lawson
s->unhappy = false; /* we don't send anything */
}
}
break;
case tcp_StateFINWT2:
/* they may still be transmitting data, we must read it */
tcp_ProcessData(s, tp, len, &ph, &flags); // S. Lawson
if (s->frag[0] != 0L) break; // S. Lawson
if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
(tcp_FlagACK | tcp_FlagFIN)) {
if (( intel( tp->acknum ) == s->seqnum) &&
( intel( tp->seqnum ) == s->acknum )) {
s->acknum++;
s->flags = tcp_FlagACK;
tcp_send( s, __LINE__ );
s->unhappy = false; /* we don't send anything */
#ifdef NOTUSED // S. Lawson - move to TIME_WAIT, not CLOSED
s->timeout = set_timeout( 2 );
s->state = tcp_StateCLOSED;
#else
s->timeout = set_timeout( TW_TO );
s->state = tcp_StateTIMEWT;
#endif
return;
}
}
break;
case tcp_StateCLOSING:
if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
// S. Lawson - per FINWT1 above, tcp->acknum should be s->seqnum+1, which
// we should cause us to bump s->seqnum to match
// if (( tp->acknum == intel(s->seqnum) ) &&
//AGW if (( tp->acknum >= (intel(s->seqnum) + 1) ) && // S. Lawson
if ((laterthan(intel(tp->acknum),s->seqnum) ) && //AGW - moved intel() so +1 OK 6th Jan 2001
( tp->seqnum == intel(s->acknum))) {
s->seqnum++; // S. Lawson
s->state = tcp_StateTIMEWT;
s->timeout = set_timeout( TW_TO );
s->unhappy = false;
}
}
break;
case tcp_StateLASTACK:
if ( flags & tcp_FlagFIN )
{ /* they lost our two packets, back up */
s->flags = tcp_FlagACK | tcp_FlagFIN;
tcp_send( s, __LINE__ );
s->unhappy = TRUE; /* FALSE; */
return;
} else
{
// if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
if ((laterthan(intel(tp->acknum),s->seqnum) ) && // AGW allow for any later acks 6th Jan 2001
( intel( tp->seqnum ) == s->acknum ))
{
s->state = tcp_StateCLOSED; /* no 2msl necessary */
s->unhappy = false; /* we're done */
return;
}
}
break;
case tcp_StateTIMEWT:
if ( (flags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN)) {
/* he needs an ack */
s->flags = tcp_FlagACK;
tcp_send( s, __LINE__ );
s->unhappy = false;
s->state = tcp_StateCLOSED; /* support 2 msl in rst code */
}
break;
}
if (s->unhappy) tcp_sendsoon(s);
}
/*
* Process the data in an incoming packet.
* Called from all states where incoming data can be received: established,
* fin-wait-1, fin-wait-2
* S. Lawson - added flagsp so we can disable FIN with segment(s) missing
*/
static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len,
tcp_PseudoHeader *ph, word *flagsp)
{
long ldiff, tmpldiff; // S. Lawson
int diff, tmpdiff, x; // S. Lawson
word flags;
byte *dp;
// S. Lawson word *options, numoptions, opt_temp;
byte *options; // S. Lawson
word numoptions, opt_temp; // S. Lawson
if ( s->stress > 0 ) s->stress--;
if ( (s->window = intel16( tp->window )) > 0x7fff )
s->window = 0x7fff;
flags = intel16( tp->flags );
ldiff = s->acknum - intel( tp->seqnum );
if ( flags & tcp_FlagSYN ) ldiff--; /* back up to 0 */
diff = abs((int) ldiff); // S. Lawson - make positive
/* find the data portion */
x = tcp_GetDataOffset(tp) << 2; /* quadword to byte format */
dp = (byte *)tp + x;
/* process those options */
if ( (numoptions = x - sizeof( tcp_Header )) != 0 ) {
// S. Lawson options = (word *)((byte *)(tp) + sizeof( tcp_Header));
options = ((byte *)(tp) + sizeof( tcp_Header)); // S. Lawson
while ( numoptions-- > 0 ) {
switch ( *options++ ) {
case 0 : numoptions = 0; /* end of options */
break;
case 1 : break; /* nop */
/* we are very liberal on MSS stuff */
// S. Lawson - this is broken, *options includes type/len bytes
// case 2 : if (*options == 2) {
case 2 : if (*options == 4) {
opt_temp = intel16( *(word*)(&options[1]));
if (opt_temp < s->mss )
s->mss = opt_temp;
}
#ifdef NOTUSED // S. Lawson - this is broken, *options includes type/len
numoptions -= 2 + *options;
options += *options;
break;
#else
// S. Lawson - fallthrough (case 2),
// also skips unknown options (thanks GV)
default: // S. Lawson - handle 2 and others
numoptions -= (*options - 1);
options += (*options - 1);
break;
#endif
}
}
}
/* done option processing */
len -= x; /* remove the header length */
if ( ldiff >= 0 ) { /* skip already received bytes */
dp += diff;
len -= diff;
if (s->dataHandler) {
s->acknum += s->dataHandler(s, dp, len, ph, tp); // 94.11.19
// s->acknum += s->dataHandler(s, dp, len);
} else {
/* no handler, just dump to buffer, should be indexed, handles goofs */
/* limit receive size to our window */
if ( s->rdatalen >= 0 ) {
if ( len > ( x = s->maxrdatalen - s->rdatalen )) {
len = x;
}
// S. Lawson - no writing into fragment
if (s->frag[0] != 0L) {
tmpldiff=s->frag[0] - s->acknum;
tmpdiff= abs((int) tmpldiff);
if (tmpldiff>=0 && len>tmpdiff) len=tmpdiff;
}
if ( len > 0 ) {
s->acknum += len; /* our new ack begins at end of data */
movmem(dp, s->rdata + s->rdatalen, len );
s->rdatalen += len;
/*
s->karn_count = 3;
*/
}
// S. Lawson - see if we reached fragment
if (s->frag[0] != 0L) {
if (s->frag[0]==s->acknum) {
tmpldiff=s->frag[1] - s->acknum;
tmpdiff=abs((int) tmpldiff);
if (tmpldiff>0) {
s->rdatalen += tmpdiff;
s->acknum=s->frag[1];
}
s->frag[0]=s->frag[1]=0L;
}
}
}
}
s->unhappy = (s->datalen) ? true : false;
if (ldiff ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -