int udp_listener_init(struct udp_listener *u, struct poller *p, const endpoint_t *ep,
		udp_listener_callback_t func, struct obj *obj)
{
	struct poller_item i;
	struct udp_listener_callback *cb;

	cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL);
	cb->func = func;
	cb->p = obj_get_o(obj);
	cb->ul = u;

	if (open_socket(&u->sock, SOCK_DGRAM, ep->port, &ep->address))
		goto fail;

	ipv6only(u->sock.fd, 1);

	ZERO(i);
	i.fd = u->sock.fd;
	i.closed = udp_listener_closed;
	i.readable = udp_listener_incoming;
	i.obj = &cb->obj;
	if (poller_add_item(p, &i))
		goto fail;

	return 0;

fail:
	close_socket(&u->sock);
	obj_put_o(obj);
	obj_put(cb);
	return -1;
}
示例#2
0
static void control_incoming(int fd, void *p, uintptr_t u) {
	int nfd;
	struct control_tcp *c = p;
	struct control_stream *s;
	struct poller_item i;
	struct sockaddr_in sin;
	socklen_t sinl;

next:
	sinl = sizeof(sin);
	nfd = accept(fd, (struct sockaddr *) &sin, &sinl);
	if (nfd == -1) {
		if (errno == EAGAIN || errno == EWOULDBLOCK)
			return;
		goto next;
	}
	nonblock(nfd);

	ilog(LOG_INFO, "New control connection from " DF, DP(sin));

	s = obj_alloc0("control_stream", sizeof(*s), control_stream_free);

	s->fd = nfd;
	s->control = c;
	s->poller = c->poller;
	s->inbuf = streambuf_new(c->poller, nfd);
	s->outbuf = streambuf_new(c->poller, nfd);
	memcpy(&s->inaddr, &sin, sizeof(s->inaddr));
	mutex_init(&s->lock);
	s->linked = 1;

	ZERO(i);
	i.fd = nfd;
	i.closed = control_stream_closed;
	i.readable = control_stream_readable;
	i.writeable = control_stream_writeable;
	i.timer = control_stream_timer;
	i.obj = &s->obj;

	if (poller_add_item(c->poller, &i))
		goto fail;

	mutex_lock(&c->lock);
	/* let the list steal our own ref */
	c->streams = g_list_prepend(c->streams, s);
	mutex_unlock(&c->lock);

	goto next;

fail:
	obj_put(s);
	goto next;
}
示例#3
0
int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr ip, u_int16_t port, udp_listener_callback_t func, struct obj *obj) {
	struct sockaddr_in6 sin;
	struct poller_item i;
	struct udp_listener_callback *cb;

	cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL);
	cb->func = func;
	cb->p = obj_get_o(obj);

	u->fd = socket(AF_INET6, SOCK_DGRAM, 0);
	if (u->fd == -1)
		goto fail;

	nonblock(u->fd);
	reuseaddr(u->fd);
	ipv6only(u->fd, 0);

	ZERO(sin);
	sin.sin6_family = AF_INET6;
	sin.sin6_addr = ip;
	sin.sin6_port = htons(port);
	if (bind(u->fd, (struct sockaddr *) &sin, sizeof(sin)))
		goto fail;

	ZERO(i);
	i.fd = u->fd;
	i.closed = udp_listener_closed;
	i.readable = udp_listener_incoming;
	i.obj = &cb->obj;
	if (poller_add_item(p, &i))
		goto fail;

	return 0;

fail:
	if (u->fd != -1)
		close(u->fd);
	obj_put_o(obj);
	obj_put(cb);
	return -1;
}
示例#4
0
struct control_tcp *control_tcp_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) {
	int fd;
	struct control_tcp *c;
	struct poller_item i;
	struct sockaddr_in sin;
	const char *errptr;
	int erroff;

	if (!p)
		return NULL;
	if (!m)
		return NULL;

	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd == -1)
		return NULL;

	nonblock(fd);
	reuseaddr(fd);

	ZERO(sin);
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = ip;
	sin.sin_port = htons(port);
	if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)))
		goto fail;

	if (listen(fd, 5))
		goto fail;


	c = obj_alloc0("control", sizeof(*c), NULL);

	c->parse_re = pcre_compile(
			/*      reqtype          callid   streams     ip      fromdom   fromtype   todom     totype    agent          info  |reqtype     callid         info  | reqtype */
			"^(?:(request|lookup)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+info=(\\S*)|(delete)\\s+(\\S+)\\s+info=(\\S*)|(build|version|controls|quit|exit|status))$",
			PCRE_DOLLAR_ENDONLY | PCRE_DOTALL, &errptr, &erroff, NULL);
	c->parse_ree = pcre_study(c->parse_re, 0, &errptr);

	c->fd = fd;
	c->poller = p;
	c->callmaster = m;
	mutex_init(&c->lock);

	ZERO(i);
	i.fd = fd;
	i.closed = control_closed;
	i.readable = control_incoming;
	i.obj = &c->obj;
	if (poller_add_item(p, &i))
		goto fail2;

	obj_put(c);
	return c;

fail2:
	obj_put(c);
fail:
	close(fd);
	return NULL;
}