Browse Source

Fixed a bug in the TCP state machine. Added a transition from ESTABLISHED to LAST_ACK on receiving a FIN,ACK

tags/v0.9.3
Nikhil Chandru Rao 18 years ago
parent
commit
dccb8358bd
1 changed files with 46 additions and 57 deletions
  1. 46
    57
      src/net/tcp.c

+ 46
- 57
src/net/tcp.c View File

329
 	conn->tcp_lstate = conn->tcp_state;
329
 	conn->tcp_lstate = conn->tcp_state;
330
 	conn->tcp_state = nxt_state;
330
 	conn->tcp_state = nxt_state;
331
 
331
 
332
+	DBG ( "Transition from %s to %s\n", tcp_states[conn->tcp_lstate], tcp_states[conn->tcp_state] );
333
+
332
 	/* TODO: Check if this check is required */
334
 	/* TODO: Check if this check is required */
333
 	if ( conn->tcp_lstate == conn->tcp_state || 
335
 	if ( conn->tcp_lstate == conn->tcp_state || 
334
 	     conn->tcp_state == TCP_INVALID ) {
336
 	     conn->tcp_state == TCP_INVALID ) {
682
 	tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
684
 	tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
683
 	
685
 	
684
 	/* Dump the TCP header */
686
 	/* Dump the TCP header */
687
+	tcp_dump ( tcphdr );
685
 
688
 
686
 	/* Start the timer */
689
 	/* Start the timer */
687
 	if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
690
 	if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
719
 		goto done;
722
 		goto done;
720
 	}
723
 	}
721
 
724
 
722
-
723
 	/* Process TCP header */
725
 	/* Process TCP header */
724
 	tcphdr = pkb->data;
726
 	tcphdr = pkb->data;
725
 	tcp_dump ( tcphdr );
727
 	tcp_dump ( tcphdr );
726
 
728
 
727
 	/* Verify header length */
729
 	/* Verify header length */
728
 	hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
730
 	hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
731
+	if ( hlen < sizeof ( *tcphdr ) ) {
732
+		DBG ( "Bad header length (%d bytes)\n", hlen );
733
+		rc = -EINVAL;
734
+		goto done;
735
+	}
736
+	/* TODO: Parse TCP options */
729
 	if ( hlen != sizeof ( *tcphdr ) ) {
737
 	if ( hlen != sizeof ( *tcphdr ) ) {
730
-		if ( hlen == sizeof ( *tcphdr ) + 4 ) {
731
-			DBG ( "TCP options sent\n" );
732
-		} else {
733
-			DBG ( "Bad header length (%d bytes)\n", hlen );
734
-			rc = -EINVAL;
735
-			goto done;
736
-		}
738
+		DBG ( "Ignoring TCP options\n" );
737
 	}
739
 	}
738
 
740
 
739
-
740
 	/* TODO: Verify checksum */
741
 	/* TODO: Verify checksum */
741
 	
742
 	
742
 	/* Demux TCP connection */
743
 	/* Demux TCP connection */
828
 		/* Unexpected packet */
829
 		/* Unexpected packet */
829
 		goto unexpected;
830
 		goto unexpected;
830
 	case TCP_ESTABLISHED:
831
 	case TCP_ESTABLISHED:
831
-#if 0
832
 		if ( tcphdr->flags & TCP_FIN ) {
832
 		if ( tcphdr->flags & TCP_FIN ) {
833
-			tcp_trans ( conn, TCP_CLOSE_WAIT );
833
+			if ( tcphdr->flags & TCP_ACK ) {
834
+				tcp_trans ( conn, TCP_LAST_ACK );
835
+				conn->tcp_flags |= TCP_FIN;
836
+			} else {
837
+				tcp_trans ( conn, TCP_CLOSE_WAIT );
838
+			}
834
 			/* FIN consumes one byte */
839
 			/* FIN consumes one byte */
835
 			conn->rcv_nxt++;
840
 			conn->rcv_nxt++;
836
 			conn->tcp_flags |= TCP_ACK;
841
 			conn->tcp_flags |= TCP_ACK;
837
-			/* Send an acknowledgement */
842
+			/* Send the packet */
838
 			goto send_tcp_nomsg;
843
 			goto send_tcp_nomsg;
839
 		}
844
 		}
840
-#endif
841
 		/* Packet might contain data */
845
 		/* Packet might contain data */
842
 		break;
846
 		break;
843
 	case TCP_FIN_WAIT_1:
847
 	case TCP_FIN_WAIT_1:
