static void nc_set_default_options(struct instance *nci) { int status; nci->ctx = NULL; nci->log_level = NC_LOG_DEFAULT; nci->log_filename = NC_LOG_PATH; nci->conf_filename = NC_CONF_PATH; nci->stats_port = NC_STATS_PORT; nci->stats_addr = NC_STATS_ADDR; nci->stats_interval = NC_STATS_INTERVAL; status = nc_gethostname(nci->hostname, NC_MAXHOSTNAMELEN); if (status < 0) { log_warn("gethostname failed, ignored: %s", strerror(errno)); nc_snprintf(nci->hostname, NC_MAXHOSTNAMELEN, "unknown"); } nci->hostname[NC_MAXHOSTNAMELEN - 1] = '\0'; nci->mbuf_chunk_size = NC_MBUF_SIZE; nci->mbuf_pool_size = NC_MBUF_POOL_SIZE; nci->pid = (pid_t)-1; nci->pid_filename = NULL; nci->pidfile = 0; }
static rstatus_t nc_create_pidfile(struct instance *nci) { char pid[NC_UINTMAX_MAXLEN]; int fd, pid_len; ssize_t n; fd = open(nci->pid_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { log_error("opening pid file '%s' failed: %s", nci->pid_filename, strerror(errno)); return NC_ERROR; } nci->pidfile = 1; pid_len = nc_snprintf(pid, NC_UINTMAX_MAXLEN, "%d", nci->pid); n = nc_write(fd, pid, pid_len); if (n < 0) { log_error("write to pid file '%s' failed: %s", nci->pid_filename, strerror(errno)); return NC_ERROR; } close(fd); return NC_OK; }
static int nc_resolve_inet(struct string *name, int port, struct sockinfo *si) { int status; struct addrinfo *ai, *cai; /* head and current addrinfo */ struct addrinfo hints; char *node, service[NC_UINTMAX_MAXLEN]; bool found; ASSERT(nc_valid_port(port)); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV; //ai_numericserv hints.ai_family = AF_UNSPEC; /* AF_INET or AF_INET6 */ hints.ai_socktype = SOCK_STREAM; //sock_stream hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; if (name != NULL) { node = (char *)name->data; } else { /* * If AI_PASSIVE flag is specified in hints.ai_flags, and node is * NULL, then the returned socket addresses will be suitable for * bind(2)ing a socket that will accept(2) connections. The returned * socket address will contain the wildcard IP address. */ node = NULL; hints.ai_flags |= AI_PASSIVE; } nc_snprintf(service, NC_UINTMAX_MAXLEN, "%d", port); status = getaddrinfo(node, service, &hints, &ai); if (status < 0) { log_error("address resolution of node '%s' service '%s' failed: %s", node, service, gai_strerror(status)); return -1; } /* * getaddrinfo() can return a linked list of more than one addrinfo, * since we requested for both AF_INET and AF_INET6 addresses and the * host itself can be multi-homed. Since we don't care whether we are * using ipv4 or ipv6, we just use the first address from this collection * in the order in which it was returned. * * The sorting function used within getaddrinfo() is defined in RFC 3484; * the order can be tweaked for a particular system by editing * /etc/gai.conf */ for (cai = ai, found = false; cai != NULL; cai = cai->ai_next) { si->family = cai->ai_family; si->addrlen = cai->ai_addrlen; nc_memcpy(&si->addr, cai->ai_addr, si->addrlen); found = true; break; } freeaddrinfo(ai); return !found ? -1 : 0; }
/* * Unresolve the socket address by translating it to a character string * describing the host and service * 返回地址字符串 * This routine is not reentrant */ char * nc_unresolve_addr(struct sockaddr *addr, socklen_t addrlen) { static char unresolve[NI_MAXHOST + NI_MAXSERV]; static char host[NI_MAXHOST], service[NI_MAXSERV]; int status; status = getnameinfo(addr, addrlen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); if (status < 0) { return "unknown"; } nc_snprintf(unresolve, sizeof(unresolve), "%s:%s", host, service); return unresolve; }
static rstatus_t stats_begin_nesting(struct stats *st, struct string *key) { struct stats_buffer *buf; uint8_t *pos; size_t room; int n; buf = &st->buf; pos = buf->data + buf->len; room = buf->size - buf->len - 1; n = nc_snprintf(pos, room, "\"%.*s\": {", key->len, key->data); if (n < 0 || n >= (int)room) { return NC_ERROR; } buf->len += (size_t)n; return NC_OK; }
static rstatus_t stats_add_float(struct stats *st, struct string *key, float val) { struct stats_buffer *buf; uint8_t *pos; size_t room; int n; buf = &st->buf; pos = buf->data + buf->len; room = buf->size - buf->len - 1; n = nc_snprintf(pos, room, "\"%.*s\":%.2f, ", key->len, key->data, val); if (n < 0 || n >= (int)room) { return NC_ERROR; } buf->len += (size_t)n; return NC_OK; }
struct server * sentinel_init(uint16_t sentinel_port, char *sentinel_ip) { rstatus_t status; struct server *sentinel; struct string address; struct sockinfo info; char pname[NC_PNAME_MAXLEN]; string_init(&address); sentinel_status = SENTINEL_CONN_DISCONNECTED; sentinel = (struct server *)nc_alloc(sizeof(*sentinel)); if(sentinel == NULL) { goto error; } /* sentinel server don't have owner server pool */ sentinel->owner = NULL; sentinel->ns_conn_q = 0; TAILQ_INIT(&sentinel->s_conn_q); sentinel->addr = NULL; string_init(&sentinel->pname); string_init(&sentinel->name); nc_snprintf(pname, NC_PNAME_MAXLEN, "%s:%d:0", sentinel_ip, sentinel_port); status = string_copy(&sentinel->pname, pname, (uint32_t)(nc_strlen(pname))); if (status != NC_OK) { goto error; } string_copy(&sentinel->name, pname, (uint32_t)(nc_strlen(pname)) - 2); if (status != NC_OK) { goto error; } sentinel->port = sentinel_port; status = string_copy(&address, sentinel_ip, (uint32_t)(nc_strlen(sentinel_ip))); if (status != NC_OK) { goto error; } status = nc_resolve(&address, sentinel_port, &info); if (status != NC_OK) { goto error; } sentinel->family = info.family; sentinel->addrlen = info.addrlen; sentinel->addr = (struct sockaddr*)nc_alloc(info.addrlen); if (sentinel->addr == NULL) { goto error; } nc_memcpy(sentinel->addr, &info.addr, info.addrlen); done: string_deinit(&address); return sentinel; error: sentinel_deinit(sentinel); sentinel = NULL; goto done; }