Пример #1
0
void nn_pipebase_getopt(struct nn_pipebase *self, int level, int option,void *optval, size_t *optvallen)
{
    int rc,intval;

    if ( level == NN_SOL_SOCKET )
    {
        switch (option)
        {
        /*  Endpoint options  */
        case NN_SNDPRIO:
            intval = self->options.sndprio;
            break;
        case NN_RCVPRIO:
            intval = self->options.rcvprio;
            break;
        case NN_IPV4ONLY:
            intval = self->options.ipv4only;
            break;

        /*  Fallback to socket options  */
        default:
            rc = nn_sock_getopt_inner(self->sock, level,option, optval, optvallen);
            errnum_assert (rc == 0, -rc);
            return;
        }
        memcpy (optval, &intval,*optvallen < sizeof (int) ? *optvallen : sizeof (int));
        *optvallen = sizeof (int);
        return;
    }
    rc = nn_sock_getopt_inner (self->sock, level, option, optval, optvallen);
    errnum_assert (rc == 0, -rc);
}
Пример #2
0
static int nn_xsub_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xsub *xsub;

    xsub = nn_cont (self, struct nn_xsub, sockbase);

    /*  Loop while a matching message is found or when there are no more
        messages to receive. */
    while (1) {
        rc = nn_fq_recv (&xsub->fq, msg, NULL);
        if (nn_slow (rc == -EAGAIN))
            return -EAGAIN;
        errnum_assert (rc >= 0, -rc);
        rc = nn_trie_match (&xsub->trie, nn_chunkref_data (&msg->body),
            nn_chunkref_size (&msg->body));
        if (rc == 0) {
            nn_msg_term (msg);
            continue;
        }
        if (rc == 1)
            return 0;
        errnum_assert (0, -rc);
    }
}
Пример #3
0
static void nn_bipc_start_listening (struct nn_bipc *self)
{
    int rc;
    struct sockaddr_storage ss;
    struct sockaddr_un *un;
    const char *addr;

    /*  First, create the AF_UNIX address. */
    addr = nn_epbase_getaddr (&self->epbase);
    memset (&ss, 0, sizeof (ss));
    un = (struct sockaddr_un*) &ss;
    nn_assert (strlen (addr) < sizeof (un->sun_path));
    ss.ss_family = AF_UNIX;
    strncpy (un->sun_path, addr, sizeof (un->sun_path));

    /*  Delete the IPC file left over by eventual previous runs of
        the application. */
    rc = unlink (addr);
    errno_assert (rc == 0 || errno == ENOENT);

    /*  Start listening for incoming connections. */
    rc = nn_usock_start (&self->usock, AF_UNIX, SOCK_STREAM, 0);
    /*  TODO: EMFILE error can happen here. We can wait a bit and re-try. */
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_bind (&self->usock,
        (struct sockaddr*) &ss, sizeof (struct sockaddr_un));
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_listen (&self->usock, NN_BIPC_BACKLOG);
    errnum_assert (rc == 0, -rc);
}
Пример #4
0
int nn_sem_wait (struct nn_sem *myself)
{
    int rc;

    /*  With OSX, semaphores are global named objects. They are not useful for
        our use case. To get a similar object we exploit the implementation
        detail of pthread_cond_wait() in Darwin kernel: It exits if signal is
        caught. Note that this behaviour is not mandated by POSIX
        and may break with future versions of Darwin. */
    rc = pthread_mutex_lock (&myself->mutex);
    errnum_assert (rc == 0, rc);
    if (nn_fast (myself->signaled)) {
        rc = pthread_mutex_unlock (&myself->mutex);
        errnum_assert (rc == 0, rc);
        return 0;
    }
    rc = pthread_cond_wait (&myself->cond, &myself->mutex);
    errnum_assert (rc == 0, rc);
    if (nn_slow (!myself->signaled)) {
        rc = pthread_mutex_unlock (&myself->mutex);
        errnum_assert (rc == 0, rc);
        return -EINTR;
    }
    myself->signaled = 0;
    rc = pthread_mutex_unlock (&myself->mutex);
    errnum_assert (rc == 0, rc);

    return 0;
}
Пример #5
0
static int nn_ipc_binit (const char *addr, struct nn_usock *usock,
    struct nn_cp *cp, int backlog)
{
    int rc;
    struct sockaddr_storage ss;
    socklen_t sslen;
    struct sockaddr_un *un;

    /*  Create the AF_UNIX address. */
    memset (&ss, 0, sizeof (ss));
    un = (struct sockaddr_un*) &ss;
    if (strlen (addr) >= sizeof (un->sun_path))
        return -ENAMETOOLONG;
    ss.ss_family = AF_UNIX;
    strncpy (un->sun_path, addr, sizeof (un->sun_path));
    sslen = sizeof (struct sockaddr_un);

    /*  Delete the ipc file left over by eventual previous runs of
        the application. */
    rc = unlink (addr);
    errno_assert (rc == 0 || errno == ENOENT);

    /*  Open the listening socket. */
    rc = nn_usock_init (usock, NULL, AF_UNIX, SOCK_STREAM, 0, -1, -1, cp);
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_bind (usock, (struct sockaddr*) &ss, sslen);
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_listen (usock, backlog);
    errnum_assert (rc == 0, -rc);

    return 0;
}
Пример #6
0
void nn_sem_term (struct nn_sem *myself)
{
    int rc;

    rc = pthread_cond_destroy (&myself->cond);
    errnum_assert (rc == 0, rc);
    rc = pthread_mutex_destroy (&myself->mutex);
    errnum_assert (rc == 0, rc);
}
Пример #7
0
void nn_sem_init (struct nn_sem *myself)
{
    int rc;

    rc = pthread_mutex_init (&myself->mutex, NULL);
    errnum_assert (rc == 0, rc);
    rc = pthread_cond_init (&myself->cond, NULL);
    errnum_assert (rc == 0, rc);
    myself->signaled = 0;
}
Пример #8
0
static void nn_btcp_start_listening (struct nn_btcp *self)
{
    int rc;
    struct sockaddr_storage ss;
    size_t sslen;
    int ipv4only;
    size_t ipv4onlylen;
    const char *addr;
    const char *end;
    const char *pos;
    uint16_t port;

    /*  First, resolve the IP address. */
    addr = nn_epbase_getaddr (&self->epbase);
    memset (&ss, 0, sizeof (ss));

    /*  Parse the port. */
    end = addr + strlen (addr);
    pos = strrchr (addr, ':');
    nn_assert (pos);
    ++pos;
    rc = nn_port_resolve (pos, end - pos);
    nn_assert (rc >= 0);
    port = rc;

    /*  Parse the address. */
    ipv4onlylen = sizeof (ipv4only);
    nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_IPV4ONLY,
        &ipv4only, &ipv4onlylen);
    nn_assert (ipv4onlylen == sizeof (ipv4only));
    rc = nn_iface_resolve (addr, pos - addr - 1, ipv4only, &ss, &sslen);
    errnum_assert (rc == 0, -rc);

    /*  Combine the port and the address. */
    if (ss.ss_family == AF_INET) {
        ((struct sockaddr_in*) &ss)->sin_port = htons (port);
        sslen = sizeof (struct sockaddr_in);
    }
    else if (ss.ss_family == AF_INET6) {
        ((struct sockaddr_in6*) &ss)->sin6_port = htons (port);
        sslen = sizeof (struct sockaddr_in6);
    }
    else
        nn_assert (0);

    /*  Start listening for incoming connections. */
    rc = nn_usock_start (&self->usock, ss.ss_family, SOCK_STREAM, 0);
    /*  TODO: EMFILE error can happen here. We can wait a bit and re-try. */
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_bind (&self->usock, (struct sockaddr*) &ss, (size_t) sslen);
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_listen (&self->usock, NN_BTCP_BACKLOG);
    errnum_assert (rc == 0, -rc);
}
Пример #9
0
void xs_sock_term (xs_sock *self)
{
    int rc;

    xs_tcpout_term (&self->out);
    rc = pthread_cond_destroy (&self->readable);
    errnum_assert (rc);
    rc = pthread_cond_destroy (&self->writeable);
    errnum_assert (rc);
    xs_mutex_term (&self->sync);
}
Пример #10
0
int nn_sock_term (struct nn_sock *self)
{
    int rc;
    int i;

    /*  NOTE: nn_sock_stop must have already been called. */

    /*  Some endpoints may still be alive.  Here we are going to wait
        till they are all closed.  This loop is not interruptible, because
        making it so would leave a partially cleaned up socket, and we don't
        have a way to defer resource deallocation. */
    for (;;) {
        rc = nn_sem_wait (&self->termsem);
        if (nn_slow (rc == -EINTR))
            continue;
        errnum_assert (rc == 0, -rc);
        break;
    }

    /*  Also, wait for all holds on the socket to be released.  */
    for (;;) {
        rc = nn_sem_wait (&self->relesem);
        if (nn_slow (rc == -EINTR))
            continue;
        errnum_assert (rc == 0, -rc);
        break;
    }

    /*  Threads that posted the semaphore(s) can still have the ctx locked
        for a short while. By simply entering the context and exiting it
        immediately we can be sure that any such threads have already
        exited the context. */
    nn_ctx_enter (&self->ctx);
    nn_ctx_leave (&self->ctx);

    /*  At this point, we can be reasonably certain that no other thread
        has any references to the socket. */

    nn_fsm_stopped_noevent (&self->fsm);
    nn_fsm_term (&self->fsm);
    nn_sem_term (&self->termsem);
    nn_list_term (&self->sdeps);
    nn_list_term (&self->eps);
    nn_clock_term (&self->clock);
    nn_ctx_term (&self->ctx);

    /*  Destroy any optsets associated with the socket. */
    for (i = 0; i != NN_MAX_TRANSPORT; ++i)
        if (self->optsets [i])
            self->optsets [i]->vfptr->destroy (self->optsets [i]);

    return 0;
}
Пример #11
0
void nn_sem_post (struct nn_sem *myself)
{
    int rc;

    rc = pthread_mutex_lock (&myself->mutex);
    errnum_assert (rc == 0, rc);
    nn_assert (myself->signaled == 0);
    myself->signaled = 1;
    rc = pthread_cond_signal (&myself->cond);
    errnum_assert (rc == 0, rc);
    rc = pthread_mutex_unlock (&myself->mutex);
    errnum_assert (rc == 0, rc);
}
Пример #12
0
static int nn_tcp_cresolve (const char *addr, struct sockaddr_storage *local,
    socklen_t *locallen, struct sockaddr_storage *remote, socklen_t *remotelen)
{
    int rc;
    int port;
    const char *end;
    const char *colon;
    const char *semicolon;
    int res;

    res = 0;

    /*  Make sure we're working from a clean slate. Required on Mac OS X. */
    memset (remote, 0, sizeof (struct sockaddr_storage));

    /*  Parse the port. */
    end = addr + strlen (addr);
    colon = strrchr (addr, ':');
    port = nn_addr_parse_port (colon + 1, end - colon - 1);
    if (nn_slow (port == -EINVAL))
        return -EINVAL;
    errnum_assert (port > 0, -port);

    /*  Parse the local address, if any. */
    semicolon = strchr (addr, ';');
    if (semicolon) {
        memset (local, 0, sizeof (struct sockaddr_storage));
        rc = nn_addr_parse_local (addr, semicolon - addr, NN_ADDR_IPV4ONLY,
            local, locallen);
        errnum_assert (rc == 0, -rc);
        addr = semicolon + 1;
        res |= NN_CSTREAM_DOBIND;
    }

    /*  Parse the remote address. */
    /*  TODO:  Get the actual value of the IPV4ONLY socket option. */
    rc = nn_addr_parse_remote (addr, colon - addr, NN_ADDR_IPV4ONLY,
        remote, remotelen);
    if (nn_slow (rc < 0))
        return rc;

    /*  Combine the port and the address. */
    if (remote->ss_family == AF_INET)
        ((struct sockaddr_in*) remote)->sin_port = htons (port);
    else if (remote->ss_family == AF_INET6)
        ((struct sockaddr_in6*) remote)->sin6_port = htons (port);
    else
        nn_assert (0);

    return res;
}
Пример #13
0
static int nn_tcp_binit (const char *addr, struct nn_usock *usock,
    struct nn_cp *cp, int backlog)
{
    int rc;
    int port;
    const char *end;
    const char *pos;
    struct sockaddr_storage ss;
    socklen_t sslen;

