FreeBSD/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c
/*
 * User issued close, and wish to trail through shutdown states:
 * if never received SYN, just forget it.  If got a SYN from peer,
 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
 * If already got a FIN from peer, then almost done; go to LAST_ACK
 * state.  In all other cases, have already sent FIN to peer (e.g.
 * after PRU_SHUTDOWN), and just have to play tedious game waiting
 * for peer to send FIN or not respond to keep-alives, etc.
 * We can let the user exit from the close as soon as the FIN is acked.
 */
User issued close, and wish to trail through shutdown states:
if never received SYN, just forget it.  If got a SYN from peer,
but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
If already got a FIN from peer, then almost done; go to LAST_ACK
state.  In all other cases, have already sent FIN to peer , and just have to play tedious game waiting
for peer to send FIN or not respond to keep-alives, etc.
We can let the user exit from the close as soon as the FIN is acked.
User issued close and wish to trail through shutdown states : if never received SYN just forget it . If got a SYN from peer but haven ' t sent FIN then go to FIN_WAIT_1 state to send peer a FIN . If already got a FIN from peer then almost done ; go to LAST_ACK state . In all other cases have already sent FIN to peer and just have to play tedious game waiting for peer to send FIN or not respond to keep - alives etc . We can let the user exit from the close as soon as the FIN is acked .
static void
sdp_usrclosed(struct sdp_sock *ssk)
{
	SDP_WLOCK_ASSERT(ssk);
	switch (ssk->state) {
	case TCPS_LISTEN:
		ssk->state = TCPS_CLOSED;
		SDP_WUNLOCK(ssk);
		sdp_destroy_cma(ssk);
		SDP_WLOCK(ssk);
	case TCPS_CLOSED:
		ssk = sdp_closed(ssk);
		KASSERT(ssk != NULL,
		    ("sdp_usrclosed: sdp_closed() returned NULL"));
		break;
	case TCPS_SYN_SENT:
	case TCPS_SYN_RECEIVED:
		ssk->flags |= SDP_NEEDFIN;
		break;
	case TCPS_ESTABLISHED:
		ssk->flags |= SDP_NEEDFIN;
		ssk->state = TCPS_FIN_WAIT_1;
		break;
	case TCPS_CLOSE_WAIT:
		ssk->state = TCPS_LAST_ACK;
		break;
	}
	if (ssk->state >= TCPS_FIN_WAIT_2) {
		if (ssk->state == TCPS_FIN_WAIT_2)
			sdp_2msl_wait(ssk);
		else
			soisdisconnected(ssk->socket);
	}
}
static void sdp_usrclosed ( struct sdp_sock * ssk ) { SDP_WLOCK_ASSERT ( ssk ) ; switch ( ssk -> state ) { case TCPS_LISTEN : ssk -> state = TCPS_CLOSED ; SDP_WUNLOCK ( ssk ) ; sdp_destroy_cma ( ssk ) ; SDP_WLOCK ( ssk ) ; case TCPS_CLOSED : ssk = sdp_closed ( ssk ) ; KASSERT ( ssk != NULL , ( " " ) ) ; break ; case TCPS_SYN_SENT : case TCPS_SYN_RECEIVED : ssk -> flags |= SDP_NEEDFIN ; break ; case TCPS_ESTABLISHED : ssk -> flags |= SDP_NEEDFIN ; ssk -> state = TCPS_FIN_WAIT_1 ; break ; case TCPS_CLOSE_WAIT : ssk -> state = TCPS_LAST_ACK ; break ; } if ( ssk -> state >= TCPS_FIN_WAIT_2 ) { if ( ssk -> state == TCPS_FIN_WAIT_2 ) sdp_2msl_wait ( ssk ) ; else soisdisconnected ( ssk -> socket ) ; } }
User issued close, and wish to trail through shutdown states:
 if never received SYN, just forget it.
User issued close and wish to trail through shutdown states : if never received SYN just forget it .
/* FALLTHROUGH */ /*
		 * sdp_closed() should never return NULL here as the socket is
		 * still open.
		 */ /* FALLTHROUGH */ /* Prevent the connection hanging in FIN_WAIT_2 forever. */