Browse Source

Add tcp-fast-open support for ss-redir

pull/1379/head
lqs 7 years ago
committed by Max Lv
parent
commit
fda287d76f
3 changed files with 102 additions and 17 deletions
  1. 115
      src/redir.c
  2. 2
      src/redir.h
  3. 2
      src/utils.c

115
src/redir.c

@ -97,6 +97,7 @@ static int mode = TCP_ONLY;
#ifdef HAVE_SETRLIMIT
static int nofile = 0;
#endif
static int fast_open = 0;
static struct ev_signal sigint_watcher;
static struct ev_signal sigterm_watcher;
@ -191,6 +192,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
server_t *server = server_recv_ctx->server;
remote_t *remote = server->remote;
ev_timer_stop(EV_A_ & server->delayed_connect_watcher);
ssize_t r = recv(server->fd, remote->buf->data + remote->buf->len,
BUF_SIZE - remote->buf->len, 0);
@ -332,6 +335,28 @@ server_send_cb(EV_P_ ev_io *w, int revents)
}
}
static void
delayed_connect_cb(EV_P_ ev_timer *watcher, int revents)
{
server_t *server = cork_container_of(watcher, server_t,
delayed_connect_watcher);
remote_t *remote = server->remote;
int r = connect(remote->fd, remote->addr,
get_sockaddr_len(remote->addr));
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else {
// listen to remote connected event
ev_io_start(EV_A_ & remote->send_ctx->io);
ev_timer_start(EV_A_ & remote->send_ctx->watcher);
}
}
static void
remote_timeout_cb(EV_P_ ev_timer *watcher, int revents)
{
@ -426,10 +451,13 @@ remote_send_cb(EV_P_ ev_io *w, int revents)
server_t *server = remote->server;
if (!remote_send_ctx->connected) {
struct sockaddr_storage addr;
memset(&addr, 0, sizeof(struct sockaddr_storage));
socklen_t len = sizeof addr;
int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
int r = 0;
if (remote->addr == NULL) {
struct sockaddr_storage addr;
memset(&addr, 0, sizeof(struct sockaddr_storage));
socklen_t len = sizeof addr;
r = getpeername(remote->fd, (struct sockaddr *)&addr, &len);
}
if (r == 0) {
remote_send_ctx->connected = 1;
ev_io_stop(EV_A_ & remote_send_ctx->io);
@ -516,8 +544,37 @@ remote_send_cb(EV_P_ ev_io *w, int revents)
return;
} else {
// has data to send
ssize_t s = send(remote->fd, remote->buf->data + remote->buf->idx,
remote->buf->len, 0);
ssize_t s;
if (remote->addr != NULL) {
s = sendto(remote->fd, remote->buf->data + remote->buf->idx,
remote->buf->len, MSG_FASTOPEN, remote->addr,
get_sockaddr_len(remote->addr));
if (s == -1 && (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT ||
errno == ENOPROTOOPT)) {
fast_open = 0;
LOGE("fast open is not supported on this platform");
s = connect(remote->fd, remote->addr,
get_sockaddr_len(remote->addr));
}
remote->addr = NULL;
if (s == -1) {
if (errno == CONNECT_IN_PROGRESS || errno == EAGAIN
|| errno == EWOULDBLOCK) {
ev_io_start(EV_A_ & remote_send_ctx->io);
ev_timer_start(EV_A_ & remote_send_ctx->watcher);
return;
} else {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
}
} else {
s = send(remote->fd, remote->buf->data + remote->buf->idx,
remote->buf->len, 0);
}
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("send");
@ -626,6 +683,9 @@ new_server(int fd)
ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);
ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);
ev_timer_init(&server->delayed_connect_watcher, delayed_connect_cb, 0.05,
0);
return server;
}
@ -661,6 +721,7 @@ close_and_free_server(EV_P_ server_t *server)
if (server != NULL) {
ev_io_stop(EV_A_ & server->send_ctx->io);
ev_io_stop(EV_A_ & server->recv_ctx->io);
ev_timer_stop(EV_A_ & server->delayed_connect_watcher);
close(server->fd);
free_server(server);
}
@ -736,18 +797,23 @@ accept_cb(EV_P_ ev_io *w, int revents)
remote->server = server;
server->destaddr = destaddr;
int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));
if (fast_open) {
// save remote addr for fast open
remote->addr = remote_addr;
ev_timer_start(EV_A_ & server->delayed_connect_watcher);
} else {
int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr));
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
if (r == -1 && errno != CONNECT_IN_PROGRESS) {
ERROR("connect");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
// listen to remote connected event
ev_io_start(EV_A_ & remote->send_ctx->io);
ev_timer_start(EV_A_ & remote->send_ctx->watcher);
}
// listen to remote connected event
ev_io_start(EV_A_ & remote->send_ctx->io);
ev_timer_start(EV_A_ & remote->send_ctx->watcher);
ev_io_start(EV_A_ & server->recv_ctx->io);
}
@ -803,6 +869,7 @@ main(int argc, char **argv)
char *remote_port = NULL;
static struct option long_options[] = {
{ "fast-open", no_argument, NULL, GETOPT_VAL_FAST_OPEN },
{ "mtu", required_argument, NULL, GETOPT_VAL_MTU },
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
@ -821,6 +888,9 @@ main(int argc, char **argv)
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A",
long_options, NULL)) != -1) {
switch (c) {
case GETOPT_VAL_FAST_OPEN:
fast_open = 1;
break;
case GETOPT_VAL_MTU:
mtu = atoi(optarg);
LOGI("set MTU to %d", mtu);
@ -968,6 +1038,9 @@ main(int argc, char **argv)
if (reuse_port == 0) {
reuse_port = conf->reuse_port;
}
if (fast_open == 0) {
fast_open = conf->fast_open;
}
#ifdef HAVE_SETRLIMIT
if (nofile == 0) {
nofile = conf->nofile;
@ -1018,6 +1091,16 @@ main(int argc, char **argv)
local_addr = "127.0.0.1";
}
if (fast_open == 1) {
#ifdef TCP_FASTOPEN
LOGI("using tcp fast open");
#else
LOGE("tcp fast open is not supported by this environment");
fast_open = 0;
#endif
}
if (pid_flags) {
USE_SYSLOG(argv[0]);
daemonize(pid_path);

2
src/redir.h

@ -61,6 +61,7 @@ typedef struct server {
size_t hostname_len;
struct sockaddr_storage destaddr;
ev_timer delayed_connect_watcher;
} server_t;
typedef struct remote_ctx {
@ -77,6 +78,7 @@ typedef struct remote {
struct remote_ctx *send_ctx;
struct server *server;
uint32_t counter;
struct sockaddr *addr;
} remote_t;
#endif // _REDIR_H

2
src/utils.c

@ -345,7 +345,7 @@ usage()
#endif
printf(
" [--reuse-port] Enable port reuse.\n");
#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL)
#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL) || defined(MODULE_REDIR)
printf(
" [--fast-open] Enable TCP fast open.\n");
printf(

Loading…
Cancel
Save