901
 	assert ( ( tcphdr->flags & TCP_ACK ) ||
905
 	assert ( ( tcphdr->flags & TCP_ACK ) ||
902
 		 pkb_len ( pkb ) > sizeof ( *tcphdr ) );
906
 		 pkb_len ( pkb ) > sizeof ( *tcphdr ) );
903
 
907
 
904
-	/* Check for new data */
905
-	toack = pkb_len ( pkb ) - hlen;
906
-	if ( toack > 0 ) {
907
-		/* Check if expected sequence number */
908
-		if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
909
-			conn->rcv_nxt += toack;
910
-			conn->tcp_op->newdata ( conn, pkb->data + hlen,
911
-						toack );
912
-		} else {
913
-			DBG ( "Unexpected sequence number %lx (wanted %lx)\n", 
914
-			      ntohl ( tcphdr->seq ), conn->rcv_nxt );
915
-		}
916
-
917
-		/* Acknowledge new data */
918
-		conn->tcp_flags |= TCP_ACK;
919
-		if ( !( tcphdr->flags & TCP_ACK ) ) {
920
-			goto send_tcp_nomsg;
921
-		}
922
-	}
923
-
924
-	/* Process ACK */
908
+	/**
909
+	 * Check if the received packet ACKs sent data
910
+	 */
925
 	if ( tcphdr->flags & TCP_ACK ) {
911
 	if ( tcphdr->flags & TCP_ACK ) {
926
 		acked = ntohl ( tcphdr->ack ) - conn->snd_una;
912
 		acked = ntohl ( tcphdr->ack ) - conn->snd_una;
927
-		if ( acked < 0 ) { /* TODO: Replace all uint32_t arith */
928
-			DBG ( "Previously ACKed (%d)\n", tcphdr->ack );
913
+		if ( acked < 0 ) {
914
+			/* Packet ACKs previously ACKed data */
915
+			DBG ( "Previously ACKed data %lx\n", 
916
+						ntohl ( tcphdr->ack ) );
929
 			rc = 0;
917
 			rc = 0;
930
 			goto done;
918
 			goto done;
931
 		}
919
 		}
932
-		/* Advance snd stream */
920
+		/* Invoke the acked() callback */
933
 		conn->snd_una += acked;
921
 		conn->snd_una += acked;
934
-		/* Invoke the acked() callback function */
935
 		conn->tcp_op->acked ( conn, acked );
922
 		conn->tcp_op->acked ( conn, acked );
936
-		/* Invoke the senddata() callback function */
937
-		tcp_senddata ( conn );
938
 	}
923
 	}
939
-
940
-	/* If the connection is in ESTABLISHED and it receives a FIN */
941
-	if ( conn->tcp_state == ESTABLISHED && ( tcphdr->flags & TCP_FIN ) ) {
942
-		if ( tcphdr->flags & TCP_ACK ) {
943
-			tcp_trans ( conn, TCP_LAST_ACK );
944
-			goto send_tcp_nomsg;
945
-		}
946
-		tcp_trans ( conn, TCP_CLOSE_WAIT );
947
-//		conn->tcp_op->closed ( conn, CONN_SNDCLOSE );	
948
-		conn->rcv_nxt++;
949
-		if ( ! ( tcphdr->flags & TCP_ACK ) ) {
950
-			conn->tcp_flags |= TCP_ACK;
951
-			/* Send an acknowledgement */
952
-			goto send_tcp_nomsg;
924
+	
925
+	/**
926
+	 * Check if packet contains new data
927
+	 */
928
+	toack = pkb_len ( pkb ) - hlen;
929
+	if ( toack >= 0 ) {
930
+		/* Check the sequence number */
931
+		if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
932
+			conn->rcv_nxt += toack;
933
+			conn->tcp_op->newdata ( conn,
934
+						pkb->data + hlen, toack );
935
+		} else {
936
+			DBG ( "Unexpected sequence number %lx (wanted %lx)\n",
937
+				ntohl ( tcphdr->ack ), conn->rcv_nxt );
953
 		}
938
 		}
954
-		/* Otherwise, the packet has been ACKed already */
939
+		conn->tcp_flags |= TCP_ACK;
955
 	}
940
 	}
956
-	rc = 0;
957
-	goto done;
941
+	
942
+	/**
943
+	 * Send data
944
+	 */
945
+	tcp_senddata ( conn );
946
+	return 0;
958
 
947
 
959
   send_tcp_nomsg:
948
   send_tcp_nomsg:
960
 	free_pkb ( conn->tx_pkb );
949
 	free_pkb ( conn->tx_pkb );

Loading…
Cancel
Save