From ab148987cee793487dd951149f05dd1d8b04eada Mon Sep 17 00:00:00 2001 From: zhengshuxin Date: Thu, 25 May 2023 19:00:22 +0800 Subject: [PATCH] service templates in the mode of fiber or thread can bind wildcad addresses. --- lib_acl/include/net/acl_ifconf.h | 10 ++ .../src/master/template/acl_threads_server.c | 60 +++------ lib_acl/src/net/acl_ifconf.c | 68 ++++++++++- lib_fiber/cpp/src/fiber_server.cpp | 115 ++++-------------- 4 files changed, 118 insertions(+), 135 deletions(-) diff --git a/lib_acl/include/net/acl_ifconf.h b/lib_acl/include/net/acl_ifconf.h index 9b2f90f9e..666e06d0c 100644 --- a/lib_acl/include/net/acl_ifconf.h +++ b/lib_acl/include/net/acl_ifconf.h @@ -56,6 +56,16 @@ ACL_API void acl_free_ifaddrs(ACL_IFCONF *ifconf); */ ACL_API ACL_IFCONF *acl_ifconf_search(const char *pattern); +/** + * 扫描本机所有网卡 IP, 将匹配的地址集合返回 + * @param patterns {const char*} + * @param unix_path {const char*} 当所匹配的地址为 unix domain 类型时, 该路径 + * 为全路径的前缀路径 + * @return {ACL_ARGV*} 返回非空时则返回对象中存放以字符串表示的地址集合, 用完 + * 后需调用 acl_argv_free 释放;如果返回 NULL 则表示没有找到匹配的地址 + */ +ACL_API ACL_ARGV *acl_search_addrs(const char *patterns, const char *unix_path); + #ifdef __cplusplus } #endif diff --git a/lib_acl/src/master/template/acl_threads_server.c b/lib_acl/src/master/template/acl_threads_server.c index 7f845703e..17510b501 100644 --- a/lib_acl/src/master/template/acl_threads_server.c +++ b/lib_acl/src/master/template/acl_threads_server.c @@ -1246,50 +1246,29 @@ static ACL_VSTREAM **server_daemon_open(ACL_EVENT *event, #endif -static int is_ipaddr(const char *addr) -{ - // Just only the port, such as: 8088 - if (acl_alldig(addr)) { - return 1; - } - - // Such as: ip:port, or ip|port, or :port, or |port - if (strrchr(addr, ':') || strrchr(addr, ACL_ADDR_SEP)) { - return 1; - } - - if (acl_valid_ipv6_hostaddr(addr, 0) || acl_valid_ipv4_hostaddr(addr, 0)) { - return 1; - } - - return 0; -} - -static void correct_addr(const char *addr, char *buf, size_t size) -{ - if (is_ipaddr(addr)) { - ACL_SAFE_STRNCPY(buf, addr, size); - } else { - const char *pri = !strcmp(acl_var_threads_master_private, "y") ? - "private" : "public"; -#if defined(_WIN32) || defined(_WIN64) - _snprintf(buf, size, "%s/%s/%s", acl_var_threads_queue_dir, pri, addr); -#else - snprintf(buf, size, "%s/%s/%s", acl_var_threads_queue_dir, pri, addr); -#endif - } -} - static ACL_VSTREAM **server_alone_open(ACL_EVENT *event, acl_pthread_pool_t *threads, const char *addrs) { const char *myname = "server_alone_open"; - ACL_ARGV* tokens = acl_argv_split(addrs, ";, \t"); + const char *pri = !strcmp(acl_var_threads_master_private, "y") ? + "private" : "public"; + char *unix_path = acl_concatenate(acl_var_threads_queue_dir, "/", + pri, NULL); + ACL_ARGV* tokens = acl_search_addrs(addrs, unix_path); ACL_ITER iter; int i; unsigned flag = ACL_INET_FLAG_NONE; - ACL_VSTREAM **streams = (ACL_VSTREAM **) - acl_mycalloc(tokens->argc + 1, sizeof(ACL_VSTREAM *)); + ACL_VSTREAM **streams; + + acl_myfree(unix_path); + + if (tokens == NULL) { + acl_msg_fatal("%s(%d), %s: can't find valid addrs from %s", + __FILE__, __LINE__, __FUNCTION__, addrs); + } + + streams = (ACL_VSTREAM **) acl_mycalloc(tokens->argc + 1, sizeof(ACL_VSTREAM *)); + if (var_threads_master_reuseport) { flag |= ACL_INET_FLAG_REUSEPORT; @@ -1302,14 +1281,11 @@ static ACL_VSTREAM **server_alone_open(ACL_EVENT *event, i = 0; acl_foreach(iter, tokens) { const char* addr = (const char*) iter.data; - char addrbuf[512]; - - correct_addr(addr, addrbuf, sizeof(addrbuf)); - ACL_VSTREAM* sstream = acl_vstream_listen_ex(addrbuf, 128, + ACL_VSTREAM* sstream = acl_vstream_listen_ex(addr, 128, flag, 0, 0); if (sstream == NULL) { acl_msg_error("%s(%d): listen %s error(%s)", - myname, __LINE__, addrbuf, acl_last_serror()); + myname, __LINE__, addr, acl_last_serror()); exit(2); } diff --git a/lib_acl/src/net/acl_ifconf.c b/lib_acl/src/net/acl_ifconf.c index 7b491beb1..9f810b8d3 100644 --- a/lib_acl/src/net/acl_ifconf.c +++ b/lib_acl/src/net/acl_ifconf.c @@ -618,12 +618,19 @@ static void patterns_addrs_add(ACL_ARGV *patterns, ACL_IFCONF *acl_ifconf_search(const char *patterns) { - ACL_IFCONF *ifconf = acl_get_ifaddrs(), *ifconf2; + ACL_IFCONF *ifconf, *ifconf2; ACL_ARGV *patterns_tokens; ACL_HTABLE *table; ACL_ARRAY *addrs; ACL_ITER iter; + if (patterns == NULL || *patterns == 0) { + acl_msg_error("%s(%d), %s: patterns null", + __FILE__, __LINE__, __FUNCTION__); + return NULL; + } + + ifconf = acl_get_ifaddrs(); if (ifconf == NULL) { acl_msg_error("%s(%d), %s: acl_get_ifaddrs error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); @@ -686,3 +693,62 @@ ACL_IFCONF *acl_ifconf_search(const char *patterns) acl_array_free(addrs, acl_myfree_fn); return ifconf2; } + +/*--------------------------------------------------------------------------*/ + +static int is_ipaddr(const char *addr) +{ + /* Just only the port, such as: 8088 */ + if (acl_alldig(addr)) { + return 1; + } + + /* Such as: ip:port, or ip|port, or :port, or |port */ + if (strrchr(addr, ':') || strrchr(addr, ACL_ADDR_SEP)) { + return 1; + } + + if (acl_valid_ipv6_hostaddr(addr, 0) || acl_valid_ipv4_hostaddr(addr, 0)) { + return 1; + } + + return 0; +} + +static char *get_addr(const char *addr, const char *path) +{ + char *buf; + + if (is_ipaddr(addr) || path == NULL || *path == 0) { + buf = acl_mystrdup(addr); + return buf; + } + + buf = acl_concatenate(path, "/", addr, NULL); + return buf; +} + +ACL_ARGV *acl_search_addrs(const char *patterns, const char *unix_path) +{ + ACL_IFCONF *ifconf = acl_ifconf_search(patterns); + ACL_ITER iter; + ACL_ARGV *addrs; + + if (ifconf == NULL) { + acl_msg_error("%s(%d): acl_ifconf_search null", + __FUNCTION__, __LINE__); + return NULL; + } + + addrs = acl_argv_alloc(1); + + acl_foreach(iter, ifconf) { + const ACL_IFADDR *ifaddr = (const ACL_IFADDR *) iter.data; + char *addr = get_addr(ifaddr->addr, unix_path); + acl_argv_add(addrs, addr, NULL); + acl_myfree(addr); + } + + acl_free_ifaddrs(ifconf); + return addrs; +} diff --git a/lib_fiber/cpp/src/fiber_server.cpp b/lib_fiber/cpp/src/fiber_server.cpp index 5a3b28daf..098414d84 100644 --- a/lib_fiber/cpp/src/fiber_server.cpp +++ b/lib_fiber/cpp/src/fiber_server.cpp @@ -764,84 +764,6 @@ static void servers_daemon(int count, int fdtype, int nthreads) } #endif -static void server_alone_open(FIBER_SERVER *server, ACL_ARGV *addrs) -{ - const char *myname = "server_alone_open"; - ACL_ITER iter; - unsigned flag = ACL_INET_FLAG_NONE; - int i = 0; - - if (var_fiber_master_reuseport) { - flag |= ACL_INET_FLAG_REUSEPORT; - } - - acl_foreach(iter, addrs) { - const char* addr = (const char*) iter.data; - ACL_VSTREAM* sstream = acl_vstream_listen_ex(addr, 128, - flag, 0, 0); - if (sstream != NULL) { - acl_msg_info("%s: thread-%lu, listen %s ok", myname, - (unsigned long) acl_pthread_self(), addr); -#if !defined(_WIN32) && !defined(_WIN64) - acl_close_on_exec(ACL_VSTREAM_SOCK(sstream), ACL_CLOSE_ON_EXEC); -#endif - server->sstreams[i++] = sstream; - } else { - acl_msg_fatal("%s(%d): thread-%lu, listen %s error(%s)", - myname, __LINE__, (long) acl_pthread_self(), - addr, acl_last_serror()); - } - } -} - -static void servers_alone(const char *addrs, int fdtype, int nthreads) -{ - ACL_ARGV* tokens = acl_argv_split(addrs, ";, \t"); - int i; - - __servers = servers_alloc(nthreads, tokens->argc, fdtype); - - for (i = 0; i < nthreads; i++) { - server_alone_open(__servers[i], tokens); - } - - acl_argv_free(tokens); -} - -static int is_ipaddr(const char *addr) -{ - // Just only the port, such as: 8088 - if (acl_alldig(addr)) { - return 1; - } - - // Such as: ip:port, or ip|port, or :port, or |port - if (strrchr(addr, ':') || strrchr(addr, ACL_ADDR_SEP)) { - return 1; - } - - if (acl_valid_ipv6_hostaddr(addr, 0) || acl_valid_ipv4_hostaddr(addr, 0)) { - return 1; - } - - return 0; -} - -static void correct_addr(const char *addr, char *buf, size_t size) -{ - if (is_ipaddr(addr)) { - ACL_SAFE_STRNCPY(buf, addr, size); - } else { - const char *pri = !strcmp(acl_var_fiber_master_private, "y") ? - "private" : "public"; -#if defined(_WIN32) || defined(_WIN64) - _snprintf(buf, size, "%s/%s/%s", acl_var_fiber_queue_dir, pri, addr); -#else - snprintf(buf, size, "%s/%s/%s", acl_var_fiber_queue_dir, pri, addr); -#endif - } -} - static void server_open(FIBER_SERVER *server, ACL_ARGV *addrs) { const char *myname = "server_open"; @@ -855,29 +777,38 @@ static void server_open(FIBER_SERVER *server, ACL_ARGV *addrs) acl_foreach(iter, addrs) { const char* addr = (const char*) iter.data; - char addrbuf[512]; - - correct_addr(addr, addrbuf, sizeof(addrbuf)); - ACL_VSTREAM* sstream = acl_vstream_listen_ex(addrbuf, 128, + ACL_VSTREAM* sstream = acl_vstream_listen_ex(addr, 128, flag, 0, 0); - if (sstream != NULL) { - acl_msg_info("%s: listen %s ok", myname, addr); -#if !defined(_WIN32) && !defined(_WIN64) - acl_close_on_exec(ACL_VSTREAM_SOCK(sstream), ACL_CLOSE_ON_EXEC); -#endif - server->sstreams[i++] = sstream; - } else { + if (sstream == NULL) { acl_msg_fatal("%s(%d): listen %s error(%s)", myname, __LINE__, addr, acl_last_serror()); } + + acl_msg_info("%s: listen %s ok", myname, addr); + +#if !defined(_WIN32) && !defined(_WIN64) + acl_close_on_exec(ACL_VSTREAM_SOCK(sstream), ACL_CLOSE_ON_EXEC); +#endif + server->sstreams[i++] = sstream; } } static void servers_open(const char *addrs, int fdtype, int nthreads) { - ACL_ARGV* tokens = acl_argv_split(addrs, ";, \t"); + const char *pri = !strcmp(acl_var_fiber_master_private, "y") ? + "private" : "public"; + char *unix_path = acl_concatenate(acl_var_fiber_queue_dir, "/", + pri, NULL); + ACL_ARGV* tokens = acl_search_addrs(addrs, unix_path); int i; + acl_myfree(unix_path); + + if (tokens == NULL) { + acl_msg_fatal("%s(%d), %s: can't find valid addrs from %s", + __FILE__, __LINE__, __FUNCTION__, addrs); + } + __servers = servers_alloc(nthreads, tokens->argc, fdtype); for (i = 0; i < nthreads; i++) { @@ -1245,7 +1176,7 @@ void acl_fiber_server_main(int argc, char *argv[], parse_args(); #if defined(_WIN32) || defined(_WIN64) - servers_alone(addrs, fdtype, acl_var_fiber_threads); + servers_open(addrs, fdtype, acl_var_fiber_threads); #else if (root_dir) { root_dir = acl_var_fiber_queue_dir; @@ -1284,7 +1215,7 @@ void acl_fiber_server_main(int argc, char *argv[], addrs = acl_var_fiber_master_service; } assert(addrs && *addrs); - servers_alone(addrs, fdtype, acl_var_fiber_threads); + servers_open(addrs, fdtype, acl_var_fiber_threads); } else if (var_fiber_master_reuseport) { assert(acl_var_fiber_master_service); assert(*acl_var_fiber_master_service);