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,6 +329,8 @@ void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
329 329
 	conn->tcp_lstate = conn->tcp_state;
330 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 334
 	/* TODO: Check if this check is required */
333 335
 	if ( conn->tcp_lstate == conn->tcp_state || 
334 336
 	     conn->tcp_state == TCP_INVALID ) {
@@ -682,6 +684,7 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
682 684
 	tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
683 685
 	
684 686
 	/* Dump the TCP header */
687
+	tcp_dump ( tcphdr );
685 688
 
686 689
 	/* Start the timer */
687 690
 	if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
@@ -719,24 +722,22 @@ static int tcp_rx ( struct pk_buff *pkb,
719 722
 		goto done;
720 723
 	}
721 724
 
722
-
723 725
 	/* Process TCP header */
724 726
 	tcphdr = pkb->data;
725 727
 	tcp_dump ( tcphdr );
726 728
 
727 729
 	/* Verify header length */
728 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 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 741
 	/* TODO: Verify checksum */
741 742
 	
742 743
 	/* Demux TCP connection */
@@ -828,16 +829,19 @@ static int tcp_rx ( struct pk_buff *pkb,
828 829
 		/* Unexpected packet */
829 830
 		goto unexpected;
830 831
 	case TCP_ESTABLISHED:
831
-#if 0
832 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 839
 			/* FIN consumes one byte */
835 840
 			conn->rcv_nxt++;
836 841
 			conn->tcp_flags |= TCP_ACK;
837
-			/* Send an acknowledgement */
842
+			/* Send the packet */
838 843
 			goto send_tcp_nomsg;
839 844
 		}
840
-#endif
841 845
 		/* Packet might contain data */
842 846
 		break;
843 847
 	case TCP_FIN_WAIT_1:
@@ -901,60 +905,45 @@ static int tcp_rx ( struct pk_buff *pkb,
901 905
 	assert ( ( tcphdr->flags & TCP_ACK ) ||
902 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 911
 	if ( tcphdr->flags & TCP_ACK ) {
926 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 917
 			rc = 0;
930 918
 			goto done;
931 919
 		}
932
-		/* Advance snd stream */
920
+		/* Invoke the acked() callback */
933 921
 		conn->snd_una += acked;
934
-		/* Invoke the acked() callback function */
935 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 948
   send_tcp_nomsg:
960 949
 	free_pkb ( conn->tx_pkb );

Loading…
Cancel
Save