Commit c33578329ce7476f9fa0a667eb864abcecc45a09

Authored by Georg Hopp
1 parent fb0dd8ad

changed from select(UNIX) to poll(POSIX)

... ... @@ -2,20 +2,24 @@
2 2 #define __SERVER_H__
3 3
4 4 #include <stdio.h> /* for printf() and fprintf() */
5   -#include <sys/select.h> /* for select system call and related */
  5 +#include <poll.h> /* for select system call and related */
6 6
7 7 #include "socket.h"
8 8 #include "logger.h"
9 9 #include "cclass.h"
10 10
  11 +#define POLL_FD_NSIZE 1024
  12 +#define POLL_FD_SIZE (sizeof(struct pollfd) * POLL_FD_NSIZE)
  13 +#define POLL_FD_MOVE(idx) (sizeof(struct pollfd) * (POLL_FD_NSIZE-(idx)+1))
  14 +
11 15
12 16 typedef void (*server_read_hook)(const char *);
13 17
14 18 CLASS(SERVER) {
15   - LOGGER logger;
16   - SOCK sock;
17   - unsigned int max_fd;
18   - fd_set fdset;
  19 + LOGGER logger;
  20 + SOCK sock;
  21 + nfds_t nfds;
  22 + struct pollfd fds[POLL_FD_NSIZE];
19 23
20 24 struct {
21 25 SOCK sock;
... ... @@ -23,14 +27,13 @@ CLASS(SERVER) {
23 27 char * rbuf;
24 28 unsigned int rpos;
25 29 unsigned int wpos;
26   - } conns[FD_SETSIZE];
  30 + } conns[POLL_FD_NSIZE];
27 31
28 32 server_read_hook read_hook;
29 33 };
30 34
31 35 void server_run(SERVER this);
32   -//void server_close(SERVER this);
33   -//void server_shutdown(SERVER this);
  36 +void server_close_conn(SERVER this, unsigned int handle);
34 37
35 38 #endif // __SERVER_H__
36 39
... ...
1   -#include <sys/select.h> /* for select system call and related */
  1 +#include <poll.h> /* for select system call and related */
2 2 #include <string.h> /* for memset and stuff */
3 3 #include <stdlib.h> /* for getopt */
4 4
... ... @@ -8,7 +8,6 @@
8 8 #include "logger.h"
9 9 #include "cclass.h"
10 10
11   -
12 11 INIT_CLASS(SERVER);
13 12
14 13 __construct(SERVER)
... ... @@ -20,27 +19,23 @@ __construct(SERVER)
20 19 port = va_arg(* params, int);
21 20 backlog = va_arg(* params, unsigned int);
22 21
23   - FD_ZERO(&(this->fdset));
24   -
25   - this->sock = new(SOCK, port);
  22 + this->sock = new(SOCK, this->logger, port);
26 23 sock_listen(this->sock, backlog);
27 24
28   - this->max_fd = this->sock->handle;
29   - FD_SET(this->sock->handle, &(this->fdset));
  25 + (this->fds)[0].fd = this->sock->handle;
  26 + (this->fds)[0].events = POLLIN;
  27 + this->nfds = 1;
