Пример #1
0
struct nn_binproc *nn_binproc_create (void *hint)
{
    struct nn_binproc *self;
    size_t sz;

    self = nn_alloc (sizeof (struct nn_binproc), "binproc");
    alloc_assert (self);

    nn_epbase_init (&self->epbase, &nn_binproc_vfptr, hint);
    nn_fsm_init_root (&self->fsm, nn_binproc_handler,
        nn_epbase_getctx (&self->epbase));
    self->state = NN_BINPROC_STATE_IDLE;
    nn_list_init (&self->sinprocs);
    nn_list_item_init (&self->item);
    sz = sizeof (self->protocol);
    nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_PROTOCOL,
        &self->protocol, &sz);
    nn_assert (sz == sizeof (self->protocol));
    self->connects = 0;

    /*  Start the state machine. */
    nn_fsm_start (&self->fsm);

    return self;
}
Пример #2
0
int nn_ep_init (struct nn_ep *self, int src, struct nn_sock *sock, int eid,
    struct nn_transport *transport, int bind, const char *addr)
{
    int rc;

    nn_fsm_init (&self->fsm, nn_ep_handler, nn_ep_shutdown,
        src, self, &sock->fsm);
    self->state = NN_EP_STATE_IDLE;

    self->epbase = NULL;
    self->sock = sock;
    self->eid = eid;
    self->last_errno = 0;
    nn_list_item_init (&self->item);
    memcpy (&self->options, &sock->ep_template, sizeof(struct nn_ep_options));

    /*  Store the textual form of the address. */
    nn_assert (strlen (addr) <= NN_SOCKADDR_MAX);
    strcpy (self->addr, addr);

    /*  Create transport-specific part of the endpoint. */
    if (bind)
        rc = transport->bind ((void*) self, &self->epbase);
    else
        rc = transport->connect ((void*) self, &self->epbase);

    /*  Endpoint creation failed. */
    if (rc < 0) {
        nn_list_item_term (&self->item);
        nn_fsm_term (&self->fsm);
        return rc;
    }

