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