Browse Source

changed from select(UNIX) to poll(POSIX)

master
Georg Hopp 14 years ago
parent
commit
c33578329c
  1. 19
      include/server.h
  2. 25
      src/server.c
  3. 12
      src/server_close_conn.c
  4. 67
      src/server_run.c
  5. 12
      src/socket_accept.c
  6. 16
      tests/Makefile.am
  7. 58
      tests/serverTest.c
  8. 3
      tests/socketTest.c

19
include/server.h

@ -2,20 +2,24 @@
#define __SERVER_H__
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/select.h> /* for select system call and related */
#include <poll.h> /* 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__

25
src/server.c

@ -1,4 +1,4 @@
#include <sys/select.h> /* for select system call and related */
#include <poll.h> /* for select system call and related */
#include <string.h> /* for memset and stuff */
#include <stdlib.h> /* 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; i<this->nfds; i++) {
/*
* @TODO do some finalization...buffer handling...etc.
*/
delete(&(this->conns[i]).sock);
}
delete(&this->sock);

12
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:

67
src/server_run.c

@ -1,4 +1,4 @@
#include <sys/select.h> /* for select system call and related */
#include <poll.h> /* for select system call and related */
#include <string.h> /* for memset and stuff */
#include <stdlib.h> /* for exit */
#include <errno.h> /* 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; i<this->nfds; 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);
}
}

12
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;
}

16
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

58
tests/serverTest.c

@ -1,34 +1,38 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#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;
}

3
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;

Loading…
Cancel
Save