Browse Source

Add mptcp option, close #756

pull/760/head
Max Lv 8 years ago
parent
commit
d319c0300c
16 changed files with 160 additions and 40 deletions
  1. 5
      doc/ss-local.asciidoc
  2. 5
      doc/ss-redir.asciidoc
  3. 5
      doc/ss-server.asciidoc
  4. 5
      doc/ss-tunnel.asciidoc
  5. 6
      src/jconf.c
  6. 3
      src/jconf.h
  7. 43
      src/local.c
  8. 1
      src/local.h
  9. 5
      src/netutils.h
  10. 45
      src/redir.c
  11. 1
      src/redir.h
  12. 34
      src/server.c
  13. 2
      src/shadowsocks.h
  14. 37
      src/tunnel.c
  15. 1
      src/tunnel.h
  16. 2
      src/utils.c

5
doc/ss-local.asciidoc

@ -105,6 +105,11 @@ Enable ACL (Access Control List) and specify config file.
--mtu <MTU>::
Specify the MTU of your network interface.
--mptcp::
Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
-v::
Enable verbose mode.

5
doc/ss-redir.asciidoc

@ -92,6 +92,11 @@ Enable onetime authentication.
--mtu <MTU>::
Specify the MTU of your network interface.
--mptcp::
Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
-v::
Enable verbose mode.

5
doc/ss-server.asciidoc

@ -118,6 +118,11 @@ Only available in server and manager mode.
--mtu <MTU>::
Specify the MTU of your network interface.
--mptcp::
Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
-v::
Enable verbose mode.

5
doc/ss-tunnel.asciidoc

@ -103,6 +103,11 @@ Only used and available in tunnel mode.
--mtu <MTU>::
Specify the MTU of your network interface.
--mptcp::
Enable Multipath TCP.
+
Only available with MPTCP enabled Linux kernel.
-v::
Enable verbose mode.

6
src/jconf.c

