//拷贝conf_server数组中的相关内容到server_pool->server中
rstatus_t
conf_server_each_transform(void *elem, void *data)
{
    struct conf_server *cs = elem;
    struct array *server = data;
    struct server *s;

    ASSERT(cs->valid);

    s = array_push(server);
    ASSERT(s != NULL);

    s->idx = array_idx(server, s);
    s->owner = NULL;

    s->pname = cs->pname;
    s->name = cs->name;
    s->addrstr = cs->addrstr;
    s->port = (uint16_t)cs->port;
    s->weight = (uint32_t)cs->weight;

    nc_memcpy(&s->info, &cs->info, sizeof(cs->info));

    s->ns_conn_q = 0;
    TAILQ_INIT(&s->s_conn_q);

    s->next_retry = 0LL;
    s->failure_count = 0;

    log_debug(LOG_VERB, "transform to server %"PRIu32" '%.*s'",
              s->idx, s->pname.len, s->pname.data);

    return NC_OK;
}
Exemple #2
0
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;
}
Exemple #3
0
/*
 * Copy n bytes from memory area pos to mbuf.
 *
 * The memory areas should not overlap and the mbuf should have
 * enough space for n bytes.
 */
void
mbuf_copy(struct mbuf *mbuf, uint8_t *pos, size_t n)
{
    if (n == 0) {
        return;
    }

    /* mbuf has space for n bytes */
    ASSERT(!mbuf_full(mbuf) && n <= mbuf_size(mbuf));

    /* no overlapping copy */
    ASSERT(pos < mbuf->start || pos >= mbuf->end);

    nc_memcpy(mbuf->last, pos, n);
    mbuf->last += n;
}
Exemple #4
0
/**
 *文件套接宇
 */
