Browse Source

Re-add support for MinGW

pull/1962/head
Linus Yang 7 years ago
parent
commit
2ed8791dab
21 changed files with 441 additions and 47 deletions
  1. 16
      configure.ac
  2. 45
      src/Makefile.am
  3. 3
      src/aead.c
  4. 2
      src/crypto.c
  5. 2
      src/crypto.h
  6. 8
      src/json.c
  7. 49
      src/local.c
  8. 2
      src/netutils.c
  9. 4
      src/netutils.h
  10. 4
      src/plugin.c
  11. 13
      src/resolv.c
  12. 2
      src/resolv.h
  13. 47
      src/server.c
  14. 2
      src/stream.h
  15. 2
      src/tls.c
  16. 39
      src/tunnel.c
  17. 19
      src/udprelay.c
  18. 20
      src/utils.c
  19. 48
      src/utils.h
  20. 75
      src/winsock.c
  21. 86
      src/winsock.h

16
configure.ac

@ -66,7 +66,7 @@ dnl Add library for mingw
case $host in
*-mingw*)
CFLAGS="$CFLAGS -mno-ms-bitfields"
LIBS="$LIBS -ladvapi32 -lgdi32 -lws2_32 -lcrypt32"
LIBS="$LIBS -lws2_32"
;;
*-cygwin*)
CFLAGS="$CFLAGS -mno-ms-bitfields"
@ -93,6 +93,10 @@ case $host in
os_support=linux
AC_MSG_RESULT(Linux)
;;
*-mingw*)
os_support=mingw
AC_MSG_RESULT(MinGW)
;;
*)
AC_MSG_RESULT(transparent proxy does not support for $host)
;;
@ -161,6 +165,10 @@ AC_CHECK_HEADERS([net/if.h], [], [],
])
case $host in
*-mingw*)
AC_DEFINE([CONNECT_IN_PROGRESS], [WSAEWOULDBLOCK], [errno for incomplete non-blocking connect(2)])
AC_CHECK_HEADERS([winsock2.h ws2tcpip.h], [], [AC_MSG_ERROR([Missing MinGW headers])], [])
;;
*-linux*)
AC_DEFINE([CONNECT_IN_PROGRESS], [EINPROGRESS], [errno for incomplete non-blocking connect(2)])
dnl Checks for netfilter headers
@ -219,6 +227,12 @@ AC_CHECK_LIB(socket, connect)
dnl Checks for library functions.
AC_CHECK_FUNCS([malloc memset posix_memalign socket])
AC_ARG_WITH(ev,
AS_HELP_STRING([--with-ev=DIR], [use a specific libev library]),
[CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_CHECK_HEADERS([ev.h libev/ev.h], [], [])
AC_CHECK_LIB([ev], [ev_loop_destroy], [LIBS="-lev $LIBS"], [AC_MSG_ERROR([Couldn't find libev. Try installing libev-dev@<:@el@:>@.])])

45
src/Makefile.am

@ -19,7 +19,10 @@ SS_COMMON_LIBS += -lbloom -lcork -lcorkipset
endif
SS_COMMON_LIBS += -lev -lsodium -lm
bin_PROGRAMS = ss-local ss-tunnel ss-server ss-manager
bin_PROGRAMS = ss-local ss-tunnel ss-server
if !BUILD_WINCOMPAT
bin_PROGRAMS += ss-manager
endif
sni_src = http.c \
tls.c
@ -30,41 +33,37 @@ acl_src = rule.c \
crypto_src = crypto.c \
aead.c \
stream.c \
ppbloom.c \
ppbloom.c \
base64.c
plugin_src = plugin.c
ss_local_SOURCES = utils.c \
jconf.c \
json.c \
udprelay.c \
cache.c \
netutils.c \
local.c \
common_src = utils.c \
jconf.c \
json.c \
udprelay.c \
cache.c \
netutils.c
if BUILD_WINCOMPAT
common_src += winsock.c
endif
ss_local_SOURCES = local.c \
$(common_src) \
$(crypto_src) \
$(plugin_src) \
$(sni_src) \
$(acl_src)
ss_tunnel_SOURCES = utils.c \
jconf.c \
json.c \
udprelay.c \
cache.c \
netutils.c \
tunnel.c \
ss_tunnel_SOURCES = tunnel.c \
$(common_src) \
$(crypto_src) \
$(plugin_src)
ss_server_SOURCES = utils.c \
netutils.c \
jconf.c \
json.c \
udprelay.c \
cache.c \
resolv.c \
ss_server_SOURCES = resolv.c \
server.c \
$(common_src) \
$(crypto_src) \
$(plugin_src) \
$(sni_src) \

3
src/aead.c

@ -31,11 +31,14 @@
#include <assert.h>
#include <sodium.h>
#ifndef __MINGW32__
#include <arpa/inet.h>
#endif
#include "ppbloom.h"
#include "aead.h"
#include "utils.h"
#include "winsock.h"
#define NONE (-1)
#define AES128GCM 0

2
src/crypto.c

@ -372,7 +372,7 @@ crypto_parse_key(const char *base64, uint8_t *key, size_t key_len)
rand_bytes(key, key_len);
base64_encode(out_key, out_len, key, key_len);
LOGE("Invalid key for your chosen cipher!");
LOGE("It requires a %zu-byte key encoded with URL-safe Base64", key_len);
LOGE("It requires a " SIZE_FMT "-byte key encoded with URL-safe Base64", key_len);
LOGE("Generating a new random key: %s", out_key);
FATAL("Please use the key above or input a valid key");
return key_len;

2
src/crypto.h

@ -23,7 +23,9 @@
#ifndef _CRYPTO_H
#define _CRYPTO_H
#ifndef __MINGW32__
#include <sys/socket.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

8
src/json.c

@ -35,6 +35,12 @@
#endif
#endif
#ifdef __MINGW32__
#define CONV_PTR (uintptr_t)
#else
#define CONV_PTR (unsigned long)
#endif
const struct _json_value json_value_none;
#include <stdio.h>
@ -138,7 +144,7 @@ static int new_value (json_state * state,
values_size = sizeof (*value->u.object.values) * value->u.object.length;
if (! (value->u.object.values = (json_object_entry *) json_alloc
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
(state, values_size + (CONV_PTR value->u.object.values), 0)) )
{
return 0;
}

49
src/local.c

@ -33,12 +33,12 @@
#include <strings.h>
#include <unistd.h>
#include <getopt.h>
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#endif
#ifdef LIB_ONLY
#include "shadowsocks.h"
#endif
@ -59,6 +59,7 @@
#include "tls.h"
#include "plugin.h"
#include "local.h"
#include "winsock.h"
#ifndef LIB_ONLY
#ifdef __APPLE__
@ -104,8 +105,10 @@ static int udp_fd = 0;
static struct ev_signal sigint_watcher;
static struct ev_signal sigterm_watcher;
#ifndef __MINGW32__
static struct ev_signal sigchld_watcher;
static struct ev_signal sigusr1_watcher;
#endif
#ifdef HAVE_SETRLIMIT
#ifndef LIB_ONLY
@ -135,6 +138,7 @@ static server_t *new_server(int fd);
static struct cork_dllist connections;
#ifndef __MINGW32__
int
setnonblocking(int fd)
{
@ -144,6 +148,7 @@ setnonblocking(int fd)
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
int
create_and_bind(const char *addr, const char *port)
@ -1213,18 +1218,22 @@ signal_cb(EV_P_ ev_signal *w, int revents)
{
if (revents & EV_SIGNAL) {
switch (w->signum) {
#ifndef __MINGW32__
case SIGCHLD:
if (!is_plugin_running())
LOGE("plugin service exit unexpectedly");
else
return;
case SIGUSR1:
#endif
case SIGINT:
case SIGTERM:
ev_signal_stop(EV_DEFAULT, &sigint_watcher);
ev_signal_stop(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_stop(EV_DEFAULT, &sigchld_watcher);
ev_signal_stop(EV_DEFAULT, &sigusr1_watcher);
#endif
keep_resolving = 0;
ev_unloop(EV_A_ EVUNLOOP_ALL);
}
@ -1276,7 +1285,9 @@ 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));
@ -1501,7 +1512,12 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
#ifdef __MINGW32__
winsock_init();
#endif
if (plugin != NULL) {
#ifndef __MINGW32__
uint16_t port = get_local_port();
if (port == 0) {
FATAL("failed to find a free port");
@ -1511,6 +1527,9 @@ main(int argc, char **argv)
plugin_port = tmp_port;
LOGI("plugin \"%s\" enabled", plugin);
#else
FATAL("plugins not implemented in MinGW port");
#endif
}
if (method == NULL) {
@ -1560,6 +1579,7 @@ main(int argc, char **argv)
LOGI("resolving hostname to IPv6 address first");
}
#ifndef __MINGW32__
if (plugin != NULL) {
int len = 0;
size_t buf_size = 256 * remote_num;
@ -1577,10 +1597,13 @@ main(int argc, char **argv)
FATAL("failed to start the plugin");
}
}
#endif
#ifndef __MINGW32__
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
// Setup keys
LOGI("initializing ciphers... %s", method);
@ -1621,8 +1644,10 @@ main(int argc, char **argv)
ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
ev_signal_start(EV_DEFAULT, &sigint_watcher);
ev_signal_start(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigchld_watcher);
#endif
if (strcmp(local_addr, ":") > 0)
LOGI("listening at [%s]:%s", local_addr, local_port);
@ -1674,6 +1699,7 @@ main(int argc, char **argv)
else
#endif
#ifndef __MINGW32__
// setuid
if (user != NULL && !run_as(user)) {
FATAL("failed to switch user");
@ -1682,6 +1708,7 @@ main(int argc, char **argv)
if (geteuid() == 0) {
LOGI("running from root user");
}
#endif
// Init connections
cork_dllist_init(&connections);
@ -1694,9 +1721,11 @@ 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);
@ -1711,6 +1740,10 @@ main(int argc, char **argv)
free_udprelay();
}
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}
@ -1743,6 +1776,10 @@ _start_ss_local_server(profile_t profile, ss_local_callback callback, void *udat
sprintf(local_port_str, "%d", local_port);
sprintf(remote_port_str, "%d", remote_port);
#ifdef __MINGW32__
winsock_init();
#endif
USE_LOGFILE(log);
if (profile.acl != NULL) {
@ -1753,18 +1790,22 @@ _start_ss_local_server(profile_t profile, ss_local_callback callback, void *udat
local_addr = "127.0.0.1";
}
#ifndef __MINGW32__
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
ev_signal_start(EV_DEFAULT, &sigint_watcher);
ev_signal_start(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigusr1_watcher);
ev_signal_start(EV_DEFAULT, &sigchld_watcher);
#endif
// Setup keys
LOGI("initializing ciphers... %s", method);
@ -1848,6 +1889,10 @@ _start_ss_local_server(profile_t profile, ss_local_callback callback, void *udat
free_udprelay();
}
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}

2
src/netutils.c

@ -28,10 +28,12 @@
#include "config.h"
#endif
#ifndef __MINGW32__
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)
#include <net/if.h>

4
src/netutils.h

@ -23,7 +23,11 @@
#ifndef _NETUTILS_H
#define _NETUTILS_H
#ifdef __MINGW32__
#include "winsock.h"
#else
#include <sys/socket.h>
#endif
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>

4
src/plugin.c

@ -24,6 +24,8 @@
#include "config.h"
#endif
#ifndef __MINGW32__
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
@ -299,3 +301,5 @@ is_plugin_running()
}
return 0;
}
#endif

13
src/resolv.c

@ -32,13 +32,13 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#ifndef __MINGW32__
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#endif
#include <ares.h>
#ifdef HAVE_LIBEV_EV_H
@ -52,6 +52,13 @@
#include "resolv.h"
#include "utils.h"
#include "netutils.h"
#include "winsock.h"
#ifdef __MINGW32__
#define CONV_STATE_CB (ares_sock_state_cb)
#else
#define CONV_STATE_CB
#endif
/*
* Implement DNS resolution interface using libc-ares
@ -147,7 +154,7 @@ resolv_init(struct ev_loop *loop, char *nameservers, int ipv6first)
memset(&default_ctx, 0, sizeof(struct resolv_ctx));
default_ctx.options.sock_state_cb_data = &default_ctx;
default_ctx.options.sock_state_cb = resolv_sock_state_cb;
default_ctx.options.sock_state_cb = CONV_STATE_CB resolv_sock_state_cb;
default_ctx.options.timeout = 3000;
default_ctx.options.tries = 2;

2
src/resolv.h

@ -31,7 +31,9 @@
#endif
#include <stdint.h>
#ifndef __MINGW32__
#include <sys/socket.h>
#endif
struct resolv_query;

47
src/server.c

@ -35,14 +35,14 @@
#include <unistd.h>
#include <getopt.h>
#include <math.h>
#ifndef __MINGW32__
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/un.h>
#endif
#include <libcork/core.h>
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)
@ -56,6 +56,7 @@
#include "acl.h"
#include "plugin.h"
#include "server.h"
#include "winsock.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
@ -134,15 +135,20 @@ static char *manager_addr = NULL;
uint64_t tx = 0;
uint64_t rx = 0;
#ifndef __MINGW32__
ev_timer stat_update_watcher;
#endif
ev_timer block_list_watcher;
static struct ev_signal sigint_watcher;
static struct ev_signal sigterm_watcher;
#ifndef __MINGW32__
static struct ev_signal sigchld_watcher;
#endif
static struct cork_dllist connections;
#ifndef __MINGW32__
static void
stat_update_cb(EV_P_ ev_timer *watcher, int revents)
{
@ -218,6 +224,7 @@ stat_update_cb(EV_P_ ev_timer *watcher, int revents)
close(sfd);
}
#endif
static void
free_connections(struct ev_loop *loop)
@ -320,6 +327,7 @@ setfastopen(int fd)
return s;
}
#ifndef __MINGW32__
int
setnonblocking(int fd)
{
@ -329,6 +337,7 @@ setnonblocking(int fd)
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
int
create_and_bind(const char *host, const char *port, int mptcp)
@ -1409,16 +1418,20 @@ signal_cb(EV_P_ ev_signal *w, int revents)
{
if (revents & EV_SIGNAL) {
switch (w->signum) {
#ifndef __MINGW32__
case SIGCHLD:
if (!is_plugin_running())
LOGE("plugin service exit unexpectedly");
else
return;
#endif
case SIGINT:
case SIGTERM:
ev_signal_stop(EV_DEFAULT, &sigint_watcher);
ev_signal_stop(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_stop(EV_DEFAULT, &sigchld_watcher);
#endif
ev_unloop(EV_A_ EVUNLOOP_ALL);
}
}
@ -1493,7 +1506,9 @@ main(int argc, char **argv)
char *server_port = NULL;
char *plugin_opts = NULL;
char *plugin_port = NULL;
#ifndef __MINGW32__
char tmp_port[8];
#endif
int server_num = 0;
const char *server_host[MAX_REMOTE_NUM];
@ -1717,7 +1732,12 @@ main(int argc, char **argv)
remote_port = server_port;
#ifdef __MINGW32__
winsock_init();
#endif
if (plugin != NULL) {
#ifndef __MINGW32__
uint16_t port = get_local_port();
if (port == 0) {
FATAL("failed to find a free port");
@ -1725,6 +1745,9 @@ main(int argc, char **argv)
snprintf(tmp_port, 8, "%d", port);
plugin_port = server_port;
server_port = tmp_port;
#else
FATAL("plugins not implemented in MinGW port");
#endif
}
if (method == NULL) {
@ -1782,16 +1805,20 @@ main(int argc, char **argv)
LOGI("enable TCP no-delay");
}
#ifndef __MINGW32__
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigint_watcher);
ev_signal_start(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigchld_watcher);
#endif
// setup keys
LOGI("initializing ciphers... %s", method);
@ -1808,6 +1835,7 @@ main(int argc, char **argv)
if (nameservers != NULL)
LOGI("using nameserver: %s", nameservers);
#ifndef __MINGW32__
// Start plugin server
if (plugin != NULL) {
int len = 0;
@ -1827,6 +1855,7 @@ main(int argc, char **argv)
FATAL("failed to start the plugin");
}
}
#endif
// initialize listen context
listen_ctx_t listen_ctx_list[server_num];
@ -1888,14 +1917,17 @@ main(int argc, char **argv)
}
}
#ifndef __MINGW32__
if (manager_addr != NULL) {
ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
ev_timer_start(EV_DEFAULT, &stat_update_watcher);
}
#endif
ev_timer_init(&block_list_watcher, block_list_clear_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
ev_timer_start(EV_DEFAULT, &block_list_watcher);
#ifndef __MINGW32__
// setuid
if (user != NULL && !run_as(user)) {
FATAL("failed to switch user");
@ -1904,6 +1936,7 @@ main(int argc, char **argv)
if (geteuid() == 0) {
LOGI("running from root user");
}
#endif
// init block list
init_block_list();
@ -1921,15 +1954,19 @@ main(int argc, char **argv)
// Free block list
free_block_list();
#ifndef __MINGW32__
if (manager_addr != NULL) {
ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
}
#endif
ev_timer_stop(EV_DEFAULT, &block_list_watcher);
#ifndef __MINGW32__
if (plugin != NULL) {
stop_plugin();
}
#endif
// Clean up
@ -1953,5 +1990,9 @@ main(int argc, char **argv)
free_udprelay();
}
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}

2
src/stream.h

@ -23,7 +23,9 @@
#ifndef _STREAM_H
#define _STREAM_H
#ifndef __MINGW32__
#include <sys/socket.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

2
src/tls.c

@ -36,7 +36,9 @@
#include <stdio.h>
#include <stdlib.h> /* malloc() */
#include <string.h> /* strncpy() */
#ifndef __MINGW32__
#include <sys/socket.h>
#endif
#include "tls.h"
#include "protocol.h"

39
src/tunnel.c

@ -29,13 +29,13 @@
#include <strings.h>
#include <unistd.h>
#include <getopt.h>
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -52,6 +52,7 @@
#include "utils.h"
#include "plugin.h"
#include "tunnel.h"
#include "winsock.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
@ -98,8 +99,11 @@ static int no_delay = 0;
static struct ev_signal sigint_watcher;
static struct ev_signal sigterm_watcher;
#ifndef __MINGW32__
static struct ev_signal sigchld_watcher;
#endif
#ifndef __MINGW32__
static int
setnonblocking(int fd)
{
@ -109,6 +113,7 @@ setnonblocking(int fd)
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
int
create_and_bind(const char *addr, const char *port)
@ -738,16 +743,20 @@ signal_cb(EV_P_ ev_signal *w, int revents)
{
if (revents & EV_SIGNAL) {
switch (w->signum) {
#ifndef __MINGW32__
case SIGCHLD:
if (!is_plugin_running())
LOGE("plugin service exit unexpectedly");
else
return;
#endif
case SIGINT:
case SIGTERM:
ev_signal_stop(EV_DEFAULT, &sigint_watcher);
ev_signal_stop(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_stop(EV_DEFAULT, &sigchld_watcher);
#endif
keep_resolving = 0;
ev_unloop(EV_A_ EVUNLOOP_ALL);
}
@ -778,7 +787,9 @@ main(int argc, char **argv)
char *plugin_opts = NULL;
char *plugin_host = NULL;
char *plugin_port = NULL;
#ifndef __MINGW32__
char tmp_port[8];
#endif
int remote_num = 0;
ss_addr_t remote_addr[MAX_REMOTE_NUM];
@ -993,7 +1004,12 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
#ifdef __MINGW32__
winsock_init();
#endif
if (plugin != NULL) {
#ifndef __MINGW32__
uint16_t port = get_local_port();
if (port == 0) {
FATAL("failed to find a free port");
@ -1003,6 +1019,9 @@ main(int argc, char **argv)
plugin_port = tmp_port;
LOGI("plugin \"%s\" enabled", plugin);
#else
FATAL("plugins not implemented in MinGW port");
#endif
}
if (method == NULL) {
@ -1046,6 +1065,7 @@ main(int argc, char **argv)
FATAL("tunnel port is not defined");
}
#ifndef __MINGW32__
if (plugin != NULL) {
int len = 0;
size_t buf_size = 256 * remote_num;
@ -1062,17 +1082,22 @@ main(int argc, char **argv)
FATAL("failed to start the plugin");
}
}
#endif
#ifndef __MINGW32__
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigint_watcher);
ev_signal_start(EV_DEFAULT, &sigterm_watcher);
#ifndef __MINGW32__
ev_signal_init(&sigchld_watcher, signal_cb, SIGCHLD);
ev_signal_start(EV_DEFAULT, &sigchld_watcher);
#endif
// Setup keys
LOGI("initializing ciphers... %s", method);
@ -1149,6 +1174,7 @@ main(int argc, char **argv)
LOGI("TCP relay disabled");
}
#ifndef __MINGW32__
// setuid
if (user != NULL && !run_as(user)) {
FATAL("failed to switch user");
@ -1157,12 +1183,19 @@ main(int argc, char **argv)
if (geteuid() == 0) {
LOGI("running from root user");
}
#endif
ev_run(loop, 0);
#ifndef __MINGW32__
if (plugin != NULL) {
stop_plugin();
}
#endif
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}

19
src/udprelay.c

@ -29,13 +29,13 @@
#include <strings.h>
#include <time.h>
#include <unistd.h>
#ifndef __MINGW32__
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -52,6 +52,7 @@
#include "netutils.h"
#include "cache.h"
#include "udprelay.h"
#include "winsock.h"
#ifdef MODULE_REMOTE
#define MAX_UDP_CONN_NUM 512
@ -105,6 +106,7 @@ static int buf_size = DEFAULT_PACKET_SIZE * 2;
static int server_num = 0;
static server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL };
#ifndef __MINGW32__
static int
setnonblocking(int fd)
{
@ -114,6 +116,7 @@ setnonblocking(int fd)
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
#if defined(MODULE_REMOTE) && defined(SO_BROADCAST)
static int
@ -724,7 +727,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
goto CLEAN_UP;
} else if (r > packet_size) {
if (verbose) {
LOGI("[udp] remote_recv_recvfrom fragmentation, MTU at least be: %zd", r + PACKET_HEADER_SIZE);
LOGI("[udp] remote_recv_recvfrom fragmentation, MTU at least be: " SSIZE_FMT, r + PACKET_HEADER_SIZE);
}
}
@ -798,7 +801,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
if (buf->len > packet_size) {
if (verbose) {
LOGI("[udp] remote_recv_sendto fragmentation, MTU at least be: %zd", buf->len + PACKET_HEADER_SIZE);
LOGI("[udp] remote_recv_sendto fragmentation, MTU at least be: " SSIZE_FMT, buf->len + PACKET_HEADER_SIZE);
}
}
@ -902,7 +905,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
goto CLEAN_UP;
} else if (buf->len > packet_size) {
if (verbose) {
LOGI("[udp] UDP server_recv_recvmsg fragmentation, MTU at least be: %zd", buf->len + PACKET_HEADER_SIZE);
LOGI("[udp] UDP server_recv_recvmsg fragmentation, MTU at least be: " SSIZE_FMT, buf->len + PACKET_HEADER_SIZE);
}
}
@ -924,7 +927,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
goto CLEAN_UP;
} else if (r > packet_size) {
if (verbose) {
LOGI("[udp] server_recv_recvfrom fragmentation, MTU at least be: %zd", r + PACKET_HEADER_SIZE);
LOGI("[udp] server_recv_recvfrom fragmentation, MTU at least be: " SSIZE_FMT, r + PACKET_HEADER_SIZE);
}
}
@ -1208,7 +1211,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
if (buf->len > packet_size) {
if (verbose) {
LOGI("[udp] server_recv_sendto fragmentation, MTU at least be: %zd", buf->len + PACKET_HEADER_SIZE);
LOGI("[udp] server_recv_sendto fragmentation, MTU at least be: " SSIZE_FMT, buf->len + PACKET_HEADER_SIZE);
}
}
@ -1225,7 +1228,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
if (buf->len - addr_header_len > packet_size) {
if (verbose) {
LOGI("[udp] server_recv_sendto fragmentation, MTU at least be: %zd", buf->len - addr_header_len + PACKET_HEADER_SIZE);
LOGI("[udp] server_recv_sendto fragmentation, MTU at least be: " SSIZE_FMT, buf->len - addr_header_len + PACKET_HEADER_SIZE);
}
}

20
src/utils.c

@ -25,12 +25,14 @@
#endif
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifndef __MINGW32__
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
@ -55,12 +57,14 @@ FILE *logfile;
int use_syslog = 0;
#endif
#ifndef __MINGW32__
void
ERROR(const char *s)
{
char *msg = strerror(errno);
LOGE("%s: %s", s, msg);
}
#endif
int use_tty = 1;
@ -102,6 +106,7 @@ ss_isnumeric(const char *s)
int
run_as(const char *user)
{
#ifndef __MINGW32__
if (user[0]) {
/* Convert user to a long integer if it is a non-negative number.
* -1 means it is a user name. */
@ -195,6 +200,9 @@ run_as(const char *user)
}
#endif
}
#else
LOGE("run_as(): not implemented in MinGW port");
#endif
return 1;
}
@ -400,6 +408,7 @@ usage()
void
daemonize(const char *path)
{
#ifndef __MINGW32__
/* Our process ID and Session ID */
pid_t pid, sid;
@ -444,6 +453,9 @@ daemonize(const char *path)
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
#else
LOGE("daemonize(): not implemented in MinGW port");
#endif
}
#ifdef HAVE_SETRLIMIT
@ -478,6 +490,7 @@ set_nofile(int nofile)
char *
get_default_conf(void)
{
#ifndef __MINGW32__
static char sysconf[] = "/etc/shadowsocks-libev/config.json";
static char userconf[PATH_MAX] = { 0 };
char *conf_home;
@ -498,4 +511,7 @@ get_default_conf(void)
// If not, fall back to the system-wide config.
return sysconf;
#else
return "config.json";
#endif
}

48
src/utils.h

@ -87,6 +87,35 @@ extern FILE *logfile;
#else // not LIB_ONLY
#ifdef __MINGW32__
#define USE_TTY()
#define USE_SYSLOG(ident, _cond)
#define USE_LOGFILE(ident)
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
#define LOGI(format, ...) \
do { \
time_t now = time(NULL); \
char timestr[20]; \
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
fprintf(stdout, " %s INFO: " format "\n", timestr, \
## __VA_ARGS__); \
} \
while (0)
#define LOGE(format, ...) \
do { \
time_t now = time(NULL); \
char timestr[20]; \
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
fprintf(stdout, " %s ERROR: " format "\n", timestr, \
## __VA_ARGS__); \
} \
while (0)
#else // not __MINGW32__
#include <syslog.h>
extern int use_tty;
extern int use_syslog;
@ -146,11 +175,30 @@ extern int use_syslog;
} } \
while (0)
#endif // if __MINGW32__
#endif // if LIB_ONLY
#endif // if __ANDROID__
// Workaround for "%z" in Windows printf
#ifdef __MINGW32__
#define SSIZE_FMT "%Id"
#define SIZE_FMT "%Iu"
#else
#define SSIZE_FMT "%zd"
#define SIZE_FMT "%zu"
#endif
#ifdef __MINGW32__
#ifdef ERROR
#undef ERROR
#endif
#define ERROR(s) ss_error(s)
void ss_error(const char *s); // Implemented in winsock.c
#else
void ERROR(const char *s);
#endif
char *ss_itoa(int i);
int ss_isnumeric(const char *s);

75
src/winsock.c

@ -0,0 +1,75 @@
/*
* winsock.c - Windows socket compatibility layer
*
* Copyright (C) 2013 - 2018, Max Lv <max.c.lv@gmail.com>
*
* This file is part of the shadowsocks-libev.
*
* shadowsocks-libev is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* shadowsocks-libev is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with shadowsocks-libev; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifdef __MINGW32__
#include "winsock.h"
#include "utils.h"
void
winsock_init(void)
{
int ret;
WSADATA wsa_data;
ret = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (ret != 0) {
FATAL("Failed to initialize winsock");
}
}
void
winsock_cleanup(void)
{
WSACleanup();
}
int
setnonblocking(SOCKET socket)
{
u_long arg = 1;
return ioctlsocket(socket, FIONBIO, &arg);
}
void
ss_error(const char *s)
{
char *msg = NULL;
DWORD err = WSAGetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&msg, 0, NULL);
if (msg != NULL) {
// Remove trailing newline character
ssize_t len = strlen(msg) - 1;
if (len >= 0 && msg[len] == '\n') {
msg[len] = '\0';
}
LOGE("%s: [%ld] %s", s, err, msg);
LocalFree(msg);
}
}
#endif // __MINGW32__

86
src/winsock.h

@ -0,0 +1,86 @@
/*
* winsock.h - Windows socket compatibility layer
*
* Copyright (C) 2013 - 2018, Max Lv <max.c.lv@gmail.com>
*
* This file is part of the shadowsocks-libev.
*
* shadowsocks-libev is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* shadowsocks-libev is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with shadowsocks-libev; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef _WINSOCK_H
#define _WINSOCK_H
#ifdef __MINGW32__
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
#undef _WIN32_WINNT
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Override error number
#ifdef errno
#undef errno
#endif
#define errno WSAGetLastError()
#ifdef EWOULDBLOCK
#undef EWOULDBLOCK
#endif
#define EWOULDBLOCK WSAEWOULDBLOCK
#ifdef CONNECT_IN_PROGRESS
#undef CONNECT_IN_PROGRESS
#endif
#define CONNECT_IN_PROGRESS WSAEWOULDBLOCK
// Override close function
#define close(fd) closesocket(fd)
// Override MinGW functions
#define setsockopt(a,b,c,d,e) setsockopt(a,b,c,(const char *)(d),e)
#define inet_ntop(a,b,c,d) inet_ntop(a,(void *)(b),c,d)
// Override Windows built-in functions
#ifdef ERROR
#undef ERROR
#endif
#define ERROR(s) ss_error(s)
#ifndef _UTILS_H
void ss_error(const char *s);
#endif
// Missing unistd.h functions
#define sleep(x) Sleep((x) * 1000)
// Winsock compatibility functions
int setnonblocking(SOCKET socket);
void winsock_init(void);
void winsock_cleanup(void);
#endif // __MINGW32__
#endif // _WINSOCK_H
Loading…
Cancel
Save