@ -99,6 +99,8 @@ jconf_t *read_jconf(const char *file)
{
static jconf_t conf;
memset(&conf, 0, sizeof(jconf_t));
char *buf;
json_value *obj;
@ -206,6 +208,10 @@ jconf_t *read_jconf(const char *file)
LOGI("ignore unknown mode: %s, use tcp_only as fallback",
mode_str);
free(mode_str);
} else if (strcmp(name, "mtu") == 0) {
conf.mtu = value->u.integer;
} else if (strcmp(name, "mptcp") == 0) {
conf.mptcp = value->u.boolean;
}
}
} else {

3
src/jconf.h

@ -33,7 +33,6 @@
#define TCP_AND_UDP 1
#define UDP_ONLY 3
typedef struct {
char *host;
char *port;
@ -61,6 +60,8 @@ typedef struct {
char *nameserver;
char *tunnel_address;
int mode;
int mtu;
int mptcp;
} jconf_t;
jconf_t *read_jconf(const char *file);

43
src/local.c

@ -218,7 +218,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -280,7 +280,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
// connecting, wait until connected
int r = connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len);
if (r < 0 && errno != CONNECT_IN_PROGRESS) {
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
@ -587,7 +587,7 @@ static void server_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(server->fd, server->buf->array + server->buf->idx,
server->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("server_send_cb_send");
close_and_free_remote(EV_A_ remote);
@ -656,7 +656,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -750,7 +750,7 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
remote->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("remote_send_cb_send");
// close and free
@ -911,7 +911,7 @@ static remote_t *create_remote(listen_ctx_t *listener,
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (remotefd < 0) {
if (remotefd == -1) {
ERROR("socket");
return NULL;
}
@ -922,6 +922,13 @@ static remote_t *create_remote(listen_ctx_t *listener,
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
if (listener->mptcp == 1) {
int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
}
}
// Setup
setnonblocking(remotefd);
#ifdef SET_INTERFACE
@ -982,7 +989,8 @@ int main(int argc, char **argv)
{
int i, c;
int pid_flags = 0;
int mtu = 0;
int mtu = 0;
int mptcp = 0;
char *user = NULL;
char *local_port = NULL;
char *local_addr = NULL;
@ -1004,6 +1012,7 @@ int main(int argc, char **argv)
{ "fast-open", no_argument , 0, 0 },
{ "acl" , required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "mptcp" , no_argument , 0, 0 },
{ "help" , no_argument , 0, 0 },
{ 0, 0, 0, 0 }
};
@ -1028,8 +1037,11 @@ int main(int argc, char **argv)
acl = !init_acl(optarg, BLACK_LIST);
} else if (option_index == 2) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
LOGI("set MTU to %d", mtu);
} else if (option_index == 3) {
mptcp = 1;
LOGI("enable multipath TCP");
} else if (option_index == 4) {
usage();
exit(EXIT_SUCCESS);
}
@ -1150,6 +1162,12 @@ int main(int argc, char **argv)
if (mode == TCP_ONLY) {
mode = conf->mode;
}
if (mtu == 0) {
mtu = conf->mtu;
}
if (mptcp == 0) {
mptcp = conf->mptcp;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;
@ -1230,6 +1248,7 @@ int main(int argc, char **argv)
listen_ctx.timeout = atoi(timeout);
listen_ctx.iface = iface;
listen_ctx.method = m;
listen_ctx.mptcp = mptcp;
// Setup signal handler
struct ev_signal sigint_watcher;
@ -1245,7 +1264,7 @@ int main(int argc, char **argv)
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port);
if (listenfd < 0) {
if (listenfd == -1) {
FATAL("bind() error");
}
if (listen(listenfd, SOMAXCONN) == -1) {
@ -1324,11 +1343,14 @@ int start_ss_local_server(profile_t profile)
int local_port = profile.local_port;
int timeout = profile.timeout;
int mtu = 0;
int mptcp = 0;
auth = profile.auth;
mode = profile.mode;
fast_open = profile.fast_open;
verbose = profile.verbose;
mtu = profile.mtu;
mptcp = profile.mptcp;
char local_port_str[16];
char remote_port_str[16];
@ -1385,13 +1407,14 @@ int start_ss_local_server(profile_t profile)
listen_ctx.timeout = timeout;
listen_ctx.method = m;
listen_ctx.iface = NULL;
listen_ctx.mptcp = mptcp;
if (mode != UDP_ONLY) {
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port_str);
if (listenfd < 0) {
if (listenfd == -1) {
ERROR("bind()");
return -1;
}

1
src/local.h

@ -38,6 +38,7 @@ typedef struct listen_ctx {
int method;
int timeout;
int fd;
int mptcp;
struct sockaddr **remote_addr;
} listen_ctx_t;

5
src/netutils.h

@ -23,6 +23,11 @@
#ifndef _NETUTILS_H
#define _NETUTILS_H
/* Define the flag MPTCP_ENABLED if not defined*/
#ifndef MPTCP_ENABLED
#define MPTCP_ENABLED 26
#endif
/** byte size of ip4 address */
#define INET_SIZE 4
/** byte size of ip6 address */

45
src/redir.c

@ -181,7 +181,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -273,7 +273,7 @@ static void server_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(server->fd, server->buf->array + server->buf->idx,
server->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("send");
close_and_free_remote(EV_A_ remote);
@ -321,7 +321,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -451,7 +451,7 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
remote->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("send");
// close and free
@ -622,11 +622,12 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (remotefd < 0) {
if (remotefd == -1) {
ERROR("socket");
return;
}
// Set flags
setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
@ -642,9 +643,17 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
setsockopt(remotefd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(remotefd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
// Setup
// Set non blocking
setnonblocking(remotefd);
// Enable MPTCP
if (listener->mptcp == 1) {
int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
}
}
server_t *server = new_server(serverfd, listener->method);
remote_t *remote = new_remote(remotefd, listener->timeout);
server->remote = remote;
@ -653,7 +662,7 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));
if (r < 0 && errno != CONNECT_IN_PROGRESS) {
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
@ -683,6 +692,7 @@ int main(int argc, char **argv)
int i, c;
int pid_flags = 0;
int mptcp = 0;
int mtu = 0;
char *user = NULL;
char *local_port = NULL;
@ -699,9 +709,10 @@ int main(int argc, char **argv)
int option_index = 0;
static struct option long_options[] = {
{ "mtu", required_argument, 0, 0 },
{ "help", no_argument , 0, 0 },
{ 0, 0 , 0, 0 }
{ "mtu", required_argument, 0, 0 },
{ "mptcp", no_argument , 0, 0 },
{ "help", no_argument , 0, 0 },
{ 0, 0 , 0, 0 }
};
opterr = 0;
@ -712,8 +723,11 @@ int main(int argc, char **argv)
case 0:
if (option_index == 0) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
LOGI("set MTU to %d", mtu);
} else if (option_index == 1) {
mptcp = 1;
LOGI("enable multipath TCP");
} else if (option_index == 2) {
usage();
exit(EXIT_SUCCESS);
}
@ -818,6 +832,12 @@ int main(int argc, char **argv)
if (auth == 0) {
auth = conf->auth;
}
if (mtu == 0) {
mtu = conf->mtu;
}
if (mptcp == 0) {
mptcp = conf->mptcp;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;
@ -885,6 +905,7 @@ int main(int argc, char **argv)
}
listen_ctx.timeout = atoi(timeout);
listen_ctx.method = m;
listen_ctx.mptcp = mptcp;
struct ev_loop *loop = EV_DEFAULT;
@ -892,7 +913,7 @@ int main(int argc, char **argv)
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port);
if (listenfd < 0) {
if (listenfd == -1) {
FATAL("bind() error");
}
if (listen(listenfd, SOMAXCONN) == -1) {

1
src/redir.h

@ -33,6 +33,7 @@ typedef struct listen_ctx {
int timeout;
int fd;
int method;
int mptcp;
struct sockaddr **remote_addr;
} listen_ctx_t;

34
src/server.c

@ -303,7 +303,7 @@ int setnonblocking(int fd)
#endif
int create_and_bind(const char *host, const char *port)
int create_and_bind(const char *host, const char *port, int mptcp)
{
struct addrinfo hints;
struct addrinfo *result, *rp, *ipv4v6bindall;
@ -372,6 +372,13 @@ int create_and_bind(const char *host, const char *port)
LOGI("port reuse enabled");
}
if (mptcp == 1) {
int err = setsockopt(listen_sock, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
}
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
/* We managed to bind successfully! */
@ -404,7 +411,7 @@ static remote_t *connect_to_remote(struct addrinfo *res,
// initialize remote socks
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) {
if (sockfd == -1) {
ERROR("socket");
close(sockfd);
return NULL;
@ -484,7 +491,7 @@ static remote_t *connect_to_remote(struct addrinfo *res,
if (!fast_open) {
int r = connect(sockfd, res->ai_addr, res->ai_addrlen);
if (r < 0 && errno != CONNECT_IN_PROGRESS) {
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close(sockfd);
return NULL;
@ -859,7 +866,7 @@ static void server_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(server->fd, server->buf->array + server->buf->idx,
server->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("server_send_send");
close_and_free_remote(EV_A_ remote);
@ -995,7 +1002,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -1338,6 +1345,7 @@ int main(int argc, char **argv)
{
int i, c;
int pid_flags = 0;
int mptcp = 0;
int mtu = 0;
char *user = NULL;
char *password = NULL;
@ -1360,6 +1368,7 @@ int main(int argc, char **argv)
{ "acl" , required_argument, 0, 0 },
{ "manager-address", required_argument, 0, 0 },
{ "mtu" , required_argument, 0, 0 },
{ "mptcp" , no_argument , 0, 0 },
{ "help" , no_argument , 0, 0 },
{ 0, 0, 0, 0 }
};
@ -1382,8 +1391,11 @@ int main(int argc, char **argv)
manager_address = optarg;
} else if (option_index == 3) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
LOGI("set MTU to %d", mtu);
} else if (option_index == 4) {
mptcp = 1;
LOGI("enable multipath TCP");
} else if (option_index == 5) {
usage();
exit(EXIT_SUCCESS);
}
@ -1497,6 +1509,12 @@ int main(int argc, char **argv)
if (mode == TCP_ONLY) {
mode = conf->mode;
}
if (mtu == 0) {
mtu = conf->mtu;
}
if (mptcp == 0) {
mptcp = conf->mptcp;
}
#ifdef TCP_FASTOPEN
if (fast_open == 0) {
fast_open = conf->fast_open;
@ -1617,8 +1635,8 @@ int main(int argc, char **argv)
if (mode != UDP_ONLY) {
// Bind to port
int listenfd;
listenfd = create_and_bind(host, server_port);
if (listenfd < 0) {
listenfd = create_and_bind(host, server_port, mptcp);
if (listenfd == -1) {
FATAL("bind() error");
}
if (listen(listenfd, SSMAXCONN) == -1) {

2
src/shadowsocks.h

@ -38,6 +38,8 @@ typedef struct {
int fast_open; // enable tcp fast open
int mode; // enable udp relay
int auth; // enable one-time authentication
int mtu; // MTU of interface
int mptcp; // enable multipath TCP
int verbose; // verbose mode
} profile_t;

37
src/tunnel.c

@ -183,7 +183,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -249,7 +249,7 @@ static void server_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(server->fd, server->buf->array + server->buf->idx,
server->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("send");
close_and_free_remote(EV_A_ remote);
@ -307,7 +307,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else if (r < 0) {
} else if (r == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// no data
// continue to wait for recv
@ -465,7 +465,7 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
// has data to send
ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx,
remote->buf->len, 0);
if (s < 0) {
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("send");
// close and free
@ -627,7 +627,7 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (remotefd < 0) {
if (remotefd == -1) {
ERROR("socket");
return;
}
@ -647,6 +647,13 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
if (listener->mptcp == 1) {
int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
}
}
// Setup
setnonblocking(remotefd);
#ifdef SET_INTERFACE
@ -664,7 +671,7 @@ static void accept_cb(EV_P_ ev_io *w, int revents)
int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));
if (r < 0 && errno != CONNECT_IN_PROGRESS) {
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
@ -692,7 +699,8 @@ int main(int argc, char **argv)
int i, c;
int pid_flags = 0;
int mtu = 0;
int mptcp = 0;
int mtu = 0;
char *user = NULL;
char *local_port = NULL;
char *local_addr = NULL;
@ -713,6 +721,7 @@ int main(int argc, char **argv)
int option_index = 0;
static struct option long_options[] = {
{ "mtu", required_argument, 0, 0 },
{ "mptcp",no_argument, 0, 0 },
{ "help", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
};
@ -732,8 +741,11 @@ int main(int argc, char **argv)
case 0:
if (option_index == 0) {
mtu = atoi(optarg);
LOGI("Set MTU to %d", mtu);
LOGI("set MTU to %d", mtu);
} else if (option_index == 1) {
mptcp = 1;
LOGI("enable multipath TCP");
} else if (option_index == 2) {
usage();
exit(EXIT_SUCCESS);
}
@ -858,6 +870,12 @@ int main(int argc, char **argv)
if (mode == TCP_ONLY) {
mode = conf->mode;
}
if (mtu == 0) {
mtu = conf->mtu;
}
if (mptcp == 0) {
mptcp = conf->mptcp;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;
@ -938,6 +956,7 @@ int main(int argc, char **argv)
listen_ctx.timeout = atoi(timeout);
listen_ctx.iface = iface;
listen_ctx.method = m;
listen_ctx.mptcp = mptcp;
struct ev_loop *loop = EV_DEFAULT;
@ -945,7 +964,7 @@ int main(int argc, char **argv)
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port);
if (listenfd < 0) {
if (listenfd == -1) {
FATAL("bind() error:");
}
if (listen(listenfd, SOMAXCONN) == -1) {

1
src/tunnel.h

@ -37,6 +37,7 @@ typedef struct listen_ctx {
int method;
int timeout;
int fd;
int mptcp;
struct sockaddr **remote_addr;
} listen_ctx_t;

2
src/utils.c

@ -311,6 +311,8 @@ void usage()
#endif
printf(
" [--mtu <MTU>] MTU of your network interface.\n");
printf(
" [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n");
printf("\n");
printf(
" [-v] Verbose mode.\n");

Loading…
Cancel
Save