diff --git a/Makefile b/Makefile index 257ebeea..2bb3b7a9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ main: main.o - gcc -g -O2 main.o -lev -L/usr/local/lib -o main + gcc -g -O2 main.o -lev -lssl -L/usr/local/lib -o main main.o: *.c *.h Makefile gcc -g -O2 -c -o main.o main.c .PHONY: clean diff --git a/main.c b/main.c index c6ada511..330eb164 100644 --- a/main.c +++ b/main.c @@ -23,6 +23,10 @@ #define PORT 1090 #define REPLY "HTTP/1.1 200 OK\n\nhello" +#define min(a,b) \ + ({ typeof (a) _a = (a); \ + typeof (b) _b = (b); \ + _a < _b ? _a : _b; }) // every watcher type has its own typedef'd struct // with the name ev_TYPE @@ -82,80 +86,52 @@ int create_and_bind(char *port) { return listen_sock; } -void send_cb (EV_P_ ev_io *w, int revents) -{ - struct client_ctx *client = (struct client_ctx *)w; - ev_io_stop(EV_A_ &client->io); - close(client->fd); - free(client); -} -void recv_cb (EV_P_ ev_io *w, int revents) -{ - struct client_ctx *client = (struct client_ctx *)w; - char buf[4096]; - int n = recv(client->fd, buf, 4096, 0); - if (n == 0) { - ev_io_stop(EV_A_ &client->io); - close(client->fd); - free(client); - return; - } else if (n < 0) { - perror("recv"); - return; - } - send(client->fd, REPLY, sizeof(REPLY), MSG_NOSIGNAL); - ev_io_stop(EV_A_ &client->io); - ev_io_init(&client->io, send_cb, client->fd, EV_WRITE); - ev_io_start(EV_A_ &client->io); -} - - -struct client_ctx* client_new(int fd) { - struct client_ctx* client; - - client = malloc(sizeof(struct client_ctx)); - client->fd = fd; - //client->server = server; - setnonblocking(client->fd); - ev_io_init(&client->io, recv_cb, client->fd, EV_READ); - return client; -} static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct server_ctx *server_recv_ctx = (struct server_ctx *)w; struct server *server = server_recv_ctx->server; struct remote *remote = server->remote; while (1) { - ssize_t r = recv(server->fd, server->buf, BUF_SIZE, 0); + ssize_t r = recv(server->fd, remote->buf, BUF_SIZE, 0); if (r == 0) { - // TODO connection closed + // connection closed + remote->buf_len = 0; + close_and_free_server(EV_A_ server); + if (remote != NULL) { + ev_io_start(EV_A_ &remote->send_ctx->io); + } return; - } else if(r == -1) { + } else if(r < 0) { perror("recv"); if (errno == EAGAIN) { // no data // continue to wait for recv break; + } else { + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; } } - int w = send(remote->fd, server->buf, r, MSG_NOSIGNAL); - if (w == 0) { - // TODO connection closed - return; - } else if(w == -1) { + int w = send(remote->fd, remote->buf, r, MSG_NOSIGNAL); + if(w == -1) { perror("send"); if (errno == EAGAIN) { // no data, wait for send ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io); break; + } else { + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; } } else if(w < r) { char *pt; - for (pt = server->buf; pt < pt + w; pt++) { + for (pt = remote->buf; pt < pt + min(w, BUF_SIZE); pt++) { *pt = *(pt + w); } - server->buf_len = w; + remote->buf_len = r - w; ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io); break; @@ -166,29 +142,44 @@ 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->buf_len == 0) { - // TODO close and free + if (server->buf_len == 0) { + // close and free + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; } else { // has data to send - ssize_t r = send(server->fd, remote->buf, - remote->buf_len, 0); + ssize_t r = send(server->fd, server->buf, + server->buf_len, 0); if (r < 0) { perror("send"); - // TODO close and free + if (errno != EAGAIN) { + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; + } return; } - if (r < remote->buf_len) { + if (r < server->buf_len) { + // printf("r=%d\n", r); + // printf("server->buf_len=%d\n", server->buf_len); // partly sent, move memory, wait for the next time to send char *pt; - for (pt = remote->buf; pt < pt + r; pt++) { + for (pt = server->buf; pt < pt + min(r, BUF_SIZE); pt++) { *pt = *(pt + r); } - remote->buf_len = r; + server->buf_len -= r; return; } else { // all sent out, wait for reading ev_io_stop(EV_A_ &server_send_ctx->io); - ev_io_start(EV_A_ &remote->recv_ctx->io); + 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); + return; + } } } @@ -198,36 +189,48 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { struct remote *remote = remote_recv_ctx->remote; struct server *server = remote->server; while (1) { - ssize_t r = recv(remote->fd, remote->buf, BUF_SIZE, 0); + ssize_t r = recv(remote->fd, server->buf, BUF_SIZE, 0); + // printf("after recv: r=%d\n", r); if (r == 0) { - // TODO connection closed + // 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); + } return; - } else if(r == -1) { + } else if(r < 0) { perror("recv"); if (errno == EAGAIN) { // no data // continue to wait for recv break; + } else { + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; } } - int w = send(server->fd, remote->buf, r, MSG_NOSIGNAL); - if (w == 0) { - // TODO connection closed - return; - } else if(w == -1) { + int w = send(server->fd, server->buf, r, MSG_NOSIGNAL); + // printf("after send: w=%d\n", w); + if(w == -1) { perror("send"); if (errno == EAGAIN) { // no data, wait for send ev_io_stop(EV_A_ &remote_recv_ctx->io); ev_io_start(EV_A_ &server->send_ctx->io); break; + } else { + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; } } else if(w < r) { char *pt; - for (pt = remote->buf; pt < pt + w; pt++) { + for (pt = server->buf; pt < pt + min(w, BUF_SIZE); pt++) { *pt = *(pt + w); } - remote->buf_len = w; + server->buf_len = r - w; ev_io_stop(EV_A_ &remote_recv_ctx->io); ev_io_start(EV_A_ &server->send_ctx->io); break; @@ -253,35 +256,51 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { } else { perror("getpeername"); // not connected - // TODO + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); return; } } else { - if (server->buf_len == 0) { - // TODO close and free + if (remote->buf_len == 0) { + // close and free + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; } else { // has data to send - ssize_t r = send(remote->fd, server->buf, - server->buf_len, 0); + ssize_t r = send(remote->fd, remote->buf, + remote->buf_len, 0); if (r < 0) { perror("send"); - // TODO close and free + if (errno != EAGAIN) { + // close and free + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } return; } - if (r < server->buf_len) { + if (r < remote->buf_len) { // partly sent, move memory, wait for the next time to send char *pt; - for (pt = server->buf; pt < pt + r; pt++) { + for (pt = remote->buf; pt < pt + min(r, BUF_SIZE); pt++) { *pt = *(pt + r); } - server->buf_len = r; + remote->buf_len -= r; return; } else { // all sent out, wait for reading ev_io_stop(EV_A_ &remote_send_ctx->io); - ev_io_start(EV_A_ &server->recv_ctx->io); + if (server != NULL) { + ev_io_start(EV_A_ &server->recv_ctx->io); + } else { + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } } } + } } @@ -297,8 +316,28 @@ struct remote* new_remote(int fd) { remote->recv_ctx->connected = 0; remote->send_ctx->remote = remote; remote->send_ctx->connected = 0; + fprintf(stderr, "new remote\n"); return remote; } +void free_remote(struct remote *remote) { + if (remote != NULL) { + if (remote->server != NULL) { + remote->server->remote = NULL; + } + free(remote->recv_ctx); + free(remote->send_ctx); + free(remote); + fprintf(stderr, "free remote\n"); + } +} +void close_and_free_remote(EV_P_ struct remote *remote) { + if (remote != NULL) { + ev_io_stop(EV_A_ &remote->send_ctx->io); + ev_io_stop(EV_A_ &remote->recv_ctx->io); + close(remote->fd); + free_remote(remote); + } +} struct server* new_server(int fd) { struct server *server; server = malloc(sizeof(struct server)); @@ -311,9 +350,28 @@ struct server* new_server(int fd) { server->recv_ctx->connected = 0; server->send_ctx->server = server; server->send_ctx->connected = 0; + fprintf(stderr, "new server\n"); return server; } - +void free_server(struct server *server) { + if (server != NULL) { + if (server->remote != NULL) { + server->remote->server = NULL; + } + free(server->recv_ctx); + free(server->send_ctx); + free(server); + fprintf(stderr, "free server\n"); + } +} +void close_and_free_server(EV_P_ struct server *server) { + if (server != NULL) { + ev_io_stop(EV_A_ &server->send_ctx->io); + ev_io_stop(EV_A_ &server->recv_ctx->io); + close(server->fd); + free_server(server); + } +} static void accept_cb (EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; @@ -334,7 +392,9 @@ static void accept_cb (EV_P_ ev_io *w, int revents) sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { perror("socket"); - exit(1); // TODO close, free and return + close(sockfd); + free_server(server); + continue; } setnonblocking(sockfd); struct remote *remote = new_remote(sockfd); diff --git a/main.h b/main.h index baff1439..34f3980d 100644 --- a/main.h +++ b/main.h @@ -12,7 +12,7 @@ struct listen_ctx { struct server { int fd; - char buf[BUF_SIZE]; // server recv into, remote send from + char buf[BUF_SIZE]; // server send from, remote recv into int buf_len; struct server_ctx *recv_ctx; struct server_ctx *send_ctx; @@ -25,7 +25,7 @@ struct server_ctx { }; struct remote { int fd; - char buf[BUF_SIZE]; // remote recv into, server send from + char buf[BUF_SIZE]; // remote send from, server recv into int buf_len; struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; @@ -43,4 +43,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents); static void server_send_cb (EV_P_ ev_io *w, int revents); 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* new_remote(int fd); +void free_remote(struct remote *remote); +void close_and_free_remote(EV_P_ struct remote *remote); +struct server* new_server(int fd); +void free_server(struct server *server); +void close_and_free_server(EV_P_ struct server *server);