Пример #1
0
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);
    }
}
Пример #2
0
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);
    }
}