Call closed() method only when the connection is genuinely in the

TCP_CLOSED state (i.e. after the final FIN/ACK exchange), and has been
removed from the list of TCP connections.
pull/1/head
Michael Brown 2006-12-05 22:53:28 +00:00
parent fcc70c9d60
commit cc0b92652f
1 changed files with 19 additions and 14 deletions

View File

@ -378,21 +378,27 @@ void tcp_init_conn ( struct tcp_connection *conn ) {
* @v over Failure indicator * @v over Failure indicator
*/ */
void tcp_expired ( struct retry_timer *timer, int over ) { void tcp_expired ( struct retry_timer *timer, int over ) {
struct tcp_connection *conn; struct tcp_connection *conn =
conn = ( struct tcp_connection * ) container_of ( timer, container_of ( timer, struct tcp_connection, timer );
struct tcp_connection, timer );
DBG ( "Timer expired in %s\n", tcp_states[conn->tcp_state] ); DBG ( "Timer expired in %s\n", tcp_states[conn->tcp_state] );
switch ( conn->tcp_state ) { switch ( conn->tcp_state ) {
case TCP_SYN_SENT: case TCP_SYN_SENT:
if ( over ) { if ( over ) {
list_del ( &conn->list );
tcp_trans ( conn, TCP_CLOSED ); tcp_trans ( conn, TCP_CLOSED );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, -ETIMEDOUT );
DBG ( "Timeout! Connection closed\n" ); DBG ( "Timeout! Connection closed\n" );
return; return;
} }
goto send_tcp_nomsg; goto send_tcp_nomsg;
case TCP_SYN_RCVD: case TCP_SYN_RCVD:
if ( over ) { if ( over ) {
list_del ( &conn->list );
tcp_trans ( conn, TCP_CLOSED ); tcp_trans ( conn, TCP_CLOSED );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, -ETIMEDOUT );
goto send_tcp_nomsg; goto send_tcp_nomsg;
} }
goto send_tcp_nomsg; goto send_tcp_nomsg;
@ -416,7 +422,10 @@ void tcp_expired ( struct retry_timer *timer, int over ) {
} }
return; return;
case TCP_TIME_WAIT: case TCP_TIME_WAIT:
list_del ( &conn->list );
tcp_trans ( conn, TCP_CLOSED ); tcp_trans ( conn, TCP_CLOSED );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, 0 );
return; return;
} }
/* Retransmit the data */ /* Retransmit the data */
@ -496,8 +505,6 @@ int tcp_close ( struct tcp_connection *conn ) {
case TCP_SYN_RCVD: case TCP_SYN_RCVD:
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
tcp_trans ( conn, TCP_FIN_WAIT_1 ); tcp_trans ( conn, TCP_FIN_WAIT_1 );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, CONN_SNDCLOSE ); /* TODO: Check! */
/* FIN consumes one byte on the snd stream */ /* FIN consumes one byte on the snd stream */
// conn->snd_una++; // conn->snd_una++;
goto send_tcp_nomsg; goto send_tcp_nomsg;
@ -511,12 +518,10 @@ int tcp_close ( struct tcp_connection *conn ) {
list_del ( &conn->list ); list_del ( &conn->list );
tcp_trans ( conn, TCP_CLOSED ); tcp_trans ( conn, TCP_CLOSED );
if ( conn->tcp_op->closed ) if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, CONN_SNDCLOSE ); conn->tcp_op->closed ( conn, 0 );
return 0; return 0;
case TCP_CLOSE_WAIT: case TCP_CLOSE_WAIT:
tcp_trans ( conn, TCP_LAST_ACK ); tcp_trans ( conn, TCP_LAST_ACK );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, CONN_SNDCLOSE ); /* TODO: Check! */
/* FIN consumes one byte on the snd stream */ /* FIN consumes one byte on the snd stream */
// conn->snd_una++; // conn->snd_una++;
goto send_tcp_nomsg; goto send_tcp_nomsg;
@ -715,8 +720,8 @@ static int tcp_rx ( struct pk_buff *pkb,
struct sockaddr_tcpip *st_dest __unused ) { struct sockaddr_tcpip *st_dest __unused ) {
struct tcp_connection *conn; struct tcp_connection *conn;
struct tcp_header *tcphdr; struct tcp_header *tcphdr;
uint32_t acked, toack; int32_t acked, toack;
int hlen; unsigned int hlen;
int rc; int rc;
/* Sanity check */ /* Sanity check */
@ -817,7 +822,7 @@ static int tcp_rx ( struct pk_buff *pkb,
if ( tcphdr->flags & TCP_RST ) { if ( tcphdr->flags & TCP_RST ) {
tcp_trans ( conn, TCP_LISTEN ); tcp_trans ( conn, TCP_LISTEN );
if ( conn->tcp_op->closed ) if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, CONN_RESTART ); conn->tcp_op->closed ( conn, -ECONNRESET );
rc = 0; rc = 0;
goto done; goto done;
} }
@ -855,9 +860,6 @@ static int tcp_rx ( struct pk_buff *pkb,
if ( tcphdr->flags & TCP_FIN ) { if ( tcphdr->flags & TCP_FIN ) {
conn->rcv_nxt++; conn->rcv_nxt++;
conn->tcp_flags |= TCP_ACK; conn->tcp_flags |= TCP_ACK;
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, CONN_SNDCLOSE );
if ( tcphdr->flags & TCP_ACK ) { if ( tcphdr->flags & TCP_ACK ) {
tcp_trans ( conn, TCP_TIME_WAIT ); tcp_trans ( conn, TCP_TIME_WAIT );
} else { } else {
@ -898,7 +900,10 @@ static int tcp_rx ( struct pk_buff *pkb,
break; break;
case TCP_LAST_ACK: case TCP_LAST_ACK:
if ( tcphdr->flags & TCP_ACK ) { if ( tcphdr->flags & TCP_ACK ) {
list_del ( &conn->list );
tcp_trans ( conn, TCP_CLOSED ); tcp_trans ( conn, TCP_CLOSED );
if ( conn->tcp_op->closed )
conn->tcp_op->closed ( conn, 0 );
rc = 0; rc = 0;
goto done; goto done;
} }