static void nn_cinproc_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_cinproc *cinproc; cinproc = nn_cont (self, struct nn_cinproc, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { /* First, unregister the endpoint from the global repository of inproc endpoints. This way, new connections cannot be created anymore. */ nn_ins_disconnect (&cinproc->item); /* Stop the existing connection. */ nn_sinproc_stop (&cinproc->sinproc); cinproc->state = NN_CINPROC_STATE_STOPPING; } if (nn_slow (cinproc->state == NN_CINPROC_STATE_STOPPING)) { if (!nn_sinproc_isidle (&cinproc->sinproc)) return; cinproc->state = NN_CINPROC_STATE_IDLE; nn_fsm_stopped_noevent (&cinproc->fsm); nn_epbase_stopped (&cinproc->item.epbase); return; } nn_fsm_bad_state(cinproc->state, src, type); }
static void nn_cipc_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_cipc *cipc; cipc = nn_cont (self, struct nn_cipc, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { if (!nn_sipc_isidle (&cipc->sipc)) { nn_epbase_stat_increment (&cipc->epbase, NN_STAT_DROPPED_CONNECTIONS, 1); nn_sipc_stop (&cipc->sipc); } cipc->state = NN_CIPC_STATE_STOPPING_SIPC_FINAL; } if (nn_slow (cipc->state == NN_CIPC_STATE_STOPPING_SIPC_FINAL)) { if (!nn_sipc_isidle (&cipc->sipc)) return; nn_backoff_stop (&cipc->retry); nn_usock_stop (&cipc->usock); cipc->state = NN_CIPC_STATE_STOPPING; } if (nn_slow (cipc->state == NN_CIPC_STATE_STOPPING)) { if (!nn_backoff_isidle (&cipc->retry) || !nn_usock_isidle (&cipc->usock)) return; cipc->state = NN_CIPC_STATE_IDLE; nn_fsm_stopped_noevent (&cipc->fsm); nn_epbase_stopped (&cipc->epbase); return; } nn_fsm_bad_state(cipc->state, src, type); }
static void nn_cws_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_cws *cws; cws = nn_cont (self, struct nn_cws, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { if (!nn_sws_isidle (&cws->sws)) { nn_ep_stat_increment (cws->ep, NN_STAT_DROPPED_CONNECTIONS, 1); nn_sws_stop (&cws->sws); } cws->state = NN_CWS_STATE_STOPPING_SWS_FINAL; } if (nn_slow (cws->state == NN_CWS_STATE_STOPPING_SWS_FINAL)) { if (!nn_sws_isidle (&cws->sws)) return; nn_backoff_stop (&cws->retry); nn_usock_stop (&cws->usock); nn_dns_stop (&cws->dns); cws->state = NN_CWS_STATE_STOPPING; } if (nn_slow (cws->state == NN_CWS_STATE_STOPPING)) { if (!nn_backoff_isidle (&cws->retry) || !nn_usock_isidle (&cws->usock) || !nn_dns_isidle (&cws->dns)) return; cws->state = NN_CWS_STATE_IDLE; nn_fsm_stopped_noevent (&cws->fsm); nn_ep_stopped (cws->ep); return; } nn_fsm_bad_state (cws->state, src, type); }
static void nn_btcp_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_btcp *btcp; struct nn_list_item *it; struct nn_atcp *atcp; btcp = nn_cont (self, struct nn_btcp, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_atcp_stop (btcp->atcp); btcp->state = NN_BTCP_STATE_STOPPING_ATCP; } if (nn_slow (btcp->state == NN_BTCP_STATE_STOPPING_ATCP)) { if (!nn_atcp_isidle (btcp->atcp)) return; nn_atcp_term (btcp->atcp); nn_free (btcp->atcp); btcp->atcp = NULL; nn_usock_stop (&btcp->usock); btcp->state = NN_BTCP_STATE_STOPPING_USOCK; } if (nn_slow (btcp->state == NN_BTCP_STATE_STOPPING_USOCK)) { if (!nn_usock_isidle (&btcp->usock)) return; for (it = nn_list_begin (&btcp->atcps); it != nn_list_end (&btcp->atcps); it = nn_list_next (&btcp->atcps, it)) { atcp = nn_cont (it, struct nn_atcp, item); nn_atcp_stop (atcp); } btcp->state = NN_BTCP_STATE_STOPPING_ATCPS; goto atcps_stopping; } if (nn_slow (btcp->state == NN_BTCP_STATE_STOPPING_ATCPS)) { nn_assert (src == NN_BTCP_SRC_ATCP && type == NN_ATCP_STOPPED); atcp = (struct nn_atcp *) srcptr; nn_list_erase (&btcp->atcps, &atcp->item); nn_atcp_term (atcp); nn_free (atcp); /* If there are no more atcp state machines, we can stop the whole btcp object. */ atcps_stopping: if (nn_list_empty (&btcp->atcps)) { btcp->state = NN_BTCP_STATE_IDLE; nn_fsm_stopped_noevent (&btcp->fsm); nn_epbase_stopped (&btcp->epbase); return; } return; } nn_fsm_bad_action(btcp->state, src, type); }
static void nn_bipc_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_bipc *bipc; struct nn_list_item *it; struct nn_aipc *aipc; bipc = nn_cont (self, struct nn_bipc, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_aipc_stop (bipc->aipc); bipc->state = NN_BIPC_STATE_STOPPING_AIPC; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_AIPC)) { if (!nn_aipc_isidle (bipc->aipc)) return; nn_aipc_term (bipc->aipc); nn_free (bipc->aipc); bipc->aipc = NULL; nn_usock_stop (&bipc->usock); bipc->state = NN_BIPC_STATE_STOPPING_USOCK; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_USOCK)) { if (!nn_usock_isidle (&bipc->usock)) return; for (it = nn_list_begin (&bipc->aipcs); it != nn_list_end (&bipc->aipcs); it = nn_list_next (&bipc->aipcs, it)) { aipc = nn_cont (it, struct nn_aipc, item); nn_aipc_stop (aipc); } bipc->state = NN_BIPC_STATE_STOPPING_AIPCS; goto aipcs_stopping; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_AIPCS)) { nn_assert (src == NN_BIPC_SRC_AIPC && type == NN_AIPC_STOPPED); aipc = (struct nn_aipc *) srcptr; nn_list_erase (&bipc->aipcs, &aipc->item); nn_aipc_term (aipc); nn_free (aipc); /* If there are no more aipc state machines, we can stop the whole bipc object. */ aipcs_stopping: if (nn_list_empty (&bipc->aipcs)) { bipc->state = NN_BIPC_STATE_IDLE; nn_fsm_stopped_noevent (&bipc->fsm); nn_epbase_stopped (&bipc->epbase); return; } return; } nn_fsm_bad_state(bipc->state, src, type); }
int nn_sock_term (struct nn_sock *self) { int rc; int i; /* NOTE: nn_sock_stop must have already been called. */ /* Some endpoints may still be alive. Here we are going to wait till they are all closed. This loop is not interruptible, because making it so would leave a partially cleaned up socket, and we don't have a way to defer resource deallocation. */ for (;;) { rc = nn_sem_wait (&self->termsem); if (nn_slow (rc == -EINTR)) continue; errnum_assert (rc == 0, -rc); break; } /* Also, wait for all holds on the socket to be released. */ for (;;) { rc = nn_sem_wait (&self->relesem); if (nn_slow (rc == -EINTR)) continue; errnum_assert (rc == 0, -rc); break; } /* Threads that posted the semaphore(s) can still have the ctx locked for a short while. By simply entering the context and exiting it immediately we can be sure that any such threads have already exited the context. */ nn_ctx_enter (&self->ctx); nn_ctx_leave (&self->ctx); /* At this point, we can be reasonably certain that no other thread has any references to the socket. */ nn_fsm_stopped_noevent (&self->fsm); nn_fsm_term (&self->fsm); nn_sem_term (&self->termsem); nn_list_term (&self->sdeps); nn_list_term (&self->eps); nn_clock_term (&self->clock); nn_ctx_term (&self->ctx); /* Destroy any optsets associated with the socket. */ for (i = 0; i != NN_MAX_TRANSPORT; ++i) if (self->optsets [i]) self->optsets [i]->vfptr->destroy (self->optsets [i]); return 0; }
int nn_sock_term (struct nn_sock *self) { int rc; int i; /* Ask the state machine to start closing the socket. */ nn_ctx_enter (&self->ctx); nn_fsm_stop (&self->fsm); nn_ctx_leave (&self->ctx); /* Shutdown process was already started but some endpoints may still alive. Here we are going to wait till they are all closed. */ rc = nn_sem_wait (&self->termsem); if (nn_slow (rc == -EINTR)) return -EINTR; errnum_assert (rc == 0, -rc); /* The thread that posted the semaphore can still have the ctx locked for a short while. By simply entering the context and exiting it immediately we can be sure that the thread in question have already exited the context. */ nn_ctx_enter (&self->ctx); nn_ctx_leave (&self->ctx); /* Deallocate the resources. */ nn_fsm_stopped_noevent (&self->fsm); nn_fsm_term (&self->fsm); nn_sem_term (&self->termsem); nn_list_term (&self->sdeps); nn_list_term (&self->eps); nn_clock_term (&self->clock); nn_ctx_term (&self->ctx); /* Destroy any optsets associated with the socket. */ for (i = 0; i != NN_MAX_TRANSPORT; ++i) if (self->optsets [i]) self->optsets [i]->vfptr->destroy (self->optsets [i]); return 0; }
static void nn_surveyor_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_surveyor *surveyor; surveyor = nn_cont (self, struct nn_surveyor, fsm); if (nn_slow (src== NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_timer_stop (&surveyor->timer); surveyor->state = NN_SURVEYOR_STATE_STOPPING; } if (nn_slow (surveyor->state == NN_SURVEYOR_STATE_STOPPING)) { if (!nn_timer_isidle (&surveyor->timer)) return; surveyor->state = NN_SURVEYOR_STATE_IDLE; nn_fsm_stopped_noevent (&surveyor->fsm); nn_sockbase_stopped (&surveyor->xsurveyor.sockbase); return; } nn_fsm_bad_state(surveyor->state, src, type); }
void nn_req_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_req *req; req = nn_cont (self, struct nn_req, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_timer_stop (&req->task.timer); req->state = NN_REQ_STATE_STOPPING; } if (nn_slow (req->state == NN_REQ_STATE_STOPPING)) { if (!nn_timer_isidle (&req->task.timer)) return; req->state = NN_REQ_STATE_IDLE; nn_fsm_stopped_noevent (&req->fsm); nn_sockbase_stopped (&req->xreq.sockbase); return; } nn_fsm_bad_state(req->state, src, type); }
static void nn_cipc_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_cipc *cipc; cipc = nn_cont (self, struct nn_cipc, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_sipc_stop (&cipc->sipc); cipc->state = NN_CIPC_STATE_STOPPING_SIPC_FINAL; } if (nn_slow (cipc->state == NN_CIPC_STATE_STOPPING_SIPC_FINAL)) { if (!nn_sipc_isidle (&cipc->sipc)) return; nn_backoff_stop (&cipc->retry); nn_usock_stop (&cipc->usock); cipc->state = NN_CIPC_STATE_STOPPING; } if (nn_slow (cipc->state == NN_CIPC_STATE_STOPPING)) { if (!nn_backoff_isidle (&cipc->retry) || !nn_usock_isidle (&cipc->usock)) return; cipc->state = NN_CIPC_STATE_IDLE; nn_fsm_stopped_noevent (&cipc->fsm); nn_epbase_stopped (&cipc->epbase); return; } switch (cipc->state) { /******************************************************************************/ /* IDLE state. */ /* The state machine wasn't yet started. */ /******************************************************************************/ case NN_CIPC_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_cipc_start_connecting (cipc); return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* CONNECTING state. */ /* Non-blocking connect is under way. */ /******************************************************************************/ case NN_CIPC_STATE_CONNECTING: switch (src) { case NN_CIPC_SRC_USOCK: switch (type) { case NN_USOCK_CONNECTED: nn_sipc_start (&cipc->sipc, &cipc->usock); cipc->state = NN_CIPC_STATE_ACTIVE; return; case NN_USOCK_ERROR: nn_usock_stop (&cipc->usock); cipc->state = NN_CIPC_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /* Connection is established and handled by the sipc state machine. */ /******************************************************************************/ case NN_CIPC_STATE_ACTIVE: switch (src) { case NN_CIPC_SRC_SIPC: switch (type) { case NN_SIPC_ERROR: nn_sipc_stop (&cipc->sipc); cipc->state = NN_CIPC_STATE_STOPPING_SIPC; return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* STOPPING_SIPC state. */ /* sipc object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CIPC_STATE_STOPPING_SIPC: switch (src) { case NN_CIPC_SRC_SIPC: switch (type) { case NN_SIPC_STOPPED: nn_usock_stop (&cipc->usock); cipc->state = NN_CIPC_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* STOPPING_USOCK state. */ /* usock object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CIPC_STATE_STOPPING_USOCK: switch (src) { case NN_CIPC_SRC_USOCK: switch (type) { case NN_USOCK_STOPPED: nn_backoff_start (&cipc->retry); cipc->state = NN_CIPC_STATE_WAITING; return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* WAITING state. */ /* Waiting before re-connection is attempted. This way we won't overload */ /* the system by continuous re-connection attemps. */ /******************************************************************************/ case NN_CIPC_STATE_WAITING: switch (src) { case NN_CIPC_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_TIMEOUT: nn_backoff_stop (&cipc->retry); cipc->state = NN_CIPC_STATE_STOPPING_BACKOFF; return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* STOPPING_BACKOFF state. */ /* backoff object was asked to stop, but it haven't stopped yet. */ /******************************************************************************/ case NN_CIPC_STATE_STOPPING_BACKOFF: switch (src) { case NN_CIPC_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_STOPPED: nn_cipc_start_connecting (cipc); return; default: nn_fsm_bad_action (cipc->state, src, type); } default: nn_fsm_bad_source (cipc->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (cipc->state, src, type); } }
static void nn_req_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_req *req; req = nn_cont (self, struct nn_req, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_timer_stop (&req->timer); req->state = NN_REQ_STATE_STOPPING; } if (nn_slow (req->state == NN_REQ_STATE_STOPPING)) { if (!nn_timer_isidle (&req->timer)) return; req->state = NN_REQ_STATE_IDLE; nn_fsm_stopped_noevent (&req->fsm); nn_sockbase_stopped (&req->xreq.sockbase); return; } switch (req->state) { /******************************************************************************/ /* IDLE state. */ /* The socket was created recently. Intermediate state. */ /* Pass straight to the PASSIVE state. */ /******************************************************************************/ case NN_REQ_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: req->state = NN_REQ_STATE_PASSIVE; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* PASSIVE state. */ /* No request is submitted. */ /******************************************************************************/ case NN_REQ_STATE_PASSIVE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_SENT: nn_req_action_send (req); return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* DELAYED state. */ /* Request was submitted but it could not be sent to the network because */ /* there was no peer available at the moment. Now we are waiting for the */ /* peer to arrive to send the request to it. */ /******************************************************************************/ case NN_REQ_STATE_DELAYED: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_OUT: nn_req_action_send (req); return; case NN_REQ_ACTION_SENT: /* New request was sent while the old one was still being processed. Cancel the old request first. */ nn_timer_stop (&req->timer); req->state = NN_REQ_STATE_CANCELLING; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* ACTIVE state. */ /* Request was submitted. Waiting for reply. */ /******************************************************************************/ case NN_REQ_STATE_ACTIVE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_IN: /* Reply arrived. */ nn_timer_stop (&req->timer); req->state = NN_REQ_STATE_STOPPING_TIMER; return; case NN_REQ_ACTION_SENT: /* New request was sent while the old one was still being processed. Cancel the old request first. */ nn_timer_stop (&req->timer); req->state = NN_REQ_STATE_CANCELLING; return; default: nn_assert (0); } case NN_REQ_SRC_RESEND_TIMER: switch (type) { case NN_TIMER_TIMEOUT: nn_timer_stop (&req->timer); req->state = NN_REQ_STATE_TIMED_OUT; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* TIMED_OUT state. */ /* Waiting for reply has timer out. Stopping the timer. Afterwards, we'll */ /* re-send the request. */ /******************************************************************************/ case NN_REQ_STATE_TIMED_OUT: switch (src) { case NN_REQ_SRC_RESEND_TIMER: switch (type) { case NN_TIMER_STOPPED: nn_req_action_send (req); return; default: nn_assert (0); } case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_SENT: req->state = NN_REQ_STATE_CANCELLING; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* CANCELLING state. */ /* Request was canceled. Waiting till the timer is stopped. */ /******************************************************************************/ case NN_REQ_STATE_CANCELLING: switch (src) { case NN_REQ_SRC_RESEND_TIMER: switch (type) { case NN_TIMER_STOPPED: nn_req_action_send (req); return; default: nn_assert (0); } case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_SENT: return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* STOPPING_TIMER state. */ /* Reply was delivered. Waiting till the timer is stopped. */ /******************************************************************************/ case NN_REQ_STATE_STOPPING_TIMER: switch (src) { case NN_REQ_SRC_RESEND_TIMER: switch (type) { case NN_TIMER_STOPPED: req->state = NN_REQ_STATE_DONE; return; default: nn_assert (0); } case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_SENT: req->state = NN_REQ_STATE_CANCELLING; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* DONE state. */ /* Reply was received but not yet retrieved by the user. */ /******************************************************************************/ case NN_REQ_STATE_DONE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_REQ_ACTION_RECEIVED: req->state = NN_REQ_STATE_PASSIVE; return; case NN_REQ_ACTION_SENT: nn_req_action_send (req); return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_assert (0); } }
static void nn_bipc_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_bipc *bipc; struct nn_list_item *it; struct nn_aipc *aipc; bipc = nn_cont (self, struct nn_bipc, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_aipc_stop (bipc->aipc); bipc->state = NN_BIPC_STATE_STOPPING_AIPC; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_AIPC)) { if (!nn_aipc_isidle (bipc->aipc)) return; nn_aipc_term (bipc->aipc); nn_free (bipc->aipc); bipc->aipc = NULL; nn_usock_stop (&bipc->usock); bipc->state = NN_BIPC_STATE_STOPPING_USOCK; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_USOCK)) { if (!nn_usock_isidle (&bipc->usock)) return; for (it = nn_list_begin (&bipc->aipcs); it != nn_list_end (&bipc->aipcs); it = nn_list_next (&bipc->aipcs, it)) { aipc = nn_cont (it, struct nn_aipc, item); nn_aipc_stop (aipc); } bipc->state = NN_BIPC_STATE_STOPPING_AIPCS; goto aipcs_stopping; } if (nn_slow (bipc->state == NN_BIPC_STATE_STOPPING_AIPCS)) { nn_assert (src == NN_BIPC_SRC_AIPC && type == NN_AIPC_STOPPED); aipc = (struct nn_aipc *) srcptr; nn_list_erase (&bipc->aipcs, &aipc->item); nn_aipc_term (aipc); nn_free (aipc); /* If there are no more aipc state machines, we can stop the whole bipc object. */ aipcs_stopping: if (nn_list_empty (&bipc->aipcs)) { bipc->state = NN_BIPC_STATE_IDLE; nn_fsm_stopped_noevent (&bipc->fsm); nn_epbase_stopped (&bipc->epbase); return; } return; } switch (bipc->state) { /******************************************************************************/ /* IDLE state. */ /******************************************************************************/ case NN_BIPC_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_bipc_start_listening (bipc); nn_bipc_start_accepting (bipc); bipc->state = NN_BIPC_STATE_ACTIVE; return; default: nn_fsm_bad_action (bipc->state, src, type); } default: nn_fsm_bad_source (bipc->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /* The execution is yielded to the aipc state machine in this state. */ /******************************************************************************/ case NN_BIPC_STATE_ACTIVE: if (srcptr == bipc->aipc) { switch (type) { case NN_AIPC_ACCEPTED: /* Move the newly created connection to the list of existing connections. */ nn_list_insert (&bipc->aipcs, &bipc->aipc->item, nn_list_end (&bipc->aipcs)); bipc->aipc = NULL; /* Start waiting for a new incoming connection. */ nn_bipc_start_accepting (bipc); return; default: nn_fsm_bad_action (bipc->state, src, type); } } /* For all remaining events we'll assume they are coming from one of remaining child aipc objects. */ nn_assert (src == NN_BIPC_SRC_AIPC); aipc = (struct nn_aipc*) srcptr; switch (type) { case NN_AIPC_ERROR: nn_aipc_stop (aipc); return; case NN_AIPC_STOPPED: nn_list_erase (&bipc->aipcs, &aipc->item); nn_aipc_term (aipc); nn_free (aipc); return; default: nn_fsm_bad_action (bipc->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (bipc->state, src, type); } }
static void nn_surveyor_handler (struct nn_fsm *self, int src, int type, void *srcptr) { int rc; struct nn_surveyor *surveyor; surveyor = nn_cont (self, struct nn_surveyor, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src== NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_timer_stop (&surveyor->timer); surveyor->state = NN_SURVEYOR_STATE_STOPPING; } if (nn_slow (surveyor->state == NN_SURVEYOR_STATE_STOPPING)) { if (!nn_timer_isidle (&surveyor->timer)) return; surveyor->state = NN_SURVEYOR_STATE_IDLE; nn_fsm_stopped_noevent (&surveyor->fsm); nn_sockbase_stopped (&surveyor->xsurveyor.sockbase); return; } switch (surveyor->state) { /******************************************************************************/ /* IDLE state. */ /* The socket was created recently. */ /******************************************************************************/ case NN_SURVEYOR_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: surveyor->state = NN_SURVEYOR_STATE_PASSIVE; return; default: nn_fsm_bad_action (surveyor->state, src, type); } default: nn_fsm_bad_source (surveyor->state, src, type); } /******************************************************************************/ /* PASSIVE state. */ /* There's no survey going on. */ /******************************************************************************/ case NN_SURVEYOR_STATE_PASSIVE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_SURVEYOR_ACTION_START: rc = nn_xsurveyor_send (&surveyor->xsurveyor.sockbase, &surveyor->tosend); errnum_assert (rc == 0, -rc); nn_timer_start (&surveyor->timer, surveyor->deadline); surveyor->state = NN_SURVEYOR_STATE_ACTIVE; return; default: nn_fsm_bad_action (surveyor->state, src, type); } default: nn_fsm_bad_source (surveyor->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /* Survey was sent, waiting for responses. */ /******************************************************************************/ case NN_SURVEYOR_STATE_ACTIVE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_SURVEYOR_ACTION_CANCEL: nn_timer_stop (&surveyor->timer); surveyor->state = NN_SURVEYOR_STATE_CANCELLING; return; default: nn_fsm_bad_action (surveyor->state, src, type); } case NN_SURVEYOR_SRC_DEADLINE_TIMER: switch (type) { case NN_TIMER_TIMEOUT: nn_timer_stop (&surveyor->timer); surveyor->state = NN_SURVEYOR_STATE_STOPPING_TIMER; return; default: nn_fsm_bad_action (surveyor->state, src, type); } default: nn_fsm_bad_source (surveyor->state, src, type); } /******************************************************************************/ /* CANCELLING state. */ /* Survey was cancelled, but the old timer haven't stopped yet. The new */ /* survey thus haven't been sent and is stored in 'tosend'. */ /******************************************************************************/ case NN_SURVEYOR_STATE_CANCELLING: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_SURVEYOR_ACTION_CANCEL: return; default: nn_fsm_bad_action (surveyor->state, src, type); } case NN_SURVEYOR_SRC_DEADLINE_TIMER: switch (type) { case NN_TIMER_STOPPED: rc = nn_xsurveyor_send (&surveyor->xsurveyor.sockbase, &surveyor->tosend); errnum_assert (rc == 0, -rc); nn_timer_start (&surveyor->timer, surveyor->deadline); surveyor->state = NN_SURVEYOR_STATE_ACTIVE; return; default: nn_fsm_bad_action (surveyor->state, src, type); } default: nn_fsm_bad_source (surveyor->state, src, type); } /******************************************************************************/ /* STOPPING_TIMER state. */ /* Survey timeout expired. Now we are stopping the timer. */ /******************************************************************************/ case NN_SURVEYOR_STATE_STOPPING_TIMER: switch (src) { case NN_SURVEYOR_SRC_DEADLINE_TIMER: switch (type) { case NN_TIMER_STOPPED: surveyor->state = NN_SURVEYOR_STATE_PASSIVE; return; default: nn_fsm_bad_action (surveyor->state, src, type); } default: nn_fsm_bad_source (surveyor->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (surveyor->state, src, type); } }
static void nn_bws_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_bws *bws; struct nn_list_item *it; struct nn_aws *aws; bws = nn_cont (self, struct nn_bws, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { if (bws->aws) { nn_aws_stop (bws->aws); bws->state = NN_BWS_STATE_STOPPING_AWS; } else { bws->state = NN_BWS_STATE_STOPPING_USOCK; } } if (nn_slow (bws->state == NN_BWS_STATE_STOPPING_AWS)) { if (!nn_aws_isidle (bws->aws)) return; nn_aws_term (bws->aws); nn_free (bws->aws); bws->aws = NULL; nn_usock_stop (&bws->usock); bws->state = NN_BWS_STATE_STOPPING_USOCK; } if (nn_slow (bws->state == NN_BWS_STATE_STOPPING_USOCK)) { if (!nn_usock_isidle (&bws->usock)) return; for (it = nn_list_begin (&bws->awss); it != nn_list_end (&bws->awss); it = nn_list_next (&bws->awss, it)) { aws = nn_cont (it, struct nn_aws, item); nn_aws_stop (aws); } bws->state = NN_BWS_STATE_STOPPING_AWSS; goto awss_stopping; } if (nn_slow (bws->state == NN_BWS_STATE_STOPPING_AWSS)) { nn_assert (src == NN_BWS_SRC_AWS && type == NN_AWS_STOPPED); aws = (struct nn_aws *) srcptr; nn_list_erase (&bws->awss, &aws->item); nn_aws_term (aws); nn_free (aws); /* If there are no more aws state machines, we can stop the whole bws object. */ awss_stopping: if (nn_list_empty (&bws->awss)) { bws->state = NN_BWS_STATE_IDLE; nn_fsm_stopped_noevent (&bws->fsm); nn_epbase_stopped (&bws->epbase); return; } return; } nn_fsm_bad_action (bws->state, src, type); }