From c33578329ce7476f9fa0a667eb864abcecc45a09 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Tue, 17 Jan 2012 14:49:49 +0100 Subject: [PATCH] changed from select(UNIX) to poll(POSIX) --- include/server.h | 19 +++++++----- src/server.c | 25 ++++++--------- src/server_close_conn.c | 12 ++++++++ src/server_run.c | 67 ++++++++++++++++++----------------------- src/socket_accept.c | 12 ++------ tests/Makefile.am | 16 +++++++--- tests/serverTest.c | 58 ++++++++++++++++++++++++----------- tests/socketTest.c | 3 +- 8 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 src/server_close_conn.c diff --git a/include/server.h b/include/server.h index a07671c..415ef20 100644 --- a/include/server.h +++ b/include/server.h @@ -2,20 +2,24 @@ #define __SERVER_H__ #include /* for printf() and fprintf() */ -#include /* for select system call and related */ +#include /* for select system call and related */ #include "socket.h" #include "logger.h" #include "cclass.h" +#define POLL_FD_NSIZE 1024 +#define POLL_FD_SIZE (sizeof(struct pollfd) * POLL_FD_NSIZE) +#define POLL_FD_MOVE(idx) (sizeof(struct pollfd) * (POLL_FD_NSIZE-(idx)+1)) + typedef void (*server_read_hook)(const char *); CLASS(SERVER) { - LOGGER logger; - SOCK sock; - unsigned int max_fd; - fd_set fdset; + LOGGER logger; + SOCK sock; + nfds_t nfds; + struct pollfd fds[POLL_FD_NSIZE]; struct { SOCK sock; @@ -23,14 +27,13 @@ CLASS(SERVER) { char * rbuf; unsigned int rpos; unsigned int wpos; - } conns[FD_SETSIZE]; + } conns[POLL_FD_NSIZE]; server_read_hook read_hook; }; void server_run(SERVER this); -//void server_close(SERVER this); -//void server_shutdown(SERVER this); +void server_close_conn(SERVER this, unsigned int handle); #endif // __SERVER_H__ diff --git a/src/server.c b/src/server.c index 63f4614..73304c9 100644 --- a/src/server.c +++ b/src/server.c @@ -1,4 +1,4 @@ -#include /* for select system call and related */ +#include /* for select system call and related */ #include /* for memset and stuff */ #include /* for getopt */ @@ -8,7 +8,6 @@ #include "logger.h" #include "cclass.h" - INIT_CLASS(SERVER); __construct(SERVER) @@ -20,27 +19,23 @@ __construct(SERVER) port = va_arg(* params, int); backlog = va_arg(* params, unsigned int); - FD_ZERO(&(this->fdset)); - - this->sock = new(SOCK, port); + this->sock = new(SOCK, this->logger, port); sock_listen(this->sock, backlog); - this->max_fd = this->sock->handle; - FD_SET(this->sock->handle, &(this->fdset)); + (this->fds)[0].fd = this->sock->handle; + (this->fds)[0].events = POLLIN; + this->nfds = 1; } __destruct(SERVER) { int i; - for (i=3; i<=this->max_fd; i++) { - if (FD_ISSET(i, &(this->fdset)) && i != this->sock->handle) { - /* - * @TODO do some finalization...buffer handling...etc. - */ - delete(&(this->conns[i]).sock); - FD_CLR(i, &(this->fdset)); - } + for (i=1; infds; i++) { + /* + * @TODO do some finalization...buffer handling...etc. + */ + delete(&(this->conns[i]).sock); } delete(&this->sock); diff --git a/src/server_close_conn.c b/src/server_close_conn.c new file mode 100644 index 0000000..8c44658 --- /dev/null +++ b/src/server_close_conn.c @@ -0,0 +1,12 @@ +#include "server.h" + + +void +server_close_conn(SERVER this, unsigned int i) +{ + memmove(&((this->fds)[i]), &((this->fds)[i+1]), POLL_FD_MOVE(i+1)); + this->nfds--; + delete(&((this->conns)[i].sock)); +} + +// vim: set ts=4 sw=4: diff --git a/src/server_run.c b/src/server_run.c index 902739e..2a19690 100644 --- a/src/server_run.c +++ b/src/server_run.c @@ -1,4 +1,4 @@ -#include /* for select system call and related */ +#include /* for select system call and related */ #include /* for memset and stuff */ #include /* for exit */ #include /* for errno */ @@ -13,17 +13,14 @@ #define MAX(x,y) ((x) > (y) ? (x) : (y)) static -fd_set +int server_select(SERVER this) { - fd_set rfds; - - memcpy(&rfds, &(this->fdset), sizeof(fd_set)); + int events; /* * wait for handles to become ready */ - if (-1 == select((this->max_fd)+1, &rfds, NULL, NULL, NULL)) - { + if (-1 == (events = poll(this->fds, this->nfds, -1))) { switch (errno) { default: case EBADF: @@ -36,56 +33,48 @@ server_select(SERVER this) { logger_log(this->logger, LOGGER_CRIT, "select systemcall failed: [%s] - service terminated", strerror(errno)); - exit(EXIT_FAILURE); /* @TODO do real shutdown here */ + //exit(EXIT_FAILURE); /* @TODO do real shutdown here */ } } - return rfds; + return events; } static void -server_handle_accept(SERVER this, fd_set * rfds) +server_handle_accept(SERVER this) { - if (FD_ISSET(this->sock->handle, rfds)) { - int fd; + if (0 != ((this->fds)[0].revents & POLLIN)) { 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); + (this->conns)[this->nfds].sock = acc; // save the socket handle + (this->fds)[this->nfds].fd = acc->handle; + (this->fds)[this->nfds].events = POLLIN; + this->nfds++; } else { delete(&acc); } - FD_CLR(this->sock->handle, rfds); + (this->fds)[0].revents |= POLLIN; } } -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) +server_read(SERVER this) { unsigned int i; - size_t _read; - char buffer[1024]; + size_t _read; + char buffer[1024]; - for (i=3; i<=this->max_fd; i++) { - if (FD_ISSET(i, rfds)) { + for (i=1; infds; i++) { + if (0 != ((this->fds)[i].revents & POLLIN)) { memset(buffer, 0, 1024); - switch (_read = read(i, buffer, 1023)) { + switch (_read = read((this->fds)[i].fd, buffer, 1023)) { case 0: /* * normal close: write remaining data @@ -101,6 +90,7 @@ server_read(SERVER this, fd_set * rfds) break; default: + (this->fds)[i].revents |= POLLIN; if (NULL != this->read_hook) { this->read_hook(buffer); } @@ -116,24 +106,27 @@ void server_run(SERVER this) { /* - * @TODO again a hint...add verbosity to logger.... + * @TODO again...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); + int events; + /* + * @TODO take return value of poll into account with + * further handling! + */ + events = server_select(this); + if (doShutdown) break; /* * handle accept */ - server_handle_accept(this, &rfds); + server_handle_accept(this); /* handle reads */ - server_read(this, &rfds); + server_read(this); } } diff --git a/src/socket_accept.c b/src/socket_accept.c index daa5084..e01bdfe 100644 --- a/src/socket_accept.c +++ b/src/socket_accept.c @@ -32,17 +32,9 @@ sock_accept(SOCK this, char remoteAddr[16]) logger_log(this->logger, LOGGER_WARNING, "error acception connection: %s", strerror(errno)); } else { - strncpy (remoteAddr, inet_ntoa((sock->addr).sin_addr), sizeof(remoteAddr)-1); - } - - /* clntSock is connected to a client! */ - /** - * @TODO add verbosity level to logger - */ -// if (0 != this->logger->verbose) { logger_log(this->logger, LOGGER_INFO, - "handling client %s\n", inet_ntoa((this->addr).sin_addr)); -// } + "handling client %s\n", inet_ntoa((sock->addr).sin_addr)); + } return sock; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 69f5507..cafbe6f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,18 +4,24 @@ TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet TESTS = cclassTest loggerTest socketTest serverTest check_PROGRAMS = cclassTest loggerTest socketTest serverTest -SOURCES = runtest.c ../src/cclass.c +COMMON = runtest.c ../src/cclass.c +CCLASS = $(COMMON) mock/class.c +LOGGER = $(COMMON) ../src/logger.c +SOCKET = $(LOGGER) ../src/socket.c ../src/socket_listen.c \ + ../src/socket_accept.c ../src/socket_connect.c +SERVER = $(SOCKET) ../src/server.c ../src/server_run.c \ + ../src/server_close_conn.c ../src/signalHandling.c -cclassTest_SOURCES = $(SOURCES) cclassTest.c mock/class.c +cclassTest_SOURCES = $(CCLASS) cclassTest.c cclassTest_CFLAGS = -Wall -ggdb -O0 -finline-functions -I ../include -I .. -I . -loggerTest_SOURCES = $(SOURCES) loggerTest.c ../src/logger.c +loggerTest_SOURCES = $(LOGGER) loggerTest.c 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_SOURCES = $(SOCKET) socketTest.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 ../src/server_run.c ../src/signalHandling.c +serverTest_SOURCES = $(SERVER) serverTest.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 9de7780..95e74e4 100644 --- a/tests/serverTest.c +++ b/tests/serverTest.c @@ -1,34 +1,38 @@ #include #include +#include +#include #include "runtest.h" #include "logger.h" #include "cclass.h" #include "server.h" +#include "signalHandling.h" -#define TEST_PORT 11212 +#define TEST_PORT 11218 +#define TEST_DATA "test" -int level = -1; -char * msg = NULL; -char * buffer = NULL; +int level = -1; +char msg[1024]; +char buffer[1024]; static void read_hook(const char * _buffer) { if (NULL != _buffer) { - buffer = malloc(strlen(_buffer) + 1); - strcpy(buffer, _buffer); + strncpy(buffer, _buffer, 1023); } + + doShutdown = 1; } static void logfnct_mock(int _level, const char * _msg) { level = _level; - msg = malloc(strlen(_msg) + 1); - strcpy(msg, _msg); + strncpy(msg, _msg, 1023); } const char testname[] = "serverTest"; @@ -48,7 +52,6 @@ __setUp() ASSERT_INSTANCE_OF(LOGGER, server->logger); ASSERT_INSTANCE_OF(SOCK, server->sock); ASSERT_EQUAL(TEST_PORT, server->sock->port); - ASSERT_EQUAL(server->max_fd, server->sock->handle); server->read_hook = read_hook; @@ -62,9 +65,9 @@ __tearDown() { level = -1; - if (NULL != msg) { - free(msg); - msg = NULL; + if (NULL != server) { + ASSERT_OBJECT(server); + delete(&server); } if (NULL != logger) { @@ -72,11 +75,6 @@ __tearDown() delete(&logger); } - if (NULL != server) { - ASSERT_OBJECT(server); - delete(&server); - } - return TEST_OK; } int (* const tearDown)() = __tearDown; @@ -85,6 +83,32 @@ static int testDummy() { + SOCK con; + pid_t pid; + int status; + + pid = fork(); + + switch(pid) { + case 0: + con = new(SOCK, logger, TEST_PORT); + sleep(1); + sock_connect(con, "127.0.0.1"); + write(con->handle, TEST_DATA, strlen(TEST_DATA)+1); + delete(&con); + __tearDown(); + exit(EXIT_SUCCESS); + + case -1: + return TEST_FAILED; + + default: + init_signals(); + server_run(server); + } + + ASSERT_STRING_EQUAL(TEST_DATA, buffer); + return TEST_OK; } diff --git a/tests/socketTest.c b/tests/socketTest.c index a452121..adcf547 100644 --- a/tests/socketTest.c +++ b/tests/socketTest.c @@ -8,7 +8,7 @@ #include "socket.h" -#define TEST_PORT 11212 +#define TEST_PORT 11213 int level = -1; @@ -98,7 +98,6 @@ testAccept() delete(&con); __tearDown(); exit(EXIT_SUCCESS); - break; case -1: return TEST_FAILED;