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; }
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; }
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); }
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; }
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)); }
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); }
/* 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); }
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); }
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); }
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); }
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; }
void nn_ins_item_init (struct nn_ins_item *self, struct nn_ep *ep) { self->ep = ep; nn_list_item_init (&self->item); }
/* 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)); } }
/* 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--; } } }