static void nn_aipc_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_aipc *aipc; aipc = nn_cont (self, struct nn_aipc, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_sipc_stop (&aipc->sipc); aipc->state = NN_AIPC_STATE_STOPPING_SIPC_FINAL; } if (nn_slow (aipc->state == NN_AIPC_STATE_STOPPING_SIPC_FINAL)) { if (!nn_sipc_isidle (&aipc->sipc)) return; nn_usock_stop (&aipc->usock); aipc->state = NN_AIPC_STATE_STOPPING; } if (nn_slow (aipc->state == NN_AIPC_STATE_STOPPING)) { if (!nn_usock_isidle (&aipc->usock)) return; if (aipc->listener) { nn_assert (aipc->listener_owner.fsm); nn_usock_swap_owner (aipc->listener, &aipc->listener_owner); aipc->listener = NULL; aipc->listener_owner.src = 1; aipc->listener_owner.fsm = NULL; } aipc->state = NN_AIPC_STATE_IDLE; nn_fsm_stopped (&aipc->fsm, NN_AIPC_STOPPED); return; } nn_fsm_bad_state(aipc->state, src, type); }
static void nn_stcp_shutdown(struct nn_fsm *self,int32_t src,int32_t type,NN_UNUSED void *srcptr) { struct nn_stcp *stcp; stcp = nn_cont (self, struct nn_stcp, fsm); if ( nn_slow(src == NN_FSM_ACTION && type == NN_FSM_STOP) ) { nn_pipebase_stop(&stcp->pipebase); nn_streamhdr_stop(&stcp->streamhdr); stcp->state = NN_STCP_STATE_STOPPING; } if ( nn_slow(stcp->state == NN_STCP_STATE_STOPPING) ) { if ( nn_streamhdr_isidle(&stcp->streamhdr) ) { nn_usock_swap_owner(stcp->usock,&stcp->usock_owner); stcp->usock = NULL; stcp->usock_owner.src = -1; stcp->usock_owner.fsm = NULL; stcp->state = NN_STCP_STATE_IDLE; nn_fsm_stopped (&stcp->fsm,NN_STCP_STOPPED); return; } return; } nn_fsm_bad_state(stcp->state,src,type); }
static void nn_sws_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_sws *sws; sws = nn_cont (self, struct nn_sws, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { /* TODO: Consider sending a close code here? */ nn_pipebase_stop (&sws->pipebase); nn_wshdr_stop (&sws->wshdr); sws->state = NN_SWS_STATE_STOPPING; } if (nn_slow (sws->state == NN_SWS_STATE_STOPPING)) { if (nn_wshdr_isidle (&sws->wshdr)) { nn_usock_swap_owner (sws->usock, &sws->usock_owner); sws->usock = NULL; sws->usock_owner.src = -1; sws->usock_owner.fsm = NULL; sws->state = NN_SWS_STATE_IDLE; nn_fsm_stopped (&sws->fsm, NN_SWS_RETURN_STOPPED); return; } return; } nn_fsm_bad_state (sws->state, src, type); }
static void nn_ep_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_ep *ep; ep = nn_cont (self, struct nn_ep, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { ep->epbase->vfptr->stop (ep->epbase); ep->state = NN_EP_STATE_STOPPING; return; } if (nn_slow (ep->state == NN_EP_STATE_STOPPING)) { if (src != NN_FSM_ACTION || type != NN_EP_ACTION_STOPPED) return; ep->state = NN_EP_STATE_IDLE; nn_fsm_stopped (&ep->fsm, NN_EP_STOPPED); return; } nn_fsm_bad_state (ep->state, src, type); }
static void nn_aws_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_aws *aws; aws = nn_cont (self, struct nn_aws, fsm); nn_assert (aws); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { if (!nn_sws_isidle (&aws->sws)) { nn_epbase_stat_increment (aws->epbase, NN_STAT_DROPPED_CONNECTIONS, 1); nn_sws_stop (&aws->sws); } aws->state = NN_AWS_STATE_STOPPING_SWS_FINAL; } if (nn_slow (aws->state == NN_AWS_STATE_STOPPING_SWS_FINAL)) { if (!nn_sws_isidle (&aws->sws)) return; nn_usock_stop (&aws->usock); aws->state = NN_AWS_STATE_STOPPING; } if (nn_slow (aws->state == NN_AWS_STATE_STOPPING)) { if (!nn_usock_isidle (&aws->usock)) return; if (aws->listener) { nn_assert (aws->listener_owner.fsm); nn_usock_swap_owner (aws->listener, &aws->listener_owner); aws->listener = NULL; aws->listener_owner.src = -1; aws->listener_owner.fsm = NULL; } aws->state = NN_AWS_STATE_IDLE; nn_fsm_stopped (&aws->fsm, NN_AWS_STOPPED); return; } nn_fsm_bad_action (aws->state, src, type); }
static void nn_timer_shutdown (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_timer *timer; timer = nn_cont (self, struct nn_timer, fsm); if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_worker_execute (timer->worker, &timer->stop_task); timer->state = NN_TIMER_STATE_STOPPING; return; } if (nn_slow (timer->state == NN_TIMER_STATE_STOPPING)) { if (src != NN_TIMER_SRC_STOP_TASK) return; nn_assert (type == NN_WORKER_TASK_EXECUTE); nn_worker_rm_timer (timer->worker, &timer->wtimer); timer->state = NN_TIMER_STATE_IDLE; nn_fsm_stopped (&timer->fsm, NN_TIMER_STOPPED); return; } nn_fsm_bad_state(timer->state, src, type); }
static void nn_usock_shutdown (struct nn_fsm *self, int src, int type, NN_UNUSED void *srcptr) { struct nn_usock *usock; usock = nn_cont (self, struct nn_usock, fsm); if (nn_internal_tasks (usock, src, type)) return; if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { /* Socket in ACCEPTING or CANCELLING state cannot be closed. Stop the socket being accepted first. */ nn_assert (usock->state != NN_USOCK_STATE_ACCEPTING && usock->state != NN_USOCK_STATE_CANCELLING); usock->errnum = 0; /* Synchronous stop. */ if (usock->state == NN_USOCK_STATE_IDLE) goto finish3; if (usock->state == NN_USOCK_STATE_DONE) goto finish2; if (usock->state == NN_USOCK_STATE_STARTING || usock->state == NN_USOCK_STATE_ACCEPTED || usock->state == NN_USOCK_STATE_ACCEPTING_ERROR || usock->state == NN_USOCK_STATE_LISTENING) goto finish1; /* When socket that's being accepted is asked to stop, we have to ask the listener socket to stop accepting first. */ if (usock->state == NN_USOCK_STATE_BEING_ACCEPTED) { nn_fsm_action (&usock->asock->fsm, NN_USOCK_ACTION_CANCEL); usock->state = NN_USOCK_STATE_STOPPING_ACCEPT; return; } /* Asynchronous stop. */ if (usock->state != NN_USOCK_STATE_REMOVING_FD) nn_usock_async_stop (usock); usock->state = NN_USOCK_STATE_STOPPING; return; } if (nn_slow (usock->state == NN_USOCK_STATE_STOPPING_ACCEPT)) { nn_assert (src == NN_FSM_ACTION && type == NN_USOCK_ACTION_DONE); goto finish2; } if (nn_slow (usock->state == NN_USOCK_STATE_STOPPING)) { if (src != NN_USOCK_SRC_TASK_STOP) return; nn_assert (type == NN_WORKER_TASK_EXECUTE); nn_worker_rm_fd (usock->worker, &usock->wfd); finish1: nn_closefd (usock->s); usock->s = -1; finish2: usock->state = NN_USOCK_STATE_IDLE; nn_fsm_stopped (&usock->fsm, NN_USOCK_STOPPED); finish3: return; } nn_fsm_bad_state(usock->state, src, type); }
static void nn_aipc_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_aipc *aipc; aipc = nn_cont (self, struct nn_aipc, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_sipc_stop (&aipc->sipc); aipc->state = NN_AIPC_STATE_STOPPING_SIPC_FINAL; } if (nn_slow (aipc->state == NN_AIPC_STATE_STOPPING_SIPC_FINAL)) { if (!nn_sipc_isidle (&aipc->sipc)) return; nn_usock_stop (&aipc->usock); aipc->state = NN_AIPC_STATE_STOPPING; } if (nn_slow (aipc->state == NN_AIPC_STATE_STOPPING)) { if (!nn_usock_isidle (&aipc->usock)) return; if (aipc->listener) { nn_assert (aipc->listener_owner.fsm); nn_usock_swap_owner (aipc->listener, &aipc->listener_owner); aipc->listener = NULL; aipc->listener_owner.src = 1; aipc->listener_owner.fsm = NULL; } aipc->state = NN_AIPC_STATE_IDLE; nn_fsm_stopped (&aipc->fsm, NN_AIPC_STOPPED); return; } switch (aipc->state) { /******************************************************************************/ /* IDLE state. */ /* The state machine wasn't yet started. */ /******************************************************************************/ case NN_AIPC_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_usock_accept (&aipc->usock, aipc->listener); aipc->state = NN_AIPC_STATE_ACCEPTING; return; default: nn_fsm_bad_action (aipc->state, src, type); } default: nn_fsm_bad_source (aipc->state, src, type); } /******************************************************************************/ /* ACCEPTING state. */ /* Waiting for incoming connection. */ /******************************************************************************/ case NN_AIPC_STATE_ACCEPTING: switch (src) { case NN_AIPC_SRC_USOCK: switch (type) { case NN_USOCK_ACCEPTED: /* Return ownership of the listening socket to the parent. */ nn_usock_swap_owner (aipc->listener, &aipc->listener_owner); aipc->listener = NULL; aipc->listener_owner.src = -1; aipc->listener_owner.fsm = NULL; nn_fsm_raise (&aipc->fsm, &aipc->accepted, NN_AIPC_ACCEPTED); /* Start the sipc state machine. */ nn_usock_activate (&aipc->usock); nn_sipc_start (&aipc->sipc, &aipc->usock); aipc->state = NN_AIPC_STATE_ACTIVE; return; default: nn_fsm_bad_action (aipc->state, src, type); } default: nn_fsm_bad_source (aipc->state, src, type); } /******************************************************************************/ /* ACTIVE state. */ /******************************************************************************/ case NN_AIPC_STATE_ACTIVE: switch (src) { case NN_AIPC_SRC_SIPC: switch (type) { case NN_SIPC_ERROR: nn_sipc_stop (&aipc->sipc); aipc->state = NN_AIPC_STATE_STOPPING_SIPC; return; default: nn_fsm_bad_action (aipc->state, src, type); } default: nn_fsm_bad_source (aipc->state, src, type); } /******************************************************************************/ /* STOPPING_SIPC state. */ /******************************************************************************/ case NN_AIPC_STATE_STOPPING_SIPC: switch (src) { case NN_AIPC_SRC_SIPC: switch (type) { case NN_SIPC_STOPPED: nn_usock_stop (&aipc->usock); aipc->state = NN_AIPC_STATE_STOPPING_USOCK; return; default: nn_fsm_bad_action (aipc->state, src, type); } default: nn_fsm_bad_source (aipc->state, src, type); } /******************************************************************************/ /* STOPPING_USOCK state. */ /******************************************************************************/ case NN_AIPC_STATE_STOPPING_USOCK: switch (src) { case NN_AIPC_SRC_USOCK: switch (type) { case NN_USOCK_STOPPED: nn_fsm_raise (&aipc->fsm, &aipc->done, NN_AIPC_ERROR); aipc->state = NN_AIPC_STATE_DONE; return; default: nn_fsm_bad_action (aipc->state, src, type); } default: nn_fsm_bad_source (aipc->state, src, type); } /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (aipc->state, src, type); } }
static void nn_streamhdr_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_streamhdr *streamhdr; struct nn_iovec iovec; int protocol; streamhdr = nn_cont (self, struct nn_streamhdr, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING; } if (nn_slow (streamhdr->state == NN_STREAMHDR_STATE_STOPPING)) { if (!nn_timer_isidle (&streamhdr->timer)) return; streamhdr->state = NN_STREAMHDR_STATE_IDLE; nn_fsm_stopped (&streamhdr->fsm, NN_STREAMHDR_STOPPED); return; } switch (streamhdr->state) { /******************************************************************************/ /* IDLE state. */ /******************************************************************************/ case NN_STREAMHDR_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_timer_start (&streamhdr->timer, 1000); iovec.iov_base = streamhdr->protohdr; iovec.iov_len = sizeof (streamhdr->protohdr); nn_usock_send (streamhdr->usock, &iovec, 1); streamhdr->state = NN_STREAMHDR_STATE_SENDING; return; default: nn_fsm_bad_action (streamhdr->state, src, type); } default: nn_fsm_bad_source (streamhdr->state, src, type); } /******************************************************************************/ /* SENDING state. */ /******************************************************************************/ case NN_STREAMHDR_STATE_SENDING: switch (src) { case NN_STREAMHDR_SRC_USOCK: switch (type) { case NN_USOCK_SENT: nn_usock_recv (streamhdr->usock, streamhdr->protohdr, sizeof (streamhdr->protohdr)); streamhdr->state = NN_STREAMHDR_STATE_RECEIVING; return; case NN_USOCK_ERROR: nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING_TIMER_ERROR; return; default: nn_fsm_bad_action (streamhdr->state, src, type); } case NN_STREAMHDR_SRC_TIMER: switch (type) { case NN_TIMER_TIMEOUT: nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING_TIMER_ERROR; return; default: nn_fsm_bad_action (streamhdr->state, src, type); } default: nn_fsm_bad_source (streamhdr->state, src, type); } /******************************************************************************/ /* RECEIVING state. */ /******************************************************************************/ case NN_STREAMHDR_STATE_RECEIVING: switch (src) { case NN_STREAMHDR_SRC_USOCK: switch (type) { case NN_USOCK_RECEIVED: /* Here we are checking whether the peer speaks the same protocol as this socket. */ if (memcmp (streamhdr->protohdr, "\0SP\0", 4) != 0) goto invalidhdr; protocol = nn_gets (streamhdr->protohdr + 4); if (!nn_pipebase_ispeer (streamhdr->pipebase, protocol)) goto invalidhdr; nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING_TIMER_DONE; return; case NN_USOCK_ERROR: invalidhdr: nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING_TIMER_ERROR; return; default: nn_assert (0); } case NN_STREAMHDR_SRC_TIMER: switch (type) { case NN_TIMER_TIMEOUT: nn_timer_stop (&streamhdr->timer); streamhdr->state = NN_STREAMHDR_STATE_STOPPING_TIMER_ERROR; return; default: nn_fsm_bad_action (streamhdr->state, src, type); } default: nn_fsm_bad_source (streamhdr->state, src, type); } /******************************************************************************/ /* STOPPING_TIMER_ERROR state. */ /******************************************************************************/ case NN_STREAMHDR_STATE_STOPPING_TIMER_ERROR: switch (src) { case NN_STREAMHDR_SRC_TIMER: switch (type) { case NN_TIMER_STOPPED: nn_usock_swap_owner (streamhdr->usock, &streamhdr->usock_owner); streamhdr->usock = NULL; streamhdr->usock_owner.src = -1; streamhdr->usock_owner.fsm = NULL; streamhdr->state = NN_STREAMHDR_STATE_DONE; nn_fsm_raise (&streamhdr->fsm, &streamhdr->done, NN_STREAMHDR_ERROR); return; default: nn_fsm_bad_action (streamhdr->state, src, type); } default: nn_fsm_bad_source (streamhdr->state, src, type); } /******************************************************************************/ /* STOPPING_TIMER_DONE state. */ /******************************************************************************/ case NN_STREAMHDR_STATE_STOPPING_TIMER_DONE: switch (src) { case NN_STREAMHDR_SRC_TIMER: switch (type) { case NN_TIMER_STOPPED: nn_usock_swap_owner (streamhdr->usock, &streamhdr->usock_owner); streamhdr->usock = NULL; streamhdr->usock_owner.src = -1; streamhdr->usock_owner.fsm = NULL; streamhdr->state = NN_STREAMHDR_STATE_DONE; nn_fsm_raise (&streamhdr->fsm, &streamhdr->done, NN_STREAMHDR_OK); return; default: nn_fsm_bad_action (streamhdr->state, src, type); } default: nn_fsm_bad_source (streamhdr->state, src, type); } /******************************************************************************/ /* DONE state. */ /* The header exchange was either done successfully of failed. There's */ /* nothing that can be done in this state except stopping the object. */ /******************************************************************************/ case NN_STREAMHDR_STATE_DONE: nn_fsm_bad_source (streamhdr->state, src, type); /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_fsm_bad_state (streamhdr->state, src, type); } }
static void nn_timer_handler (struct nn_fsm *self, int src, int type, void *srcptr) { struct nn_timer *timer; timer = nn_cont (self, struct nn_timer, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (srcptr == NULL && type == NN_FSM_STOP)) { nn_worker_execute (timer->worker, &timer->stop_task); timer->state = NN_TIMER_STATE_STOPPING; return; } if (nn_slow (timer->state == NN_TIMER_STATE_STOPPING)) { if (srcptr != &timer->stop_task) return; nn_assert (type == NN_WORKER_TASK_EXECUTE); nn_worker_rm_timer (timer->worker, &timer->wtimer); timer->state = NN_TIMER_STATE_IDLE; nn_fsm_stopped (&timer->fsm, NN_TIMER_STOPPED); return; } switch (timer->state) { /******************************************************************************/ /* IDLE state. */ /******************************************************************************/ case NN_TIMER_STATE_IDLE: if (srcptr == NULL) { switch (type) { case NN_FSM_START: /* Send start event to the worker thread. */ nn_worker_execute (timer->worker, &timer->start_task); timer->state = NN_TIMER_STATE_ACTIVE; return; default: nn_assert (0); } } nn_assert (0); /******************************************************************************/ /* ACTIVE state. */ /******************************************************************************/ case NN_TIMER_STATE_ACTIVE: if (srcptr == &timer->start_task) { nn_assert (type == NN_WORKER_TASK_EXECUTE); nn_assert (timer->timeout >= 0); nn_worker_add_timer (timer->worker, timer->timeout, &timer->wtimer); timer->timeout = -1; return; } if (srcptr == &timer->wtimer) { switch (type) { case NN_WORKER_TIMER_TIMEOUT: /* Notify the user about the timeout. */ nn_assert (timer->timeout == -1); nn_fsm_raise (&timer->fsm, &timer->done, NN_TIMER_TIMEOUT); return; default: nn_assert (0); } } nn_assert (0); /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_assert (0); } }
static void nn_stcp_handler (struct nn_fsm *self, int src, int type, void *srcptr) { int rc; struct nn_stcp *stcp; uint64_t size; stcp = nn_cont (self, struct nn_stcp, fsm); /******************************************************************************/ /* STOP procedure. */ /******************************************************************************/ if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) { nn_pipebase_stop (&stcp->pipebase); nn_streamhdr_stop (&stcp->streamhdr); stcp->state = NN_STCP_STATE_STOPPING; } if (nn_slow (stcp->state == NN_STCP_STATE_STOPPING)) { if (nn_streamhdr_isidle (&stcp->streamhdr)) { nn_usock_swap_owner (stcp->usock, &stcp->usock_owner); stcp->usock = NULL; stcp->usock_owner.src = -1; stcp->usock_owner.fsm = NULL; stcp->state = NN_STCP_STATE_IDLE; nn_fsm_stopped (&stcp->fsm, NN_STCP_STOPPED); return; } return; } switch (stcp->state) { /******************************************************************************/ /* IDLE state. */ /******************************************************************************/ case NN_STCP_STATE_IDLE: switch (src) { case NN_FSM_ACTION: switch (type) { case NN_FSM_START: nn_streamhdr_start (&stcp->streamhdr, stcp->usock, &stcp->pipebase); stcp->state = NN_STCP_STATE_PROTOHDR; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* PROTOHDR state. */ /******************************************************************************/ case NN_STCP_STATE_PROTOHDR: switch (src) { case NN_STCP_SRC_STREAMHDR: switch (type) { case NN_STREAMHDR_OK: /* Before moving to the active state stop the streamhdr state machine. */ nn_streamhdr_stop (&stcp->streamhdr); stcp->state = NN_STCP_STATE_STOPPING_STREAMHDR; return; case NN_STREAMHDR_ERROR: /* Raise the error and move directly to the DONE state. streamhdr object will be stopped later on. */ stcp->state = NN_STCP_STATE_DONE; nn_fsm_raise (&stcp->fsm, &stcp->done, NN_STCP_ERROR); return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* STOPPING_STREAMHDR state. */ /******************************************************************************/ case NN_STCP_STATE_STOPPING_STREAMHDR: switch (src) { case NN_STCP_SRC_STREAMHDR: switch (type) { case NN_STREAMHDR_STOPPED: /* Start the pipe. */ rc = nn_pipebase_start (&stcp->pipebase); errnum_assert (rc == 0, -rc); /* Start receiving a message in asynchronous manner. */ stcp->instate = NN_STCP_INSTATE_HDR; nn_usock_recv (stcp->usock, &stcp->inhdr, sizeof (stcp->inhdr)); /* Mark the pipe as available for sending. */ stcp->outstate = NN_STCP_OUTSTATE_IDLE; stcp->state = NN_STCP_STATE_ACTIVE; return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* ACTIVE state. */ /******************************************************************************/ case NN_STCP_STATE_ACTIVE: switch (src) { case NN_STCP_SRC_USOCK: switch (type) { case NN_USOCK_SENT: /* The message is now fully sent. */ nn_assert (stcp->outstate == NN_STCP_OUTSTATE_SENDING); stcp->outstate = NN_STCP_OUTSTATE_IDLE; nn_msg_term (&stcp->outmsg); nn_msg_init (&stcp->outmsg, 0); nn_pipebase_sent (&stcp->pipebase); return; case NN_USOCK_RECEIVED: switch (stcp->instate) { case NN_STCP_INSTATE_HDR: /* Message header was received. Allocate memory for the message. */ size = nn_getll (stcp->inhdr); nn_msg_term (&stcp->inmsg); nn_msg_init (&stcp->inmsg, (size_t) size); /* Special case when size of the message body is 0. */ if (!size) { stcp->instate = NN_STCP_INSTATE_HASMSG; nn_pipebase_received (&stcp->pipebase); return; } /* Start receiving the message body. */ stcp->instate = NN_STCP_INSTATE_BODY; nn_usock_recv (stcp->usock, nn_chunkref_data (&stcp->inmsg.body), (size_t) size); return; case NN_STCP_INSTATE_BODY: /* Message body was received. Notify the owner that it can receive it. */ stcp->instate = NN_STCP_INSTATE_HASMSG; nn_pipebase_received (&stcp->pipebase); return; default: nn_assert (0); } case NN_USOCK_ERROR: nn_pipebase_stop (&stcp->pipebase); stcp->state = NN_STCP_STATE_DONE; nn_fsm_raise (&stcp->fsm, &stcp->done, NN_STCP_ERROR); return; default: nn_assert (0); } default: nn_assert (0); } /******************************************************************************/ /* DONE state. */ /* The underlying connection is closed. There's nothing that can be done in */ /* this state except stopping the object. */ /******************************************************************************/ case NN_STCP_STATE_DONE: nn_assert (0); /******************************************************************************/ /* Invalid state. */ /******************************************************************************/ default: nn_assert (0); } }