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