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); }
int main(int argc, char *argv[]) { int rc; uv_loop_t *loop; parse_opts(argc, argv); #if !defined(_WIN32) if (xsignal) { return signal_process(xsignal, pidfile); } #endif if (!password || !server_addr_buf) { print_usage(argv[0]); return 1; } init(); #if !defined(_WIN32) if (daemon_mode) { if (daemonize()) { return 1; } if (already_running(pidfile)) { logger_stderr("xsocks already running."); return 1; } } #endif loop = uv_default_loop(); rc = resolve_addr(local_addr, &bind_addr); if (rc) { logger_stderr("invalid local address"); return 1; } rc = resolve_addr(server_addr_buf, &server_addr); if (rc) { logger_stderr("invalid server address"); return 1; } udprelay_init(); if (concurrency <= 1) { struct server_context ctx; ctx.udprelay = 1; ctx.udp_fd = create_socket(SOCK_DGRAM, 0); ctx.local_addr = &bind_addr; ctx.server_addr = &server_addr; uv_tcp_init(loop, &ctx.tcp); rc = uv_tcp_bind(&ctx.tcp, &bind_addr, 0); if (rc) { logger_stderr("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_addr); #if !defined(_WIN32) setup_signal(loop, signal_cb, &ctx); #endif udprelay_start(loop, &ctx); uv_run(loop, UV_RUN_DEFAULT); close_loop(loop); } else { logger_stderr("listen error: %s", uv_strerror(rc)); } } else { #if !defined(_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 = 1; ctx->accept_cb = client_accept_cb; ctx->local_addr = &bind_addr; ctx->server_addr = &server_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_addr); 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 } udprelay_destroy(); #if !defined(_WIN32) if (daemon_mode) { delete_pidfile(pidfile); } #endif logger_exit(); return 0; }
int main(int argc, char *argv[]) { int rc; uv_loop_t *loop; struct sockaddr bind_addr; parse_opts(argc, argv); if (xsignal) { return signal_process(xsignal, pidfile); } if (!tunnel_mode || !dest_addr || !password) { print_usage(argv[0]); return 1; } if (init()) { return 1; } if (daemon_mode) { if (daemonize()) { return 1; } if (already_running(pidfile)) { logger_stderr("xtunnel already running."); return 1; } } loop = uv_default_loop(); rc = resolve_addr(source_addr, &bind_addr); if (rc) { logger_stderr("invalid local address"); return 1; } rc = resolve_addr(dest_addr, &target_addr); if (rc) { logger_stderr("invalid target address"); return 1; } if (concurrency <= 1) { struct server_context ctx; uv_tcp_init(loop, &ctx.tcp); rc = uv_tcp_bind(&ctx.tcp, &bind_addr, 0); if (rc) { logger_stderr("bind error: %s", uv_strerror(rc)); return 1; } rc = uv_listen((uv_stream_t*)&ctx.tcp, SOMAXCONN, source_accept_cb); if (rc == 0) { logger_log(LOG_INFO, "listening on %s", source_addr); setup_signal(loop, signal_cb, &ctx); uv_run(loop, UV_RUN_DEFAULT); close_loop(loop); } else { logger_stderr("listen error: %s", uv_strerror(rc)); } } else { 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->accept_cb = source_accept_cb; ctx->nameserver_num = -1; ctx->local_addr = &bind_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", source_addr); 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); } if (daemon_mode) { delete_pidfile(pidfile); } return 0; }