static int proxy_probe(struct btd_adapter *adapter) { const char *path = adapter_get_path(adapter); DBG("path %s", path); return proxy_register(connection, adapter); }
static void main_loop(proxy_t *p, char **feeders) { fd_epoll = epoll_create(8192); ASSERT(fd_epoll >= 0); if (0 > listen(p->sock_front, front_backlog)) { LOG("front(%d).listen(%d) failed", p->sock_front, front_backlog); exit(1); } proxy_init_feeders(p, feeders); proxy_register(p); while (running) { if (count_epoll) manage_monitored_items(); manage_active_channels(); manage_active_proxies(); DRAIN_STRUCT_CALL(tunnel_t); } }
static void proxy_manage_event (proxy_t *p, uint32_t events) { struct sockaddr_in6 from, to; socklen_t slen; int rc, opt; (void) events; ASSERT(!(p->flags & FLAG_LISTED)); ASSERT(!(events & EPOLLOUT)); ASSERT(!(events & (EPOLLHUP|EPOLLERR))); if (!p->events) return; tunnel_t *t = tunnel_reserve(p); retry: slen = sizeof(from); t->front.sock = accept4(p->sock_front, SA(&from), &slen, SOCK_NONBLOCK|SOCK_CLOEXEC); if (t->front.sock < 0) { if (errno == EINTR) goto retry; ASSERT (errno == EAGAIN); tunnel_release(t); return proxy_register(p); } // The proxy front socket is maybe still active. Then instead of // systematically sending the proxy in ACTIVE, check if the limit // has been reached. It it is, re-monitor for only errors. if (p->pipes.max == ++(p->pipes.count)) proxy_pause(p); else proxy_resume(p); // Poll a backend void *buf = NULL; rc = nn_recv(p->nn_feed, &buf, NN_MSG, NN_DONTWAIT); if (rc < 0) { // TODO better manage the backend's starvation (e.g. retry) return tunnel_abort(t, "backend starvation: (%d) %s", nn_errno(), nn_strerror(nn_errno())); } else if (rc > 128) { nn_freemsg(buf); return tunnel_abort(t, "invalid backend: %s", "URL too big"); } else { char *sto = alloca(rc + 1); memcpy(sto, buf, rc); sto[rc] = 0; rc = sockaddr_init(SA(&to), sto); nn_freemsg(buf); if (!rc) return tunnel_abort(t, "invalid backend: %s", "bad URL"); char sfrom[64]; sockaddr_dump(SA(&from), sfrom, sizeof(sfrom)); ACCESS("%s -> %s", sfrom, sto); } // Connect to the polled backend t->back.sock = socket(SAFAM(&to), SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); if (t->back.sock < 0) return tunnel_abort(t, "socket() error: (%d) %s", errno, strerror(errno)); slen = sizeof(struct sockaddr_in6); rc = connect(t->back.sock, SA(&to), slen); if (0 > rc && errno != EINPROGRESS) return tunnel_abort(t, "connect() error: (%d) %s", errno, strerror(errno)); // Tweak the socket options opt = PIPE_SIZE/2; setsockopt(t->front.sock, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); setsockopt(t->back.sock, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); opt = PIPE_SIZE; setsockopt(t->front.sock, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)); setsockopt(t->back.sock, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)); errno = 0; tunnel_register(t); }