Exemplo n.º 1
0
void
consumer_start(void *arg) {
    uv_loop_t loop;
    struct server_context *server = arg;

#ifndef CROSS_COMPILE
    char name[24] = {0};
    sprintf(name, "consumer-%d", server->index + 1);
    pthread_setname_np(pthread_self(), name);
#endif

    uv_loop_init(&loop);

    struct resolver_context *res = NULL;
    if (server->nameserver_num >= 0) {
        res = resolver_init(&loop, 0,
          server->nameserver_num == 0 ? NULL : server->nameservers, server->nameserver_num);
        loop.data = res;
    }

    tcp_bind(&loop, server);

    if (server->udprelay) {
        udprelay_start(&loop, server);
    }

    uv_run(&loop, UV_RUN_DEFAULT);

    close_loop(&loop);

    if (server->nameserver_num >= 0) {
        resolver_destroy(res);
    }

    uv_sem_post(&server->semaphore);
}
Exemplo n.º 2
0
int
main(int argc, char *argv[]) {
    int rc;
    uv_loop_t *loop;
    struct sockaddr local_addr;

    parse_opts(argc, argv);

#ifndef _WIN32
    if (xsignal) {
        return signal_process(xsignal, pidfile);
    }

    if (!password) {
        print_usage(argv[0]);
        return 1;
    }
#endif

#ifndef _WIN32
    if (daemon_mode) {
        if (daemonize()) {
            return 1;
        }
        if (already_running(pidfile)) {
            logger_stderr("xsocksd already running.");
            return 1;
        }
    }
#endif

    init();

    loop = uv_default_loop();

    rc = resolve_addr(local_addrbuf, &local_addr);
    if (rc) {
        logger_stderr("invalid local address");
        return 1;
    }

    if (udprelay) {
        udprelay_init();
    }

    if (concurrency <= 1) {
        struct server_context ctx;
        ctx.local_addr = &local_addr;
        ctx.udprelay = udprelay;
        ctx.resolver = 1;
        ctx.udp_fd = create_socket(SOCK_DGRAM, 0);

        uv_tcp_init(loop, &ctx.tcp);
        rc = uv_tcp_bind(&ctx.tcp, &local_addr, 0);
        if (rc) {
            logger_stderr("tcp bind error: %s", uv_strerror(rc));
            return 1;
        }

        rc = uv_listen((uv_stream_t*)&ctx.tcp, 128, client_accept_cb);
        if (rc == 0) {
            logger_log(LOG_INFO, "listening on %s", local_addrbuf);

#ifndef _WIN32
            setup_signal(loop, signal_cb, &ctx);
#endif

            struct resolver_context *dns =
              resolver_init(loop, MODE_IPV4,
                nameserver_num == 0 ? NULL : nameservers, nameserver_num);
            uv_key_set(&thread_resolver_key, dns);

            if (udprelay) {
                udprelay_start(loop, &ctx);
            }

            uv_run(loop, UV_RUN_DEFAULT);

            close_loop(loop);
            resolver_destroy(dns);

        } else {
            logger_stderr("listen error: %s", uv_strerror(rc));
        }

    } else {
#ifndef _WIN32
        struct server_context *servers = calloc(concurrency, sizeof(servers[0]));
        for (int i = 0; i < concurrency; i++) {
            struct server_context *ctx = servers + i;
            ctx->index = i;
            ctx->tcp_fd = create_socket(SOCK_STREAM, 1);
            ctx->udp_fd = create_socket(SOCK_DGRAM, 1);
            ctx->udprelay = udprelay;
            ctx->resolver = 1;
            ctx->accept_cb = client_accept_cb;
            ctx->nameservers = nameservers;
            ctx->nameserver_num = nameserver_num;
            ctx->local_addr = &local_addr;
            rc = uv_sem_init(&ctx->semaphore, 0);
            rc = uv_thread_create(&ctx->thread_id, consumer_start, ctx);
        }

        logger_log(LOG_INFO, "listening on %s", local_addrbuf);

        setup_signal(loop, signal_cb, servers);

        uv_run(loop, UV_RUN_DEFAULT);

        close_loop(loop);

        for (int i = 0; i < concurrency; i++) {
            uv_sem_wait(&servers[i].semaphore);
        }
        free(servers);
#else
        logger_stderr("don't support multithreading.");
        return 1;
#endif
    }

    if (udprelay) {
        udprelay_destroy();
    }

    uv_key_delete(&thread_resolver_key);

#ifndef _WIN32
    if (daemon_mode) {
        delete_pidfile(pidfile);
    }
#endif

    logger_exit();

    return 0;
}