aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server.c109
1 files changed, 101 insertions, 8 deletions
diff --git a/src/server.c b/src/server.c
index 6a76f1b..0adf9d6 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1,3 +1,4 @@
+#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -20,6 +21,7 @@ static int server_accept_client(const server_ctx ctx[],
size_t siz, struct epoll_event *event);
static void *
client_mainloop_epoll(void *arg);
+static int client_io_epoll(struct epoll_event *ev);
server_ctx *
@@ -144,9 +146,10 @@ static int server_accept_client(const server_ctx ctx[],
E_GAIERR(s, "Convert socket address to string");
goto error;
}
- N("New connection from %s:%s to %s:%s",
+ N("New connection from %s:%s to %s:%s: %d",
args->host_buf, args->service_buf,
- ctx[i].host_buf, ctx[i].service_buf);
+ ctx[i].host_buf, ctx[i].service_buf,
+ args->client_psock.fd);
if (pthread_create(&args->self, NULL,
client_mainloop_epoll, args))
@@ -170,8 +173,8 @@ static void *
client_mainloop_epoll(void *arg)
{
client_thread_args *args;
- int s, epoll_fd;
- struct epoll_event event;
+ int s, epoll_fd, active = 1;
+ struct epoll_event event = {0,{0}};
struct epoll_event *events;
assert(arg);
@@ -181,15 +184,48 @@ client_mainloop_epoll(void *arg)
assert(events);
epoll_fd = epoll_create1(0);
- if (epoll_fd < 0)
+ if (epoll_fd < 0) {
+ E_STRERR("Client epoll_create1");
goto finish;
+ }
event.data.fd = args->client_psock.fd;
- event.events = EPOLLIN | EPOLLOUT | EPOLLET;
- memset(&event, 0, sizeof(event));
+ event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, args->client_psock.fd, &event);
- if (s)
+ if (s) {
+ E_STRERR("Client epoll_ctl");
goto finish;
+ }
+
+ while (active) {
+ int n, i;
+
+ n = epoll_wait(epoll_fd, events, POTD_MAXEVENTS, -1);
+ if (n < 0)
+ break;
+
+ for (i = 0; i < n; ++i) {
+ if ((events[i].events & EPOLLERR) ||
+ (events[i].events & EPOLLHUP) ||
+ (!(events[i].events & EPOLLIN) &&
+ !(events[i].events & EPOLLOUT)))
+ {
+ E("Epoll for descriptor %d failed", events[i].data.fd);
+ E_STRERR("epoll_wait");
+ close(events[i].data.fd);
+ continue;
+ } else {
+ if (client_io_epoll(&events[i])) {
+ N("Lost connection to %s:%s: %d",
+ args->host_buf, args->service_buf,
+ args->client_psock.fd);
+ active = 0;
+ break;
+ }
+ }
+ W2("I/O forwarder failed: [fd: %d , npoll: %d]", events[i].data.fd, n);
+ }
+ }
finish:
close(epoll_fd);
@@ -198,3 +234,60 @@ finish:
free(args);
return NULL;
}
+
+static int client_io_epoll(struct epoll_event *ev)
+{
+ int data_avail = 1;
+ int has_input;
+ int saved_errno, io_fail = 0;
+ ssize_t siz;
+ char buf[BUFSIZ];
+
+ while (data_avail) {
+ has_input = 0;
+ saved_errno = 0;
+ siz = -1;
+
+ if (ev->events & EPOLLIN) {
+ has_input = 1;
+ siz = read(ev->data.fd, &buf[0], BUFSIZ);
+ saved_errno = errno;
+ } else if (ev->events & EPOLLOUT) {
+ W("%s", "Suffering from buffer bloat");
+ continue;
+ }
+
+ switch (siz) {
+ case -1:
+ E_STRERR("Client read");
+ if (saved_errno != EAGAIN)
+ io_fail = 1;
+ break;
+ case 0:
+ printf("DISCONNECT !!!\n");
+ io_fail = 1;
+ break;
+ default:
+ buf[siz] = 0;
+ break;
+ }
+
+ if (io_fail)
+ break;
+
+ if (has_input) {
+ printf("INPUT: ___%s___\n", buf);
+ if (strncmp(buf, "QUIT", 4) == 0)
+ io_fail = 1;
+ if (strncmp(buf, "TEST", 4) == 0) {
+ printf("------------\n");
+ write(ev->data.fd, "BLABLABLA\n", 10);
+ }
+ }
+
+ if (io_fail)
+ break;
+ }
+
+ return io_fail != 0;
+}