diff --git a/src/manager.c b/src/manager.c index eb46b736..d9acc63d 100644 --- a/src/manager.c +++ b/src/manager.c @@ -83,6 +83,15 @@ setnonblocking(int fd) return fcntl(fd, F_SETFL, flags | O_NONBLOCK); } +static void +destroy_server(struct server *server) { +// function used to free memories alloced in **get_server** + if (server->method) ss_free(server->method); + if (server->plugin) ss_free(server->plugin); + if (server->plugin_opts) ss_free(server->plugin_opts); + if (server->mode) ss_free(server->mode); +} + static void build_config(char *prefix, struct server *server) { @@ -102,6 +111,11 @@ build_config(char *prefix, struct server *server) fprintf(f, "{\n"); fprintf(f, "\"server_port\":\"%s\",\n", server->port); fprintf(f, "\"password\":\"%s\",\n", server->password); + if (server->fast_open[0]) fprintf(f, "\"fast_open\": %s,\n", server->fast_open); + if (server->mode) fprintf(f, "\"mode\":\"%s\",\n", server->mode); + if (server->method) fprintf(f, "\"method\":\"%s\",\n", server->method); + if (server->plugin) fprintf(f, "\"plugin\":\"%s\",\n", server->plugin); + if (server->plugin_opts) fprintf(f, "\"plugin_opts\":\"%s\",\n", server->plugin_opts); fprintf(f, "}\n"); fclose(f); ss_free(path); @@ -111,14 +125,16 @@ static char * construct_command_line(struct manager_ctx *manager, struct server *server) { static char cmd[BUF_SIZE]; + char *method = manager->method; int i; build_config(working_dir, server); + if (server->method) method = server->method; memset(cmd, 0, BUF_SIZE); snprintf(cmd, BUF_SIZE, "%s -m %s --manager-address %s -f %s/.shadowsocks_%s.pid -c %s/.shadowsocks_%s.conf", - executable, manager->method, manager->manager_address, + executable, method, manager->manager_address, working_dir, server->port, working_dir, server->port); if (manager->acl != NULL) { @@ -143,15 +159,15 @@ construct_command_line(struct manager_ctx *manager, struct server *server) int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -v"); } - if (manager->mode == UDP_ONLY) { + if (server->mode == NULL && manager->mode == UDP_ONLY) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -U"); } - if (manager->mode == TCP_AND_UDP) { + if (server->mode == NULL && manager->mode == TCP_AND_UDP) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -u"); } - if (manager->fast_open) { + if (server->fast_open[0] == 0 && manager->fast_open) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " --fast-open"); } @@ -163,11 +179,11 @@ construct_command_line(struct manager_ctx *manager, struct server *server) int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " --mtu %d", manager->mtu); } - if (manager->plugin) { + if (server->plugin == NULL && manager->plugin) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " --plugin \"%s\"", manager->plugin); } - if (manager->plugin_opts) { + if (server->plugin_opts == NULL && manager->plugin_opts) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " --plugin-opts \"%s\"", manager->plugin_opts); } @@ -264,6 +280,26 @@ get_server(char *buf, int len) if (value->type == json_string) { strncpy(server->password, value->u.string.ptr, 128); } + } else if (strcmp(name, "method") == 0) { + if (value->type == json_string) { + server->method = strdup(value->u.string.ptr); + } + } else if (strcmp(name, "fast_open") == 0) { + if (value->type == json_boolean) { + strncpy(server->fast_open, (value->u.boolean ? "true" : "false"), 8); + } + } else if (strcmp(name, "plugin") == 0) { + if (value->type == json_string) { + server->plugin = strdup(value->u.string.ptr); + } + } else if (strcmp(name, "plugin_opts") == 0) { + if (value->type == json_string) { + server->plugin_opts = strdup(value->u.string.ptr); + } + } else if (strcmp(name, "mode") == 0) { + if (value->type == json_string) { + server->mode = strdup(value->u.string.ptr); + } } else { LOGE("invalid data: %s", data); break; @@ -623,6 +659,7 @@ remove_server(char *prefix, char *port) cork_hash_table_delete(server_table, (void *)port, (void **)&old_port, (void **)&old_server); if (old_server != NULL) { + destroy_server(old_server); ss_free(old_server); } @@ -647,7 +684,7 @@ manager_recv_cb(EV_P_ ev_io *w, int revents) { struct manager_ctx *manager = (struct manager_ctx *)w; socklen_t len; - size_t r; + ssize_t r; struct sockaddr_un claddr; char buf[BUF_SIZE]; @@ -676,6 +713,7 @@ manager_recv_cb(EV_P_ ev_io *w, int revents) if (server == NULL || server->port[0] == 0 || server->password[0] == 0) { LOGE("invalid command: %s:%s", buf, get_data(buf, r)); if (server != NULL) { + destroy_server(server); ss_free(server); } goto ERROR_MSG; @@ -683,6 +721,8 @@ manager_recv_cb(EV_P_ ev_io *w, int revents) remove_server(working_dir, server->port); int ret = add_server(manager, server); + destroy_server(server); + ss_free(server); char *msg; int msg_len; @@ -704,12 +744,14 @@ manager_recv_cb(EV_P_ ev_io *w, int revents) if (server == NULL || server->port[0] == 0) { LOGE("invalid command: %s:%s", buf, get_data(buf, r)); if (server != NULL) { + destroy_server(server); ss_free(server); } goto ERROR_MSG; } remove_server(working_dir, server->port); + destroy_server(server); ss_free(server); char msg[3] = "ok"; diff --git a/src/manager.h b/src/manager.h index fc0ee012..6fad5542 100644 --- a/src/manager.h +++ b/src/manager.h @@ -67,6 +67,11 @@ struct manager_ctx { struct server { char port[8]; char password[128]; + char fast_open[8]; + char *mode; + char *method; + char *plugin; + char *plugin_opts; uint64_t traffic; };