void nn_ins_connect (struct nn_ins_item *item, nn_ins_fn fn) { struct nn_list_item *it; struct nn_ins_item *bitem; nn_mutex_lock (&self.sync); /* Insert the entry into the endpoint repository. */ nn_list_insert (&self.connected, &item->item, nn_list_end (&self.connected)); /* During this process a pipe may be created. */ for (it = nn_list_begin (&self.bound); it != nn_list_end (&self.bound); it = nn_list_next (&self.bound, it)) { bitem = nn_cont (it, struct nn_ins_item, item); if (strncmp (nn_ep_getaddr(item->ep), nn_ep_getaddr(bitem->ep), NN_SOCKADDR_MAX) == 0) { /* Check whether the two sockets are compatible. */ if (!nn_ep_ispeer_ep (item->ep, bitem->ep)) break; /* Call back to cinproc to create actual connection. */ fn (item, bitem); break; } } nn_mutex_unlock (&self.sync); }
int nn_ins_bind (struct nn_ins_item *item, nn_ins_fn fn) { struct nn_list_item *it; struct nn_ins_item *bitem; struct nn_ins_item *citem; nn_mutex_lock (&self.sync); /* Check whether the endpoint isn't already bound. */ /* TODO: This is an O(n) algorithm! */ for (it = nn_list_begin (&self.bound); it != nn_list_end (&self.bound); it = nn_list_next (&self.bound, it)) { bitem = nn_cont (it, struct nn_ins_item, item); if (strncmp (nn_ep_getaddr(bitem->ep), nn_ep_getaddr(item->ep), NN_SOCKADDR_MAX) == 0) { nn_mutex_unlock (&self.sync); return -EADDRINUSE; } } /* Insert the entry into the endpoint repository. */ nn_list_insert (&self.bound, &item->item, nn_list_end (&self.bound)); /* During this process new pipes may be created. */ for (it = nn_list_begin (&self.connected); it != nn_list_end (&self.connected); it = nn_list_next (&self.connected, it)) { citem = nn_cont (it, struct nn_ins_item, item); if (strncmp (nn_ep_getaddr(item->ep), nn_ep_getaddr(citem->ep), NN_SOCKADDR_MAX) == 0) { /* Check whether the two sockets are compatible. */ if (!nn_ep_ispeer_ep (item->ep, citem->ep)) continue; fn (item, citem); } } nn_mutex_unlock (&self.sync); return 0; }
static void nn_cipc_start_connecting (struct nn_cipc *self) { int rc; struct sockaddr_storage ss; struct sockaddr_un *un; const char *addr; int val; size_t sz; /* Try to start the underlying socket. */ rc = nn_usock_start (&self->usock, AF_UNIX, SOCK_STREAM, 0); if (nn_slow (rc < 0)) { nn_backoff_start (&self->retry); self->state = NN_CIPC_STATE_WAITING; return; } /* Set the relevant socket options. */ sz = sizeof (val); nn_ep_getopt (self->ep, NN_SOL_SOCKET, NN_SNDBUF, &val, &sz); nn_assert (sz == sizeof (val)); nn_usock_setsockopt (&self->usock, SOL_SOCKET, SO_SNDBUF, &val, sizeof (val)); sz = sizeof (val); nn_ep_getopt (self->ep, NN_SOL_SOCKET, NN_RCVBUF, &val, &sz); nn_assert (sz == sizeof (val)); nn_usock_setsockopt (&self->usock, SOL_SOCKET, SO_RCVBUF, &val, sizeof (val)); /* Create the IPC address from the address string. */ addr = nn_ep_getaddr (self->ep); 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)); #if defined NN_HAVE_WINDOWS /* Get/Set security attribute pointer*/ nn_ep_getopt (self->ep, NN_IPC, NN_IPC_SEC_ATTR, &self->usock.sec_attr, &sz); nn_ep_getopt (self->ep, NN_IPC, NN_IPC_OUTBUFSZ, &self->usock.outbuffersz, &sz); nn_ep_getopt (self->ep, NN_IPC, NN_IPC_INBUFSZ, &self->usock.inbuffersz, &sz); #endif /* Start connecting. */ nn_usock_connect (&self->usock, (struct sockaddr*) &ss, sizeof (struct sockaddr_un)); self->state = NN_CIPC_STATE_CONNECTING; nn_ep_stat_increment (self->ep, NN_STAT_INPROGRESS_CONNECTIONS, 1); }
static void nn_global_submit_errors (int i, struct nn_sock *s, char *name, int value) { /* TODO(tailhook) dynamically allocate buffer */ char buf[4096]; char *curbuf; int buf_left; char timebuf[20]; time_t numtime; struct tm strtime; int len; struct nn_list_item *it; struct nn_ep *ep; if (self.statistics_socket >= 0) { /* TODO(tailhook) add HAVE_GMTIME_R ifdef */ time(&numtime); #ifdef NN_HAVE_GMTIME_R gmtime_r (&numtime, &strtime); #else #error #endif strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", &strtime); if(*s->socket_name) { len = sprintf (buf, "ESTP:%s:%s:socket.%s:%s: %sZ 10 %d\n", self.hostname, self.appname, s->socket_name, name, timebuf, value); } else { len = sprintf (buf, "ESTP:%s:%s:socket.%d:%s: %sZ 10 %d\n", self.hostname, self.appname, i, name, timebuf, value); } buf_left = sizeof(buf) - len; curbuf = buf + len; for (it = nn_list_begin (&s->eps); it != nn_list_end (&s->eps); it = nn_list_next (&s->eps, it)) { ep = nn_cont (it, struct nn_ep, item); if (ep->last_errno) { #ifdef NN_HAVE_WINDOWS len = _snprintf_s (curbuf, buf_left, _TRUNCATE, " nanomsg: Endpoint %d [%s] error: %s\n", ep->eid, nn_ep_getaddr (ep), nn_strerror (ep->last_errno)); #else len = snprintf (curbuf, buf_left, " nanomsg: Endpoint %d [%s] error: %s\n", ep->eid, nn_ep_getaddr (ep), nn_strerror (ep->last_errno)); #endif if (buf_left < len) break; curbuf += len; buf_left -= len; } } (void) nn_send (self.statistics_socket, buf, sizeof(buf) - buf_left, NN_DONTWAIT); }
const char *nn_epbase_getaddr (struct nn_epbase *self) { return nn_ep_getaddr (self->ep); }
int nn_cws_create (struct nn_ep *ep) { int rc; const char *addr; size_t addrlen; const char *semicolon; const char *hostname; size_t hostlen; const char *colon; const char *slash; const char *resource; size_t resourcelen; struct sockaddr_storage ss; size_t sslen; int ipv4only; size_t ipv4onlylen; struct nn_cws *self; int reconnect_ivl; int reconnect_ivl_max; int msg_type; size_t sz; /* Allocate the new endpoint object. */ self = nn_alloc (sizeof (struct nn_cws), "cws"); alloc_assert (self); self->ep = ep; /* Initalise the endpoint. */ nn_ep_tran_setup (ep, &nn_cws_ep_ops, self); /* Check whether IPv6 is to be used. */ ipv4onlylen = sizeof (ipv4only); nn_ep_getopt (ep, NN_SOL_SOCKET, NN_IPV4ONLY, &ipv4only, &ipv4onlylen); nn_assert (ipv4onlylen == sizeof (ipv4only)); /* Start parsing the address. */ addr = nn_ep_getaddr (ep); addrlen = strlen (addr); semicolon = strchr (addr, ';'); hostname = semicolon ? semicolon + 1 : addr; colon = strrchr (addr, ':'); slash = colon ? strchr (colon, '/') : strchr (addr, '/'); resource = slash ? slash : addr + addrlen; self->remote_hostname_len = colon ? colon - hostname : resource - hostname; /* Host contains both hostname and port. */ hostlen = resource - hostname; /* Parse the port; assume port 80 if not explicitly declared. */ if (colon != NULL) { rc = nn_port_resolve (colon + 1, resource - colon - 1); if (rc < 0) { return -EINVAL; } self->remote_port = rc; } else { self->remote_port = 80; } /* Check whether the host portion of the address is either a literal or a valid hostname. */ if (nn_dns_check_hostname (hostname, self->remote_hostname_len) < 0 && nn_literal_resolve (hostname, self->remote_hostname_len, ipv4only, &ss, &sslen) < 0) { return -EINVAL; } /* If local address is specified, check whether it is valid. */ if (semicolon) { rc = nn_iface_resolve (addr, semicolon - addr, ipv4only, &ss, &sslen); if (rc < 0) { return -ENODEV; } } /* At this point, the address is valid, so begin allocating resources. */ nn_chunkref_init (&self->remote_host, hostlen + 1); memcpy (nn_chunkref_data (&self->remote_host), hostname, hostlen); ((uint8_t *) nn_chunkref_data (&self->remote_host)) [hostlen] = '\0'; if (semicolon) { nn_chunkref_init (&self->nic, semicolon - addr); memcpy (nn_chunkref_data (&self->nic), addr, semicolon - addr); } else { nn_chunkref_init (&self->nic, 1); memcpy (nn_chunkref_data (&self->nic), "*", 1); } /* The requested resource is used in opening handshake. */ resourcelen = strlen (resource); if (resourcelen) { nn_chunkref_init (&self->resource, resourcelen + 1); strncpy (nn_chunkref_data (&self->resource), resource, resourcelen + 1); } else { /* No resource specified, so allocate base path. */ nn_chunkref_init (&self->resource, 2); strncpy (nn_chunkref_data (&self->resource), "/", 2); } /* Initialise the structure. */ nn_fsm_init_root (&self->fsm, nn_cws_handler, nn_cws_shutdown, nn_ep_getctx (ep)); self->state = NN_CWS_STATE_IDLE; nn_usock_init (&self->usock, NN_CWS_SRC_USOCK, &self->fsm); sz = sizeof (msg_type); nn_ep_getopt (ep, NN_WS, NN_WS_MSG_TYPE, &msg_type, &sz); nn_assert (sz == sizeof (msg_type)); self->msg_type = (uint8_t) msg_type; sz = sizeof (reconnect_ivl); nn_ep_getopt (ep, NN_SOL_SOCKET, NN_RECONNECT_IVL, &reconnect_ivl, &sz); nn_assert (sz == sizeof (reconnect_ivl)); sz = sizeof (reconnect_ivl_max); nn_ep_getopt (ep, NN_SOL_SOCKET, NN_RECONNECT_IVL_MAX, &reconnect_ivl_max, &sz); nn_assert (sz == sizeof (reconnect_ivl_max)); if (reconnect_ivl_max == 0) reconnect_ivl_max = reconnect_ivl; nn_backoff_init (&self->retry, NN_CWS_SRC_RECONNECT_TIMER, reconnect_ivl, reconnect_ivl_max, &self->fsm); nn_sws_init (&self->sws, NN_CWS_SRC_SWS, ep, &self->fsm); nn_dns_init (&self->dns, NN_CWS_SRC_DNS, &self->fsm); /* Start the state machine. */ nn_fsm_start (&self->fsm); return 0; }