/* * Aborts a connection by sending a RST to the remote host and deletes * the local protocol control block. This is done when a connection is * killed because of shortage of memory. */ void tcp_abort (tcp_socket_t *s) { ip_t *ip = s->ip; unsigned long seqno, ackno; unsigned short remote_port, local_port; mutex_lock (&s->lock); /* Figure out on which TCP PCB list we are, and remove us. If we * are in an active state, send an RST to the remote end. */ if (s->state == TIME_WAIT) { tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&ip->lock); tcp_socket_remove (&ip->tcp_closing_sockets, s); mutex_unlock (&ip->lock); return; } seqno = s->snd_nxt; ackno = s->rcv_nxt; local_port = s->local_port; remote_port = s->remote_port; tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&ip->lock); tcp_socket_remove (&ip->tcp_sockets, s); tcp_socket_purge(s); tcp_debug ("tcp_abort: sending RST\n"); tcp_rst (ip, seqno, ackno, ipref_as_ucs(s->local_ip), s->remote_ip.ucs, local_port, remote_port); mutex_unlock (&ip->lock); }
/* * Closes the connection held by the PCB. * Return 1 on success, 0 on error. */ int tcp_close (tcp_socket_t *s) { mutex_lock (&s->lock); tcp_debug ("tcp_close: sock $%x state=%S\n", s, tcp_state_name (s->state)); switch (s->state) { default: /* Has already been closed. */ tcp_queue_free (s); mutex_unlock (&s->lock); return 1; case LISTEN: case SYN_SENT: tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&s->ip->lock); tcp_socket_remove (s->state == LISTEN ? &s->ip->tcp_listen_sockets : &s->ip->tcp_sockets, s); mutex_unlock (&s->ip->lock); return 1; case SYN_RCVD: case ESTABLISHED: case CLOSE_WAIT: break; } for (;;) { if (tcp_enqueue_option4 (s, TCP_FIN, 0)) break; mutex_wait (&s->lock); } s->state = (s->state == CLOSE_WAIT) ? LAST_ACK : FIN_WAIT_1; if (s->unsent || (s->flags & TF_ACK_NOW)) { #if TCP_LOCK_STYLE <= TCP_LOCK_SURE mutex_unlock (&s->lock); #endif tcp_output (s); #if TCP_LOCK_STYLE <= TCP_LOCK_SURE mutex_lock (&s->lock); #endif }//if (s->unsent || (s->flags & TF_ACK_NOW)) while (s->state != CLOSED) { if (s->state == TIME_WAIT && ! s->unsent) { tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&s->ip->lock); tcp_socket_remove (&s->ip->tcp_closing_sockets, s); mutex_unlock (&s->ip->lock); return 1; } mutex_wait (&s->lock); } mutex_unlock (&s->lock); return 1; }
/* * Aborts a connection by sending a RST to the remote host and deletes * the local protocol control block. This is done when a connection is * killed because of shortage of memory. */ void tcp_abort (tcp_socket_t *s) { ip_t *ip = s->ip; unsigned long seqno, ackno; unsigned short remote_port, local_port; unsigned char remote_ip[4], local_ip[4]; mutex_lock (&s->lock); /* Figure out on which TCP PCB list we are, and remove us. If we * are in an active state, send an RST to the remote end. */ if (s->state == TIME_WAIT) { tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&ip->lock); tcp_socket_remove (&ip->tcp_closing_sockets, s); mutex_unlock (&ip->lock); return; } seqno = s->snd_nxt; ackno = s->rcv_nxt; memcpy (local_ip, s->local_ip, 4); memcpy (remote_ip, s->remote_ip, 4); local_port = s->local_port; remote_port = s->remote_port; tcp_queue_free (s); mutex_unlock (&s->lock); mutex_lock (&ip->lock); tcp_socket_remove (&ip->tcp_sockets, s); if (s->unacked != 0) { tcp_segments_free (s->unacked); } if (s->unsent != 0) { tcp_segments_free (s->unsent); } tcp_debug ("tcp_abort: sending RST\n"); tcp_rst (ip, seqno, ackno, local_ip, remote_ip, local_port, remote_port); mutex_unlock (&ip->lock); }