예제 #1
0
파일: manager.c 프로젝트: Bisheg/bluez
static int proxy_probe(struct btd_adapter *adapter)
{
	const char *path = adapter_get_path(adapter);

	DBG("path %s", path);

	return proxy_register(connection, adapter);
}
예제 #2
0
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);
    }
}
예제 #3
0
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);
}