Browse Source

Remove reuse_port lock

pull/1613/head
Max Lv 7 years ago
parent
commit
8e41a43dc9
2 changed files with 7 additions and 138 deletions
  1. 138
      src/manager.c
  2. 7
      src/manager.h

138
src/manager.c

@ -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");
}
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);
/* clean socks */
for (int i = 0; i < fd_count; i++) {
if (sock_fds[i] > 0) {
close(sock_fds[i]);
}
} 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);

7
src/manager.h

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