    /*  Make sure we're working from a clean slate. Required on Mac OS X. */
    memset (&ss, 0, sizeof (ss));

    /*  Parse the port. */
    end = addr + strlen (addr);
    pos = strrchr (addr, ':');
    if (!pos)
        return -EINVAL;
    ++pos;
    rc = nn_addr_parse_port (pos, end - pos);
    if (rc < 0)
        return rc;
    port = rc;

    /*  Parse the address. */
    /*  TODO:  Get the actual value of the IPV4ONLY socket option. */
    rc = nn_addr_parse_local (addr, pos - addr - 1, NN_ADDR_IPV4ONLY,
        &ss, &sslen);
    if (rc < 0)
        return rc;

    /*  Combine the port and the address. */
    if (ss.ss_family == AF_INET)
        ((struct sockaddr_in*) &ss)->sin_port = htons (port);
    else if (ss.ss_family == AF_INET6)
        ((struct sockaddr_in6*) &ss)->sin6_port = htons (port);
    else
        nn_assert (0);

    /*  Open the listening socket. */
    rc = nn_usock_init (usock, NULL, AF_INET, SOCK_STREAM, IPPROTO_TCP,
        -1, -1, cp);
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_bind (usock, (struct sockaddr*) &ss, sslen);
    errnum_assert (rc == 0, -rc);
    rc = nn_usock_listen (usock, NN_TCP_BACKLOG);
    errnum_assert (rc == 0, -rc);

