Beispiel #1
0
int nn_sockbase_init (struct nn_sockbase *self,
                      const struct nn_sockbase_vfptr *vfptr)
{
    int rc;

    /* Make sure that at least one message direction is supported. */
    nn_assert (!(vfptr->flags & NN_SOCKBASE_FLAG_NOSEND) ||
               !(vfptr->flags & NN_SOCKBASE_FLAG_NORECV));

    /*  Open the NN_SNDFD and NN_RCVFD efds. Do so, only if the socket type
        supports send/recv, as appropriate. */
    if (vfptr->flags & NN_SOCKBASE_FLAG_NOSEND)
        memset (&self->sndfd, 0xcd, sizeof (self->sndfd));
    else {
        rc = nn_efd_init (&self->sndfd);
        if (nn_slow (rc < 0))
            return rc;
    }
    if (vfptr->flags & NN_SOCKBASE_FLAG_NORECV)
        memset (&self->rcvfd, 0xcd, sizeof (self->rcvfd));
    else {
        rc = nn_efd_init (&self->rcvfd);
        if (nn_slow (rc < 0)) {
            if (!(vfptr->flags & NN_SOCKBASE_FLAG_NOSEND))
                nn_efd_term (&self->sndfd);
            return rc;
        }
    }
    memset (&self->termsem, 0xcd, sizeof (self->termsem));
    rc = nn_cp_init (&self->cp);
    if (nn_slow (rc < 0)) {
        if (!(vfptr->flags & NN_SOCKBASE_FLAG_NORECV))
            nn_efd_term (&self->rcvfd);
        if (!(vfptr->flags & NN_SOCKBASE_FLAG_NOSEND))
            nn_efd_term (&self->sndfd);
        return rc;
    }

    self->vfptr = vfptr;
    self->flags = 0;
    nn_clock_init (&self->clock);
    nn_list_init (&self->eps);
    self->eid = 1;

    /*  Default values for NN_SOL_SOCKET options. */
    self->domain = -1;
    self->protocol = -1;
    self->linger = 1000;
    self->sndbuf = 128 * 1024;
    self->rcvbuf = 128 * 1024;
    self->sndtimeo = -1;
    self->rcvtimeo = -1;
    self->reconnect_ivl = 100;
    self->reconnect_ivl_max = 0;
    self->sndprio = 8;
    self->rcvprio = 8;

    return 0;
}
Beispiel #2
0
int nn_sock_destroy (struct nn_sock *self)
{
    int rc;
    struct nn_sockbase *sockbase;
    struct nn_list_item *it;
    struct nn_epbase *ep;

    sockbase = (struct nn_sockbase*) self;

    nn_cp_lock (&sockbase->cp);

    /*  The call may have been interrupted by a singal and restarted afterwards.
        In such case don't do the following stuff again. */
    if (!(sockbase->flags & NN_SOCK_FLAG_CLOSING)) {

        /*  Mark the socket as being in process of shutting down. */
        sockbase->flags |= NN_SOCK_FLAG_CLOSING;

        /*  Close sndfd and rcvfd. This should make any current select/poll
            using SNDFD and/or RCVFD exit. */
        if (!(sockbase->vfptr->flags & NN_SOCKBASE_FLAG_NORECV)) {
            nn_efd_term (&sockbase->rcvfd);
            memset (&sockbase->rcvfd, 0xcd, sizeof (sockbase->rcvfd));
        }
        if (!(sockbase->vfptr->flags & NN_SOCKBASE_FLAG_NOSEND)) {
            nn_efd_term (&sockbase->sndfd);
            memset (&sockbase->sndfd, 0xcd, sizeof (sockbase->sndfd));
        }

        /*  Create a semaphore to wait on for all endpoint to terminate. */
        nn_sem_init (&sockbase->termsem);

        /*  Ask all the associated endpoints to terminate. Call to nn_ep_close
            can actually deallocate the endpoint, so take care to get pointer
            to the next endpoint before the call. */
        it = nn_list_begin (&sockbase->eps);
        while (it != nn_list_end (&sockbase->eps)) {
            ep = nn_cont (it, struct nn_epbase, item);
            it = nn_list_next (&sockbase->eps, it);
            rc = nn_ep_close ((void*) ep);
            errnum_assert (rc == 0 || rc == -EINPROGRESS, -rc);
        }
    }
Beispiel #3
0
static void nn_sock_shutdown (struct nn_fsm *self, int src, int type,
    void *srcptr)
{
    struct nn_sock *sock;
    struct nn_list_item *it;
    struct nn_ep *ep;

    sock = nn_cont (self, struct nn_sock, fsm);

    if (nn_slow (src == NN_FSM_ACTION && type == NN_FSM_STOP)) {
        nn_assert (sock->state == NN_SOCK_STATE_ACTIVE ||
            sock->state == NN_SOCK_STATE_ZOMBIE);

        /*  Close sndfd and rcvfd. This should make any current
            select/poll using SNDFD and/or RCVFD exit. */
        if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NORECV)) {
            nn_efd_term (&sock->rcvfd);
            memset (&sock->rcvfd, 0xcd, sizeof (sock->rcvfd));
        }
        if (!(sock->socktype->flags & NN_SOCKTYPE_FLAG_NOSEND)) {
            nn_efd_term (&sock->sndfd);
            memset (&sock->sndfd, 0xcd, sizeof (sock->sndfd));
        }

        /*  Ask all the associated endpoints to stop. */
        it = nn_list_begin (&sock->eps);
        while (it != nn_list_end (&sock->eps)) {
            ep = nn_cont (it, struct nn_ep, item);
            it = nn_list_next (&sock->eps, it);
            nn_list_erase (&sock->eps, &ep->item);
            nn_list_insert (&sock->sdeps, &ep->item,
                nn_list_end (&sock->sdeps));
            nn_ep_stop (ep);

        }
        sock->state = NN_SOCK_STATE_STOPPING_EPS;
        goto finish2;
    }
