Browse Source

WiP

pull/14/head
Max Lv 12 years ago
parent
commit
c82ddb4f38
3 changed files with 42 additions and 173 deletions
  1. 3
      src/server.c
  2. 201
      src/udprelay.c
  3. 11
      src/udprelay.h

3
src/server.c

@ -694,9 +694,6 @@ struct server* new_server(int fd, struct listen_ctx *listener) {
void free_server(struct server *server) {
server_conn--;
if (server != NULL) {
if (server->query != NULL) {
free(query);
}
if (server->remote != NULL) {
server->remote->server = NULL;
}

201
src/udprelay.c

@ -173,59 +173,6 @@ struct remote *send_to_remote(struct addrinfo *res, const char *iface) {
return remote;
}
static void server_send_cb (EV_P_ ev_io *w, int revents) {
struct server_ctx *server_send_ctx = (struct server_ctx *)w;
struct server *server = server_send_ctx->server;
struct remote *remote = server->remote;
if (remote == NULL) {
LOGE("invalid server.");
close_and_free_server(EV_A_ server);
return;
}
if (server->buf_len == 0) {
// close and free
if (verbose) {
LOGD("server_send close the connection");
}
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else {
// has data to send
ssize_t s = send(server->fd, server->buf + server->buf_idx,
server->buf_len, 0);
if (s < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("server_send_send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
} else if (s < server->buf_len) {
// partly sent, move memory, wait for the next time to send
server->buf_len -= s;
server->buf_idx += s;
return;
} else {
// all sent out, wait for reading
server->buf_len = 0;
server->buf_idx = 0;
ev_io_stop(EV_A_ &server_send_ctx->io);
if (remote != NULL) {
ev_io_start(EV_A_ &remote->recv_ctx->io);
return;
} else {
LOGE("invalid remote.");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
}
}
static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents) {
struct server *server = (struct server *) (((void*)watcher)
- sizeof(ev_timer));
@ -248,7 +195,7 @@ static void query_resolve_cb(EV_P_ ev_timer *watcher, int revents) {
if (asyncns == NULL || query == NULL) {
LOGE("invalid dns query.");
close_and_free_server(EV_A_ server);
close_and_free_query(EV_A_ quert_ctx);
return;
}
@ -285,41 +232,36 @@ static void query_resolve_cb(EV_P_ ev_timer *watcher, int revents) {
int opt = 1;
int remotefd = create_remote_socket(rp->ai_family == AF_INET6);
if (remotefd < 0) {
ERROR("socket");
close(remotefd);
// release addrinfo
asyncns_freeaddrinfo(result);
return;
}
setnonblocking(remotefd);
if (remotefd != -1) {
setnonblocking(remotefd);
#ifdef SO_NOSIGPIPE
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
#ifdef SET_INTERFACE
if (iface) setinterface(remotefd, iface);
if (iface) setinterface(remotefd, iface);
#endif
struct remote_ctx *remote_ctx = new_remote_ctx(remotefd);
server->remote = remote;
remote->server = server;
struct remote_ctx *remote_ctx = new_remote_ctx(remotefd);
remote_ctx->addr = *rp->ai_addr;
remote_ctx->server_ctx = query_ctx->server_ctx;
// listen to remote connected event
ev_io_start(EV_A_ &remote->send_ctx->io);
ev_io_start(EV_A_ &remote_ctx->io);
} else {
ERROR("socket");
close(remotefd);
}
}
// release addrinfo
asyncns_freeaddrinfo(result);
close_and_free_query(EV_A_ quert_ctx);
}
static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
struct remote_ctx *remote_recv_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_recv_ctx->remote;
struct server *server = remote->server;
struct remote_ctx *remote_ctx = (struct remote_ctx *)w;
struct server_ctx *server_ctx = remote_ctx->server_ctx;
if (server == NULL) {
if (server_ctx == NULL) {
LOGE("invalid server.");
close_and_free_remote(EV_A_ remote);
return;
@ -383,97 +325,13 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
}
}
static void remote_send_cb (EV_P_ ev_io *w, int revents) {
struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_send_ctx->remote;
struct server *server = remote->server;
if (server == NULL) {
LOGE("invalid server.");
close_and_free_remote(EV_A_ remote);
return;
}
if (!remote_send_ctx->connected) {
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
int r = getpeername(remote->fd, (struct sockaddr*)&addr, &len);
if (r == 0) {
if (verbose) {
LOGD("remote connected.");
}
remote_send_ctx->connected = 1;
if (remote->buf_len == 0) {
server->stage = 5;
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);
return;
}
} else {
ERROR("getpeername");
// not connected
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
if (remote->buf_len == 0) {
// close and free
if (verbose) {
LOGD("remote_send close the connection");
}
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else {
// has data to send
ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
remote->buf_len, 0);
if (s == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ERROR("remote_send_send");
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
} else if (s < remote->buf_len) {
// partly sent, move memory, wait for the next time to send
remote->buf_len -= s;
remote->buf_idx += s;
return;
} else {
// all sent out, wait for reading
remote->buf_len = 0;
remote->buf_idx = 0;
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;
ev_io_start(EV_A_ &remote->recv_ctx->io);
}
} else {
LOGE("invalid server.");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
}
}
}
struct remote_ctx *new_remote_ctx(int fd) {
struct remote_ctx *ctx = malloc(sizeof(struct remote_ctx));
ctx->buf = malloc(BUF_SIZE);
ctx->buf_len = 0;
ctx->server_ctx = NULL;
ctx->fd = fd;
ev_io_init(&ctx->io, remote_recv_cb, fd, EV_READ);
return ctx;
}
@ -481,6 +339,7 @@ struct server_ctx * new_server_ctx(int fd) {
struct server_ctx *ctx = malloc(sizeof(struct server_ctx));
ctx->remote_ctx = NULL;
ctx->fd = fd;
ev_io_init(&ctx.io, server_recv_cb, fd, EV_READ);
return ctx;
}
@ -497,6 +356,16 @@ struct query_ctx *new_query_ctx(asyncns_query_t *query,
}
void close_and_free_query(EN_P_ struct query_ctx *ctx) {
if (ctx != NULL) {
ev_io_stop(EV_A_ &ctx->io);
if (ctx->buf != NULL) {
free(ctx->buf);
}
free(ctx);
}
}
void close_and_free_remote(EN_P_ struct remote_ctx *ctx) {
if (ctx != NULL) {
ev_timer_stop(EV_A_ &ctx->watcher);
if (ctx->buf != NULL) {
@ -687,12 +556,12 @@ int udprelay(const char *server_host, const char *server_port,
FATAL("udprelay bind() error..");
}
setnonblocking(serverfd);
struct server_ctx *server_ctx = new_server_ctx(serverfd);
server_ctx->method = method;
server_ctx->iface = iface;
server_ctx->asyncns = asyncns;
ev_io_init(&server_ctx.io, server_recv_cb, serverfd, EV_READ);
ev_io_start(loop, &server_ctx.io);
#ifdef UDPRELAY_LOCAL
@ -706,8 +575,6 @@ int udprelay(const char *server_host, const char *server_port,
}
setnonblocking(remotefd);
struct remote_ctx *remote_ctx = new_remote_ctx(remotefd);
struct addrinfo hints;
struct addrinfo *result;
@ -720,14 +587,14 @@ int udprelay(const char *server_host, const char *server_port,
LOGE("getaddrinfo: %s", gai_strerror(s));
return -1;
}
remote_ctx->addr = *result->ai_addr;
freeaddrinfo(result);
struct remote_ctx *remote_ctx = new_remote_ctx(remotefd);
remote_ctx->addr = *result->ai_addr;
server_ctx->remote_ctx = remote_ctx;
remote_ctx->server_ctx = server_ctx;
ev_io_init(&remote_ctx->io, remote_recv_cb, remotefd, EV_READ);
ev_io_start(loop, &remote_ctx->io);
freeaddrinfo(result);
#endif
return 0;

11
src/udprelay.h

@ -6,7 +6,10 @@
#include "encrypt.h"
#include "jconf.h"
#ifdef UDPRELAY_REMOTE
#include "asyncns.h"
#endif
#define MAX_UDP_PACKET_SIZE (64 * 1024)
@ -15,8 +18,10 @@ struct server_ctx {
int fd;
int method;
char *iface;
struct sockaddr_in src_addr;
struct remote *remote;
struct sockaddr addr;
#ifdef UDPRELAY_LOCAL
struct remote_ctx *remote_ctx;
#endif
#ifdef UDPRELAY_REMOTE
asyncns_t *asyncns;
#endif
@ -38,7 +43,7 @@ struct remote_ctx {
int buf_len;
char *buf; // remote send from, server recv into
struct sockaddr addr;
struct server *server;
struct server_ctx *server_ctx;
#ifdef UDPRELAY_REMOTE
ev_timer watcher;
#endif

Loading…
Cancel
Save