30 28 }
31 29
32 30 __destruct(SERVER)
33 31 {
34 32 int i;
35 33
36   - for (i=3; i<=this->max_fd; i++) {
37   - if (FD_ISSET(i, &(this->fdset)) && i != this->sock->handle) {
38   - /*
39   - * @TODO do some finalization...buffer handling...etc.
40   - */
41   - delete(&(this->conns[i]).sock);
42   - FD_CLR(i, &(this->fdset));
43   - }
  34 + for (i=1; i<this->nfds; i++) {
  35 + /*
  36 + * @TODO do some finalization...buffer handling...etc.
  37 + */
  38 + delete(&(this->conns[i]).sock);
44 39 }
45 40
46 41 delete(&this->sock);
... ...
  1 +#include "server.h"
  2 +
  3 +
  4 +void
  5 +server_close_conn(SERVER this, unsigned int i)
  6 +{
  7 + memmove(&((this->fds)[i]), &((this->fds)[i+1]), POLL_FD_MOVE(i+1));
  8 + this->nfds--;
  9 + delete(&((this->conns)[i].sock));
  10 +}
  11 +
  12 +// vim: set ts=4 sw=4:
... ...
1   -#include <sys/select.h> /* for select system call and related */
  1 +#include <poll.h> /* for select system call and related */
2 2 #include <string.h> /* for memset and stuff */
3 3 #include <stdlib.h> /* for exit */
4 4 #include <errno.h> /* for errno */
... ... @@ -13,17 +13,14 @@
13 13 #define MAX(x,y) ((x) > (y) ? (x) : (y))
14 14
15 15 static
16   -fd_set
  16 +int
17 17 server_select(SERVER this) {
18   - fd_set rfds;
19   -
20   - memcpy(&rfds, &(this->fdset), sizeof(fd_set));
  18 + int events;
21 19
22 20 /*
23 21 * wait for handles to become ready
24 22 */
25   - if (-1 == select((this->max_fd)+1, &rfds, NULL, NULL, NULL))
26   - {
  23 + if (-1 == (events = poll(this->fds, this->nfds, -1))) {
27 24 switch (errno) {
28 25 default:
29 26 case EBADF:
... ... @@ -36,56 +33,48 @@ server_select(SERVER this) {
36 33 logger_log(this->logger, LOGGER_CRIT,
37 34 "select systemcall failed: [%s] - service terminated",
38 35 strerror(errno));
39   - exit(EXIT_FAILURE); /* @TODO do real shutdown here */
  36 + //exit(EXIT_FAILURE); /* @TODO do real shutdown here */
40 37 }
41 38 }
42 39
43   - return rfds;
  40 + return events;
44 41 }
45 42
46 43 static
47 44 void
48   -server_handle_accept(SERVER this, fd_set * rfds)
  45 +server_handle_accept(SERVER this)
49 46 {
50   - if (FD_ISSET(this->sock->handle, rfds)) {
51   - int fd;
  47 + if (0 != ((this->fds)[0].revents & POLLIN)) {
52 48 char remoteAddr[16] = "";
53 49 SOCK acc;
54 50
55 51 acc = sock_accept(this->sock, remoteAddr);
56 52
57 53 if (-1 != acc->handle) {
58   - ((this->conns)[acc->handle].sock)->handle = fd; // save the socket handle
59   - FD_SET(fd, &(this->fdset));
60   - this->max_fd = MAX(fd, this->max_fd);
  54 + (this->conns)[this->nfds].sock = acc; // save the socket handle
  55 + (this->fds)[this->nfds].fd = acc->handle;
  56 + (this->fds)[this->nfds].events = POLLIN;
  57 + this->nfds++;
61 58 } else {
62 59 delete(&acc);
63 60 }
64 61
65   - FD_CLR(this->sock->handle, rfds);
  62 + (this->fds)[0].revents |= POLLIN;
66 63 }
67 64 }
68 65
69 66 static
70   -void
71   -server_close_conn(SERVER this, unsigned int handle)
72   -{
73   - delete(&((this->conns)[handle].sock));
74   - FD_CLR(handle, &(this->fdset));
75   -}
76   -
77   -static
78 67 int
79   -server_read(SERVER this, fd_set * rfds)
  68 +server_read(SERVER this)
80 69 {
81 70 unsigned int i;
82   - size_t _read;
83   - char buffer[1024];
  71 + size_t _read;
  72 + char buffer[1024];
84 73
85   - for (i=3; i<=this->max_fd; i++) {
86   - if (FD_ISSET(i, rfds)) {
  74 + for (i=1; i<this->nfds; i++) {
  75 + if (0 != ((this->fds)[i].revents & POLLIN)) {
87 76 memset(buffer, 0, 1024);
88   - switch (_read = read(i, buffer, 1023)) {
  77 + switch (_read = read((this->fds)[i].fd, buffer, 1023)) {
89 78 case 0:
90 79 /*
91 80 * normal close: write remaining data
... ... @@ -101,6 +90,7 @@ server_read(SERVER this, fd_set * rfds)
101 90 break;
102 91
103 92 default:
  93 + (this->fds)[i].revents |= POLLIN;
104 94 if (NULL != this->read_hook) {
105 95 this->read_hook(buffer);
106 96 }
... ... @@ -116,24 +106,27 @@ void
116 106 server_run(SERVER this)
117 107 {
118 108 /*
119   - * @TODO again a hint...add verbosity to logger....
  109 + * @TODO again...add verbosity to logger....
120 110 */
121 111 logger_log(this->logger, LOGGER_INFO, "service started");
122 112
123 113 while (!doShutdown) /* until error or signal */
124 114 {
125   - fd_set rfds;
126   - int i;
127   -
128   - rfds = server_select(this);
  115 + int events;
  116 + /*
  117 + * @TODO take return value of poll into account with
  118 + * further handling!
  119 + */
  120 + events = server_select(this);
  121 + if (doShutdown) break;
129 122
130 123 /*
131 124 * handle accept
132 125 */
133   - server_handle_accept(this, &rfds);
  126 + server_handle_accept(this);
134 127
135 128 /* handle reads */
136   - server_read(this, &rfds);
  129 + server_read(this);
137 130 }
138 131 }
139 132
... ...
... ... @@ -32,17 +32,9 @@ sock_accept(SOCK this, char remoteAddr[16])
32 32 logger_log(this->logger, LOGGER_WARNING,
33 33 "error acception connection: %s", strerror(errno));
34 34 } else {
35   - strncpy (remoteAddr, inet_ntoa((sock->addr).sin_addr), sizeof(remoteAddr)-1);
36   - }
37   -
38   - /* clntSock is connected to a client! */
39   - /**
40   - * @TODO add verbosity level to logger
41   - */
42   -// if (0 != this->logger->verbose) {
43 35 logger_log(this->logger, LOGGER_INFO,
44   - "handling client %s\n", inet_ntoa((this->addr).sin_addr));
45   -// }
  36 + "handling client %s\n", inet_ntoa((sock->addr).sin_addr));
  37 + }
46 38
47 39 return sock;
48 40 }
... ...
... ... @@ -4,18 +4,24 @@ TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet
4 4 TESTS = cclassTest loggerTest socketTest serverTest
5 5 check_PROGRAMS = cclassTest loggerTest socketTest serverTest
6 6
7   -SOURCES = runtest.c ../src/cclass.c
  7 +COMMON = runtest.c ../src/cclass.c
  8 +CCLASS = $(COMMON) mock/class.c
  9 +LOGGER = $(COMMON) ../src/logger.c
  10 +SOCKET = $(LOGGER) ../src/socket.c ../src/socket_listen.c \
  11 + ../src/socket_accept.c ../src/socket_connect.c
  12 +SERVER = $(SOCKET) ../src/server.c ../src/server_run.c \
  13 + ../src/server_close_conn.c ../src/signalHandling.c
8 14
9   -cclassTest_SOURCES = $(SOURCES) cclassTest.c mock/class.c
  15 +cclassTest_SOURCES = $(CCLASS) cclassTest.c
10 16 cclassTest_CFLAGS = -Wall -ggdb -O0 -finline-functions -I ../include -I .. -I .
11 17
12   -loggerTest_SOURCES = $(SOURCES) loggerTest.c ../src/logger.c
  18 +loggerTest_SOURCES = $(LOGGER) loggerTest.c
13 19 loggerTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I .
14 20
15   -socketTest_SOURCES = $(SOURCES) socketTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/socket_connect.c
  21 +socketTest_SOURCES = $(SOCKET) socketTest.c
16 22 socketTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I .
17 23
18   -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
  24 +serverTest_SOURCES = $(SERVER) serverTest.c
19 25 serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I .
20 26
21 27 EXTRA_DIST = runtest.h mock/class.h
... ...
1 1 #include <stdio.h>
2 2 #include <stdlib.h>
  3 +#include <unistd.h>
  4 +#include <signal.h>
3 5
4 6 #include "runtest.h"
5 7 #include "logger.h"
6 8 #include "cclass.h"
7 9 #include "server.h"
  10 +#include "signalHandling.h"
8 11
9 12
10   -#define TEST_PORT 11212
  13 +#define TEST_PORT 11218
  14 +#define TEST_DATA "test"
11 15
12 16
13   -int level = -1;
14   -char * msg = NULL;
15   -char * buffer = NULL;
  17 +int level = -1;
  18 +char msg[1024];
  19 +char buffer[1024];
16 20
17 21 static void
18 22 read_hook(const char * _buffer)
19 23 {
20 24 if (NULL != _buffer) {
21   - buffer = malloc(strlen(_buffer) + 1);
22   - strcpy(buffer, _buffer);
  25 + strncpy(buffer, _buffer, 1023);
23 26 }
  27 +
  28 + doShutdown = 1;
24 29 }
25 30
26 31 static void
27 32 logfnct_mock(int _level, const char * _msg)
28 33 {
29 34 level = _level;
30   - msg = malloc(strlen(_msg) + 1);
31   - strcpy(msg, _msg);
  35 + strncpy(msg, _msg, 1023);
32 36 }
33 37
34 38 const char testname[] = "serverTest";
... ... @@ -48,7 +52,6 @@ __setUp()
48 52 ASSERT_INSTANCE_OF(LOGGER, server->logger);
49 53 ASSERT_INSTANCE_OF(SOCK, server->sock);
50 54 ASSERT_EQUAL(TEST_PORT, server->sock->port);
51   - ASSERT_EQUAL(server->max_fd, server->sock->handle);
52 55
53 56 server->read_hook = read_hook;
54 57
... ... @@ -62,9 +65,9 @@ __tearDown()
62 65 {
63 66 level = -1;
64 67
65   - if (NULL != msg) {
66   - free(msg);
67   - msg = NULL;
  68 + if (NULL != server) {
  69 + ASSERT_OBJECT(server);
  70 + delete(&server);
68 71 }
69 72
70 73 if (NULL != logger) {
... ... @@ -72,11 +75,6 @@ __tearDown()
72 75 delete(&logger);
73 76 }
74 77
75   - if (NULL != server) {
76   - ASSERT_OBJECT(server);
77   - delete(&server);
78   - }
79   -
80 78 return TEST_OK;
81 79 }
82 80 int (* const tearDown)() = __tearDown;
... ... @@ -85,6 +83,32 @@ static
85 83 int
86 84 testDummy()
87 85 {
  86 + SOCK con;
  87 + pid_t pid;
  88 + int status;
  89 +
  90 + pid = fork();
  91 +
  92 + switch(pid) {
  93 + case 0:
  94 + con = new(SOCK, logger, TEST_PORT);
  95 + sleep(1);
  96 + sock_connect(con, "127.0.0.1");
  97 + write(con->handle, TEST_DATA, strlen(TEST_DATA)+1);
  98 + delete(&con);
  99 + __tearDown();
  100 + exit(EXIT_SUCCESS);
  101 +
  102 + case -1:
  103 + return TEST_FAILED;
  104 +
  105 + default:
  106 + init_signals();
  107 + server_run(server);
  108 + }
  109 +
  110 + ASSERT_STRING_EQUAL(TEST_DATA, buffer);
  111 +
88 112 return TEST_OK;
89 113 }
90 114
... ...
... ... @@ -8,7 +8,7 @@
8 8 #include "socket.h"
9 9
10 10
11   -#define TEST_PORT 11212
  11 +#define TEST_PORT 11213
12 12
13 13
14 14 int level = -1;
... ... @@ -98,7 +98,6 @@ testAccept()
98 98 delete(&con);
99 99 __tearDown();
100 100 exit(EXIT_SUCCESS);
101   - break;
102 101
103 102 case -1:
104 103 return TEST_FAILED;
... ...
Please register or login to post a comment