    return 0;
}
Пример #14
0
void nn_stream_init (struct nn_stream *self, struct nn_epbase *epbase,
    struct nn_usock *usock)
{
    int rc;
    int protocol;
    size_t sz;
    struct nn_iobuf iobuf;

    /*  Redirect the underlying socket's events to this state machine. */
    self->usock = usock;
    self->sink = &nn_stream_state_start;
    self->original_sink = nn_usock_setsink (usock, &self->sink);

    /*  Initialise the pipe to communicate with the user. */
    rc = nn_pipebase_init (&self->pipebase, &nn_stream_pipebase_vfptr, epbase);
    nn_assert (rc == 0);

    nn_msg_init (&self->inmsg, 0);
    nn_msg_init (&self->outmsg, 0);

    /*  Start the header timeout timer. */
    nn_timer_init (&self->hdr_timeout, &self->sink, usock->cp);
    nn_timer_start (&self->hdr_timeout, 1000);

    /*  Send the protocol header. */
    sz = sizeof (protocol);
    nn_epbase_getopt (epbase, NN_SOL_SOCKET, NN_PROTOCOL, &protocol, &sz);
    errnum_assert (rc == 0, -rc);
    nn_assert (sz == sizeof (protocol));
    memcpy (self->protohdr, "\0\0SP\0\0\0\0", 8);
    nn_puts (self->protohdr + 4, (uint16_t) protocol);
    iobuf.iov_base = self->protohdr;
    iobuf.iov_len = 8;
    nn_usock_send (usock, &iobuf, 1);
}
Пример #15
0
void xs_mutex_init (xs_mutex *self)
{
    int rc;

    rc = pthread_mutex_init (self, NULL);
    errnum_assert (rc);
}
Пример #16
0
static int nn_respondent_send (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_respondent *respondent;

    respondent = nn_cont (self, struct nn_respondent, xrespondent.sockbase);

    /*  If there's no survey going on, report EFSM error. */
    if (nn_slow (!(respondent->flags & NN_RESPONDENT_INPROGRESS)))
        return -EFSM;

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

    /*  Try to send the message. If it cannot be sent due to pushback, drop it
        silently. */
    rc = nn_xrespondent_send (&respondent->xrespondent.sockbase, msg);
    if (nn_slow (rc == -EAGAIN)) {
        nn_msg_term (msg);
        return -EAGAIN;
    }
    errnum_assert (rc == 0, -rc);

    /*  Remember that no survey is being processed. */
    respondent->flags &= ~NN_RESPONDENT_INPROGRESS;

    return 0;
}
Пример #17
0
static int nn_respondent_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_respondent *respondent;

    respondent = nn_cont (self, struct nn_respondent, xrespondent.sockbase);

    /*  Cancel current survey, if it exists. */
    respondent->flags &= ~NN_RESPONDENT_INPROGRESS;

    /*  Get next survey. */
    rc = nn_xrespondent_recv (&respondent->xrespondent.sockbase, msg);
    if (nn_slow (rc == -EAGAIN))
        return -EAGAIN;
    errnum_assert (rc == 0, -rc);

    /*  Remember the survey ID. */
    nn_assert (nn_chunkref_size (&msg->sphdr) == sizeof (uint32_t));
    respondent->surveyid = nn_getl (nn_chunkref_data (&msg->sphdr));
    nn_chunkref_term (&msg->sphdr);
    nn_chunkref_init (&msg->sphdr, 0);

    /*  Remember that survey is being processed. */
    respondent->flags |= NN_RESPONDENT_INPROGRESS;

    return 0;
}
Пример #18
0
int nn_xrespondent_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_xrespondent *xrespondent;

    xrespondent = nn_cont (self, struct nn_xrespondent, sockbase);

    /*  Get the survey. */
    rc = nn_excl_recv (&xrespondent->excl, msg);
    if (rc == -EAGAIN)
        return -EAGAIN;
    errnum_assert (rc >= 0, -rc);

    /*  Split the survey ID from the body, if needed. */
    if (!(rc & NN_PIPE_PARSED)) {
        if (nn_slow (nn_chunkref_size (&msg->body) < sizeof (uint32_t))) {
            nn_msg_term (msg);
            return -EAGAIN;
        }
        nn_chunkref_term (&msg->hdr);
        nn_chunkref_init (&msg->hdr, sizeof (uint32_t));
        memcpy (nn_chunkref_data (&msg->hdr), nn_chunkref_data (&msg->body),
            sizeof (uint32_t));
        nn_chunkref_trim (&msg->body, sizeof (uint32_t));
    }

    return 0;
}
Пример #19
0
int nn_condvar_wait (nn_condvar_t *cond, nn_mutex_t *lock, int timeout)
{
    int rc;
    struct timeval tv;
    struct timespec ts;

    if (timeout < 0) {
        /*  This is an infinite sleep.  We don't care about return values,
            as any error we can treat as just a premature wakeup. */
        (void) pthread_cond_wait (&cond->cv, &lock->mutex);
        return (0);
    }

    rc = gettimeofday(&tv, NULL);
    errnum_assert (rc == 0, rc);

    /* There are extra operations performed here, but they are done to avoid
       wrap of the tv_usec and ts_nsec members on 32-bit systems. */
    tv.tv_sec += timeout / 1000;
    tv.tv_usec += (timeout % 1000) * 1000;

    ts.tv_sec = tv.tv_sec + (tv.tv_usec / 1000000);
    ts.tv_nsec = (tv.tv_usec % 1000000) * 1000;

    rc = pthread_cond_timedwait (&cond->cv, &lock->mutex, &ts);
    if (rc == ETIMEDOUT)
        return (-ETIMEDOUT);
    /* Treat all other cases (including errors) as normal wakeup. */
    return (0);
}
Пример #20
0
int nn_rep_recv (struct nn_sockbase *self, struct nn_msg *msg)
{
    int rc;
    struct nn_rep *rep;

    rep = nn_cont (self, struct nn_rep, xrep.sockbase);

    /*  If a request is already being processed, cancel it. */
    if (nn_slow (rep->flags & NN_REP_INPROGRESS)) {
        nn_chunkref_term (&rep->backtrace);
        rep->flags &= ~NN_REP_INPROGRESS;
    }

    /*  Receive the request. */
    rc = nn_xrep_recv (&rep->xrep.sockbase, msg);
    if (nn_slow (rc == -EAGAIN))
        return -EAGAIN;
    errnum_assert (rc == 0, -rc);

    /*  Store the backtrace. */
    nn_chunkref_mv (&rep->backtrace, &msg->sphdr);
    nn_chunkref_init (&msg->sphdr, 0);
    rep->flags |= NN_REP_INPROGRESS;

    return 0;
}
Пример #21
0
int nn_getsockopt (int s, int level, int option, void *optval,
    size_t *optvallen)
{
    int rc;
    struct nn_sock *sock;

    rc = nn_global_hold_socket (&sock, s);
    if (nn_slow (rc < 0)) {
        errno = -rc;
        return -1;
    }

    if (nn_slow (!optval && optvallen)) {
        rc = -EFAULT;
        goto fail;
    }

    rc = nn_sock_getopt (sock, level, option, optval, optvallen);
    if (nn_slow (rc < 0))
        goto fail;
    errnum_assert (rc == 0, -rc);
    nn_global_rele_socket (sock);
    return 0;

fail:
    nn_global_rele_socket (sock);
    errno = -rc;
    return -1;
}
Пример #22
0
void nn_thread_init(struct nn_thread *self,nn_thread_routine *routine, void *arg)
{
    int32_t rc; sigset_t new_sigmask,old_sigmask;
    // No signals should be processed by this thread. The library doesn't use signals and thus all the signals should be delivered to application threads, not to worker threads.
    rc = sigfillset(&new_sigmask);
    errno_assert(rc == 0);
    rc = pthread_sigmask(SIG_BLOCK, &new_sigmask, &old_sigmask);
    errnum_assert(rc == 0, rc);
    self->routine = routine;
    self->arg = arg;
    rc = pthread_create(&self->handle,NULL,nn_thread_main_routine,(void *)self);
    errnum_assert (rc == 0, rc);
    //  Restore signal set to what it was before.
    rc = pthread_sigmask(SIG_BLOCK, &new_sigmask, &old_sigmask);
    errnum_assert (rc == 0, rc);
}
Пример #23
0
int grid_xreq_recv (struct grid_sockbase *self, struct grid_msg *msg)
{
    int rc;

    rc = grid_fq_recv (&grid_cont (self, struct grid_xreq, sockbase)->fq, msg, NULL);
    if (rc == -EAGAIN)
        return -EAGAIN;
    errnum_assert (rc >= 0, -rc);

    if (!(rc & GRID_PIPE_PARSED)) {

        /*  Ignore malformed replies. */
        if (grid_slow (grid_chunkref_size (&msg->body) < sizeof (uint32_t))) {
            grid_msg_term (msg);
            return -EAGAIN;
        }

        /*  Split the message into the header and the body. */
        grid_assert (grid_chunkref_size (&msg->sphdr) == 0);
        grid_chunkref_term (&msg->sphdr);
        grid_chunkref_init (&msg->sphdr, sizeof (uint32_t));
        memcpy (grid_chunkref_data (&msg->sphdr), grid_chunkref_data (&msg->body),
            sizeof (uint32_t));
        grid_chunkref_trim (&msg->body, sizeof (uint32_t));
    }

    return 0;
}
Пример #24
0
void grid_usock_recv (struct grid_usock *self, void *buf, size_t len, int *fd)
{
    int rc;
    size_t nbytes;

    /*  Make sure that the socket is actually alive. */
    grid_assert_state (self, GRID_USOCK_STATE_ACTIVE);

    /*  Try to receive the data immediately. */
    nbytes = len;
    self->in.pfd = fd;
    rc = grid_usock_recv_raw (self, buf, &nbytes);
    if (grid_slow (rc < 0)) {
        errnum_assert (rc == -ECONNRESET, -rc);
        grid_fsm_action (&self->fsm, GRID_USOCK_ACTION_ERROR);
        return;
    }

    /*  Success. */
    if (grid_fast (nbytes == len)) {
        grid_fsm_raise (&self->fsm, &self->event_received, GRID_USOCK_RECEIVED);
        return;
    }

    /*  There are still data to receive in the background. */
    self->in.buf = ((uint8_t*) buf) + nbytes;
    self->in.len = len - nbytes;

    /*  Ask the worker thread to receive the remaining data. */
    grid_worker_execute (self->worker, &self->task_recv);
}
Пример #25
0
static void nn_cstream_closing_closed (const struct nn_cp_sink **self,
    struct nn_usock *usock)
{
    int rc;
    struct nn_cstream *cstream;
    int sndbuf;
    int rcvbuf;
    size_t sz;

