Browse Source

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
pull/1037/head
GhostFlying 7 years ago
committed by Max Lv
parent
commit
9753cc54dc
4 changed files with 330 additions and 24 deletions
  1. 3
      src/Makefile.am
  2. 59
      src/Makefile.in
  3. 285
      src/manager.c
  4. 7
      src/manager.h

3
src/Makefile.am

@ -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

59
src/Makefile.in

@ -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

285
src/manager.c

@ -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

7
src/manager.h

@ -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
Loading…
Cancel
Save