server_run.c
2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#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 */
#include <unistd.h>
#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
int
server_select(SERVER this) {
int events;
/*
* wait for handles to become ready
*/
if (-1 == (events = poll(this->fds, this->nfds, -1))) {
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 events;
}
static
void
server_handle_accept(SERVER this)
{
if (0 != ((this->fds)[0].revents & POLLIN)) {
char remoteAddr[16] = "";
SOCK acc;
acc = sock_accept(this->sock, remoteAddr);
if (-1 != acc->handle) {
(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);
}
(this->fds)[0].revents |= POLLIN;
}
}
static
int
server_read(SERVER this)
{
unsigned int i;
size_t _read;
char buffer[1024];
for (i=1; i<this->nfds; i++) {
if (0 != ((this->fds)[i].revents & POLLIN)) {
memset(buffer, 0, 1024);
switch (_read = read((this->fds)[i].fd, buffer, 1023)) {
case 0:
/*
* normal close: write remaining data
*/
/* FALLTHROUGH */
case -1:
/*
* read failure / close connection
* FALLTHROUGH
*/
server_close_conn(this, i);
break;
default:
(this->fds)[i].revents |= POLLIN;
if (NULL != this->read_hook) {
this->read_hook(buffer);
}
break;
}
}
}
return 0;
}
void
server_run(SERVER this)
{
/*
* @TODO again...add verbosity to logger....
*/
logger_log(this->logger, LOGGER_INFO, "service started");
while (!doShutdown) /* until error or signal */
{
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);
/* handle reads */
server_read(this);
}
}
// vim: set ts=4 sw=4: