mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-28 11:43:50 +00:00
Check port before add port via ss-manager (#1035)
* add simple port check functions * release sock lock when manager exit * simplfy the sock lock * release sock lock when receive the stat report * simplfy dns query * add udp port check * enable port check function * clean code and logs
This commit is contained in:
@@ -72,6 +72,7 @@ ss_server_SOURCES = utils.c \
|
||||
ss_manager_SOURCES = utils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
netutils.c \
|
||||
manager.c
|
||||
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS)
|
||||
@@ -82,10 +83,12 @@ if USE_SYSTEM_SHARED_LIB
|
||||
ss_local_LDADD += -ludns
|
||||
ss_tunnel_LDADD += -ludns
|
||||
ss_server_LDADD += -ludns
|
||||
ss_manager_LDADD += -ludns
|
||||
else
|
||||
ss_local_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_tunnel_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_server_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
ss_manager_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
endif
|
||||
|
||||
ss_local_CFLAGS = $(AM_CFLAGS) -DMODULE_LOCAL
|
||||
|
||||
+39
-20
@@ -94,14 +94,16 @@ bin_PROGRAMS = ss-local$(EXEEXT) ss-tunnel$(EXEEXT) $(am__EXEEXT_1) \
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_5 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_6 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_7 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_8 = $(top_builddir)/libudns/libudns.la
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_8 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_9 = $(top_builddir)/libudns/libudns.la
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_10 = $(top_builddir)/libudns/libudns.la
|
||||
@BUILD_WINCOMPAT_TRUE@am__append_11 = win32.c
|
||||
@BUILD_WINCOMPAT_TRUE@am__append_12 = win32.c
|
||||
@BUILD_REDIRECTOR_TRUE@am__append_13 = ss-redir
|
||||
@BUILD_REDIRECTOR_TRUE@@USE_SYSTEM_SHARED_LIB_TRUE@am__append_14 = -ludns
|
||||
@BUILD_REDIRECTOR_TRUE@@USE_SYSTEM_SHARED_LIB_FALSE@am__append_15 = $(top_builddir)/libudns/libudns.la
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_11 = $(top_builddir)/libudns/libudns.la
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_12 = $(top_builddir)/libudns/libudns.la
|
||||
@BUILD_WINCOMPAT_TRUE@am__append_13 = win32.c
|
||||
@BUILD_WINCOMPAT_TRUE@am__append_14 = win32.c
|
||||
@BUILD_REDIRECTOR_TRUE@am__append_15 = ss-redir
|
||||
@BUILD_REDIRECTOR_TRUE@@USE_SYSTEM_SHARED_LIB_TRUE@am__append_16 = -ludns
|
||||
@BUILD_REDIRECTOR_TRUE@@USE_SYSTEM_SHARED_LIB_FALSE@am__append_17 = $(top_builddir)/libudns/libudns.la
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/auto/depcomp $(include_HEADERS)
|
||||
@@ -156,7 +158,7 @@ am__DEPENDENCIES_2 = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__append_3)
|
||||
am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_8)
|
||||
$(am__append_9)
|
||||
libshadowsocks_libev_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
|
||||
am__libshadowsocks_libev_la_SOURCES_DIST = utils.c jconf.c json.c \
|
||||
encrypt.c udprelay.c cache.c acl.c netutils.c local.c \
|
||||
@@ -209,15 +211,16 @@ am_ss_local_OBJECTS = ss_local-utils.$(OBJEXT) \
|
||||
$(am__objects_5) $(am__objects_6) $(am__objects_7)
|
||||
ss_local_OBJECTS = $(am_ss_local_OBJECTS)
|
||||
ss_local_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_8)
|
||||
$(am__append_9)
|
||||
ss_local_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_local_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am_ss_manager_OBJECTS = ss_manager-utils.$(OBJEXT) \
|
||||
ss_manager-jconf.$(OBJEXT) ss_manager-json.$(OBJEXT) \
|
||||
ss_manager-manager.$(OBJEXT)
|
||||
ss_manager-netutils.$(OBJEXT) ss_manager-manager.$(OBJEXT)
|
||||
ss_manager_OBJECTS = $(am_ss_manager_OBJECTS)
|
||||
ss_manager_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||
ss_manager_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_12)
|
||||
ss_manager_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_manager_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -239,7 +242,7 @@ am__objects_9 = ss_redir-http.$(OBJEXT) ss_redir-tls.$(OBJEXT) \
|
||||
@BUILD_REDIRECTOR_TRUE@ $(am__objects_8) $(am__objects_9)
|
||||
ss_redir_OBJECTS = $(am_ss_redir_OBJECTS)
|
||||
@BUILD_REDIRECTOR_TRUE@ss_redir_DEPENDENCIES = $(am__DEPENDENCIES_2) \
|
||||
@BUILD_REDIRECTOR_TRUE@ $(am__DEPENDENCIES_1) $(am__append_15)
|
||||
@BUILD_REDIRECTOR_TRUE@ $(am__DEPENDENCIES_1) $(am__append_17)
|
||||
ss_redir_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_redir_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -255,7 +258,7 @@ am_ss_server_OBJECTS = ss_server-utils.$(OBJEXT) \
|
||||
ss_server-server.$(OBJEXT) $(am__objects_10) $(am__objects_11)
|
||||
ss_server_OBJECTS = $(am_ss_server_OBJECTS)
|
||||
ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_10)
|
||||
$(am__append_11)
|
||||
ss_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -272,7 +275,7 @@ am_ss_tunnel_OBJECTS = ss_tunnel-utils.$(OBJEXT) \
|
||||
$(am__objects_12) ss_tunnel-tunnel.$(OBJEXT) $(am__objects_13)
|
||||
ss_tunnel_OBJECTS = $(am_ss_tunnel_OBJECTS)
|
||||
ss_tunnel_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_9)
|
||||
$(am__append_10)
|
||||
ss_tunnel_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_tunnel_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -492,9 +495,9 @@ obfs_src = obfs_http.c \
|
||||
|
||||
ss_local_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c cache.c \
|
||||
acl.c netutils.c local.c $(obfs_src) $(sni_src) \
|
||||
$(am__append_11)
|
||||
$(am__append_13)
|
||||
ss_tunnel_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c \
|
||||
cache.c netutils.c $(obfs_src) tunnel.c $(am__append_12)
|
||||
cache.c netutils.c $(obfs_src) tunnel.c $(am__append_14)
|
||||
ss_server_SOURCES = utils.c \
|
||||
netutils.c \
|
||||
jconf.c \
|
||||
@@ -511,12 +514,13 @@ ss_server_SOURCES = utils.c \
|
||||
ss_manager_SOURCES = utils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
netutils.c \
|
||||
manager.c
|
||||
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS) $(am__append_5) $(am__append_8)
|
||||
ss_tunnel_LDADD = $(SS_COMMON_LIBS) $(am__append_6) $(am__append_9)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_7) $(am__append_10)
|
||||
ss_manager_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_local_LDADD = $(SS_COMMON_LIBS) $(am__append_5) $(am__append_9)
|
||||
ss_tunnel_LDADD = $(SS_COMMON_LIBS) $(am__append_6) $(am__append_10)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_7) $(am__append_11)
|
||||
ss_manager_LDADD = $(SS_COMMON_LIBS) $(am__append_8) $(am__append_12)
|
||||
ss_local_CFLAGS = $(AM_CFLAGS) -DMODULE_LOCAL
|
||||
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DMODULE_TUNNEL
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
||||
@@ -535,7 +539,7 @@ ss_manager_CFLAGS = $(AM_CFLAGS) -DMODULE_MANAGER
|
||||
|
||||
@BUILD_REDIRECTOR_TRUE@ss_redir_CFLAGS = $(AM_CFLAGS) -DMODULE_REDIR
|
||||
@BUILD_REDIRECTOR_TRUE@ss_redir_LDADD = $(SS_COMMON_LIBS) \
|
||||
@BUILD_REDIRECTOR_TRUE@ $(am__append_14) $(am__append_15)
|
||||
@BUILD_REDIRECTOR_TRUE@ $(am__append_16) $(am__append_17)
|
||||
lib_LTLIBRARIES = libshadowsocks-libev.la
|
||||
libshadowsocks_libev_la_SOURCES = $(ss_local_SOURCES)
|
||||
libshadowsocks_libev_la_CFLAGS = $(ss_local_CFLAGS) -DLIB_ONLY
|
||||
@@ -760,6 +764,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_manager-jconf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_manager-json.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_manager-manager.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_manager-netutils.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_manager-utils.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_redir-base64.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_redir-cache.Po@am__quote@
|
||||
@@ -1206,6 +1211,20 @@ ss_manager-json.obj: json.c
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -c -o ss_manager-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
|
||||
|
||||
ss_manager-netutils.o: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -MT ss_manager-netutils.o -MD -MP -MF $(DEPDIR)/ss_manager-netutils.Tpo -c -o ss_manager-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_manager-netutils.Tpo $(DEPDIR)/ss_manager-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_manager-netutils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -c -o ss_manager-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
|
||||
ss_manager-netutils.obj: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -MT ss_manager-netutils.obj -MD -MP -MF $(DEPDIR)/ss_manager-netutils.Tpo -c -o ss_manager-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_manager-netutils.Tpo $(DEPDIR)/ss_manager-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_manager-netutils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -c -o ss_manager-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
|
||||
ss_manager-manager.o: manager.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_manager_CFLAGS) $(CFLAGS) -MT ss_manager-manager.o -MD -MP -MF $(DEPDIR)/ss_manager-manager.Tpo -c -o ss_manager-manager.o `test -f 'manager.c' || echo '$(srcdir)/'`manager.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_manager-manager.Tpo $(DEPDIR)/ss_manager-manager.Po
|
||||
|
||||
+281
-4
@@ -45,7 +45,6 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -67,6 +66,7 @@
|
||||
#include "json.h"
|
||||
#include "utils.h"
|
||||
#include "manager.h"
|
||||
#include "netutils.h"
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 65535
|
||||
@@ -78,6 +78,7 @@ char *working_dir = NULL;
|
||||
int working_dir_size = 0;
|
||||
|
||||
static struct cork_hash_table *server_table;
|
||||
static struct cork_hash_table *sock_table;
|
||||
|
||||
#ifndef __MINGW32__
|
||||
static int
|
||||
@@ -313,16 +314,271 @@ parse_traffic(char *buf, int len, char *port, uint64_t *traffic)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_and_bind(const char *host, const char *port, int protocol)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp, *ipv4v6bindall;
|
||||
int s, listen_sock, is_port_reuse;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
|
||||
hints.ai_socktype = protocol == IPPROTO_TCP ?
|
||||
SOCK_STREAM : SOCK_DGRAM; /* We want a TCP or UDP socket */
|
||||
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */
|
||||
hints.ai_protocol = protocol;
|
||||
|
||||
s = getaddrinfo(host, port, &hints, &result);
|
||||
|
||||
if (s != 0) {
|
||||
LOGE("getaddrinfo: %s", gai_strerror(s));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rp = result;
|
||||
|
||||
/*
|
||||
* On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with
|
||||
* AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to
|
||||
* return a list of addresses to listen on, but it is impossible to listen on
|
||||
* 0.0.0.0 and :: at the same time, if :: implies dualstack mode.
|
||||
*/
|
||||
if (!host) {
|
||||
ipv4v6bindall = result;
|
||||
|
||||
/* Loop over all address infos found until a IPV6 address is found. */
|
||||
while (ipv4v6bindall) {
|
||||
if (ipv4v6bindall->ai_family == AF_INET6) {
|
||||
rp = ipv4v6bindall; /* Take first IPV6 address available */
|
||||
break;
|
||||
}
|
||||
ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */
|
||||
}
|
||||
}
|
||||
|
||||
for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {
|
||||
listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (listen_sock == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rp->ai_family == AF_INET6) {
|
||||
int ipv6only = host ? 1 : 0;
|
||||
setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only));
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
|
||||
#endif
|
||||
/* Use port reuse to act as lock */
|
||||
int err = set_reuseport(listen_sock);
|
||||
if (err == 0) {
|
||||
if (verbose) {
|
||||
LOGI("%s port reuse enabled", protocol == IPPROTO_TCP ? "tcp" : "udp");
|
||||
}
|
||||
is_port_reuse = 1;
|
||||
}
|
||||
else {
|
||||
is_port_reuse = 0;
|
||||
}
|
||||
|
||||
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
|
||||
if (s == 0) {
|
||||
/* We managed to bind successfully! */
|
||||
break;
|
||||
} else {
|
||||
ERROR("bind");
|
||||
}
|
||||
|
||||
if (!is_port_reuse) {
|
||||
if (verbose) {
|
||||
LOGI("close sock due to %s port reuse disabled", protocol == IPPROTO_TCP ? "tcp" : "udp");
|
||||
}
|
||||
close(listen_sock);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
LOGE("Could not bind");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return is_port_reuse ? listen_sock : -2;
|
||||
}
|
||||
|
||||
static void
|
||||
release_sock_lock(sock_lock_t *sock_lock)
|
||||
{
|
||||
|
||||
ev_timer_stop(EV_DEFAULT, & sock_lock->watcher);
|
||||
|
||||
while(--sock_lock->fd_count > -1) {
|
||||
if (verbose) {
|
||||
LOGI("close sock %d then remaining fd count is %d",
|
||||
*(sock_lock->fds + sock_lock->fd_count), sock_lock->fd_count);
|
||||
}
|
||||
close(*(sock_lock->fds + sock_lock->fd_count));
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
LOGI("release sock lock: %s", sock_lock->port);
|
||||
}
|
||||
|
||||
ss_free(sock_lock->port);
|
||||
ss_free(sock_lock->fds);
|
||||
ss_free(sock_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
get_and_release_sock_lock(char* port)
|
||||
{
|
||||
if (verbose) {
|
||||
LOGI("try to get and release sock lock at port: %s", port);
|
||||
}
|
||||
|
||||
sock_lock_t *sock_lock = NULL;
|
||||
bool ret = cork_hash_table_delete(sock_table, port, NULL, (void **)&sock_lock);
|
||||
|
||||
if (ret) {
|
||||
release_sock_lock(sock_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sock_lock_timeout_cb(EV_P_ ev_timer *watcher, int revents)
|
||||
{
|
||||
sock_lock_t *sock_lock = cork_container_of(watcher, sock_lock_t, watcher);
|
||||
|
||||
cork_hash_table_delete(sock_table, sock_lock->port, NULL, NULL);
|
||||
release_sock_lock(sock_lock);
|
||||
}
|
||||
|
||||
static sock_lock_t *
|
||||
new_sock_lock(char *port, int *fds, int fd_count)
|
||||
{
|
||||
if (verbose) {
|
||||
LOGI("new sock lock with port: %s fd_count: %d", port, fd_count);
|
||||
}
|
||||
|
||||
sock_lock_t *sock_lock;
|
||||
sock_lock = ss_malloc(sizeof(sock_lock_t));
|
||||
|
||||
memset(sock_lock, 0, sizeof(sock_lock_t));
|
||||
|
||||
sock_lock->port = ss_malloc(strlen(port) * sizeof(char));
|
||||
strcpy(sock_lock->port, port);
|
||||
|
||||
sock_lock->fds = ss_malloc(fd_count * sizeof(int));
|
||||
memcpy(sock_lock->fds, fds, fd_count * sizeof(int));
|
||||
|
||||
sock_lock->fd_count = fd_count;
|
||||
|
||||
/* use 128 as ss-server may use at most 128 seconds to query dns */
|
||||
ev_timer_init(& sock_lock->watcher, sock_lock_timeout_cb, 128., 0.);
|
||||
ev_timer_start(EV_DEFAULT, & sock_lock->watcher);
|
||||
|
||||
return sock_lock;
|
||||
}
|
||||
|
||||
static int
|
||||
check_port(struct manager_ctx *manager, struct server *server)
|
||||
{
|
||||
bool both_tcp_udp = manager->mode == TCP_AND_UDP;
|
||||
int fd_count = manager->host_num * (both_tcp_udp ? 2 : 1);
|
||||
int bind_err = 0;
|
||||
|
||||
int *sock_fds = (int *)ss_malloc(fd_count * sizeof(int));
|
||||
memset(sock_fds, 0, fd_count * sizeof(int));
|
||||
|
||||
/* try to bind each interface */
|
||||
for (int i = 0; i < manager->host_num; i++) {
|
||||
LOGI("try to bind interface: %s, port: %s", manager->hosts[i], server->port);
|
||||
|
||||
if (manager->mode == UDP_ONLY) {
|
||||
sock_fds[i] = create_and_bind(manager->hosts[i], server->port, IPPROTO_UDP);
|
||||
}
|
||||
else {
|
||||
sock_fds[i] = create_and_bind(manager->hosts[i], server->port, IPPROTO_TCP);
|
||||
}
|
||||
|
||||
if (both_tcp_udp) {
|
||||
sock_fds[i + manager->host_num] = create_and_bind(manager->hosts[i], server->port, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
if (sock_fds[i] == -1 || (both_tcp_udp && sock_fds[i + manager->host_num] == -1)) {
|
||||
bind_err = -1;
|
||||
break;
|
||||
}
|
||||
else if (sock_fds[i] == -2 || (both_tcp_udp && sock_fds[i + manager->host_num] == -2)) {
|
||||
/* continue to check all hosts */
|
||||
bind_err = -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bind_err) {
|
||||
/* no err happened */
|
||||
if (verbose) {
|
||||
LOGI("port check passed and locked");
|
||||
}
|
||||
|
||||
sock_lock_t *sock_lock = new_sock_lock(server->port, sock_fds, fd_count);
|
||||
|
||||
sock_lock_t *old_sock_lock = NULL;
|
||||
bool new = false;
|
||||
|
||||
cork_hash_table_put(sock_table, (void *)sock_lock->port, (void *)sock_lock, &new, NULL, (void **)&old_sock_lock);
|
||||
|
||||
if (old_sock_lock) {
|
||||
if (verbose) {
|
||||
LOGI("release old sock lock after add new one to hash table");
|
||||
}
|
||||
release_sock_lock(old_sock_lock);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* clean socks */
|
||||
for (int i = 0; i < fd_count; i++) {
|
||||
if (sock_fds[i] > 0) {
|
||||
close(sock_fds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(sock_fds);
|
||||
|
||||
if (bind_err == -2) {
|
||||
LOGI("port is avaiable but can not be locked");
|
||||
}
|
||||
|
||||
return bind_err == -1 ? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
add_server(struct manager_ctx *manager, struct server *server)
|
||||
{
|
||||
int ret = check_port(manager, server);
|
||||
|
||||
if (ret == -1) {
|
||||
LOGE("port is not available, please check.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool new = false;
|
||||
cork_hash_table_put(server_table, (void *)server->port, (void *)server, &new, NULL, NULL);
|
||||
|
||||
char *cmd = construct_command_line(manager, server);
|
||||
if (system(cmd) == -1) {
|
||||
ERROR("add_server_system");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -435,10 +691,21 @@ manager_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
remove_server(working_dir, server->port);
|
||||
add_server(manager, server);
|
||||
int ret = add_server(manager, server);
|
||||
|
||||
char msg[3] = "ok";
|
||||
if (sendto(manager->fd, msg, 2, 0, (struct sockaddr *)&claddr, len) != 2) {
|
||||
char *msg;
|
||||
int msg_len;
|
||||
|
||||
if (ret == -1) {
|
||||
msg = "port is not available";
|
||||
msg_len = 21;
|
||||
}
|
||||
else {
|
||||
msg = "ok";
|
||||
msg_len = 2;
|
||||
}
|
||||
|
||||
if (sendto(manager->fd, msg, msg_len, 0, (struct sockaddr *)&claddr, len) != 2) {
|
||||
ERROR("add_sendto");
|
||||
}
|
||||
} else if (strcmp(action, "remove") == 0) {
|
||||
@@ -469,6 +736,7 @@ manager_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
update_stat(port, traffic);
|
||||
get_and_release_sock_lock(port);
|
||||
} else if (strcmp(action, "ping") == 0) {
|
||||
struct cork_hash_table_entry *entry;
|
||||
struct cork_hash_table_iterator server_iter;
|
||||
@@ -914,6 +1182,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
server_table = cork_string_hash_table_new(MAX_PORT_NUM, 0);
|
||||
sock_table = cork_string_hash_table_new(MAX_PORT_NUM, 0);
|
||||
|
||||
if (conf != NULL) {
|
||||
for (i = 0; i < conf->port_password_num; i++) {
|
||||
@@ -976,6 +1245,7 @@ main(int argc, char **argv)
|
||||
// Clean up
|
||||
struct cork_hash_table_entry *entry;
|
||||
struct cork_hash_table_iterator server_iter;
|
||||
struct cork_hash_table_iterator sock_iter;
|
||||
|
||||
cork_hash_table_iterator_init(server_table, &server_iter);
|
||||
|
||||
@@ -984,6 +1254,13 @@ main(int argc, char **argv)
|
||||
stop_server(working_dir, server->port);
|
||||
}
|
||||
|
||||
cork_hash_table_iterator_init(sock_table, &sock_iter);
|
||||
|
||||
while ((entry = cork_hash_table_iterator_next(&sock_iter)) != NULL) {
|
||||
sock_lock_t *sock_lock = (sock_lock_t *)entry->value;
|
||||
release_sock_lock(sock_lock);
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
winsock_cleanup();
|
||||
#endif
|
||||
|
||||
@@ -63,4 +63,11 @@ struct server {
|
||||
uint64_t traffic;
|
||||
};
|
||||
|
||||
typedef struct sock_lock {
|
||||
char *port;
|
||||
int *fds;
|
||||
int fd_count;
|
||||
ev_timer watcher;
|
||||
} sock_lock_t;
|
||||
|
||||
#endif // _MANAGER_H
|
||||
|
||||
Reference in New Issue
Block a user