示例#1
0
/*
 * 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);
}
示例#2
0
/*
 * 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;
}
示例#3
0
/*
 * 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);
}