6 changed files with 164 additions and 22 deletions
-
9include/server.h
-
140src/server_run.c
-
9src/signalHandling.c
-
4src/socket_accept.c
-
2tests/Makefile.am
-
22tests/serverTest.c
@ -0,0 +1,140 @@ |
|||
#include <sys/select.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 |
|||
fd_set |
|||
server_select(SERVER this) { |
|||
fd_set rfds; |
|||
|
|||
memcpy(&rfds, &(this->fdset), sizeof(fd_set)); |
|||
|
|||
/* |
|||
* wait for handles to become ready |
|||
*/ |
|||
if (-1 == select((this->max_fd)+1, &rfds, NULL, NULL, NULL)) |
|||
{ |
|||
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 rfds; |
|||
} |
|||
|
|||
static |
|||
void |
|||
server_handle_accept(SERVER this, fd_set * rfds) |
|||
{ |
|||
if (FD_ISSET(this->sock->handle, rfds)) { |
|||
int fd; |
|||
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); |
|||
} else { |
|||
delete(&acc); |
|||
} |
|||
|
|||
FD_CLR(this->sock->handle, rfds); |
|||
} |
|||
} |
|||
|
|||
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) |
|||
{ |
|||
unsigned int i; |
|||
size_t _read; |
|||
char buffer[1024]; |
|||
|
|||
for (i=3; i<=this->max_fd; i++) { |
|||
if (FD_ISSET(i, rfds)) { |
|||
memset(buffer, 0, 1024); |
|||
switch (_read = read(i, buffer, 1023)) { |
|||
case 0: |
|||
/* |
|||
* normal close: write remaining data |
|||
*/ |
|||
/* FALLTHROUGH */ |
|||
|
|||
case -1: |
|||
/* |
|||
* read failure / close connection |
|||
* FALLTHROUGH |
|||
*/ |
|||
server_close_conn(this, i); |
|||
break; |
|||
|
|||
default: |
|||
if (NULL != this->read_hook) { |
|||
this->read_hook(buffer); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void |
|||
server_run(SERVER this) |
|||
{ |
|||
/* |
|||
* @TODO again a hint...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); |
|||
|
|||
/* |
|||
* handle accept |
|||
*/ |
|||
server_handle_accept(this, &rfds); |
|||
|
|||
/* handle reads */ |
|||
server_read(this, &rfds); |
|||
} |
|||
} |
|||
|
|||
// vim: set ts=4 sw=4: |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue