Add initial support for native win32 platform

Should be built against MinGW, and please note that
only ss-local is ported due to lack win32 support of
libasyncns. And libev doesn't support IOCP but only
supports select
This commit is contained in:
Linus Yang
2013-09-09 20:59:22 +08:00
parent df1b991d11
commit 21b9258d77
18 changed files with 490 additions and 47 deletions
+10 -1
View File
@@ -6,7 +6,12 @@ AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
bin_PROGRAMS = ss-local ss-server
bin_PROGRAMS = ss-local
if !BUILD_WINCOMPAT
bin_PROGRAMS += ss-server
endif
ss_local_SOURCES = utils.c \
jconf.c \
json.c \
@@ -28,6 +33,10 @@ ss_server_LDADD += $(top_builddir)/libasyncns/libasyncns.la
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
if BUILD_WINCOMPAT
ss_local_SOURCES += win32.c
endif
if BUILD_REDIRECTOR
bin_PROGRAMS += ss-redir
ss_redir_SOURCES = utils.c \
+30 -14
View File
@@ -34,8 +34,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = ss-local$(EXEEXT) ss-server$(EXEEXT) $(am__EXEEXT_1)
@BUILD_REDIRECTOR_TRUE@am__append_1 = ss-redir
bin_PROGRAMS = ss-local$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
@BUILD_WINCOMPAT_FALSE@am__append_1 = ss-server
@BUILD_WINCOMPAT_TRUE@am__append_2 = win32.c
@BUILD_REDIRECTOR_TRUE@am__append_3 = ss-redir
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -51,13 +53,18 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
@BUILD_REDIRECTOR_TRUE@am__EXEEXT_1 = ss-redir$(EXEEXT)
@BUILD_WINCOMPAT_FALSE@am__EXEEXT_1 = ss-server$(EXEEXT)
@BUILD_REDIRECTOR_TRUE@am__EXEEXT_2 = ss-redir$(EXEEXT)
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am__ss_local_SOURCES_DIST = utils.c jconf.c json.c encrypt.c \
udprelay.c cache.c local.c win32.c
@BUILD_WINCOMPAT_TRUE@am__objects_1 = ss_local-win32.$(OBJEXT)
am_ss_local_OBJECTS = ss_local-utils.$(OBJEXT) \
ss_local-jconf.$(OBJEXT) ss_local-json.$(OBJEXT) \
ss_local-encrypt.$(OBJEXT) ss_local-udprelay.$(OBJEXT) \
ss_local-cache.$(OBJEXT) ss_local-local.$(OBJEXT)
ss_local-cache.$(OBJEXT) ss_local-local.$(OBJEXT) \
$(am__objects_1)
ss_local_OBJECTS = $(am_ss_local_OBJECTS)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = $(top_builddir)/libev/libev.la \
@@ -96,8 +103,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES)
DIST_SOURCES = $(ss_local_SOURCES) $(am__ss_redir_SOURCES_DIST) \
$(ss_server_SOURCES)
DIST_SOURCES = $(am__ss_local_SOURCES_DIST) \
$(am__ss_redir_SOURCES_DIST) $(ss_server_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -223,14 +230,8 @@ AM_CFLAGS = -g -O2 -Wall -fno-strict-aliasing -I$(top_builddir)/libev \
-I$(top_builddir)/libasyncns
AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
ss_local_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
local.c
ss_local_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c cache.c \
local.c $(am__append_2)
ss_server_SOURCES = utils.c \
jconf.c \
json.c \
@@ -355,6 +356,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_local-local.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_local-udprelay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_local-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_local-win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-cache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-encrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-jconf.Po@am__quote@
@@ -483,6 +485,20 @@ ss_local-local.obj: local.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_local_CFLAGS) $(CFLAGS) -c -o ss_local-local.obj `if test -f 'local.c'; then $(CYGPATH_W) 'local.c'; else $(CYGPATH_W) '$(srcdir)/local.c'; fi`
ss_local-win32.o: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_local_CFLAGS) $(CFLAGS) -MT ss_local-win32.o -MD -MP -MF $(DEPDIR)/ss_local-win32.Tpo -c -o ss_local-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_local-win32.Tpo $(DEPDIR)/ss_local-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_local-win32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_local_CFLAGS) $(CFLAGS) -c -o ss_local-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
ss_local-win32.obj: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_local_CFLAGS) $(CFLAGS) -MT ss_local-win32.obj -MD -MP -MF $(DEPDIR)/ss_local-win32.Tpo -c -o ss_local-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_local-win32.Tpo $(DEPDIR)/ss_local-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_local-win32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_local_CFLAGS) $(CFLAGS) -c -o ss_local-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
ss_server-utils.o: utils.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.o -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po
+13
View File
@@ -3,7 +3,20 @@
#include "config.h"
#ifndef __MINGW32__
#include <sys/socket.h>
#else
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+4
View File
@@ -17,7 +17,11 @@ static char *to_string(const json_value *value)
}
else if (value->type == json_integer)
{
#ifdef __MINGW32__
return strdup(ss_itoa(value->u.integer));
#else
return strdup(itoa(value->u.integer));
#endif
}
else if (value->type == json_null)
{
+33 -15
View File
@@ -1,18 +1,21 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -23,6 +26,10 @@
#define SET_INTERFACE
#endif
#ifdef __MINGW32__
#include "win32.h"
#endif
#include "utils.h"
#include "local.h"
#include "socks5.h"
@@ -42,6 +49,7 @@
int verbose = 0;
int udprelay = 0;
#ifndef __MINGW32__
static int setnonblocking(int fd)
{
int flags;
@@ -49,6 +57,7 @@ static int setnonblocking(int fd)
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
#ifdef SET_INTERFACE
int setinterface(int socket_fd, const char* interface_name)
@@ -213,13 +222,13 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
{
struct socks5_request *request = (struct socks5_request *)remote->buf;
struct sockaddr_in s_addr;
memset(&s_addr, 0, sizeof(s_addr));
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
if (udprelay && request->cmd == 3)
{
socklen_t addr_len = sizeof(s_addr);
getsockname(server->fd, (struct sockaddr *)&s_addr,
socklen_t addr_len = sizeof(sock_addr);
getsockname(server->fd, (struct sockaddr *)&sock_addr,
&addr_len);
if (verbose)
{
@@ -338,11 +347,11 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
response.atyp = 1;
memcpy(server->buf, &response, sizeof(struct socks5_response));
memcpy(server->buf + sizeof(struct socks5_response), &s_addr.sin_addr, sizeof(s_addr.sin_addr));
memcpy(server->buf + sizeof(struct socks5_response) + sizeof(s_addr.sin_addr),
&s_addr.sin_port, sizeof(s_addr.sin_port));
memcpy(server->buf + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr));
memcpy(server->buf + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr),
&sock_addr.sin_port, sizeof(sock_addr.sin_port));
int reply_size = sizeof(struct socks5_response) + sizeof(s_addr.sin_addr) + sizeof(s_addr.sin_port);
int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port);
int s = send(server->fd, server->buf, reply_size, 0);
if (s < reply_size)
{
@@ -884,12 +893,16 @@ int main (int argc, char **argv)
demonize(pid_path);
}
#ifdef __MINGW32__
winsock_init();
#else
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
// Setup keys
LOGD("initialize cihpers... %s", method);
LOGD("initialize ciphers... %s", method);
int m = enc_init(password, method);
// Setup socket
@@ -937,6 +950,11 @@ int main (int argc, char **argv)
}
ev_run (loop, 0);
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}
+17 -8
View File
@@ -1,19 +1,22 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#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 <netinet/tcp.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -24,6 +27,10 @@
#define SET_INTERFACE
#endif
#ifdef __MINGW32__
#include "win32.h"
#endif
#include <openssl/md5.h>
#include "utils.h"
@@ -51,6 +58,7 @@ static char *iface;
static int remote_conn = 0;
static int server_conn = 0;
#ifndef __MINGW32__
static int setnonblocking(int fd)
{
int flags;
@@ -58,6 +66,7 @@ static int setnonblocking(int fd)
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
#ifdef SET_INTERFACE
static int setinterface(int socket_fd, const char* interface_name)
@@ -740,11 +749,11 @@ int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_REMOTE
asyncns_t *asyncns,
#endif
int method, const char *interface)
int method, const char *interface_name)
{
iface = interface;
iface = interface_name;
// Inilitialize ev loop
struct ev_loop *loop = EV_DEFAULT;
+1 -1
View File
@@ -79,6 +79,6 @@ int udprelay(const char *server_host, const char *server_port,
#ifdef UDPRELAY_REMOTE
asyncns_t *asyncns,
#endif
int method, const char *interface);
int method, const char *interface_name);
#endif // _UDPRELAY_H
+8 -3
View File
@@ -1,9 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -16,14 +14,20 @@
#define INT_DIGITS 19 /* enough for 64 bit integer */
#ifndef __MINGW32__
void ERROR(const char *s)
{
char *msg = strerror(errno);
LOGE("%s: %s", s, msg);
}
#endif
#ifdef __MINGW32__
char *ss_itoa(int i)
#else
char *itoa(int i)
#endif
{
/* Room for INT_DIGITS digits, - and '\0' */
static char buf[INT_DIGITS + 2];
@@ -103,7 +107,7 @@ void usage()
void demonize(const char* path)
{
#ifndef __MINGW32__
/* Our process ID and Session ID */
pid_t pid, sid;
@@ -150,5 +154,6 @@ void demonize(const char* path)
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
#endif
}
+43 -2
View File
@@ -1,6 +1,9 @@
#ifndef _UTILS_H
#define _UTILS_H
#include <stdio.h>
#include <time.h>
#ifdef ANDROID
#include <android/log.h>
@@ -12,6 +15,27 @@
#define STR(x) #x
#define TOSTR(x) STR(x)
#ifdef _WIN32
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
#define LOGD(format, ...) do {\
time_t now = time(NULL);\
char timestr[20];\
strftime(timestr, 20, TIME_FORMAT, localtime(&now));\
fprintf(stderr, " %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(stderr, " %s ERROR: " format "\n", timestr, ##__VA_ARGS__);}\
while(0)
#else
#define TIME_FORMAT "%F %T"
#define LOGD(format, ...) do {\
@@ -28,13 +52,30 @@ while(0)
fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format "\n", timestr, ##__VA_ARGS__);}\
while(0)
#endif
/* _WIN32 */
#endif
#ifdef __MINGW32__
#ifdef ERROR
#undef ERROR
#endif
#define ERROR(s) ss_error(s)
char *ss_itoa(int i);
#else
void ERROR(const char *s);
char *itoa(int i);
#endif
void FATAL(const char *msg);
void ERROR(const char *s);
void usage(void);
void demonize(const char* path);
char *itoa(int i);
char *ss_strndup(const char *s, size_t n);
#endif // _UTILS_H
+75
View File
@@ -0,0 +1,75 @@
#include "win32.h"
#ifdef setsockopt
#undef setsockopt
#endif
void winsock_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int ret;
wVersionRequested = MAKEWORD(1, 1);
ret = WSAStartup(wVersionRequested, &wsaData);
if (ret != 0) {
FATAL("Could not initialize winsock");
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
WSACleanup();
FATAL("Could not find a usable version of winsock");
}
}
void winsock_cleanup(void)
{
WSACleanup();
}
void ss_error(const char *s)
{
LPVOID *msg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msg, 0, NULL);
if (msg != NULL) {
LOGE("%s: %s", s, msg);
LocalFree(msg);
}
}
int setnonblocking(int fd)
{
u_long iMode = 0;
int iResult;
iResult = ioctlsocket(fd, FIONBIO, &iMode);
if (iResult != NO_ERROR) {
LOGE("ioctlsocket failed with error: %ld\n", iResult);
}
return iResult;
}
size_t strnlen(const char *s, size_t maxlen)
{
const char *end = memchr(s, 0, maxlen);
return end ? (size_t) (end - s) : maxlen;
}
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
struct sockaddr_storage ss;
unsigned long s = size;
ZeroMemory(&ss, sizeof(ss));
ss.ss_family = af;
switch (af) {
case AF_INET:
((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
break;
case AF_INET6:
((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
break;
default:
return NULL;
}
return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0) ? dst : NULL;
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef _WIN32_H
#define _WIN32_H
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
#include "utils.h"
#ifdef EWOULDBLOCK
#undef EWOULDBLOCK
#endif
#ifdef errno
#undef errno
#endif
#ifdef ERROR
#undef ERROR
#endif
#define EWOULDBLOCK WSAEWOULDBLOCK
#define errno WSAGetLastError()
#define close(fd) closesocket(fd)
#define ERROR(s) ss_error(s)
#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (char *) (d), e)
void winsock_init(void);
void winsock_cleanup(void);
void ss_error(const char *s);
size_t strnlen(const char *s, size_t maxlen);
#endif