    return 0;
}
Пример #3
0
void nn_priolist_add (struct nn_priolist *self, struct nn_pipe *pipe,
    struct nn_priolist_data *data, int priority)
{
    data->pipe = pipe;
    data->priority = priority;
    nn_list_item_init (&data->item);
}
Пример #4
0
int ftw_publisher_construct(struct ftw_socket_callsite **callsite, const char *addr,
    int linger, struct ftw_socket **sock)
{
    struct ftw_socket *inst;
    int rcs;
    int rco;
    int rcb;

    /*  Preconditions expected of LabVIEW. */
    ftw_assert(*callsite && addr);
    nn_mutex_lock(&(*callsite)->sync);

    rcs = nn_socket(AF_SP, NN_PUB);

    /*  Socket creation failure? */
    if (rcs < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcs;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_LINGER, &linger, sizeof(linger));
    if (rco < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    rcb = nn_bind(rcs, addr);

    /*  Endpoint creation failure? */
    if (rcb < 0) {
        nn_close(rcs);
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcb;
    }

    inst = ftw_malloc(sizeof(struct ftw_socket));
    ftw_assert(inst);

    memset(inst, 0, sizeof(*inst));

    inst->id = rcs;
    inst->callsite = *callsite;

    nn_list_item_init(&inst->item);
    nn_list_insert(&(*callsite)->active_sockets, &inst->item,
        nn_list_end(&(*callsite)->active_sockets));

    *sock = inst;

    (*callsite)->lifetime_sockets++;
    nn_mutex_unlock(&(*callsite)->sync);

    return 0;

}
Пример #5
0
void nn_ins_item_init (struct nn_ins_item *myself,const struct nn_epbase_vfptr *vfptr, void *hint)
{
    size_t sz;

    nn_epbase_init (&myself->epbase, vfptr, hint);
    nn_list_item_init (&myself->item);
    sz = sizeof (myself->protocol);
    nn_epbase_getopt (&myself->epbase, NN_SOL_SOCKET, NN_PROTOCOL,&myself->protocol, &sz);
    nn_assert (sz == sizeof (myself->protocol));
}
Пример #6
0
void nn_aipc_init (struct nn_aipc *self, int src,
    struct nn_epbase *epbase, struct nn_fsm *owner)
{
    nn_fsm_init (&self->fsm, nn_aipc_handler, src, self, owner);
    self->state = NN_AIPC_STATE_IDLE;
    nn_usock_init (&self->usock, NN_AIPC_SRC_USOCK, &self->fsm);
    self->listener = NULL;
    self->listener_owner.src = -1;
    self->listener_owner.fsm = NULL;
    nn_sipc_init (&self->sipc, NN_AIPC_SRC_SIPC, epbase, &self->fsm);
    nn_fsm_event_init (&self->accepted);
    nn_fsm_event_init (&self->done);
    nn_list_item_init (&self->item);
}
Пример #7
0
/*  Allocate a new message chunk, append it to message array, and return
    pointer to its buffer. */
static void *nn_msg_chunk_new (size_t size, struct nn_list *msg_array)
{
    struct msg_chunk *self;

    self = nn_alloc (sizeof (struct msg_chunk), "msg_chunk");
    alloc_assert (self);

    nn_chunkref_init (&self->chunk, size);
    nn_list_item_init (&self->item);

    nn_list_insert (msg_array, &self->item, nn_list_end (msg_array));

    return nn_chunkref_data (&self->chunk);
}
Пример #8
0
void nn_atcp_init (struct nn_atcp *self, int src,
    struct nn_epbase *epbase, struct nn_fsm *owner)
{
    nn_fsm_init (&self->fsm, nn_atcp_handler, nn_atcp_shutdown,
        src, self, owner);
    self->state = NN_ATCP_STATE_IDLE;
    self->epbase = epbase;
    nn_usock_init (&self->usock, NN_ATCP_SRC_USOCK, &self->fsm);
    self->listener = NULL;
    self->listener_owner.src = -1;
    self->listener_owner.fsm = NULL;
    nn_stcp_init (&self->stcp, NN_ATCP_SRC_STCP, epbase, &self->fsm);
    nn_fsm_event_init (&self->accepted);
    nn_fsm_event_init (&self->done);
    nn_list_item_init (&self->item);
}
Пример #9
0
void nn_astream_init (struct nn_astream *self, struct nn_epbase *epbase,
    int s, struct nn_usock *usock, struct nn_bstream *bstream)
{
    int sndbuf;
    int rcvbuf;
    size_t sz;

    /*  Switch the state. */
    self->sink = &nn_astream_state_connected;
    self->bstream = bstream;

    /*  This stearm does not belong yet to the bstream. */
    nn_list_item_init (&self->item);

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

    /*  Start the stream state machine. */
    nn_usock_init_child (&self->usock, usock, s, &self->sink, sndbuf, rcvbuf,
        usock->cp);
    
    /*  Note: must add myself to the astreams list *before* initializing my
        stream, which may fail and terminate me. */
    nn_list_insert (&bstream->astreams, &self->item,
        nn_list_end (&bstream->astreams));

    /*  Note: may fail and terminate me - do not reference self after
        this point! */
    nn_stream_init (&self->stream, epbase, &self->usock);
}
Пример #10
0
void nn_dist_add (struct nn_dist *self, struct nn_pipe *pipe,
    struct nn_dist_data *data)
{
    data->pipe = pipe;
    nn_list_item_init (&data->item);
}
Пример #11
0
int ftw_subscriber_construct(struct ftw_socket_callsite **callsite, LVUserEventRef *lv_event,
    const char *addr, int linger, int max_recv_size, struct ftw_socket **sock)
{
    struct ftw_socket *inst;
    int rcc;
    int rcs;
    int rco;

    /*  Preconditions expected of LabVIEW. */
    ftw_assert(*callsite && addr);
    nn_mutex_lock(&(*callsite)->sync);

    rcs = nn_socket(AF_SP, NN_SUB);

    /*  Socket creation failure? */
    if (rcs < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcs;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_LINGER, &linger, sizeof(linger));
    if (rco < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_RCVMAXSIZE, &max_recv_size, sizeof(max_recv_size));
    if (rco < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    rcc = nn_connect(rcs, addr);

    /*  Endpoint creation failure? */
    if (rcc < 0) {
        nn_close(rcs);
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcc;
    }

    rco = nn_setsockopt (rcs, NN_SUB, NN_SUB_SUBSCRIBE, "", 0);
    if (rco < 0) {
        nn_close(rcs);
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    inst = ftw_malloc(sizeof(struct ftw_socket));
    ftw_assert(inst);

    inst->incoming_msg_notifier_event = *lv_event;
    inst->id = rcs;
    inst->callsite = *callsite;

    nn_list_item_init(&inst->item);
    nn_list_insert(&(*callsite)->active_sockets, &inst->item,
        nn_list_end(&(*callsite)->active_sockets));

    nn_sem_init(&inst->msg_acknowledged);

    /*  Launch thread and wait for it to initialize. */
    nn_sem_init(&inst->async_recv_ready);
    nn_thread_init(&inst->async_recv_thread, ftw_subscriber_async_recv_thread, inst);
    nn_sem_wait(&inst->async_recv_ready);

    *sock = inst;

    (*callsite)->lifetime_sockets++;
    nn_mutex_unlock(&(*callsite)->sync);

    return 0;
}
Пример #12
0
void nn_ins_item_init (struct nn_ins_item *self, struct nn_ep *ep)
{
    self->ep = ep;
    nn_list_item_init (&self->item);
}
Пример #13
0
/*  Main body of the daemon. */
static void nn_tcpmuxd_routine (void *arg)
{
    int rc;
    struct nn_tcpmuxd_ctx *ctx;
    struct pollfd pfd [2];
    int conn;
    int pos;
    char service [256];
    struct nn_tcpmuxd_conn *tc;
    size_t sz;
    ssize_t ssz;
    int i;
    struct nn_list_item *it;
    unsigned char buf [2];
    struct timeval tv;

    ctx = (struct nn_tcpmuxd_ctx*) arg;

    pfd [0].fd = ctx->tcp_listener;
    pfd [0].events = POLLIN;
    pfd [1].fd = ctx->ipc_listener;
    pfd [1].events = POLLIN;

    while (1) {

        /*  Wait for events. */
        rc = poll (pfd, 2, -1);
        errno_assert (rc >= 0);
        nn_assert (rc != 0);

        /*  There's an incoming TCP connection. */
        if (pfd [0].revents & POLLIN) {

            /*  Accept the connection. */
            conn = accept (ctx->tcp_listener, NULL, NULL);
            if (conn < 0 && errno == ECONNABORTED)
                continue;
            errno_assert (conn >= 0);
            tv.tv_sec = 0;
            tv.tv_usec = 100000;
            rc = setsockopt (conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv));
            errno_assert (rc == 0);
            rc = setsockopt (conn, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv));
            errno_assert (rc == 0);

            /*  Read TCPMUX header. */
            pos = 0;
            while (1) {
                nn_assert (pos < sizeof (service));
                ssz = recv (conn, &service [pos], 1, 0);
                if (ssz < 0 && errno == EAGAIN) {
                    close (conn);
                    continue;
                }
                errno_assert (ssz >= 0);
                nn_assert (ssz == 1);
                service [pos] = tolower (service [pos]);
                if (pos > 0 && service [pos - 1] == 0x0d &&
                      service [pos] == 0x0a)
                    break;
                ++pos;
            }
            service [pos - 1] = 0;
            
            /*  Check whether specified service is listening. */
            for (it = nn_list_begin (&ctx->conns);
                  it != nn_list_end (&ctx->conns);
                  it = nn_list_next (&ctx->conns, it)) {
                tc = nn_cont (it, struct nn_tcpmuxd_conn, item);
                if (strcmp (service, tc->service) == 0)
                    break;
            }

            /* If no one is listening, tear down the connection. */
            if (it == nn_list_end (&ctx->conns)) {
                ssz = send (conn, "-\x0d\x0a", 3, 0);
                if (ssz < 0 && errno == EAGAIN) {
                    close (conn);
                    continue;
                }
                errno_assert (ssz >= 0);
                nn_assert (ssz == 3);
                close (conn);
                continue;
            }

            /*  Send TCPMUX reply. */
            ssz = send (conn, "+\x0d\x0a", 3, 0);
            if (ssz < 0 && errno == EAGAIN) {
                close (conn);
                continue;
            }
            errno_assert (ssz >= 0);
            nn_assert (ssz == 3);

            /*  Pass the file descriptor to the listening process. */
            rc = send_fd (tc->fd, conn);
            errno_assert (rc == 0);
        }

        /*  There's an incoming IPC connection. */
        if (pfd [1].revents & POLLIN) {

            /*  Accept the connection. */
            conn = accept (ctx->ipc_listener, NULL, NULL);
            if (conn < 0 && errno == ECONNABORTED)
                continue;
            errno_assert (conn >= 0);

            /*  Create new connection entry. */
            tc = nn_alloc (sizeof (struct nn_tcpmuxd_conn), "tcpmuxd_conn");
            nn_assert (tc);
            tc->fd = conn;
            nn_list_item_init (&tc->item);    

            /*  Read the connection header. */
            ssz = recv (conn, buf, 2, 0);
            errno_assert (ssz >= 0);
            nn_assert (ssz == 2);
            sz = nn_gets (buf);
            tc->service = nn_alloc (sz + 1, "tcpmuxd_conn.service");
            nn_assert (tc->service);
            ssz = recv (conn, tc->service, sz, 0);
            errno_assert (ssz >= 0);
            nn_assert (ssz == sz);
            for (i = 0; i != sz; ++i)
                tc->service [sz] = tolower (tc->service [sz]);
            tc->service [sz] = 0;
            
            /*  Add the entry to the IPC connections list. */
            nn_list_insert (&ctx->conns, &tc->item, nn_list_end (&ctx->conns));
        }
    }
Пример #14
0
/*  Main body of the daemon. */
static void nn_tcpmuxd_routine (void *arg)
{
    int rc;
    struct nn_tcpmuxd_ctx *ctx;
    int conn;
    int pos;
    char service [256];
    struct nn_tcpmuxd_conn *tc = 0;
    size_t sz;
    ssize_t ssz;
    int i;
    struct nn_list_item *it;
    unsigned char buf [2];
    struct timeval tv;

    ctx = (struct nn_tcpmuxd_ctx*) arg;

    while (1) {

        /*  Wait for events. */
        rc = (int32_t)poll (ctx->pfd, (int32_t)ctx->pfd_size, -1);
        errno_assert (rc >= 0);
        nn_assert (rc != 0);

        /*  There's an incoming TCP connection. */
        if (ctx->pfd [0].revents & POLLIN) {

            /*  Accept the connection. */
            conn = accept (ctx->tcp_listener, NULL, NULL);
            if (conn < 0 && errno == ECONNABORTED)
                continue;
            errno_assert (conn >= 0);

            /*  Set timeouts to prevent malevolent client blocking the service.
                Note that these options are not supported on Solaris. */
            tv.tv_sec = 0;
            tv.tv_usec = 100000;
            rc = setsockopt (conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv));
            errno_assert (rc == 0 || (rc < 0 && errno == ENOPROTOOPT));
            rc = setsockopt (conn, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv));
            errno_assert (rc == 0 || (rc < 0 && errno == ENOPROTOOPT));

            /*  Read TCPMUX header. */
            pos = 0;
            while (1) {
                nn_assert (pos < sizeof (service));
                ssz = recv (conn, &service [pos], 1, 0);
                if (ssz < 0 && errno == EAGAIN) {
                    close (conn);
                    continue;
                }
                errno_assert (ssz >= 0);
                nn_assert (ssz == 1);
                service [pos] = tolower ((uint32_t)service [pos]);
                if (pos > 0 && service [pos - 1] == 0x0d &&
                      service [pos] == 0x0a)
                    break;
                ++pos;
            }
            service [pos - 1] = 0;
            
            /*  Check whether specified service is listening. */
            for (it = nn_list_begin (&ctx->conns);
                  it != nn_list_end (&ctx->conns);
                  it = nn_list_next (&ctx->conns, it)) {
                tc = nn_cont (it, struct nn_tcpmuxd_conn, item);
                if (strcmp (service, tc->service) == 0)
                    break;
            }

            /* If no one is listening, tear down the connection. */
            if (it == nn_list_end (&ctx->conns)) {
                ssz = send (conn, "-\x0d\x0a", 3, 0);
                if (ssz < 0 && errno == EAGAIN) {
                    close (conn);
                    continue;
                }
                errno_assert (ssz >= 0);
                nn_assert (ssz == 3);
                close (conn);
                continue;
            }

            /*  Send TCPMUX reply. */
            ssz = send (conn, "+\x0d\x0a", 3, 0);
            if (ssz < 0 && errno == EAGAIN) {
                close (conn);
                continue;
            }
            errno_assert (ssz >= 0);
            nn_assert (ssz == 3);
            nn_assert (tc != 0);

            /*  Pass the file descriptor to the listening process. */
            rc = nn_tcpmuxd_send_fd (tc->fd, conn);
            errno_assert (rc == 0);
        }

        /*  There's an incoming IPC connection. */
        if (ctx->pfd [1].revents & POLLIN) {

            /*  Accept the connection. */
            conn = accept (ctx->ipc_listener, NULL, NULL);
            if (conn < 0 && errno == ECONNABORTED)
                continue;
            errno_assert (conn >= 0);

            /*  Create new connection entry. */
            tc = nn_alloc (sizeof (struct nn_tcpmuxd_conn), "tcpmuxd_conn");
            nn_assert (tc);
            tc->fd = conn;
            nn_list_item_init (&tc->item); 

            /*  Adjust the pollset. We will poll for errors only. */
            ctx->pfd_size++;
            if (ctx->pfd_size > ctx->pfd_capacity) {
                ctx->pfd_capacity *= 2;
                ctx->pfd = nn_realloc (ctx->pfd,
                    sizeof (struct pollfd) * ctx->pfd_capacity);
                alloc_assert (ctx->pfd);
            }
            ctx->pfd [ctx->pfd_size - 1].fd = conn;
            ctx->pfd [ctx->pfd_size - 1].events = 0;
            ctx->pfd [ctx->pfd_size - 1].revents = 0;

            /*  Read the connection header. */
            ssz = recv (conn, buf, 2, 0);
            errno_assert (ssz >= 0);
            nn_assert (ssz == 2);
            sz = nn_gets (buf);
            tc->service = nn_alloc (sz + 1, "tcpmuxd_conn.service");
            nn_assert (tc->service);
            ssz = recv (conn, tc->service, sz, 0);
            errno_assert (ssz >= 0);
            nn_assert (ssz == sz);
            for (i = 0; i != sz; ++i)
                tc->service [i] = tolower ((uint32_t)tc->service [i]);
            tc->service [sz] = 0;
            
            /*  Add the entry to the IPC connections list. */
            nn_list_insert (&ctx->conns, &tc->item, nn_list_end (&ctx->conns));
        }

        for (i = 2; i < ctx->pfd_size; ++i) {
            if (ctx->pfd [i].revents & POLLERR ||
                  ctx->pfd [i].revents & POLLHUP) {
                nn_tcpmuxd_disconnect (ctx, i);
                i--;
            }
        }
    }