Esempio n. 1
0
static int nn_surveyor_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_surveyor *surveyor;

    surveyor = nn_cont (self, struct nn_surveyor, xsurveyor.sockbase);

    /*  Cancel any ongoing survey. */
    if (nn_slow (surveyor->flags & NN_SURVEYOR_INPROGRESS)) {
        surveyor->flags &= ~NN_SURVEYOR_INPROGRESS;
        nn_timer_stop (&surveyor->deadline_timer);
    }

    /*  Generate new survey ID. */
    ++surveyor->surveyid;

    /*  Tag the survey body with survey ID. */
    nn_assert (nn_chunkref_size (&msg->hdr) == 0);
    nn_chunkref_term (&msg->hdr);
    nn_chunkref_init (&msg->hdr, 4);
    nn_putl (nn_chunkref_data (&msg->hdr), surveyor->surveyid);

    /*  Send the survey. */
    rc = nn_xsurveyor_send (&surveyor->xsurveyor.sockbase, msg);
    errnum_assert (rc == 0, -rc);

    surveyor->flags |= NN_SURVEYOR_INPROGRESS;

    /*  Set up the re-send timer. */
    nn_timer_start (&surveyor->deadline_timer, surveyor->deadline);

    return 0;
}
Esempio n. 2
0
static void nn_req_in (struct nn_sockbase *self, struct nn_pipe *pipe)
{
    int rc;
    struct nn_req *req;
    uint32_t reqid;

    req = nn_cont (self, struct nn_req, xreq.sockbase);

    /*  Pass the pipe to the raw REQ socket. */
    nn_xreq_in (&req->xreq.sockbase, pipe);

    while (1) {

        /*  Get new reply. */
        rc = nn_xreq_recv (&req->xreq.sockbase, &req->reply);
        if (nn_slow (rc == -EAGAIN))
            return;
        errnum_assert (rc == 0, -rc);

        /*  No request was sent. Getting a reply doesn't make sense. */
        if (nn_slow (req->state != NN_REQ_STATE_SENT)) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Ignore malformed replies. */
        if (nn_slow (nn_chunkref_size (&req->reply.hdr) != sizeof (uint32_t))) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Ignore replies with incorrect request IDs. */
        reqid = nn_getl (nn_chunkref_data (&req->reply.hdr));
        if (nn_slow (!(reqid & 0x80000000))) {
            nn_msg_term (&req->reply);
            continue;
        }
        if (nn_slow (reqid != (req->reqid | 0x80000000))) {
            nn_msg_term (&req->reply);
            continue;
        }

        /*  Trim the request ID. */
        nn_chunkref_term (&req->reply.hdr);
        nn_chunkref_init (&req->reply.hdr, 0);

        /*  Swtich to RECEIVED state. */
        nn_timer_stop (&req->resend_timer);
        nn_msg_term (&req->request);
        req->state = NN_REQ_STATE_RECEIVED;

        return;
    }
}
Esempio n. 3
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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
static void nn_stream_hdr_received (const struct nn_cp_sink **self,
    struct nn_usock *usock)
{
    struct nn_stream *stream;
    int protocol;

    stream = nn_cont (self, struct nn_stream, sink);

    stream->sink = &nn_stream_state_active;
    nn_timer_stop (&stream->hdr_timeout);

    /*  TODO: If it does not conform, drop the connection. */
    protocol = nn_gets (stream->protohdr + 4);
    if (!nn_pipebase_ispeer (&stream->pipebase, protocol))
        nn_assert (0);

    /*  Connection is ready for sending. Make outpipe available
        to the SP socket. */
    nn_pipebase_activate (&stream->pipebase);

    /*  Start waiting for incoming messages. First, read the 8-byte size. */
    stream->instate = NN_STREAM_INSTATE_HDR;
    nn_usock_recv (stream->usock, stream->inhdr, 8);
}
Esempio n. 6
0
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);
    }
}
Esempio n. 7
0
void nn_backoff_stop (struct nn_backoff *self)
{
    nn_timer_stop (&self->timer);
}
Esempio n. 8
0
static void nn_surveyor_handler (struct nn_fsm *self, int src, int type,
    NN_UNUSED void *srcptr)
{
    struct nn_surveyor *surveyor;

    surveyor = nn_cont (self, struct nn_surveyor, fsm);

    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:
                nn_surveyor_resend (surveyor);
                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;
                surveyor->timedout = NN_SURVEYOR_TIMEDOUT;
                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:
                nn_surveyor_resend (surveyor);
                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_FSM_ACTION:
            switch (type) {
            case NN_SURVEYOR_ACTION_CANCEL:
                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_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);
    }
}
Esempio n. 9
0
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);
    }
}
Esempio n. 10
0
void nn_req_handler (struct nn_fsm *self, int src, int type,
    NN_UNUSED void *srcptr)
{
    struct nn_req *req;

    req = nn_cont (self, struct nn_req, fsm);

    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_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  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, 1);
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  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, 0);
                return;
            case NN_REQ_ACTION_SENT:
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  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->task.timer);
                req->task.sent_to = NULL;
                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->task.timer);
                req->task.sent_to = NULL;
                req->state = NN_REQ_STATE_CANCELLING;
                return;

            case NN_REQ_ACTION_PIPE_RM:
                /*  Pipe that we sent request to is removed  */
                nn_timer_stop (&req->task.timer);
                req->task.sent_to = NULL;
                /*  Pretend we timed out so request resent immediately  */
                req->state = NN_REQ_STATE_TIMED_OUT;
                return;

            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        case NN_REQ_SRC_RESEND_TIMER:
            switch (type) {
            case NN_TIMER_TIMEOUT:
                nn_timer_stop (&req->task.timer);
                req->task.sent_to = NULL;
                req->state = NN_REQ_STATE_TIMED_OUT;
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  TIMED_OUT state.                                                          */
/*  Waiting for reply has timed 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, 1);
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        case NN_FSM_ACTION:
            switch (type) {
            case NN_REQ_ACTION_SENT:
                req->state = NN_REQ_STATE_CANCELLING;
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  CANCELLING state.                                                         */
/*  Request was canceled. Waiting till the timer is stopped. Note that        */
/*  cancelling is done by sending a new request. Thus there's already         */
/*  a request waiting to be sent in this state.                               */
/******************************************************************************/
    case NN_REQ_STATE_CANCELLING:
        switch (src) {

        case NN_REQ_SRC_RESEND_TIMER:
            switch (type) {
            case NN_TIMER_STOPPED:

                /*  Timer is stopped. Now we can send the delayed request. */
                nn_req_action_send (req, 1);
                return;

            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        case NN_FSM_ACTION:
             switch (type) {
             case NN_REQ_ACTION_SENT:

                 /*  No need to do anything here. Old delayed request is just
                     replaced by the new one that will be sent once the timer
                     is closed. */
                 return;

             default:
                 nn_fsm_bad_action (req->state, src, type);
             }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  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_fsm_bad_action (req->state, src, type);
            }

        case NN_FSM_ACTION:
            switch (type) {
            case NN_REQ_ACTION_SENT:
                req->state = NN_REQ_STATE_CANCELLING;
                return;
            default:
                nn_fsm_bad_action (req->state, src, type);
            }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  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, 1);
                 return;
             default:
                 nn_fsm_bad_action (req->state, src, type);
             }

        default:
            nn_fsm_bad_source (req->state, src, type);
        }

/******************************************************************************/
/*  Invalid state.                                                            */
/******************************************************************************/
    default:
        nn_fsm_bad_state (req->state, src, type);
    }
}
Esempio n. 11
0
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);
    }
}