Commit c33578329ce7476f9fa0a667eb864abcecc45a09

Authored by Georg Hopp
1 parent fb0dd8ad

changed from select(UNIX) to poll(POSIX)

@@ -2,20 +2,24 @@ @@ -2,20 +2,24 @@
2 #define __SERVER_H__ 2 #define __SERVER_H__
3 3
4 #include <stdio.h> /* for printf() and fprintf() */ 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 #include "socket.h" 7 #include "socket.h"
8 #include "logger.h" 8 #include "logger.h"
9 #include "cclass.h" 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 typedef void (*server_read_hook)(const char *); 16 typedef void (*server_read_hook)(const char *);
13 17
14 CLASS(SERVER) { 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 struct { 24 struct {
21 SOCK sock; 25 SOCK sock;
@@ -23,14 +27,13 @@ CLASS(SERVER) { @@ -23,14 +27,13 @@ CLASS(SERVER) {
23 char * rbuf; 27 char * rbuf;
24 unsigned int rpos; 28 unsigned int rpos;
25 unsigned int wpos; 29 unsigned int wpos;
26 - } conns[FD_SETSIZE]; 30 + } conns[POLL_FD_NSIZE];
27 31
28 server_read_hook read_hook; 32 server_read_hook read_hook;
29 }; 33 };
30 34
31 void server_run(SERVER this); 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 #endif // __SERVER_H__ 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 #include <string.h> /* for memset and stuff */ 2 #include <string.h> /* for memset and stuff */
3 #include <stdlib.h> /* for getopt */ 3 #include <stdlib.h> /* for getopt */
4 4
@@ -8,7 +8,6 @@ @@ -8,7 +8,6 @@
8 #include "logger.h" 8 #include "logger.h"
9 #include "cclass.h" 9 #include "cclass.h"
10 10
11 -  
12 INIT_CLASS(SERVER); 11 INIT_CLASS(SERVER);
13 12
14 __construct(SERVER) 13 __construct(SERVER)
@@ -20,27 +19,23 @@ __construct(SERVER) @@ -20,27 +19,23 @@ __construct(SERVER)
20 port = va_arg(* params, int); 19 port = va_arg(* params, int);
21 backlog = va_arg(* params, unsigned int); 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 sock_listen(this->sock, backlog); 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 __destruct(SERVER) 30 __destruct(SERVER)
33 { 31 {
34 int i; 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 delete(&this->sock); 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 #include <string.h> /* for memset and stuff */ 2 #include <string.h> /* for memset and stuff */
3 #include <stdlib.h> /* for exit */ 3 #include <stdlib.h> /* for exit */
4 #include <errno.h> /* for errno */ 4 #include <errno.h> /* for errno */
@@ -13,17 +13,14 @@ @@ -13,17 +13,14 @@
13 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 13 #define MAX(x,y) ((x) > (y) ? (x) : (y))
14 14
15 static 15 static
16 -fd_set 16 +int
17 server_select(SERVER this) { 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 * wait for handles to become ready 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 switch (errno) { 24 switch (errno) {
28 default: 25 default:
29 case EBADF: 26 case EBADF:
@@ -36,56 +33,48 @@ server_select(SERVER this) { @@ -36,56 +33,48 @@ server_select(SERVER this) {
36 logger_log(this->logger, LOGGER_CRIT, 33 logger_log(this->logger, LOGGER_CRIT,
37 "select systemcall failed: [%s] - service terminated", 34 "select systemcall failed: [%s] - service terminated",
38 strerror(errno)); 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 static 43 static
47 void 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 char remoteAddr[16] = ""; 48 char remoteAddr[16] = "";
53 SOCK acc; 49 SOCK acc;
54 50
55 acc = sock_accept(this->sock, remoteAddr); 51 acc = sock_accept(this->sock, remoteAddr);
56 52
57 if (-1 != acc->handle) { 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 } else { 58 } else {
62 delete(&acc); 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 static 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 int 67 int
79 -server_read(SERVER this, fd_set * rfds) 68 +server_read(SERVER this)
80 { 69 {
81 unsigned int i; 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 memset(buffer, 0, 1024); 76 memset(buffer, 0, 1024);
88 - switch (_read = read(i, buffer, 1023)) { 77 + switch (_read = read((this->fds)[i].fd, buffer, 1023)) {
89 case 0: 78 case 0:
90 /* 79 /*
91 * normal close: write remaining data 80 * normal close: write remaining data
@@ -101,6 +90,7 @@ server_read(SERVER this, fd_set * rfds) @@ -101,6 +90,7 @@ server_read(SERVER this, fd_set * rfds)
101 break; 90 break;
102 91
103 default: 92 default:
  93 + (this->fds)[i].revents |= POLLIN;
104 if (NULL != this->read_hook) { 94 if (NULL != this->read_hook) {
105 this->read_hook(buffer); 95 this->read_hook(buffer);
106 } 96 }
@@ -116,24 +106,27 @@ void @@ -116,24 +106,27 @@ void
116 server_run(SERVER this) 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 logger_log(this->logger, LOGGER_INFO, "service started"); 111 logger_log(this->logger, LOGGER_INFO, "service started");
122 112
123 while (!doShutdown) /* until error or signal */ 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 * handle accept 124 * handle accept
132 */ 125 */
133 - server_handle_accept(this, &rfds); 126 + server_handle_accept(this);
134 127
135 /* handle reads */ 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,17 +32,9 @@ sock_accept(SOCK this, char remoteAddr[16])
32 logger_log(this->logger, LOGGER_WARNING, 32 logger_log(this->logger, LOGGER_WARNING,
33 "error acception connection: %s", strerror(errno)); 33 "error acception connection: %s", strerror(errno));
34 } else { 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 logger_log(this->logger, LOGGER_INFO, 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 return sock; 39 return sock;
48 } 40 }
@@ -4,18 +4,24 @@ TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet @@ -4,18 +4,24 @@ TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet
4 TESTS = cclassTest loggerTest socketTest serverTest 4 TESTS = cclassTest loggerTest socketTest serverTest
5 check_PROGRAMS = cclassTest loggerTest socketTest serverTest 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 cclassTest_CFLAGS = -Wall -ggdb -O0 -finline-functions -I ../include -I .. -I . 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 loggerTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . 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 socketTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . 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 serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . 25 serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I .
20 26
21 EXTRA_DIST = runtest.h mock/class.h 27 EXTRA_DIST = runtest.h mock/class.h
1 #include <stdio.h> 1 #include <stdio.h>
2 #include <stdlib.h> 2 #include <stdlib.h>
  3 +#include <unistd.h>
  4 +#include <signal.h>
3 5
4 #include "runtest.h" 6 #include "runtest.h"
5 #include "logger.h" 7 #include "logger.h"
6 #include "cclass.h" 8 #include "cclass.h"
7 #include "server.h" 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 static void 21 static void
18 read_hook(const char * _buffer) 22 read_hook(const char * _buffer)
19 { 23 {
20 if (NULL != _buffer) { 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 static void 31 static void
27 logfnct_mock(int _level, const char * _msg) 32 logfnct_mock(int _level, const char * _msg)
28 { 33 {
29 level = _level; 34 level = _level;
30 - msg = malloc(strlen(_msg) + 1);  
31 - strcpy(msg, _msg); 35 + strncpy(msg, _msg, 1023);
32 } 36 }
33 37
34 const char testname[] = "serverTest"; 38 const char testname[] = "serverTest";
@@ -48,7 +52,6 @@ __setUp() @@ -48,7 +52,6 @@ __setUp()
48 ASSERT_INSTANCE_OF(LOGGER, server->logger); 52 ASSERT_INSTANCE_OF(LOGGER, server->logger);
49 ASSERT_INSTANCE_OF(SOCK, server->sock); 53 ASSERT_INSTANCE_OF(SOCK, server->sock);
50 ASSERT_EQUAL(TEST_PORT, server->sock->port); 54 ASSERT_EQUAL(TEST_PORT, server->sock->port);
51 - ASSERT_EQUAL(server->max_fd, server->sock->handle);  
52 55
53 server->read_hook = read_hook; 56 server->read_hook = read_hook;
54 57
@@ -62,9 +65,9 @@ __tearDown() @@ -62,9 +65,9 @@ __tearDown()
62 { 65 {
63 level = -1; 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 if (NULL != logger) { 73 if (NULL != logger) {
@@ -72,11 +75,6 @@ __tearDown() @@ -72,11 +75,6 @@ __tearDown()
72 delete(&logger); 75 delete(&logger);
73 } 76 }
74 77
75 - if (NULL != server) {  
76 - ASSERT_OBJECT(server);  
77 - delete(&server);  
78 - }  
79 -  
80 return TEST_OK; 78 return TEST_OK;
81 } 79 }
82 int (* const tearDown)() = __tearDown; 80 int (* const tearDown)() = __tearDown;
@@ -85,6 +83,32 @@ static @@ -85,6 +83,32 @@ static
85 int 83 int
86 testDummy() 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 return TEST_OK; 112 return TEST_OK;
89 } 113 }
90 114
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 #include "socket.h" 8 #include "socket.h"
9 9
10 10
11 -#define TEST_PORT 11212 11 +#define TEST_PORT 11213
12 12
13 13
14 int level = -1; 14 int level = -1;
@@ -98,7 +98,6 @@ testAccept() @@ -98,7 +98,6 @@ testAccept()
98 delete(&con); 98 delete(&con);
99 __tearDown(); 99 __tearDown();
100 exit(EXIT_SUCCESS); 100 exit(EXIT_SUCCESS);
101 - break;  
102 101
103 case -1: 102 case -1:
104 return TEST_FAILED; 103 return TEST_FAILED;
Please register or login to post a comment