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_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_bipc_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_bipc *bipc; struct nn_aipc *aipc; bipc = nn_cont (self, struct nn_bipc, fsm); nn_assert(bipc); 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); 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); } /******************************************************************************/ /* CLOSING_USOCK state. */ /* usock object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_BIPC_STATE_CLOSING: switch (src) { case NN_BIPC_SRC_USOCK: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_USOCK_STOPPED: nn_backoff_start (&bipc->retry); bipc->state = NN_BIPC_STATE_WAITING; return; default: nn_fsm_bad_action (bipc->state, src, type); } default: nn_fsm_bad_source (bipc->state, src, type); } /******************************************************************************/ /* WAITING state. */ /* Waiting before re-bind is attempted. This way we won't overload */ /* the system by continuous re-bind attemps. */ /******************************************************************************/ case NN_BIPC_STATE_WAITING: switch (src) { case NN_BIPC_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_TIMEOUT: nn_backoff_stop (&bipc->retry); bipc->state = NN_BIPC_STATE_STOPPING_BACKOFF; return; default: nn_fsm_bad_action (bipc->state, src, type); } default: nn_fsm_bad_source (bipc->state, src, type); } /******************************************************************************/ /* STOPPING_BACKOFF state. */ /* backoff object was asked to stop, but it haven't stopped yet. */ /******************************************************************************/ case NN_BIPC_STATE_STOPPING_BACKOFF: switch (src) { case NN_BIPC_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_STOPPED: nn_bipc_start_listening (bipc); return; default: nn_fsm_bad_action (bipc->state, src, type); } default: nn_fsm_bad_source (bipc->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (bipc->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); nn_assert(bipc); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_backoff_stop (&bipc->retry); if (bipc->aipc) { nn_aipc_stop (bipc->aipc); bipc->state = NN_BIPC_STATE_STOPPING_AIPC; } else { bipc->state = NN_BIPC_STATE_STOPPING_USOCK; } } 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); }
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_backoff_stop (&btcp->retry); if (btcp->atcp) { nn_atcp_stop (btcp->atcp); btcp->state = NN_BTCP_STATE_STOPPING_ATCP; } else { btcp->state = NN_BTCP_STATE_STOPPING_USOCK; } } 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) || !nn_backoff_isidle (&btcp->retry)) 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_ctcp_handler (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_ctcp *ctcp; ctcp = nn_cont (self, struct nn_ctcp, fsm); switch (ctcp->state) { /******************************************************************************/ /* IDLE state. */ /* The state machine wasn't yet started. */ /******************************************************************************/ case NN_CTCP_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_ctcp_start_resolving (ctcp); return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* RESOLVING state. */ /* Name of the host to connect to is being resolved to get an IP address. */ /******************************************************************************/ case NN_CTCP_STATE_RESOLVING: switch (src) { case NN_CTCP_SRC_DNS: switch (type) { case NN_DNS_DONE: nn_dns_stop (&ctcp->dns); ctcp->state = NN_CTCP_STATE_STOPPING_DNS; return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* STOPPING_DNS state. */ /* dns object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CTCP_STATE_STOPPING_DNS: switch (src) { case NN_CTCP_SRC_DNS: switch (type) { case NN_DNS_STOPPED: if (ctcp->dns_result.error == 0) { nn_ctcp_start_connecting (ctcp, &ctcp->dns_result.addr, ctcp->dns_result.addrlen); return; } nn_backoff_start (&ctcp->retry); ctcp->state = NN_CTCP_STATE_WAITING; return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* CONNECTING state. */ /* Non-blocking connect is under way. */ /******************************************************************************/ case NN_CTCP_STATE_CONNECTING: switch (src) { case NN_CTCP_SRC_USOCK: switch (type) { case NN_USOCK_CONNECTED: nn_stcp_start (&ctcp->stcp, &ctcp->usock); ctcp->state = NN_CTCP_STATE_ACTIVE; nn_epbase_stat_increment (&ctcp->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&ctcp->epbase, NN_STAT_ESTABLISHED_CONNECTIONS, 1); nn_epbase_clear_error (&ctcp->epbase); return; case NN_USOCK_ERROR: nn_epbase_set_error (&ctcp->epbase,nn_usock_geterrno(&ctcp->usock),__FILE__,__LINE__); nn_usock_stop (&ctcp->usock); ctcp->state = NN_CTCP_STATE_STOPPING_USOCK; nn_epbase_stat_increment (&ctcp->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&ctcp->epbase, NN_STAT_CONNECT_ERRORS, 1); return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /* Connection is established and handled by the stcp state machine. */ /******************************************************************************/ case NN_CTCP_STATE_ACTIVE: switch (src) { case NN_CTCP_SRC_STCP: switch (type) { case NN_STCP_ERROR: nn_stcp_stop (&ctcp->stcp); ctcp->state = NN_CTCP_STATE_STOPPING_STCP; nn_epbase_stat_increment (&ctcp->epbase, NN_STAT_BROKEN_CONNECTIONS, 1); return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* STOPPING_STCP state. */ /* stcp object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CTCP_STATE_STOPPING_STCP: switch (src) { case NN_CTCP_SRC_STCP: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_STCP_STOPPED: nn_usock_stop (&ctcp->usock); ctcp->state = NN_CTCP_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* STOPPING_USOCK state. */ /* usock object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CTCP_STATE_STOPPING_USOCK: switch (src) { case NN_CTCP_SRC_USOCK: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_USOCK_STOPPED: nn_backoff_start (&ctcp->retry); ctcp->state = NN_CTCP_STATE_WAITING; return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->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_CTCP_STATE_WAITING: switch (src) { case NN_CTCP_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_TIMEOUT: nn_backoff_stop (&ctcp->retry); ctcp->state = NN_CTCP_STATE_STOPPING_BACKOFF; return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* STOPPING_BACKOFF state. */ /* backoff object was asked to stop, but it haven't stopped yet. */ /******************************************************************************/ case NN_CTCP_STATE_STOPPING_BACKOFF: switch (src) { case NN_CTCP_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_STOPPED: nn_ctcp_start_resolving (ctcp); return; default: nn_fsm_bad_action (ctcp->state, src, type); } default: nn_fsm_bad_source (ctcp->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (ctcp->state, src, type); } }
static void nn_cipc_handler (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_cipc *cipc; cipc = nn_cont (self, struct nn_cipc, fsm); 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; nn_epbase_stat_increment (&cipc->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&cipc->epbase, NN_STAT_ESTABLISHED_CONNECTIONS, 1); nn_epbase_clear_error (&cipc->epbase); return; case NN_USOCK_ERROR: nn_epbase_set_error (&cipc->epbase,nn_usock_geterrno (&cipc->usock),__FILE__,__LINE__); nn_usock_stop (&cipc->usock); cipc->state = NN_CIPC_STATE_STOPPING_USOCK; nn_epbase_stat_increment (&cipc->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&cipc->epbase, NN_STAT_CONNECT_ERRORS, 1); 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; nn_epbase_stat_increment (&cipc->epbase, NN_STAT_BROKEN_CONNECTIONS, 1); 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_USOCK_SHUTDOWN: return; 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_SHUTDOWN: return; 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_cws_handler (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_cws *cws; cws = nn_cont (self, struct nn_cws, fsm); switch (cws->state) { /******************************************************************************/ /* IDLE state. */ /* The state machine wasn't yet started. */ /******************************************************************************/ case NN_CWS_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_cws_start_resolving (cws); return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* RESOLVING state. */ /* Name of the host to connect to is being resolved to get an IP address. */ /******************************************************************************/ case NN_CWS_STATE_RESOLVING: switch (src) { case NN_CWS_SRC_DNS: switch (type) { case NN_DNS_DONE: nn_dns_stop (&cws->dns); cws->state = NN_CWS_STATE_STOPPING_DNS; return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* STOPPING_DNS state. */ /* dns object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CWS_STATE_STOPPING_DNS: switch (src) { case NN_CWS_SRC_DNS: switch (type) { case NN_DNS_STOPPED: if (cws->dns_result.error == 0) { nn_cws_start_connecting (cws, &cws->dns_result.addr, cws->dns_result.addrlen); return; } nn_backoff_start (&cws->retry); cws->state = NN_CWS_STATE_WAITING; return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* CONNECTING state. */ /* Non-blocking connect is under way. */ /******************************************************************************/ case NN_CWS_STATE_CONNECTING: switch (src) { case NN_CWS_SRC_USOCK: switch (type) { case NN_USOCK_CONNECTED: nn_sws_start (&cws->sws, &cws->usock, NN_WS_CLIENT, nn_chunkref_data (&cws->resource), nn_chunkref_data (&cws->remote_host), cws->msg_type); cws->state = NN_CWS_STATE_ACTIVE; cws->peer_gone = 0; nn_epbase_stat_increment (&cws->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&cws->epbase, NN_STAT_ESTABLISHED_CONNECTIONS, 1); nn_epbase_clear_error (&cws->epbase); return; case NN_USOCK_ERROR: nn_epbase_set_error (&cws->epbase, nn_usock_geterrno (&cws->usock)); nn_usock_stop (&cws->usock); cws->state = NN_CWS_STATE_STOPPING_USOCK; nn_epbase_stat_increment (&cws->epbase, NN_STAT_INPROGRESS_CONNECTIONS, -1); nn_epbase_stat_increment (&cws->epbase, NN_STAT_CONNECT_ERRORS, 1); return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /* Connection is established and handled by the sws state machine. */ /******************************************************************************/ case NN_CWS_STATE_ACTIVE: switch (src) { case NN_CWS_SRC_SWS: switch (type) { case NN_SWS_RETURN_CLOSE_HANDSHAKE: /* Peer closed connection without intention to reconnect, or local endpoint failed remote because of invalid data. */ nn_sws_stop (&cws->sws); cws->state = NN_CWS_STATE_STOPPING_SWS; cws->peer_gone = 1; return; case NN_SWS_RETURN_ERROR: nn_sws_stop (&cws->sws); cws->state = NN_CWS_STATE_STOPPING_SWS; nn_epbase_stat_increment (&cws->epbase, NN_STAT_BROKEN_CONNECTIONS, 1); return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* STOPPING_SWS state. */ /* sws object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CWS_STATE_STOPPING_SWS: switch (src) { case NN_CWS_SRC_SWS: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_SWS_RETURN_STOPPED: nn_usock_stop (&cws->usock); cws->state = NN_CWS_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* STOPPING_USOCK state. */ /* usock object was asked to stop but it haven't stopped yet. */ /******************************************************************************/ case NN_CWS_STATE_STOPPING_USOCK: switch (src) { case NN_CWS_SRC_USOCK: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_USOCK_STOPPED: /* If the peer has confirmed itself gone with a Closing Handshake, or if the local endpoint failed the remote, don't try to reconnect. */ if (!cws->peer_gone) { nn_backoff_start (&cws->retry); cws->state = NN_CWS_STATE_WAITING; } return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->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_CWS_STATE_WAITING: switch (src) { case NN_CWS_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_TIMEOUT: nn_backoff_stop (&cws->retry); cws->state = NN_CWS_STATE_STOPPING_BACKOFF; return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* STOPPING_BACKOFF state. */ /* backoff object was asked to stop, but it haven't stopped yet. */ /******************************************************************************/ case NN_CWS_STATE_STOPPING_BACKOFF: switch (src) { case NN_CWS_SRC_RECONNECT_TIMER: switch (type) { case NN_BACKOFF_STOPPED: nn_cws_start_resolving (cws); return; default: nn_fsm_bad_action (cws->state, src, type); } default: nn_fsm_bad_source (cws->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (cws->state, src, type); } }