diff --git a/src/hev-config.h b/src/hev-config.h index d68879665..e760a8668 100644 --- a/src/hev-config.h +++ b/src/hev-config.h @@ -10,8 +10,6 @@ #ifndef __HEV_CONFIG_H__ #define __HEV_CONFIG_H__ -#include - int hev_config_init (const char *path); void hev_config_fini (void); diff --git a/src/hev-main.c b/src/hev-main.c index 0ae7c44ca..c7d7c055c 100644 --- a/src/hev-main.c +++ b/src/hev-main.c @@ -2,20 +2,18 @@ ============================================================================ Name : hev-main.c Author : Heiher - Copyright : Copyright (c) 2017 - 2023 hev + Copyright : Copyright (c) 2017 - 2024 hev Description : Main ============================================================================ */ #include -#include -#include -#include #include #include #include +#include "hev-misc.h" #include "hev-config.h" #include "hev-config-const.h" #include "hev-logger.h" @@ -31,39 +29,6 @@ show_help (const char *self_path) MICRO_VERSION, COMMIT_ID); } -static void -run_as_daemon (const char *pid_file) -{ - FILE *fp; - - fp = fopen (pid_file, "w+"); - if (!fp) { - LOG_E ("open pid file %s", pid_file); - return; - } - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - if (daemon (0, 0)) { - /* ignore return value */ - } -#pragma GCC diagnostic pop - - fprintf (fp, "%u\n", getpid ()); - fclose (fp); -} - -static int -set_limit_nofile (int limit_nofile) -{ - struct rlimit limit = { - .rlim_cur = limit_nofile, - .rlim_max = limit_nofile, - }; - - return setrlimit (RLIMIT_NOFILE, &limit); -} - int main (int argc, char *argv[]) { diff --git a/src/hev-socks5-proxy.c b/src/hev-socks5-proxy.c index 6357517f6..d223f81a8 100644 --- a/src/hev-socks5-proxy.c +++ b/src/hev-socks5-proxy.c @@ -2,7 +2,7 @@ ============================================================================ Name : hev-socks5-proxy.c Author : Heiher - Copyright : Copyright (c) 2017 - 2022 hev + Copyright : Copyright (c) 2017 - 2024 hev Description : Socks5 Proxy ============================================================================ */ @@ -35,7 +35,93 @@ static pthread_t *work_threads; static HevSocketFactory *factory; static HevSocks5Worker **worker_list; -static void hev_socks5_proxy_load (void); +static void +hev_socks5_proxy_load_file (HevSocks5Authenticator *auth, const char *file) +{ + char *line = NULL; + size_t len = 0; + ssize_t nread; + FILE *fp; + + fp = fopen (file, "r"); + if (!fp) { + hev_object_unref (HEV_OBJECT (auth)); + return; + } + + while ((nread = getline (&line, &len, fp)) != -1) { + HevSocks5UserMark *user; + unsigned int nlen; + unsigned int plen; + char name[256]; + char pass[256]; + long mark = 0; + int res; + + res = sscanf (line, "%255s %255s %lx\n", name, pass, &mark); + if (res < 2) { + LOG_E ("socks5 proxy user/pass format"); + continue; + } + + nlen = strlen (name); + plen = strlen (pass); + user = hev_socks5_user_mark_new (name, nlen, pass, plen, mark); + hev_object_set_atomic (HEV_OBJECT (user), 1); + res = hev_socks5_authenticator_add (auth, HEV_SOCKS5_USER (user)); + if (res < 0) { + LOG_E ("socks5 proxy user conflict"); + hev_object_unref (HEV_OBJECT (user)); + } + } + + free (line); + fclose (fp); +} + +static void +hev_socks5_proxy_load (void) +{ + HevSocks5Authenticator *auth; + const char *file, *name, *pass; + int i; + + LOG_D ("socks5 proxy load"); + + file = hev_config_get_auth_file (); + name = hev_config_get_auth_username (); + pass = hev_config_get_auth_password (); + + if (!file && !name && !pass) + return; + + auth = hev_socks5_authenticator_new (); + if (!auth) + return; + + hev_object_set_atomic (HEV_OBJECT (auth), 1); + + if (file) { + hev_socks5_proxy_load_file (auth, file); + } else { + HevSocks5UserMark *user; + + user = hev_socks5_user_mark_new (name, strlen (name), pass, + strlen (pass), 0); + hev_socks5_authenticator_add (auth, HEV_SOCKS5_USER (user)); + hev_object_set_atomic (HEV_OBJECT (user), 1); + } + + for (i = 0; i < workers; i++) { + HevSocks5Worker *worker; + + worker = worker_list[i]; + hev_socks5_worker_set_auth (worker, auth); + hev_socks5_worker_reload (worker); + } + + hev_object_unref (HEV_OBJECT (auth)); +} static void sigint_handler (int signum) @@ -68,39 +154,23 @@ hev_socks5_proxy_init (void) goto exit; } - if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) { - LOG_E ("socks5 proxy sigpipe"); - goto free; - } - - if (signal (SIGINT, sigint_handler) == SIG_ERR) { - LOG_E ("socks5 proxy sigint"); - goto free; - } - - if (signal (SIGUSR1, sigint_handler) == SIG_ERR) { - LOG_E ("socks5 proxy sigusr1"); - goto free; - } - task = hev_task_new (-1); if (!task) { LOG_E ("socks5 proxy task"); - goto free; + goto exit; } workers = hev_config_get_workers (); - work_threads = hev_malloc0 (sizeof (pthread_t) * workers); if (!work_threads) { LOG_E ("socks5 proxy work threads"); - goto free; + goto exit; } worker_list = hev_malloc0 (sizeof (HevSocks5Worker *) * workers); if (!worker_list) { LOG_E ("socks5 proxy worker list"); - goto free; + goto exit; } factory = hev_socket_factory_new (hev_config_get_listen_address (), @@ -108,14 +178,17 @@ hev_socks5_proxy_init (void) hev_config_get_listen_ipv6_only ()); if (!factory) { LOG_E ("socks5 proxy socket factory"); - goto free; + goto exit; } + signal (SIGPIPE, SIG_IGN); + signal (SIGINT, sigint_handler); + signal (SIGUSR1, sigint_handler); + return 0; -free: - hev_socks5_proxy_fini (); exit: + hev_socks5_proxy_fini (); return -1; } @@ -238,85 +311,3 @@ hev_socks5_proxy_run (void) worker_list[0] = NULL; } } - -static void -hev_socks5_proxy_load (void) -{ - HevSocks5Authenticator *auth; - const char *file, *name, *pass; - int i; - - LOG_D ("socks5 proxy load"); - - file = hev_config_get_auth_file (); - name = hev_config_get_auth_username (); - pass = hev_config_get_auth_password (); - - if (!file && !name && !pass) - return; - - auth = hev_socks5_authenticator_new (); - if (!auth) - return; - - hev_object_set_atomic (HEV_OBJECT (auth), 1); - - if (!file) { - HevSocks5UserMark *user; - - user = hev_socks5_user_mark_new (name, strlen (name), pass, - strlen (pass), 0); - hev_socks5_authenticator_add (auth, HEV_SOCKS5_USER (user)); - hev_object_set_atomic (HEV_OBJECT (user), 1); - } else { - char *line = NULL; - size_t len = 0; - ssize_t nread; - FILE *fp; - - fp = fopen (file, "r"); - if (!fp) { - hev_object_unref (HEV_OBJECT (auth)); - return; - } - - while ((nread = getline (&line, &len, fp)) != -1) { - HevSocks5UserMark *user; - unsigned int nlen; - unsigned int plen; - char name[256]; - char pass[256]; - long mark = 0; - int res; - - res = sscanf (line, "%255s %255s %lx\n", name, pass, &mark); - if (res < 2) { - LOG_E ("socks5 proxy user/pass format"); - continue; - } - - nlen = strlen (name); - plen = strlen (pass); - user = hev_socks5_user_mark_new (name, nlen, pass, plen, mark); - hev_object_set_atomic (HEV_OBJECT (user), 1); - res = hev_socks5_authenticator_add (auth, HEV_SOCKS5_USER (user)); - if (res < 0) { - LOG_E ("socks5 proxy user conflict"); - hev_object_unref (HEV_OBJECT (user)); - } - } - - free (line); - fclose (fp); - } - - for (i = 0; i < workers; i++) { - HevSocks5Worker *worker; - - worker = worker_list[i]; - hev_socks5_worker_set_auth (worker, auth); - hev_socks5_worker_reload (worker); - } - - hev_object_unref (HEV_OBJECT (auth)); -} diff --git a/src/hev-socks5-session.c b/src/hev-socks5-session.c index 1fd124aa2..895eebeec 100644 --- a/src/hev-socks5-session.c +++ b/src/hev-socks5-session.c @@ -2,16 +2,12 @@ ============================================================================ Name : hev-socks5-session.c Author : Heiher - Copyright : Copyright (c) 2017 - 2021 hev + Copyright : Copyright (c) 2017 - 2024 hev Description : Socks5 Session ============================================================================ */ #include -#include -#include -#include -#include #include @@ -55,8 +51,10 @@ hev_socks5_session_terminate (HevSocks5Session *self) static int hev_socks5_session_bind (HevSocks5 *self, int fd, const struct sockaddr *dest) { + HevSocks5Server *srv = HEV_SOCKS5_SERVER (self); const char *saddr; const char *iface; + int res; LOG_D ("%p socks5 session bind", self); @@ -65,7 +63,6 @@ hev_socks5_session_bind (HevSocks5 *self, int fd, const struct sockaddr *dest) if (saddr) { struct sockaddr_in6 addr; - int res; res = hev_netaddr_resolve (&addr, saddr, NULL); if (res < 0) @@ -77,43 +74,20 @@ hev_socks5_session_bind (HevSocks5 *self, int fd, const struct sockaddr *dest) } if (iface) { - int res = 0; -#if defined(__linux__) - struct ifreq ifr = { 0 }; - - strncpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name) - 1); - res = setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)); -#elif defined(__APPLE__) || defined(__MACH__) - int i; - - i = if_nametoindex (iface); - if (i == 0) { - return -1; - } - - res = setsockopt (fd, IPPROTO_IPV6, IPV6_BOUND_IF, &i, sizeof (i)); -#endif + res = set_sock_bind (fd, iface); if (res < 0) return -1; } -#if defined(__linux__) - HevSocks5Server *srv = HEV_SOCKS5_SERVER (self); - if (srv->user) { HevSocks5UserMark *user = HEV_SOCKS5_USER_MARK (srv->user); if (user->mark) { - int mark; - int res; - - mark = user->mark; - res = setsockopt (fd, SOL_SOCKET, SO_MARK, &mark, sizeof (mark)); + res = set_sock_mark (fd, user->mark); if (res < 0) return -1; } } -#endif return 0; } diff --git a/src/hev-socks5-worker.c b/src/hev-socks5-worker.c index 4bd3ff001..c21b2942d 100644 --- a/src/hev-socks5-worker.c +++ b/src/hev-socks5-worker.c @@ -2,7 +2,7 @@ ============================================================================ Name : hev-socks5-worker.c Author : Heiher - Copyright : Copyright (c) 2017 - 2021 hev + Copyright : Copyright (c) 2017 - 2024 hev Description : Socks5 Worker ============================================================================ */ @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "hev-config.h" @@ -38,134 +37,33 @@ struct _HevSocks5Worker HevSocks5Authenticator *auth_next; }; -static void hev_socks5_event_task_entry (void *data); -static void hev_socks5_worker_task_entry (void *data); -static void hev_socks5_worker_load (HevSocks5Worker *self); - -HevSocks5Worker * -hev_socks5_worker_new (void) -{ - HevSocks5Worker *self; - - self = calloc (1, sizeof (HevSocks5Worker)); - if (!self) - return NULL; - - LOG_D ("%p socks5 worker new", self); - - self->fd = -1; - self->event_fds[0] = -1; - self->event_fds[1] = -1; - - return self; -} - -void -hev_socks5_worker_destroy (HevSocks5Worker *self) -{ - LOG_D ("%p works worker destroy", self); - - if (self->auth_curr) - hev_object_unref (HEV_OBJECT (self->auth_curr)); - if (self->auth_next) - hev_object_unref (HEV_OBJECT (self->auth_next)); - - if (self->fd >= 0) - close (self->fd); - - free (self); -} - -int -hev_socks5_worker_init (HevSocks5Worker *self, int fd) -{ - LOG_D ("%p works worker init", self); - - self->task_worker = hev_task_new (-1); - if (!self->task_worker) { - LOG_E ("socks5 worker task worker"); - return -1; - } - - self->task_event = hev_task_new (-1); - if (!self->task_event) { - LOG_E ("socks5 worker task event"); - hev_task_unref (self->task_worker); - return -1; - } - - self->fd = fd; - - return 0; -} - -void -hev_socks5_worker_start (HevSocks5Worker *self) -{ - LOG_D ("%p works worker start", self); - - hev_task_run (self->task_event, hev_socks5_event_task_entry, self); - hev_task_run (self->task_worker, hev_socks5_worker_task_entry, self); -} - -void -hev_socks5_worker_stop (HevSocks5Worker *self) -{ - char val = 's'; - - LOG_D ("%p works worker stop", self); - - if (self->event_fds[1] < 0) - return; - - val = write (self->event_fds[1], &val, sizeof (val)); - if (val < 0) - LOG_E ("socks5 proxy write event"); -} - -void -hev_socks5_worker_reload (HevSocks5Worker *self) +static int +task_io_yielder (HevTaskYieldType type, void *data) { - char val = 'r'; - - LOG_D ("%p works worker reload", self); + HevSocks5Worker *self = data; - if (self->event_fds[1] < 0) - return; + hev_task_yield (type); - val = write (self->event_fds[1], &val, sizeof (val)); - if (val < 0) - LOG_E ("socks5 proxy write event"); + return self->quit ? -1 : 0; } -void -hev_socks5_worker_set_auth (HevSocks5Worker *self, HevSocks5Authenticator *auth) +static void +hev_socks5_worker_load (HevSocks5Worker *self) { atomic_intptr_t *ptr; intptr_t prev; - LOG_D ("%p works worker set auth", self); + LOG_D ("%p works worker load", self); - hev_object_ref (HEV_OBJECT (auth)); + ptr = (atomic_intptr_t *)&self->auth_next; + prev = atomic_exchange_explicit (ptr, 0, memory_order_relaxed); + if (!prev) + return; if (self->auth_curr) - ptr = (atomic_intptr_t *)&self->auth_next; - else - ptr = (atomic_intptr_t *)&self->auth_curr; - - prev = atomic_exchange (ptr, (intptr_t)auth); - if (prev) - hev_object_unref (HEV_OBJECT (prev)); -} - -static int -task_io_yielder (HevTaskYieldType type, void *data) -{ - HevSocks5Worker *self = data; - - hev_task_yield (type); + hev_object_unref (HEV_OBJECT (self->auth_curr)); - return self->quit ? -1 : 0; + self->auth_curr = HEV_SOCKS5_AUTHENTICATOR (prev); } static void @@ -274,21 +172,118 @@ hev_socks5_event_task_entry (void *data) close (self->event_fds[1]); } -static void -hev_socks5_worker_load (HevSocks5Worker *self) +HevSocks5Worker * +hev_socks5_worker_new (void) +{ + HevSocks5Worker *self; + + self = calloc (1, sizeof (HevSocks5Worker)); + if (!self) + return NULL; + + LOG_D ("%p socks5 worker new", self); + + self->fd = -1; + self->event_fds[0] = -1; + self->event_fds[1] = -1; + + return self; +} + +void +hev_socks5_worker_destroy (HevSocks5Worker *self) +{ + LOG_D ("%p works worker destroy", self); + + if (self->auth_curr) + hev_object_unref (HEV_OBJECT (self->auth_curr)); + if (self->auth_next) + hev_object_unref (HEV_OBJECT (self->auth_next)); + + if (self->fd >= 0) + close (self->fd); + + free (self); +} + +int +hev_socks5_worker_init (HevSocks5Worker *self, int fd) +{ + LOG_D ("%p works worker init", self); + + self->task_worker = hev_task_new (-1); + if (!self->task_worker) { + LOG_E ("socks5 worker task worker"); + return -1; + } + + self->task_event = hev_task_new (-1); + if (!self->task_event) { + LOG_E ("socks5 worker task event"); + hev_task_unref (self->task_worker); + return -1; + } + + self->fd = fd; + + return 0; +} + +void +hev_socks5_worker_start (HevSocks5Worker *self) +{ + LOG_D ("%p works worker start", self); + + hev_task_run (self->task_event, hev_socks5_event_task_entry, self); + hev_task_run (self->task_worker, hev_socks5_worker_task_entry, self); +} + +void +hev_socks5_worker_stop (HevSocks5Worker *self) +{ + char val = 's'; + + LOG_D ("%p works worker stop", self); + + if (self->event_fds[1] < 0) + return; + + val = write (self->event_fds[1], &val, sizeof (val)); + if (val < 0) + LOG_E ("socks5 proxy write event"); +} + +void +hev_socks5_worker_reload (HevSocks5Worker *self) +{ + char val = 'r'; + + LOG_D ("%p works worker reload", self); + + if (self->event_fds[1] < 0) + return; + + val = write (self->event_fds[1], &val, sizeof (val)); + if (val < 0) + LOG_E ("socks5 proxy write event"); +} + +void +hev_socks5_worker_set_auth (HevSocks5Worker *self, HevSocks5Authenticator *auth) { atomic_intptr_t *ptr; intptr_t prev; - LOG_D ("%p works worker load", self); + LOG_D ("%p works worker set auth", self); - ptr = (atomic_intptr_t *)&self->auth_next; - prev = atomic_exchange_explicit (ptr, 0, memory_order_relaxed); - if (!prev) - return; + hev_object_ref (HEV_OBJECT (auth)); if (self->auth_curr) - hev_object_unref (HEV_OBJECT (self->auth_curr)); + ptr = (atomic_intptr_t *)&self->auth_next; + else + ptr = (atomic_intptr_t *)&self->auth_curr; - self->auth_curr = HEV_SOCKS5_AUTHENTICATOR (prev); + prev = atomic_exchange (ptr, (intptr_t)auth); + if (prev) + hev_object_unref (HEV_OBJECT (prev)); } diff --git a/src/misc/hev-compiler.h b/src/misc/hev-compiler.h index e1aef91cd..93aca9d6e 100644 --- a/src/misc/hev-compiler.h +++ b/src/misc/hev-compiler.h @@ -27,7 +27,7 @@ extern "C" { #define EXPORT_SYMBOL __attribute__ ((visibility ("default"))) #endif -#define barrier() __asm__ __volatile__("" : : : "memory") +#define barrier() __asm__ __volatile__ ("" : : : "memory") static inline void __read_once_size (void *dst, const volatile void *src, int size) @@ -86,7 +86,7 @@ __write_once_size (volatile void *dst, const void *src, int size) { \ typeof (x) __val; \ char __c[1]; \ - } __u = { .__val = (typeof (x)) (val) }; \ + } __u = { .__val = (typeof (x))(val) }; \ __write_once_size (&(x), __u.__c, sizeof (x)); \ __u.__val; \ }) diff --git a/src/misc/hev-misc.c b/src/misc/hev-misc.c index 7935631a1..7b72fdbe9 100644 --- a/src/misc/hev-misc.c +++ b/src/misc/hev-misc.c @@ -2,16 +2,21 @@ ============================================================================ Name : hev-misc.c Authors : Heiher - Copyright : Copyright (c) 2022 everyone. + Copyright : Copyright (c) 2022 - 2024 everyone. Description : Misc ============================================================================ */ +#include #include -#include +#include +#include +#include #include +#include "hev-logger.h" + #include "hev-misc.h" int @@ -48,3 +53,71 @@ hev_netaddr_resolve (struct sockaddr_in6 *daddr, const char *addr, return 0; } + +void +run_as_daemon (const char *pid_file) +{ + FILE *fp; + + fp = fopen (pid_file, "w+"); + if (!fp) { + LOG_E ("open pid file %s", pid_file); + return; + } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + if (daemon (0, 0)) { + /* ignore return value */ + } +#pragma GCC diagnostic pop + + fprintf (fp, "%u\n", getpid ()); + fclose (fp); +} + +int +set_limit_nofile (int limit_nofile) +{ + struct rlimit limit = { + .rlim_cur = limit_nofile, + .rlim_max = limit_nofile, + }; + + return setrlimit (RLIMIT_NOFILE, &limit); +} + +int +set_sock_bind (int fd, const char *iface) +{ + int res = 0; + +#if defined(__linux__) + struct ifreq ifr = { 0 }; + + strncpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name) - 1); + res = setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)); +#elif defined(__APPLE__) || defined(__MACH__) + int i; + + i = if_nametoindex (iface); + if (i == 0) { + return -1; + } + + res = setsockopt (fd, IPPROTO_IPV6, IPV6_BOUND_IF, &i, sizeof (i)); +#endif + + return res; +} + +int +set_sock_mark (int fd, unsigned int mark) +{ +#if defined(__linux__) + return setsockopt (fd, SOL_SOCKET, SO_MARK, &mark, sizeof (mark)); +#elif defined(__FreeBSD__) + return setsockopt (fd, SOL_SOCKET, SO_USER_COOKIE, &mark, sizeof (mark)); +#endif + return 0; +} diff --git a/src/misc/hev-misc.h b/src/misc/hev-misc.h index 11f9c73ce..81f75ba61 100644 --- a/src/misc/hev-misc.h +++ b/src/misc/hev-misc.h @@ -2,7 +2,7 @@ ============================================================================ Name : hev-misc.h Authors : Heiher - Copyright : Copyright (c) 2022 everyone. + Copyright : Copyright (c) 2022 - 2024 everyone. Description : Misc ============================================================================ */ @@ -10,7 +10,15 @@ #ifndef __HEV_MISC_H__ #define __HEV_MISC_H__ +#include + int hev_netaddr_resolve (struct sockaddr_in6 *daddr, const char *addr, const char *port); +void run_as_daemon (const char *pid_file); +int set_limit_nofile (int limit_nofile); + +int set_sock_bind (int fd, const char *iface); +int set_sock_mark (int fd, unsigned int mark); + #endif /* __HEV_MISC_H__ */