Beispiel #4
0
void nn_worker_term (struct nn_worker *self)
{
    /*  Ask worker thread to terminate. */
    nn_mutex_lock (&self->sync);
    nn_queue_push (&self->tasks, &self->stop);
    nn_efd_signal (&self->efd);
    nn_mutex_unlock (&self->sync);

    /*  Wait till worker thread terminates. */
    nn_thread_term (&self->thread);

    /*  Clean up. */
    nn_timerset_term (&self->timerset);
    nn_poller_term (&self->poller);
    nn_efd_term (&self->efd);
    nn_queue_item_term (&self->stop);
    nn_queue_term (&self->tasks);
    nn_mutex_term (&self->sync);
}
Beispiel #5
0
/*  Initialize a socket.  A hold is placed on the initialized socket for
    the caller as well. */
int nn_sock_init (struct nn_sock *self, struct nn_socktype *socktype, int fd)
{
    int rc;
    int i;

    /* Make sure that at least one message direction is supported. */
    nn_assert (!(socktype->flags & NN_SOCKTYPE_FLAG_NOSEND) ||
        !(socktype->flags & NN_SOCKTYPE_FLAG_NORECV));

    /*  Create the AIO context for the SP socket. */
    nn_ctx_init (&self->ctx, nn_global_getpool (), nn_sock_onleave);

    /*  Initialise the state machine. */
    nn_fsm_init_root (&self->fsm, nn_sock_handler,
        nn_sock_shutdown, &self->ctx);
    self->state = NN_SOCK_STATE_INIT;

    /*  Open the NN_SNDFD and NN_RCVFD efds. Do so, only if the socket type
        supports send/recv, as appropriate. */
    if (socktype->flags & NN_SOCKTYPE_FLAG_NOSEND)
        memset (&self->sndfd, 0xcd, sizeof (self->sndfd));
    else {
        rc = nn_efd_init (&self->sndfd);
        if (nn_slow (rc < 0))
            return rc;
    }
    if (socktype->flags & NN_SOCKTYPE_FLAG_NORECV)
        memset (&self->rcvfd, 0xcd, sizeof (self->rcvfd));
    else {
        rc = nn_efd_init (&self->rcvfd);
        if (nn_slow (rc < 0)) {
            if (!(socktype->flags & NN_SOCKTYPE_FLAG_NOSEND))
                nn_efd_term (&self->sndfd);
            return rc;
        }
    }
    nn_sem_init (&self->termsem);
    nn_sem_init (&self->relesem);
    if (nn_slow (rc < 0)) {
        if (!(socktype->flags & NN_SOCKTYPE_FLAG_NORECV))
            nn_efd_term (&self->rcvfd);
        if (!(socktype->flags & NN_SOCKTYPE_FLAG_NOSEND))
            nn_efd_term (&self->sndfd);
        return rc;
    }

    self->holds = 1;   /*  Callers hold. */
    self->flags = 0;
    nn_clock_init (&self->clock);
    nn_list_init (&self->eps);
    nn_list_init (&self->sdeps);
    self->eid = 1;

    /*  Default values for NN_SOL_SOCKET options. */
    self->linger = 1000;
    self->sndbuf = 128 * 1024;
    self->rcvbuf = 128 * 1024;
    self->rcvmaxsize = 1024 * 1024;
    self->sndtimeo = -1;
    self->rcvtimeo = -1;
    self->reconnect_ivl = 100;
    self->reconnect_ivl_max = 0;
    self->ep_template.sndprio = 8;
    self->ep_template.rcvprio = 8;
    self->ep_template.ipv4only = 1;

    /* Initialize statistic entries */
    self->statistics.established_connections = 0;
    self->statistics.accepted_connections = 0;
    self->statistics.dropped_connections = 0;
    self->statistics.broken_connections = 0;
    self->statistics.connect_errors = 0;
    self->statistics.bind_errors = 0;
    self->statistics.accept_errors = 0;

    self->statistics.messages_sent = 0;
    self->statistics.messages_received = 0;
    self->statistics.bytes_sent = 0;
    self->statistics.bytes_received = 0;

    self->statistics.current_connections = 0;
    self->statistics.inprogress_connections = 0;
    self->statistics.current_snd_priority = 0;
    self->statistics.current_ep_errors = 0;

    /*  Should be pretty much enough space for just the number  */
    sprintf(self->socket_name, "%d", fd);

    /*  The transport-specific options are not initialised immediately,
        rather, they are allocated later on when needed. */
    for (i = 0; i != NN_MAX_TRANSPORT; ++i)
        self->optsets [i] = NULL;

    /*  Create the specific socket type itself. */
    rc = socktype->create ((void*) self, &self->sockbase);
    errnum_assert (rc == 0, -rc);
    self->socktype = socktype;

    /*  Launch the state machine. */
    nn_ctx_enter (&self->ctx);
    nn_fsm_start (&self->fsm);
    nn_ctx_leave (&self->ctx);

    return 0;
}