mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-28 03:33:42 +00:00
Fix #972
This commit is contained in:
@@ -48,4 +48,11 @@ int protect_socket(int fd);
|
||||
int send_traffic_stat(uint64_t tx, uint64_t rx);
|
||||
#endif
|
||||
|
||||
#define STAGE_ERROR -1 /* Error detected */
|
||||
#define STAGE_INIT 0 /* Initial stage */
|
||||
#define STAGE_HANDSHAKE 1 /* Handshake with client */
|
||||
#define STAGE_PARSE 2 /* Parse the header */
|
||||
#define STAGE_RESOLVE 4 /* Resolve the hostname */
|
||||
#define STAGE_STREAM 5 /* Stream between client and server */
|
||||
|
||||
#endif // _COMMON_H
|
||||
|
||||
+8
-7
@@ -242,7 +242,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
|
||||
while (1) {
|
||||
// local socks5 server
|
||||
if (server->stage == 5) {
|
||||
if (server->stage == STAGE_STREAM) {
|
||||
if (remote == NULL) {
|
||||
LOGE("invalid remote");
|
||||
close_and_free_server(EV_A_ server);
|
||||
@@ -401,13 +401,13 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
|
||||
// all processed
|
||||
return;
|
||||
} else if (server->stage == 0) {
|
||||
} else if (server->stage == STAGE_INIT) {
|
||||
struct method_select_response response;
|
||||
response.ver = SVERSION;
|
||||
response.method = 0;
|
||||
char *send_buf = (char *)&response;
|
||||
send(server->fd, send_buf, sizeof(response), 0);
|
||||
server->stage = 1;
|
||||
server->stage = STAGE_HANDSHAKE;
|
||||
|
||||
int off = (buf->array[1] & 0xff) + 2;
|
||||
if (buf->array[0] == 0x05 && off < (int)(buf->len)) {
|
||||
@@ -419,7 +419,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
buf->len = 0;
|
||||
|
||||
return;
|
||||
} else if (server->stage == 1 || server->stage == 2) {
|
||||
} else if (server->stage == STAGE_HANDSHAKE || server->stage == STAGE_PARSE) {
|
||||
struct socks5_request *request = (struct socks5_request *)buf->array;
|
||||
struct sockaddr_in sock_addr;
|
||||
memset(&sock_addr, 0, sizeof(sock_addr));
|
||||
@@ -449,7 +449,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
// Fake reply
|
||||
if (server->stage == 1) {
|
||||
if (server->stage == STAGE_HANDSHAKE) {
|
||||
struct socks5_response response;
|
||||
response.ver = SVERSION;
|
||||
response.rep = 0;
|
||||
@@ -557,7 +557,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
ret = tls_protocol->parse_packet(buf->array + 3 + abuf->len,
|
||||
buf->len - 3 - abuf->len, &hostname);
|
||||
if (ret == -1) {
|
||||
server->stage = 2;
|
||||
server->stage = STAGE_PARSE;
|
||||
bfree(abuf);
|
||||
return;
|
||||
} else if (ret > 0) {
|
||||
@@ -582,7 +582,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
}
|
||||
|
||||
server->stage = 5;
|
||||
server->stage = STAGE_STREAM;
|
||||
|
||||
buf->len -= (3 + abuf_len);
|
||||
if (buf->len > 0) {
|
||||
@@ -963,6 +963,7 @@ new_server(int fd, int method)
|
||||
server->recv_ctx = ss_malloc(sizeof(server_ctx_t));
|
||||
server->send_ctx = ss_malloc(sizeof(server_ctx_t));
|
||||
server->buf = ss_malloc(sizeof(buffer_t));
|
||||
server->stage = STAGE_INIT;
|
||||
server->recv_ctx->connected = 0;
|
||||
server->send_ctx->connected = 0;
|
||||
server->fd = fd;
|
||||
|
||||
+18
-20
@@ -612,7 +612,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
int len = server->buf->len;
|
||||
buffer_t *buf = server->buf;
|
||||
|
||||
if (server->stage > 2) {
|
||||
if (server->stage > STAGE_PARSE) {
|
||||
remote = server->remote;
|
||||
buf = remote->buf;
|
||||
len = 0;
|
||||
@@ -652,14 +652,14 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
|
||||
tx += r;
|
||||
|
||||
if (server->stage == -1) {
|
||||
if (server->stage == STAGE_ERROR) {
|
||||
server->buf->len = 0;
|
||||
server->buf->idx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// handle incomplete header part 1
|
||||
if (server->stage == 0) {
|
||||
if (server->stage == STAGE_INIT) {
|
||||
buf->len += r;
|
||||
if (buf->len <= enc_get_iv_len() + 1) {
|
||||
// wait for more
|
||||
@@ -679,24 +679,24 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
// handle incomplete header part 2
|
||||
if (server->stage == 0) {
|
||||
if (server->stage == STAGE_INIT) {
|
||||
int ret = is_header_complete(server->buf);
|
||||
if (ret == 1) {
|
||||
bfree(server->header_buf);
|
||||
ss_free(server->header_buf);
|
||||
server->stage = 2;
|
||||
server->stage = STAGE_PARSE;
|
||||
} else if (ret == -1) {
|
||||
server->stage = -1;
|
||||
server->stage = STAGE_ERROR;
|
||||
report_addr(server->fd, MALFORMED);
|
||||
server->buf->len = 0;
|
||||
server->buf->idx = 0;
|
||||
return;
|
||||
} else {
|
||||
server->stage = 1;
|
||||
server->stage = STAGE_HANDSHAKE;
|
||||
}
|
||||
}
|
||||
|
||||
if (server->stage == 1) {
|
||||
if (server->stage == STAGE_HANDSHAKE) {
|
||||
size_t header_len = server->header_buf->len;
|
||||
brealloc(server->header_buf, server->buf->len + header_len, BUF_SIZE);
|
||||
memcpy(server->header_buf->array + header_len,
|
||||
@@ -711,10 +711,10 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
server->buf->len = server->header_buf->len;
|
||||
bfree(server->header_buf);
|
||||
ss_free(server->header_buf);
|
||||
server->stage = 2;
|
||||
server->stage = STAGE_PARSE;
|
||||
} else {
|
||||
if (ret == -1)
|
||||
server->stage = -1;
|
||||
server->stage = STAGE_ERROR;
|
||||
server->buf->len = 0;
|
||||
server->buf->idx = 0;
|
||||
return;
|
||||
@@ -722,7 +722,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
// handshake and transmit data
|
||||
if (server->stage == 5) {
|
||||
if (server->stage == STAGE_STREAM) {
|
||||
if (server->auth && !ss_check_hash(remote->buf, server->chunk, server->d_ctx, BUF_SIZE)) {
|
||||
LOGE("hash error");
|
||||
report_addr(server->fd, BAD);
|
||||
@@ -749,7 +749,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
ev_io_start(EV_A_ & remote->send_ctx->io);
|
||||
}
|
||||
return;
|
||||
} else if (server->stage == 2) {
|
||||
} else if (server->stage == STAGE_PARSE) {
|
||||
/*
|
||||
* Shadowsocks TCP Relay Header:
|
||||
*
|
||||
@@ -963,8 +963,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
server->buf->idx = 0;
|
||||
}
|
||||
|
||||
server->stage = 4;
|
||||
|
||||
// waiting on remote connected event
|
||||
ev_io_stop(EV_A_ & server_recv_ctx->io);
|
||||
ev_io_start(EV_A_ & remote->send_ctx->io);
|
||||
@@ -974,7 +972,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
|
||||
query->server = server;
|
||||
snprintf(query->hostname, 256, "%s", host);
|
||||
|
||||
server->stage = 4;
|
||||
server->stage = STAGE_RESOLVE;
|
||||
server->query = resolv_query(host, server_resolve_cb,
|
||||
query_free_cb, query, port);
|
||||
|
||||
@@ -1060,7 +1058,7 @@ server_timeout_cb(EV_P_ ev_timer *watcher, int revents)
|
||||
LOGI("TCP connection timeout");
|
||||
}
|
||||
|
||||
if (server->stage < 2) {
|
||||
if (server->stage < STAGE_PARSE) {
|
||||
if (verbose) {
|
||||
size_t len = server->stage ?
|
||||
server->header_buf->len : server->buf->len;
|
||||
@@ -1244,7 +1242,7 @@ remote_send_cb(EV_P_ ev_io *w, int revents)
|
||||
reset_addr(server->fd);
|
||||
|
||||
if (remote->buf->len == 0) {
|
||||
server->stage = 5;
|
||||
server->stage = STAGE_STREAM;
|
||||
ev_io_stop(EV_A_ & remote_send_ctx->io);
|
||||
ev_io_start(EV_A_ & server->recv_ctx->io);
|
||||
ev_io_start(EV_A_ & remote->recv_ctx->io);
|
||||
@@ -1291,8 +1289,8 @@ remote_send_cb(EV_P_ ev_io *w, int revents)
|
||||
ev_io_stop(EV_A_ & remote_send_ctx->io);
|
||||
if (server != NULL) {
|
||||
ev_io_start(EV_A_ & server->recv_ctx->io);
|
||||
if (server->stage == 4) {
|
||||
server->stage = 5;
|
||||
if (server->stage != STAGE_STREAM) {
|
||||
server->stage = STAGE_STREAM;
|
||||
ev_io_start(EV_A_ & remote->recv_ctx->io);
|
||||
}
|
||||
} else {
|
||||
@@ -1384,7 +1382,7 @@ new_server(int fd, listen_ctx_t *listener)
|
||||
server->recv_ctx->connected = 0;
|
||||
server->send_ctx->server = server;
|
||||
server->send_ctx->connected = 0;
|
||||
server->stage = 0;
|
||||
server->stage = STAGE_INIT;
|
||||
server->query = NULL;
|
||||
server->listen_ctx = listener;
|
||||
server->remote = NULL;
|
||||
|
||||
Reference in New Issue
Block a user