diff --git a/include/server.h b/include/server.h index 3c31322..a07671c 100644 --- a/include/server.h +++ b/include/server.h @@ -9,6 +9,8 @@ #include "cclass.h" +typedef void (*server_read_hook)(const char *); + CLASS(SERVER) { LOGGER logger; SOCK sock; @@ -22,12 +24,13 @@ CLASS(SERVER) { unsigned int rpos; unsigned int wpos; } conns[FD_SETSIZE]; -}; + server_read_hook read_hook; +}; void server_run(SERVER this); -void server_close(SERVER this); -void server_shutdown(SERVER this); +//void server_close(SERVER this); +//void server_shutdown(SERVER this); #endif // __SERVER_H__ diff --git a/src/server_run.c b/src/server_run.c new file mode 100644 index 0000000..902739e --- /dev/null +++ b/src/server_run.c @@ -0,0 +1,140 @@ +#include /* for select system call and related */ +#include /* for memset and stuff */ +#include /* for exit */ +#include /* for errno */ +#include + +#include "include/logger.h" +#include "include/server.h" +#include "include/socket.h" +#include "include/signalHandling.h" + +#undef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +static +fd_set +server_select(SERVER this) { + fd_set rfds; + + memcpy(&rfds, &(this->fdset), sizeof(fd_set)); + + /* + * wait for handles to become ready + */ + if (-1 == select((this->max_fd)+1, &rfds, NULL, NULL, NULL)) + { + switch (errno) { + default: + case EBADF: + case EINVAL: + case ENOMEM: + doShutdown = 1; + /* Fallthrough */ + + case EINTR: + logger_log(this->logger, LOGGER_CRIT, + "select systemcall failed: [%s] - service terminated", + strerror(errno)); + exit(EXIT_FAILURE); /* @TODO do real shutdown here */ + } + } + + return rfds; +} + +static +void +server_handle_accept(SERVER this, fd_set * rfds) +{ + if (FD_ISSET(this->sock->handle, rfds)) { + int fd; + char remoteAddr[16] = ""; + SOCK acc; + + acc = sock_accept(this->sock, remoteAddr); + + if (-1 != acc->handle) { + ((this->conns)[acc->handle].sock)->handle = fd; // save the socket handle + FD_SET(fd, &(this->fdset)); + this->max_fd = MAX(fd, this->max_fd); + } else { + delete(&acc); + } + + FD_CLR(this->sock->handle, rfds); + } +} + +static +void +server_close_conn(SERVER this, unsigned int handle) +{ + delete(&((this->conns)[handle].sock)); + FD_CLR(handle, &(this->fdset)); +} + +static +int +server_read(SERVER this, fd_set * rfds) +{ + unsigned int i; + size_t _read; + char buffer[1024]; + + for (i=3; i<=this->max_fd; i++) { + if (FD_ISSET(i, rfds)) { + memset(buffer, 0, 1024); + switch (_read = read(i, buffer, 1023)) { + case 0: + /* + * normal close: write remaining data + */ + /* FALLTHROUGH */ + + case -1: + /* + * read failure / close connection + * FALLTHROUGH + */ + server_close_conn(this, i); + break; + + default: + if (NULL != this->read_hook) { + this->read_hook(buffer); + } + break; + } + } + } + + return 0; +} + +void +server_run(SERVER this) +{ + /* + * @TODO again a hint...add verbosity to logger.... + */ + logger_log(this->logger, LOGGER_INFO, "service started"); + + while (!doShutdown) /* until error or signal */ + { + fd_set rfds; + int i; + + rfds = server_select(this); + + /* + * handle accept + */ + server_handle_accept(this, &rfds); + + /* handle reads */ + server_read(this, &rfds); + } +} + +// vim: set ts=4 sw=4: diff --git a/src/signalHandling.c b/src/signalHandling.c index 485f26c..ed7fec9 100644 --- a/src/signalHandling.c +++ b/src/signalHandling.c @@ -1,16 +1,13 @@ #include /* for signal() and signal names */ -#include "include/monitor.h" - volatile int doShutdown; void terminate(int signum) { signal(signum, SIG_IGN); - syslogMonitor(LOG_INFO, MON_CRITICAL, "signals", - "caugth deadly signal %d", signum); - syslogMonitor(LOG_INFO, MON_FAILURE, "signals", - "caugth deadly signal %d - service terminated", signum); + /* + * @TODO do logging here + */ doShutdown = 1; } diff --git a/src/socket_accept.c b/src/socket_accept.c index ba7a15a..daa5084 100644 --- a/src/socket_accept.c +++ b/src/socket_accept.c @@ -15,8 +15,8 @@ SOCK sock_accept(SOCK this, char remoteAddr[16]) { - SOCK sock; /* Socket for client */ - unsigned int len; /* Length of client address data structure */ + SOCK sock; /* Socket for client */ + unsigned int len; /* Length of client address data structure */ /* Set the size of the in-out parameter */ len = sizeof(this->addr); diff --git a/tests/Makefile.am b/tests/Makefile.am index 1cb9e3f..69f5507 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,7 +15,7 @@ loggerTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . socketTest_SOURCES = $(SOURCES) socketTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/socket_connect.c socketTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . -serverTest_SOURCES = $(SOURCES) serverTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/server.c +serverTest_SOURCES = $(SOURCES) serverTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/server.c ../src/server_run.c ../src/signalHandling.c serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . EXTRA_DIST = runtest.h mock/class.h diff --git a/tests/serverTest.c b/tests/serverTest.c index 416fce4..9de7780 100644 --- a/tests/serverTest.c +++ b/tests/serverTest.c @@ -12,6 +12,16 @@ int level = -1; char * msg = NULL; +char * buffer = NULL; + +static void +read_hook(const char * _buffer) +{ + if (NULL != _buffer) { + buffer = malloc(strlen(_buffer) + 1); + strcpy(buffer, _buffer); + } +} static void logfnct_mock(int _level, const char * _msg) @@ -40,6 +50,8 @@ __setUp() ASSERT_EQUAL(TEST_PORT, server->sock->port); ASSERT_EQUAL(server->max_fd, server->sock->handle); + server->read_hook = read_hook; + return TEST_OK; } int (* const setUp)() = __setUp; @@ -76,16 +88,6 @@ testDummy() return TEST_OK; } -static -int -testAccept() -{ - /* - * @TODO ... - */ - return TEST_OK; -} - const testfunc tests[] = { testDummy };