    cstream = nn_cont (self, struct nn_cstream, sink);

    /*  Get the current values of NN_SNDBUF and NN_RCVBUF options. */    
    sz = sizeof (sndbuf);
    nn_epbase_getopt (&cstream->epbase, NN_SOL_SOCKET, NN_SNDBUF, &sndbuf, &sz);
    nn_assert (sz == sizeof (sndbuf));
    sz = sizeof (rcvbuf);
    nn_epbase_getopt (&cstream->epbase, NN_SOL_SOCKET, NN_RCVBUF, &rcvbuf, &sz);
    nn_assert (sz == sizeof (rcvbuf));

    /*  Create new socket. */
    rc = cstream->initsockfn (&cstream->usock, sndbuf, rcvbuf,
        nn_epbase_getcp (&cstream->epbase));
    errnum_assert (rc == 0, -rc);
    nn_usock_setsink (&cstream->usock, &cstream->sink);

    /*  Wait for the specified period. */
    cstream->sink = &nn_cstream_state_waiting;
    nn_timer_start (&cstream->retry_timer,
        nn_cstream_compute_retry_ivl (cstream));
}
Пример #26
0
void nn_glock_unlock (void)
{
    int rc;

    rc = pthread_mutex_unlock (&nn_glock_mutex);
    errnum_assert (rc == 0, rc);
}
Пример #27
0
static void nn_req_action_send (struct nn_req *self)
{
    int rc;
    struct nn_msg msg;

    /*  Send the request. */
    nn_msg_cp (&msg, &self->request);
    rc = nn_xreq_send (&self->xreq.sockbase, &msg);

    /*  If the request cannot be sent at the moment wait till
        new outbound pipe arrives. */
    if (nn_slow (rc == -EAGAIN)) {
        nn_msg_term (&msg);
        self->state = NN_REQ_STATE_DELAYED;
        return;
    }

    /*  Request was successfully sent. Set up the re-send timer
        in case the request gets lost somewhere further out
        in the topology. */
    if (nn_fast (rc == 0)) {
        nn_timer_start (&self->timer, self->resend_ivl);
        self->state = NN_REQ_STATE_ACTIVE;
        return;
    }

    /*  Unexpected error. */
    errnum_assert (0, -rc);
}
Пример #28
0
void xs_mutex_term (xs_mutex *self)
{
    int rc;

    rc = pthread_mutex_destroy (self);
    errnum_assert (rc);
}
Пример #29
0
void xs_mutex_unlock (xs_mutex *self)
{
    int rc;

    rc = pthread_mutex_unlock (self);
    errnum_assert (rc);
}
Пример #30
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;
}