mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-28 11:43:50 +00:00
Remove reuse_port lock
This commit is contained in:
+7
-131
@@ -71,7 +71,6 @@ char *working_dir = NULL;
|
||||
int working_dir_size = 0;
|
||||
|
||||
static struct cork_hash_table *server_table;
|
||||
static struct cork_hash_table *sock_table;
|
||||
|
||||
static int
|
||||
setnonblocking(int fd)
|
||||
@@ -350,7 +349,7 @@ create_and_bind(const char *host, const char *port, int protocol)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp, *ipv4v6bindall;
|
||||
int s, listen_sock = -1, is_reuse_port = 0;
|
||||
int s, listen_sock = -1;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
|
||||
@@ -403,25 +402,12 @@ create_and_bind(const char *host, const char *port, int protocol)
|
||||
#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_reuse_port = 1;
|
||||
}
|
||||
|
||||
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
|
||||
if (s == 0) {
|
||||
/* We managed to bind successfully! */
|
||||
|
||||
if (!is_reuse_port) {
|
||||
if (verbose) {
|
||||
LOGI("close sock due to %s port reuse disabled", protocol == IPPROTO_TCP ? "tcp" : "udp");
|
||||
}
|
||||
close(listen_sock);
|
||||
}
|
||||
close(listen_sock);
|
||||
|
||||
break;
|
||||
} else {
|
||||
@@ -438,80 +424,7 @@ create_and_bind(const char *host, const char *port, int protocol)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return is_reuse_port ? 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 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;
|
||||
return listen_sock;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -541,45 +454,18 @@ check_port(struct manager_ctx *manager, struct server *server)
|
||||
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");
|
||||
/* clean socks */
|
||||
for (int i = 0; i < fd_count; i++) {
|
||||
if (sock_fds[i] > 0) {
|
||||
close(sock_fds[i]);
|
||||
}
|
||||
|
||||
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 available but can not be locked");
|
||||
}
|
||||
|
||||
return bind_err == -1 ? -1 : 0;
|
||||
}
|
||||
|
||||
@@ -799,7 +685,6 @@ 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;
|
||||
@@ -1250,7 +1135,6 @@ 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++) {
|
||||
@@ -1313,7 +1197,6 @@ 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);
|
||||
|
||||
@@ -1322,13 +1205,6 @@ 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);
|
||||
}
|
||||
|
||||
ev_signal_stop(EV_DEFAULT, &sigint_watcher);
|
||||
ev_signal_stop(EV_DEFAULT, &sigterm_watcher);
|
||||
ss_free(working_dir);
|
||||
|
||||
@@ -75,11 +75,4 @@ 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