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; }
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; }
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; }
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; }