Skip to content

Commit

Permalink
Cleanup graceful shutdown of the peer
Browse files Browse the repository at this point in the history
  • Loading branch information
tuexen committed Aug 19, 2023
1 parent 226c026 commit 54af901
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 97 deletions.
96 changes: 15 additions & 81 deletions usrsctplib/netinet/sctp_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,8 +916,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
struct socket *so;
#endif

SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown: handling SHUTDOWN\n");
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_shutdown: handling SHUTDOWN\n");
if (stcb == NULL)
return;
asoc = &stcb->asoc;
Expand All @@ -934,56 +933,11 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
if (*abort_flag) {
return;
}
if (asoc->control_pdapi) {
/* With a normal shutdown
* we assume the end of last record.
*/
SCTP_INP_READ_LOCK(stcb->sctp_ep);
if (asoc->control_pdapi->on_strm_q) {
struct sctp_stream_in *strm;

strm = &asoc->strmin[asoc->control_pdapi->sinfo_stream];
if (asoc->control_pdapi->on_strm_q == SCTP_ON_UNORDERED) {
/* Unordered */
TAILQ_REMOVE(&strm->uno_inqueue, asoc->control_pdapi, next_instrm);
asoc->control_pdapi->on_strm_q = 0;
} else if (asoc->control_pdapi->on_strm_q == SCTP_ON_ORDERED) {
/* Ordered */
TAILQ_REMOVE(&strm->inqueue, asoc->control_pdapi, next_instrm);
asoc->control_pdapi->on_strm_q = 0;
#ifdef INVARIANTS
} else {
panic("Unknown state on ctrl:%p on_strm_q:%d",
asoc->control_pdapi,
asoc->control_pdapi->on_strm_q);
#endif
}
}
asoc->control_pdapi->end_added = 1;
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
#if defined(__APPLE__) && !defined(__Userspace__)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
if (stcb->sctp_socket) {
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
}
#if defined(__APPLE__) && !defined(__Userspace__)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* goto SHUTDOWN_RECEIVED state to block new requests */
/*
* FIXME MT: Handle the case where there are still incomplete received
* user messages or known missing user messages from the peer.
* One way to handle this is to abort the associations in this case.
*/
if (stcb->sctp_socket) {
if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
(SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
Expand Down Expand Up @@ -1044,9 +998,10 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
so = SCTP_INP_SO(stcb->sctp_ep);
#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
if (stcb == NULL)
"sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
if (stcb == NULL) {
return;
}

asoc = &stcb->asoc;
/* process according to association state */
Expand All @@ -1063,32 +1018,11 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
SCTP_TCB_UNLOCK(stcb);
return;
}
if (asoc->control_pdapi) {
/* With a normal shutdown
* we assume the end of last record.
*/
SCTP_INP_READ_LOCK(stcb->sctp_ep);
asoc->control_pdapi->end_added = 1;
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
#if defined(__APPLE__) && !defined(__Userspace__)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined(__APPLE__) && !defined(__Userspace__)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/*
* FIXME MT: Handle the case where there are still incomplete received
* user messages or known missing user messages from the peer.
* One way to handle this is to abort the associations in this case.
*/
#ifdef INVARIANTS
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
Expand Down Expand Up @@ -1119,7 +1053,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
#if defined(__APPLE__) && !defined(__Userspace__)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
Expand Down
8 changes: 1 addition & 7 deletions usrsctplib/netinet/sctp_pcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3969,7 +3969,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
continue;
}
if ((stcb->asoc.size_on_reasm_queue > 0) ||
(stcb->asoc.control_pdapi) ||
(stcb->asoc.size_on_all_streams > 0) ||
((so != NULL) && (SCTP_SBAVAIL(&so->so_rcv) > 0))) {
/* Left with Data unread */
Expand Down Expand Up @@ -5529,15 +5528,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* will be now.
*/
if (sq->end_added == 0) {
/* Held for PD-API clear that. */
/* Held for PD-API, clear that. */
sq->pdapi_aborted = 1;
sq->held_length = 0;
if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
/*
* Need to add a PD-API aborted indication.
* Setting the control_pdapi assures that it will
* be added right after this msg.
*/
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
stcb,
SCTP_PARTIAL_DELIVERY_ABORTED,
Expand Down
9 changes: 0 additions & 9 deletions usrsctplib/netinet/sctp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1003,15 +1003,6 @@ struct sctp_association {
uint32_t fast_recovery_tsn;
uint32_t sat_t3_recovery_tsn;
uint32_t tsn_last_delivered;
/*
* For the pd-api we should re-write this a bit more efficient. We
* could have multiple sctp_queued_to_read's that we are building at
* once. Now we only do this when we get ready to deliver to the
* socket buffer. Note that we depend on the fact that the struct is
* "stuck" on the read queue until we finish all the pd-api.
*/
struct sctp_queued_to_read *control_pdapi;

uint32_t tsn_of_pdapi_last_delivered;
uint32_t pdapi_ppid;
uint32_t context;
Expand Down

0 comments on commit 54af901

Please sign in to comment.