Browse Source

Fix #972

pull/979/head
Max Lv 8 years ago
parent
commit
fd388e0502
3 changed files with 33 additions and 27 deletions
  1. 7
      src/common.h
  2. 15
      src/local.c
  3. 38
      src/server.c

7
src/common.h

@ -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

15
src/local.c

@ -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;

38
src/server.c

@ -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;

Loading…
Cancel
Save