void nn_req_init (struct nn_req *self, const struct nn_sockbase_vfptr *vfptr, void *hint) { nn_req_handle hndl; nn_xreq_init (&self->xreq, vfptr, hint); nn_fsm_init_root (&self->fsm, nn_req_handler, nn_req_shutdown, nn_sockbase_getctx (&self->xreq.sockbase)); self->state = NN_REQ_STATE_IDLE; /* Start assigning request IDs beginning with a random number. This way there should be no key clashes even if the executable is re-started. */ nn_random_generate (&self->lastid, sizeof (self->lastid)); self->task.sent_to = NULL; nn_msg_init (&self->task.request, 0); nn_msg_init (&self->task.reply, 0); nn_timer_init (&self->task.timer, NN_REQ_SRC_RESEND_TIMER, &self->fsm); self->resend_ivl = NN_REQ_DEFAULT_RESEND_IVL; /* For now, handle is empty. */ memset (&hndl, 0, sizeof (hndl)); nn_task_init (&self->task, self->lastid, hndl); /* Start the state machine. */ nn_fsm_start (&self->fsm); }
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); }
void nn_backoff_init (struct nn_backoff *self, int src, int minivl, int maxivl, struct nn_fsm *owner) { nn_timer_init (&self->timer, src, owner); self->minivl = minivl; self->maxivl = maxivl; self->n = 1; }
void nn_streamhdr_init (struct nn_streamhdr *self, int src, struct nn_fsm *owner) { nn_fsm_init (&self->fsm, nn_streamhdr_handler, src, self, owner); self->state = NN_STREAMHDR_STATE_IDLE; nn_timer_init (&self->timer, NN_STREAMHDR_SRC_TIMER, &self->fsm); nn_fsm_event_init (&self->done); self->usock = NULL; self->usock_owner.src = -1; self->usock_owner.fsm = NULL; self->pipebase = NULL; }
int nn_cstream_init (struct nn_cstream *self, const char *addr, void *hint, int (*initsockfn) (struct nn_usock *sock, int sndbuf, int rcvbuf, struct nn_cp *cp), int (*resolvefn) (const char *addr, struct sockaddr_storage *ss, socklen_t *sslen)) { int rc; int sndbuf; int rcvbuf; size_t sz; self->initsockfn = initsockfn; self->resolvefn = resolvefn; /* TODO: Check the syntax of the address and return error if it is not a valid address string. Don't do any blocking DNS operations though! */ /* Initialise the base class. */ nn_epbase_init (&self->epbase, &nn_cstream_epbase_vfptr, addr, hint); /* Get the current values of NN_SNDBUF and NN_RCVBUF options. */ sz = sizeof (sndbuf); nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_SNDBUF, &sndbuf, &sz); nn_assert (sz == sizeof (sndbuf)); sz = sizeof (rcvbuf); nn_epbase_getopt (&self->epbase, NN_SOL_SOCKET, NN_RCVBUF, &rcvbuf, &sz); nn_assert (sz == sizeof (rcvbuf)); /* Open a socket. */ rc = self->initsockfn (&self->usock, sndbuf, rcvbuf, nn_epbase_getcp (&self->epbase)); errnum_assert (rc == 0, -rc); nn_usock_setsink (&self->usock, &self->sink); /* Initialise the retry timer. */ self->retry_ivl = -1; nn_timer_init (&self->retry_timer, &self->sink, nn_epbase_getcp (&self->epbase)); /* Pretend we were waiting for the re-connect timer and that the timer have expired. */ self->sink = &nn_cstream_state_waiting; nn_cstream_waiting_timeout (&self->sink, &self->retry_timer); return 0; }
static void nn_surveyor_init (struct nn_surveyor *self, const struct nn_sockbase_vfptr *vfptr, void *hint) { nn_xsurveyor_init (&self->xsurveyor, vfptr, hint); nn_fsm_init_root (&self->fsm, nn_surveyor_handler, nn_sockbase_getctx (&self->xsurveyor.sockbase)); self->state = NN_SURVEYOR_STATE_IDLE; /* Start assigning survey IDs beginning with a random number. This way there should be no key clashes even if the executable is re-started. */ nn_random_generate (&self->surveyid, sizeof (self->surveyid)); nn_timer_init (&self->timer, NN_SURVEYOR_SRC_DEADLINE_TIMER, &self->fsm); nn_msg_init (&self->tosend, 0); self->deadline = NN_SURVEYOR_DEFAULT_DEADLINE; /* Start the state machine. */ nn_fsm_start (&self->fsm); }
static int nn_req_init (struct nn_req *self, const struct nn_sockbase_vfptr *vfptr) { int rc; rc = nn_xreq_init (&self->xreq, vfptr); if (rc < 0) return rc; self->sink = &nn_req_sink; /* Start assigning request IDs beginning with a random number. This way there should be no key clashes even if the executable is re-started. */ nn_random_generate (&self->reqid, sizeof (self->reqid)); self->state = NN_REQ_STATE_IDLE; self->resend_ivl = NN_REQ_DEFAULT_RESEND_IVL; nn_timer_init (&self->resend_timer, &self->sink, nn_sockbase_getcp (&self->xreq.sockbase)); return 0; }
static int nn_surveyor_init (struct nn_surveyor *self, const struct nn_sockbase_vfptr *vfptr) { int rc; rc = nn_xsurveyor_init (&self->xsurveyor, vfptr); if (rc < 0) return rc; self->sink = &nn_surveyor_sink; self->flags = 0; /* Start assigning survey IDs beginning with a random number. This way there should be no key clashes even if the executable is re-started. */ nn_random_generate (&self->surveyid, sizeof (self->surveyid)); self->deadline = NN_SURVEYOR_DEFAULT_DEADLINE; nn_timer_init (&self->deadline_timer, &self->sink, nn_sockbase_getcp (&self->xsurveyor.sockbase)); return 0; }
static void nn_global_init (void) { int i; char *envvar; int rc; char *addr; #if defined NN_HAVE_WINDOWS WSADATA data; #endif /* Check whether the library was already initialised. If so, do nothing. */ if (self.socks) return; /* On Windows, initialise the socket library. */ #if defined NN_HAVE_WINDOWS rc = WSAStartup (MAKEWORD (2, 2), &data); nn_assert (rc == 0); nn_assert (LOBYTE (data.wVersion) == 2 && HIBYTE (data.wVersion) == 2); #endif /* Initialise the memory allocation subsystem. */ nn_alloc_init (); /* Seed the pseudo-random number generator. */ nn_random_seed (); /* Allocate the global table of SP sockets. */ self.socks = nn_alloc ((sizeof (struct nn_sock*) * NN_MAX_SOCKETS) + (sizeof (uint16_t) * NN_MAX_SOCKETS), "socket table"); alloc_assert (self.socks); for (i = 0; i != NN_MAX_SOCKETS; ++i) self.socks [i] = NULL; self.nsocks = 0; self.flags = 0; /* Print connection and accepting errors to the stderr */ envvar = getenv("NN_PRINT_ERRORS"); /* any non-empty string is true */ self.print_errors = envvar && *envvar; /* Print socket statistics to stderr */ envvar = getenv("NN_PRINT_STATISTICS"); self.print_statistics = envvar && *envvar; /* Allocate the stack of unused file descriptors. */ self.unused = (uint16_t*) (self.socks + NN_MAX_SOCKETS); alloc_assert (self.unused); for (i = 0; i != NN_MAX_SOCKETS; ++i) self.unused [i] = NN_MAX_SOCKETS - i - 1; /* Initialise other parts of the global state. */ nn_list_init (&self.transports); nn_list_init (&self.socktypes); /* Plug in individual transports. */ nn_global_add_transport (nn_inproc); nn_global_add_transport (nn_ipc); nn_global_add_transport (nn_tcp); nn_global_add_transport (nn_ws); nn_global_add_transport (nn_tcpmux); /* Plug in individual socktypes. */ nn_global_add_socktype (nn_pair_socktype); nn_global_add_socktype (nn_xpair_socktype); nn_global_add_socktype (nn_pub_socktype); nn_global_add_socktype (nn_sub_socktype); nn_global_add_socktype (nn_xpub_socktype); nn_global_add_socktype (nn_xsub_socktype); nn_global_add_socktype (nn_rep_socktype); nn_global_add_socktype (nn_req_socktype); nn_global_add_socktype (nn_xrep_socktype); nn_global_add_socktype (nn_xreq_socktype); nn_global_add_socktype (nn_push_socktype); nn_global_add_socktype (nn_xpush_socktype); nn_global_add_socktype (nn_pull_socktype); nn_global_add_socktype (nn_xpull_socktype); nn_global_add_socktype (nn_respondent_socktype); nn_global_add_socktype (nn_surveyor_socktype); nn_global_add_socktype (nn_xrespondent_socktype); nn_global_add_socktype (nn_xsurveyor_socktype); nn_global_add_socktype (nn_bus_socktype); nn_global_add_socktype (nn_xbus_socktype); /* Start the worker threads. */ nn_pool_init (&self.pool); /* Start FSM */ nn_fsm_init_root (&self.fsm, nn_global_handler, nn_global_shutdown, &self.ctx); self.state = NN_GLOBAL_STATE_IDLE; nn_ctx_init (&self.ctx, nn_global_getpool (), NULL); nn_timer_init (&self.stat_timer, NN_GLOBAL_SRC_STAT_TIMER, &self.fsm); nn_fsm_start (&self.fsm); /* Initializing special sockets. */ addr = getenv ("NN_STATISTICS_SOCKET"); if (addr) { self.statistics_socket = nn_global_create_socket (AF_SP, NN_PUB); errno_assert (self.statistics_socket >= 0); rc = nn_global_create_ep (self.statistics_socket, addr, 0); errno_assert (rc >= 0); } else { self.statistics_socket = -1; } addr = getenv ("NN_APPLICATION_NAME"); if (addr) { strncpy (self.appname, addr, 63); self.appname[63] = '\0'; } else { /* No cross-platform way to find out application binary. Also, MSVC suggests using _getpid() instead of getpid(), however, it's not clear whether the former is supported by older versions of Windows/MSVC. */ #if defined _MSC_VER #pragma warning (push) #pragma warning (disable:4996) #endif sprintf (self.appname, "nanomsg.%d", getpid()); #if defined _MSC_VER #pragma warning (pop) #endif } addr = getenv ("NN_HOSTNAME"); if (addr) { strncpy (self.hostname, addr, 63); self.hostname[63] = '\0'; } else { rc = gethostname (self.hostname, 63); errno_assert (rc == 0); self.hostname[63] = '\0'; } }