Commit 57f6e87f authored by Max Lv's avatar Max Lv

detect timeout

parent deed2a60
No preview for this file type
......@@ -28,11 +28,7 @@
static char *_server;
static char *_remote_port;
struct client_ctx {
ev_io io;
int fd;
};
static int _timeout;
int setnonblocking(int fd) {
int flags;
......@@ -58,11 +54,15 @@ int create_and_bind(const char *port) {
for (rp = result; rp != NULL; rp = rp->ai_next) {
listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (listen_sock == -1)
continue;
int opt = 1;
int err = setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (err) {
perror("setsocket");
}
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
/* We managed to bind successfully! */
......@@ -106,10 +106,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
if (r == 0) {
// connection closed
*buf_len = 0;
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
if (remote != NULL) {
ev_io_start(EV_A_ &remote->send_ctx->io);
}
return;
} else if(r < 0) {
if (errno == EAGAIN) {
......@@ -118,8 +116,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
break;
} else {
perror("server recv");
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
......@@ -136,8 +134,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
break;
} else {
perror("send");
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
} else if(w < r) {
......@@ -173,8 +171,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
response.atyp = 1;
char *send_buf = (char *)&response;
send(server->fd, send_buf, 4, MSG_NOSIGNAL);
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
......@@ -204,8 +202,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
addr_to_send[addr_len] = 0;
} else {
LOGE("unsupported addrtype: %d\n", request->atyp);
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
......@@ -247,8 +245,8 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
struct remote *remote = server->remote;
if (server->buf_len == 0) {
// close and free
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
} else {
// has data to send
......@@ -257,8 +255,8 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
if (r < 0) {
if (errno != EAGAIN) {
perror("send");
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
return;
......@@ -280,8 +278,8 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
if (remote != NULL) {
ev_io_start(EV_A_ &remote->recv_ctx->io);
} else {
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
......@@ -289,6 +287,24 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
}
static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) {
struct remote_ctx *remote_ctx = (struct remote_ctx *) (((void*)watcher)
- sizeof(ev_io));
struct remote *remote = remote_ctx->remote;
struct server *server = remote->server;
LOGD("remote timeout");
ev_timer_stop(EV_A_ watcher);
if (server == NULL) {
close_and_free_remote(EV_A_ remote);
return;
}
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
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;
......@@ -304,9 +320,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
// connection closed
server->buf_len = 0;
close_and_free_remote(EV_A_ remote);
if (server != NULL) {
ev_io_start(EV_A_ &server->send_ctx->io);
}
close_and_free_server(EV_A_ server);
return;
} else if(r < 0) {
if (errno == EAGAIN) {
......@@ -315,8 +329,8 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
break;
} else {
perror("remote recv");
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
......@@ -330,8 +344,8 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
break;
} else {
perror("send");
close_and_free_server(EV_A_ server);
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
} else if(w < r) {
......@@ -357,15 +371,16 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
if (!remote_send_ctx->connected) {
socklen_t len;
struct sockaddr_storage addr;
len = sizeof addr;
socklen_t len = sizeof addr;
int 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);
ev_timer_stop(EV_A_ &remote_send_ctx->watcher);
ev_io_start(EV_A_ &server->recv_ctx->io);
ev_io_start(EV_A_ &remote->recv_ctx->io);
return;
} else {
perror("getpeername");
// not connected
......@@ -423,17 +438,19 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
struct remote* new_remote(int fd) {
struct remote *remote;
remote = malloc(sizeof(struct remote));
remote->fd = fd;
remote->recv_ctx = malloc(sizeof(struct remote_ctx));
remote->send_ctx = malloc(sizeof(struct remote_ctx));
remote->fd = fd;
ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);
ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);
ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, _timeout, 0);
remote->recv_ctx->remote = remote;
remote->recv_ctx->connected = 0;
remote->send_ctx->remote = remote;
remote->send_ctx->connected = 0;
return remote;
}
void free_remote(struct remote *remote) {
if (remote != NULL) {
if (remote->server != NULL) {
......@@ -446,6 +463,7 @@ void free_remote(struct remote *remote) {
}
void close_and_free_remote(EV_P_ struct remote *remote) {
if (remote != NULL) {
ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
ev_io_stop(EV_A_ &remote->send_ctx->io);
ev_io_stop(EV_A_ &remote->recv_ctx->io);
close(remote->fd);
......@@ -455,9 +473,9 @@ void close_and_free_remote(EV_P_ struct remote *remote) {
struct server* new_server(int fd) {
struct server *server;
server = malloc(sizeof(struct server));
server->fd = fd;
server->recv_ctx = malloc(sizeof(struct server_ctx));
server->send_ctx = malloc(sizeof(struct server_ctx));
server->fd = 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);
server->recv_ctx->server = server;
......@@ -502,15 +520,32 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(_server, _remote_port, &hints, &res);
int err = getaddrinfo(_server, _remote_port, &hints, &res);
if (err) {
perror("getaddrinfo");
close_and_free_server(EV_A_ server);
break;
}
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0) {
perror("socket");
close(sockfd);
close_and_free_server(EV_A_ server);
freeaddrinfo(res);
continue;
break;
}
struct timeval timeout;
timeout.tv_sec = _timeout;
timeout.tv_usec = 0;
err = setsockopt(sockfd, SOL_SOCKET,
SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
if (err) perror("setsockopt");
err = setsockopt(sockfd, SOL_SOCKET,
SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
if (err) perror("setsockopt");
setnonblocking(sockfd);
struct remote *remote = new_remote(sockfd);
server->remote = remote;
......@@ -519,6 +554,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
freeaddrinfo(res);
// listen to remote connected event
ev_io_start(EV_A_ &remote->send_ctx->io);
ev_timer_start(EV_A_ &remote->send_ctx->watcher);
break;
}
}
......@@ -530,12 +566,13 @@ int main (int argc, char **argv)
char *remote_port = NULL;
char *port = NULL;
char *key = NULL;
char* timeout = "10";
int c;
int f_flags = 0;
opterr = 0;
while ((c = getopt (argc, argv, "fs:p:l:k:")) != -1) {
while ((c = getopt (argc, argv, "fs:p:l:k:t:")) != -1) {
switch (c) {
case 's':
server = optarg;
......@@ -552,6 +589,9 @@ int main (int argc, char **argv)
case 'f':
f_flags = 1;
break;
case 't':
timeout = optarg;
break;
}
}
......@@ -611,6 +651,7 @@ int main (int argc, char **argv)
_server = strdup(server);
_remote_port = strdup(remote_port);
_timeout = atoi(timeout);
LOGD("calculating ciphers");
get_table(key);
......
......@@ -10,6 +10,12 @@ struct listen_ctx {
struct sockaddr sock;
};
struct server_ctx {
ev_io io;
int connected;
struct server *server;
};
struct server {
int fd;
char buf[BUF_SIZE]; // server send from, remote recv into
......@@ -19,11 +25,14 @@ struct server {
struct server_ctx *send_ctx;
struct remote *remote;
};
struct server_ctx {
struct remote_ctx {
ev_io io;
ev_timer watcher;
int connected;
struct server *server;
struct remote *remote;
};
struct remote {
int fd;
char buf[BUF_SIZE]; // remote send from, server recv into
......@@ -32,11 +41,6 @@ struct remote {
struct remote_ctx *send_ctx;
struct server *server;
};
struct remote_ctx {
ev_io io;
int connected;
struct remote *remote;
};
static void accept_cb (EV_P_ ev_io *w, int revents);
......
No preview for this file type
No preview for this file type
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment