static void nn_atcp_handler (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_atcp *atcp; int val; size_t sz; atcp = nn_cont (self, struct nn_atcp, fsm); switch (atcp->state) { /******************************************************************************/ /* IDLE state. */ /* The state machine wasn't yet started. */ /******************************************************************************/ case NN_ATCP_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_usock_accept (&atcp->usock, atcp->listener); atcp->state = NN_ATCP_STATE_ACCEPTING; return; default: nn_fsm_bad_action (atcp->state, src, type); } default: nn_fsm_bad_source (atcp->state, src, type); } /******************************************************************************/ /* ACCEPTING state. */ /* Waiting for incoming connection. */ /******************************************************************************/ case NN_ATCP_STATE_ACCEPTING: switch (src) { case NN_ATCP_SRC_USOCK: switch (type) { case NN_USOCK_ACCEPTED: nn_epbase_clear_error (atcp->epbase); /* Set the relevant socket options. */ sz = sizeof (val); nn_epbase_getopt (atcp->epbase, NN_SOL_SOCKET, NN_SNDBUF, &val, &sz); nn_assert (sz == sizeof (val)); nn_usock_setsockopt (&atcp->usock, SOL_SOCKET, SO_SNDBUF, &val, sizeof (val)); sz = sizeof (val); nn_epbase_getopt (atcp->epbase, NN_SOL_SOCKET, NN_RCVBUF, &val, &sz); nn_assert (sz == sizeof (val)); nn_usock_setsockopt (&atcp->usock, SOL_SOCKET, SO_RCVBUF, &val, sizeof (val)); /* Return ownership of the listening socket to the parent. */ nn_usock_swap_owner (atcp->listener, &atcp->listener_owner); atcp->listener = NULL; atcp->listener_owner.src = -1; atcp->listener_owner.fsm = NULL; nn_fsm_raise (&atcp->fsm, &atcp->accepted, NN_ATCP_ACCEPTED); /* Start the stcp state machine. */ nn_usock_activate (&atcp->usock); nn_stcp_start (&atcp->stcp, &atcp->usock); atcp->state = NN_ATCP_STATE_ACTIVE; nn_epbase_stat_increment (atcp->epbase, NN_STAT_ACCEPTED_CONNECTIONS, 1); return; default: nn_fsm_bad_action (atcp->state, src, type); } case NN_ATCP_SRC_LISTENER: switch (type) { case NN_USOCK_ACCEPT_ERROR: nn_epbase_set_error (atcp->epbase, nn_usock_geterrno(atcp->listener)); nn_epbase_stat_increment (atcp->epbase, NN_STAT_ACCEPT_ERRORS, 1); nn_usock_accept (&atcp->usock, atcp->listener); return; default: nn_fsm_bad_action (atcp->state, src, type); } default: nn_fsm_bad_source (atcp->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /******************************************************************************/ case NN_ATCP_STATE_ACTIVE: switch (src) { case NN_ATCP_SRC_STCP: switch (type) { case NN_STCP_ERROR: nn_stcp_stop (&atcp->stcp); atcp->state = NN_ATCP_STATE_STOPPING_STCP; nn_epbase_stat_increment (atcp->epbase, NN_STAT_BROKEN_CONNECTIONS, 1); return; default: nn_fsm_bad_action (atcp->state, src, type); } default: nn_fsm_bad_source (atcp->state, src, type); } /******************************************************************************/ /* STOPPING_STCP state. */ /******************************************************************************/ case NN_ATCP_STATE_STOPPING_STCP: switch (src) { case NN_ATCP_SRC_STCP: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_STCP_STOPPED: nn_usock_stop (&atcp->usock); atcp->state = NN_ATCP_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (atcp->state, src, type); } default: nn_fsm_bad_source (atcp->state, src, type); } /******************************************************************************/ /* STOPPING_USOCK state. */ /******************************************************************************/ case NN_ATCP_STATE_STOPPING_USOCK: switch (src) { case NN_ATCP_SRC_USOCK: switch (type) { case NN_USOCK_SHUTDOWN: return; case NN_USOCK_STOPPED: nn_fsm_raise (&atcp->fsm, &atcp->done, NN_ATCP_ERROR); atcp->state = NN_ATCP_STATE_DONE; return; default: nn_fsm_bad_action (atcp->state, src, type); } default: nn_fsm_bad_source (atcp->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (atcp->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); } }