|
|
@ -109,6 +109,13 @@ static struct ev_signal sigterm_watcher; |
|
|
|
#ifndef __MINGW32__ |
|
|
|
static struct ev_signal sigchld_watcher; |
|
|
|
static struct ev_signal sigusr1_watcher; |
|
|
|
#else |
|
|
|
static struct plugin_watcher_t { |
|
|
|
ev_io io; |
|
|
|
SOCKET fd; |
|
|
|
uint16_t port; |
|
|
|
int valid; |
|
|
|
} plugin_watcher; |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef HAVE_SETRLIMIT |
|
|
@ -123,6 +130,9 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents); |
|
|
|
static void remote_send_cb(EV_P_ ev_io *w, int revents); |
|
|
|
static void accept_cb(EV_P_ ev_io *w, int revents); |
|
|
|
static void signal_cb(EV_P_ ev_signal *w, int revents); |
|
|
|
#if defined(__MINGW32__) && !defined(LIB_ONLY) |
|
|
|
static void plugin_watcher_cb(EV_P_ ev_io *w, int revents); |
|
|
|
#endif |
|
|
|
|
|
|
|
static int create_and_bind(const char *addr, const char *port); |
|
|
|
#ifdef HAVE_LAUNCHD |
|
|
@ -1312,6 +1322,8 @@ signal_cb(EV_P_ ev_signal *w, int revents) |
|
|
|
#ifndef __MINGW32__ |
|
|
|
ev_signal_stop(EV_DEFAULT, &sigchld_watcher); |
|
|
|
ev_signal_stop(EV_DEFAULT, &sigusr1_watcher); |
|
|
|
#else |
|
|
|
ev_io_stop(EV_DEFAULT, &plugin_watcher.io); |
|
|
|
#endif |
|
|
|
keep_resolving = 0; |
|
|
|
ev_unloop(EV_A_ EVUNLOOP_ALL); |
|
|
@ -1319,6 +1331,27 @@ signal_cb(EV_P_ ev_signal *w, int revents) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#if defined(__MINGW32__) && !defined(LIB_ONLY) |
|
|
|
static void |
|
|
|
plugin_watcher_cb(EV_P_ ev_io *w, int revents) |
|
|
|
{ |
|
|
|
char buf[1]; |
|
|
|
SOCKET fd = accept(plugin_watcher.fd, NULL, NULL); |
|
|
|
if (fd == INVALID_SOCKET) { |
|
|
|
return; |
|
|
|
} |
|
|
|
recv(fd, buf, 1, 0); |
|
|
|
closesocket(fd); |
|
|
|
LOGE("plugin service exit unexpectedly"); |
|
|
|
ret_val = -1; |
|
|
|
ev_signal_stop(EV_DEFAULT, &sigint_watcher); |
|
|
|
ev_signal_stop(EV_DEFAULT, &sigterm_watcher); |
|
|
|
ev_io_stop(EV_DEFAULT, &plugin_watcher.io); |
|
|
|
keep_resolving = 0; |
|
|
|
ev_unloop(EV_A_ EVUNLOOP_ALL); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
void |
|
|
|
accept_cb(EV_P_ ev_io *w, int revents) |
|
|
|
{ |
|
|
@ -1364,9 +1397,7 @@ main(int argc, char **argv) |
|
|
|
char *plugin_opts = NULL; |
|
|
|
char *plugin_host = NULL; |
|
|
|
char *plugin_port = NULL; |
|
|
|
#ifndef __MINGW32__ |
|
|
|
char tmp_port[8]; |
|
|
|
#endif |
|
|
|
|
|
|
|
srand(time(NULL)); |
|
|
|
|
|
|
@ -1596,7 +1627,6 @@ main(int argc, char **argv) |
|
|
|
#endif |
|
|
|
|
|
|
|
if (plugin != NULL) { |
|
|
|
#ifndef __MINGW32__ |
|
|
|
uint16_t port = get_local_port(); |
|
|
|
if (port == 0) { |
|
|
|
FATAL("failed to find a free port"); |
|
|
@ -1605,10 +1635,15 @@ main(int argc, char **argv) |
|
|
|
plugin_host = "127.0.0.1"; |
|
|
|
plugin_port = tmp_port; |
|
|
|
|
|
|
|
LOGI("plugin \"%s\" enabled", plugin); |
|
|
|
#else |
|
|
|
FATAL("plugins not implemented in MinGW port"); |
|
|
|
#ifdef __MINGW32__ |
|
|
|
memset(&plugin_watcher, 0, sizeof(plugin_watcher)); |
|
|
|
plugin_watcher.port = get_local_port(); |
|
|
|
if (plugin_watcher.port == 0) { |
|
|
|
LOGE("failed to assign a control port for plugin"); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
LOGI("plugin \"%s\" enabled", plugin); |
|
|
|
} |
|
|
|
|
|
|
|
if (method == NULL) { |
|
|
@ -1658,7 +1693,40 @@ main(int argc, char **argv) |
|
|
|
LOGI("resolving hostname to IPv6 address first"); |
|
|
|
} |
|
|
|
|
|
|
|
#ifndef __MINGW32__ |
|
|
|
#ifdef __MINGW32__ |
|
|
|
// Listen on plugin control port |
|
|
|
if (plugin != NULL && plugin_watcher.port != 0) { |
|
|
|
SOCKET fd; |
|
|
|
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
|
|
|
if (fd != INVALID_SOCKET) { |
|
|
|
plugin_watcher.valid = 0; |
|
|
|
do { |
|
|
|
struct sockaddr_in addr; |
|
|
|
memset(&addr, 0, sizeof(addr)); |
|
|
|
addr.sin_family = AF_INET; |
|
|
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
|
|
addr.sin_port = htons(plugin_watcher.port); |
|
|
|
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { |
|
|
|
LOGE("failed to bind plugin control port"); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (listen(fd, 1)) { |
|
|
|
LOGE("failed to listen on plugin control port"); |
|
|
|
break; |
|
|
|
} |
|
|
|
plugin_watcher.fd = fd; |
|
|
|
ev_io_init(&plugin_watcher.io, plugin_watcher_cb, fd, EV_READ); |
|
|
|
ev_io_start(EV_DEFAULT, &plugin_watcher.io); |
|
|
|
plugin_watcher.valid = 1; |
|
|
|
} while (0); |
|
|
|
if (!plugin_watcher.valid) { |
|
|
|
closesocket(fd); |
|
|
|
plugin_watcher.port = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
if (plugin != NULL) { |
|
|
|
int len = 0; |
|
|
|
size_t buf_size = 256 * remote_num; |
|
|
@ -1671,12 +1739,16 @@ main(int argc, char **argv) |
|
|
|
len = strlen(remote_str); |
|
|
|
} |
|
|
|
int err = start_plugin(plugin, plugin_opts, remote_str, |
|
|
|
remote_port, plugin_host, plugin_port, MODE_CLIENT); |
|
|
|
remote_port, plugin_host, plugin_port, |
|
|
|
#ifdef __MINGW32__ |
|
|
|
plugin_watcher.port, |
|
|
|
#endif |
|
|
|
MODE_CLIENT); |
|
|
|
if (err) { |
|
|
|
ERROR("start_plugin"); |
|
|
|
FATAL("failed to start the plugin"); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifndef __MINGW32__ |
|
|
|
// ignore SIGPIPE |
|
|
@ -1800,11 +1872,9 @@ main(int argc, char **argv) |
|
|
|
} |
|
|
|
|
|
|
|
// Clean up |
|
|
|
#ifndef __MINGW32__ |
|
|
|
if (plugin != NULL) { |
|
|
|
stop_plugin(); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
if (mode != UDP_ONLY) { |
|
|
|
ev_io_stop(loop, &listen_ctx.io); |
|
|
@ -1969,6 +2039,10 @@ _start_ss_local_server(profile_t profile, ss_local_callback callback, void *udat |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef __MINGW32__ |
|
|
|
if (plugin_watcher.valid) { |
|
|
|
closesocket(plugin_watcher.fd); |
|
|
|
} |
|
|
|
|
|
|
|
winsock_cleanup(); |
|
|
|
#endif |
|
|
|
|
|
|
|