static void nn_sock_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_sock *sock; struct nn_list_item *it; struct nn_ep *ep; sock = nn_cont (self, struct nn_sock, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_assert (sock->state == NN_SOCK_STATE_ACTIVE || sock->state == NN_SOCK_STATE_ZOMBIE); /* Close sndfd and rcvfd. This should make any current select/poll using SNDFD and/or RCVFD exit. */ if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NORECV)) { nn_efd_term (&sock->rcvfd); memset (&sock->rcvfd, 0xcd, sizeof (sock->rcvfd)); } if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NOSEND)) { nn_efd_term (&sock->sndfd); memset (&sock->sndfd, 0xcd, sizeof (sock->sndfd)); } /* Ask all the associated endpoints to stop. */ it = nn_list_begin (&sock->eps); while (it != nn_list_end (&sock->eps)) { ep = nn_cont (it, struct nn_ep, item); it = nn_list_next (&sock->eps, it); nn_list_erase (&sock->eps, &ep->item); nn_list_insert (&sock->sdeps, &ep->item, nn_list_end (&sock->sdeps)); nn_ep_stop (ep); } sock->state = NN_SOCK_STATE_STOPPING_EPS; goto finish2; }
int nn_sock_rm_ep (struct nn_sock *self, int eid) { struct nn_list_item *it; struct nn_ep *ep; nn_ctx_enter (&self->ctx); /* Find the specified enpoint. */ ep = NULL; for (it = nn_list_begin (&self->eps); it != nn_list_end (&self->eps); it = nn_list_next (&self->eps, it)) { ep = nn_cont (it, struct nn_ep, item); if (ep->eid == eid) break; ep = NULL; } /* The endpoint doesn't exist. */ if (!ep) { nn_ctx_leave (&self->ctx); return -EINVAL; } /* Move the endpoint from the list of active endpoints to the list of shutting down endpoints. */ nn_list_erase (&self->eps, &ep->item); nn_list_insert (&self->sdeps, &ep->item, nn_list_end (&self->sdeps)); /* Ask the endpoint to stop. Actual terminatation may be delayed by the transport. */ nn_ep_stop (ep); nn_ctx_leave (&self->ctx); return 0; }