static int
nc_resolve_unix(struct string *name, struct sockinfo *si)
{
    struct sockaddr_un *un;

    if (name->len >= NC_UNIX_ADDRSTRLEN) {
        return -1;
    }
    un = &si->addr.un;
    un->sun_family = AF_UNIX;
    nc_memcpy(un->sun_path, name->data, name->len);
    un->sun_path[name->len] = '\0';
    si->family = AF_UNIX;
    si->addrlen = sizeof(*un);
    /* si->addr is an alias of un */

    return 0;
}
Exemple #5
0
int tcp_connect(nsp_state *N, TCP_SOCKET *sock, char *host, unsigned short port, short int use_ssl)
{
#define __FN__ __FILE__ ":tcp_connect()"
	struct hostent *hp;
	struct sockaddr_in serv;

	if ((hp = gethostbyname(host)) == NULL) {
		n_warn(N, __FN__, "Host lookup error for %s", host);
		return -1;
	}
	nc_memset((char *)&serv, 0, sizeof(serv));
	nc_memcpy((char *)&serv.sin_addr, hp->h_addr, hp->h_length);
	serv.sin_family = hp->h_addrtype;
	serv.sin_port = htons(port);
	if ((sock->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -2;
	/*	setsockopt(sock->socket, SOL_SOCKET, SO_KEEPALIVE, 0, 0); */
	if (tcp_conn(N, sock, &serv, sizeof(serv), use_ssl) < 0) {
		/* n_warn(N, __FN__, "Error connecting to %s:%d", host, port); */
		return -2;
	}
	return 0;
#undef __FN__
}
Exemple #6
0
rstatus_t
conf_sentinel_each_transform(void *elem, void *data)
{
    struct conf_server *cs = elem;
    struct array *server = data;
    struct server *s;

    ASSERT(cs->valid);

    s = array_push(server);
    ASSERT(s != NULL);

    s->idx = array_idx(server, s);
    s->owner = NULL;

    s->pname = cs->pname;/* ref */
    s->name = cs->name;/* ref */
    s->addrstr = cs->addrstr;/* ref */
    s->port = (uint16_t)cs->port;
    s->weight = 1;

    nc_memcpy(&s->info, &cs->info, sizeof(cs->info));

    s->ns_conn_q = 0;
    TAILQ_INIT(&s->s_conn_q);

    s->timer = msg_get_raw(server);
    if (s->timer == NULL) {
        return NC_ERROR;
    }
    s->status = 0;

    log_debug(LOG_VERB, "transform to sentinel %"PRIu32" '%.*s'",
              s->idx, s->pname.len, s->pname.data);

    return NC_OK;
}
Exemple #7
0
int tcp_bind(nsp_state *N, char *ifname, unsigned short port)
{
#define __FN__ __FILE__ ":tcp_bind()"
	struct hostent *hp;
	struct sockaddr_in sin;
	int option;
	int sock;

	nc_memset((char *)&sin, 0, sizeof(sin));
	sock = socket(AF_INET, SOCK_STREAM, 0);
	sin.sin_family = AF_INET;
	if (strcasecmp("INADDR_ANY", ifname) == 0) {
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	}
	else {
		if ((hp = gethostbyname(ifname)) == NULL) {
			n_warn(N, __FN__, "Host lookup error for %s", ifname);
			return -1;
		}
		nc_memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
	}
	sin.sin_port = htons(port);
	option = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
	if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
		n_warn(N, __FN__, "bind() error [%s:%d]", ifname, port);
		return -1;
	}
	if (listen(sock, 50) < 0) {
		n_warn(N, __FN__, "listen() error");
		closesocket(sock);
		return -1;
	}
	return sock;
#undef __FN__
}
Exemple #8
0
int tcp_fgets(nsp_state *N, TCP_SOCKET *socket, char *buffer, int max)
{
#define __FN__ __FILE__ ":tcp_fgets()"
	char *pbuffer = buffer;
	char *obuffer;
	short int lf = 0;
	short int n = 0;
	int rc;
	int x;

retry:
	if (!socket->recvbufsize) {
		x = sizeof(socket->recvbuf) - socket->recvbufoffset - socket->recvbufsize - 2;
		if (x < 1) {
			nc_memset(socket->recvbuf, 0, sizeof(socket->recvbuf));
			socket->recvbufoffset = 0;
			socket->recvbufsize = 0;
			x = sizeof(socket->recvbuf) - socket->recvbufoffset - socket->recvbufsize - 2;
		}
		obuffer = socket->recvbuf + socket->recvbufoffset + socket->recvbufsize;
		if (x > max) x = max;
		if ((rc = tcp_recv(N, socket, obuffer, x, 0)) < 0) {
			return -1;
		}
		else if (rc < 1) {
			/* goto retry; */
			*pbuffer = '\0';
			return n;
		}
		socket->recvbufsize += rc;
	}
	obuffer = socket->recvbuf + socket->recvbufoffset;
	while ((n < max) && (socket->recvbufsize>0)) {
		socket->recvbufoffset++;
		socket->recvbufsize--;
		n++;
		if (*obuffer == '\n') lf = 1;
		*pbuffer++ = *obuffer++;
		if ((lf) || (*obuffer == '\0')) break;
	}
	*pbuffer = '\0';
	if (n > max - 1) {
		/* if (N->debug) n_warn(N, __FN__, "[%s:%d] %s", socket->RemoteAddr, socket->RemotePort, buffer); */
		return n;
	}
	if (!lf) {
		if (socket->recvbufsize > 0) {
			nc_memcpy(socket->recvbuf, socket->recvbuf + socket->recvbufoffset, socket->recvbufsize);
			nc_memset(socket->recvbuf + socket->recvbufsize, 0, sizeof(socket->recvbuf) - socket->recvbufsize);
			socket->recvbufoffset = 0;
		}
		else {
			nc_memset(socket->recvbuf, 0, sizeof(socket->recvbuf));
			socket->recvbufoffset = 0;
			socket->recvbufsize = 0;
		}
		goto retry;
	}
	/* if (N->debug) n_warn(N, __FN__, "[%s:%d] %s", socket->RemoteAddr, socket->RemotePort, buffer); */
	return n;
#undef __FN__
}
Exemple #9
0
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;
}
//从elem  conf_pool中拷贝到data  server_pool目标中
rstatus_t
conf_pool_each_transform(void *elem, void *data)
{
    rstatus_t status;
    struct conf_pool *cp = elem;
    struct array *server_pool = data;
    struct server_pool *sp;

    ASSERT(cp->valid);

    sp = array_push(server_pool);
    ASSERT(sp != NULL);

    sp->idx = array_idx(server_pool, sp);
    sp->ctx = NULL;

    sp->p_conn = NULL;
    sp->nc_conn_q = 0;
    TAILQ_INIT(&sp->c_conn_q);

    array_null(&sp->server);
    sp->ncontinuum = 0;
    sp->nserver_continuum = 0;
    sp->continuum = NULL;
    sp->nlive_server = 0;
    sp->next_rebuild = 0LL;

    sp->name = cp->name;
    sp->addrstr = cp->listen.pname;
    sp->port = (uint16_t)cp->listen.port;

    nc_memcpy(&sp->info, &cp->listen.info, sizeof(cp->listen.info));
    sp->perm = cp->listen.perm;

    sp->key_hash_type = cp->hash;
    sp->key_hash = hash_algos[cp->hash];
    sp->dist_type = cp->distribution;
    sp->hash_tag = cp->hash_tag;

    sp->tcpkeepalive = cp->tcpkeepalive ? 1 : 0;

    sp->redis = cp->redis ? 1 : 0;
    sp->timeout = cp->timeout;
    sp->backlog = cp->backlog;
    sp->redis_db = cp->redis_db;

    sp->redis_auth = cp->redis_auth;
    sp->require_auth = cp->redis_auth.len > 0 ? 1 : 0;

    sp->client_connections = (uint32_t)cp->client_connections;
    sp->server_connections = (uint32_t)cp->server_connections;
    sp->server_retry_timeout = (int64_t)cp->server_retry_timeout * 1000LL;
    sp->server_failure_limit = (uint32_t)cp->server_failure_limit;
    sp->auto_eject_hosts = cp->auto_eject_hosts ? 1 : 0;
    sp->preconnect = cp->preconnect ? 1 : 0;

    status = server_init(&sp->server, &cp->server, sp);
    if (status != NC_OK) {
        return status;
    }

    log_debug(LOG_VERB, "transform to pool %"PRIu32" '%.*s'", sp->idx,
              sp->name.len, sp->name.data);

    return NC_OK;
}
Exemple #11
0
uchar   *n_decompose(nsp_state *N, char *srcfile, uchar *srctext, uchar **dsttext, int *dstsize)
{
#define __FN__ __FILE__ ":n_decompose()"
	cstate state;
	obj_t *cobj, *tobj;
	unsigned short op;
	uchar *p, *p2;

	settrace();

	*dsttext = NULL;
	*dstsize = 0;

	if ((srctext[0] == 0x0D) && ((srctext[1] == 0xAC))) {
		n_warn(N, __FN__, "already chewed on this");
		return srctext;
	}
	nc_memset((char *)&state, 0, sizeof(state));
	state.lineno = 1;
	state.destmax = 1024;
	state.destbuf = (uchar *)n_alloc(N, state.destmax, 0);
	N->readptr = srctext;
	tobj = nsp_settable(N, &N->g, "decomped_script");
	nsp_freetable(N, tobj);
	state.tobj1 = nsp_settable(N, tobj, "code");
	n_decompose_sub(N, &state);
	/* header - 8 bytes */
	testgrow(8); /* safe portable use of sprintf is still considered dangerous according to openbsd */
	state.destbuf[state.offset++] = 0x0D;
	state.destbuf[state.offset++] = 0xAC;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	/* file size - 4 bytes */
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	/* optab offset  - 4 bytes (little endian) */
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	/* symtab offset - 4 bytes (little endian) */
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	state.destbuf[state.offset++] = 0;
	/* now write the ops */
	/* optab offset */
	writei4(state.offset, (state.destbuf + 12));
	/* set line number to 1 */
	testgrow((long)(5));
	state.destbuf[state.offset++] = OP_LINENUM;
	writei4(1, (state.destbuf + state.offset));
	state.offset += 4;

	for (cobj = state.tobj1->val->d.table.f; cobj; cobj = cobj->next) {
		op = (unsigned short)cobj->val->attr;
		cobj->val->attr = 0;
		if (op == OP_LINENUM) {
			testgrow((long)(5));
			state.destbuf[state.offset++] = op & 255;
			writei4((int)cobj->val->d.num, (state.destbuf + state.offset));
			state.offset += 4;
			continue;
		}
		if (!nsp_isstr(cobj)) break;
		if (op == OP_UNDEFINED) break;
		if (op == OP_POBRACE) {
			testgrow((long)(5));
			state.destbuf[state.offset++] = op & 255;
			writei4(0, (state.destbuf + state.offset));
			state.offset += 4;
			continue;
		}
		else if (op == OP_POPAREN) {
			testgrow((long)(3));
			state.destbuf[state.offset++] = op & 255;
			writei2(0, (state.destbuf + state.offset));
			state.offset += 2;
			continue;
		}
		else if (op == OP_STRDATA || op == OP_ESTRDATA) {
			testgrow((long)(6 + cobj->val->size));
			state.destbuf[state.offset++] = op & 255;
			writei4(cobj->val->size, (state.destbuf + state.offset));
			state.offset += 4;
			nc_memcpy((char *)state.destbuf + state.offset, cobj->val->d.str, cobj->val->size);
			state.offset += cobj->val->size;
			state.destbuf[state.offset++] = 0;
		}
		else if (op == OP_NUMDATA) {
			testgrow((long)(3 + cobj->val->size));
			state.destbuf[state.offset++] = op & 255;
			state.destbuf[state.offset++] = (uchar)(cobj->val->size & 255);
			nc_memcpy((char *)state.destbuf + state.offset, cobj->val->d.str, cobj->val->size);
			state.offset += cobj->val->size;
			state.destbuf[state.offset++] = 0;
		}
		else if (op == OP_LABEL) {
			testgrow((long)(3 + cobj->val->size));
			state.destbuf[state.offset++] = op & 255;
			state.destbuf[state.offset++] = (uchar)(cobj->val->size & 255);
			nc_memcpy((char *)state.destbuf + state.offset, cobj->val->d.str, cobj->val->size);
			state.offset += cobj->val->size;
			state.destbuf[state.offset++] = '\0';
		}
		else if (OP_ISMATH(op) || OP_ISKEY(op) || OP_ISPUNC(op)) {
			testgrow(1);
			state.destbuf[state.offset++] = op & 255;
			if (op == OP_KFUNC) {
				char *p = srcfile;

				//n_warn(N, __FN__, "'%s'", p);
				if (cobj->next->val->attr == OP_LABEL) {
					cobj = cobj->next;
					op = (unsigned short)cobj->val->attr;
					cobj->val->attr = 0;
					testgrow((long)(3 + cobj->val->size));
					state.destbuf[state.offset++] = op & 255;
					state.destbuf[state.offset++] = (uchar)(cobj->val->size & 255);
					nc_memcpy((char *)state.destbuf + state.offset, cobj->val->d.str, cobj->val->size);
					state.offset += cobj->val->size;
					state.destbuf[state.offset++] = '\0';
				}
				if (srcfile == NULL) p = "";
				testgrow((long)(3 + nc_strlen(p)));
				state.destbuf[state.offset++] = OP_LABEL;
				state.destbuf[state.offset++] = (uchar)(nc_strlen(p) & 255);
				nc_memcpy((char *)state.destbuf + state.offset, p, nc_strlen(p));
				state.offset += nc_strlen(p);
				state.destbuf[state.offset++] = '\0';
			}
		}
		else {
			n_warn(N, __FN__, "bad op?");
		}
	}
	/* file size */
	writei4(state.offset, (state.destbuf + 8));
	/* add some trailing nulls for fun... */
	testgrow(4); writei4(0, (state.destbuf + state.offset));
	state.offset += 4;
	/* n_dumpvars(N, &N->g, 0); */
	nsp_freetable(N, tobj);
	*dsttext = state.destbuf;
	*dstsize = state.destmax;
	for (p = *dsttext + 12; p < *dsttext + state.offset - 4;) {
		if (*p == OP_LINENUM) { p += 5; continue; }
		if (*p == OP_POBRACE) {
			p2 = n_seekop(N, p, 1);
			if (p2 <= p) {
				n_warn(N, __FN__, "pointer did not progress");
				break;
			}
			--p2;
			// if (*p2!=OP_PCBRACE) n_warn(N, __FN__, "no OP_PCBRACE? %d", (p+(p2-p)+5)[0]);
			if (*p2 != OP_PCBRACE) {
				/*
				int i;
				for (i=0;i<state.offset;i++) {
				if (i==p2-*dsttext) {
				printf("-----------------------\r\n[%d]\r\n-------------------", state.destbuf[i]);
				} else {
				if (state.destbuf[i]>=32 && state.destbuf[i]<128) {
				printf("'%c' %d\r\n", state.destbuf[i], state.destbuf[i]);
				} else {
				printf("%d\r\n", state.destbuf[i]);
				}
				}
				}
				*/
				n_warn(N, __FN__, "no OP_PCBRACE? %d .. %d %d %d %d [%d] %d %d", OP_PCBRACE, p2[-4], p2[-3], p2[-2], p2[-1], p2[0], p2[1], p2[2]);
				//n_decompile(N, *dsttext+12, *dsttext+state.offset-4, NULL, 0);
			}
			writei4((p2 - p - 5), (p + 1));
		}
		else if (*p == OP_POPAREN) {
			p2 = n_seekop(N, p, 1);
			if (p2 <= p) {
				n_warn(N, __FN__, "pointer did not progress");
				break;
			}
			--p2;
			if (*p2 != OP_PCPAREN) {
				n_warn(N, __FN__, "no OP_PCPAREN? %d .. %d %d %d %d [%d] %d %d", OP_PCPAREN, p2[-4], p2[-3], p2[-2], p2[-1], p2[0], p2[1], p2[2]);
			}
			writei2((p2 - p - 3), (p + 1));
		}
		p = n_seekop(N, p, 0);
	}
	return *dsttext;
#undef __FN__
}