From c6635e3904476c1ccd7b2e045840a73791a97d6b Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Mon, 16 Jan 2012 16:04:11 +0100 Subject: [PATCH] more work on socket handling stuff... @TODO think about renaming it to connection as it only handles TCP sockets --- include/socket.h | 3 +- src/server.c | 2 +- src/socket.c | 90 +++++++------------------------------------- src/socket_accept.c | 50 ++++++++++++++++++++++++ src/socket_connect.c | 31 +++++++++++++++ src/socket_listen.c | 40 ++++++++++++++++++++ tests/Makefile.am | 14 +++---- tests/runtest.c | 2 +- tests/socketTest.c | 45 ++++++++++++++++++---- 9 files changed, 181 insertions(+), 96 deletions(-) create mode 100644 src/socket_accept.c create mode 100644 src/socket_connect.c create mode 100644 src/socket_listen.c diff --git a/include/socket.h b/include/socket.h index 7e5d4b3..5c353aa 100644 --- a/include/socket.h +++ b/include/socket.h @@ -14,7 +14,8 @@ CLASS(SOCK) { int handle; /* socket handle for server */ }; -void sock_initServer(SOCK this, int backlog); +void sock_connect(SOCK this, const char * addr); +void sock_listen(SOCK this, int backlog); SOCK sock_accept(SOCK this, char remoteAddr[16]); #endif /* __SOCKET_H__ */ diff --git a/src/server.c b/src/server.c index bb12637..63f4614 100644 --- a/src/server.c +++ b/src/server.c @@ -23,7 +23,7 @@ __construct(SERVER) FD_ZERO(&(this->fdset)); this->sock = new(SOCK, port); - sock_initServer(this->sock, backlog); + sock_listen(this->sock, backlog); this->max_fd = this->sock->handle; FD_SET(this->sock->handle, &(this->fdset)); diff --git a/src/socket.c b/src/socket.c index 3331734..15b25ff 100644 --- a/src/socket.c +++ b/src/socket.c @@ -17,28 +17,10 @@ INIT_CLASS(SOCK); __construct(SOCK) { - this->logger = va_arg(* params, struct _logger *); - this->port = va_arg(* params, int); -} - -__destruct(SOCK) -{ - if (0 != this->handle) { - shutdown(this->handle, SHUT_RDWR); - close(this->handle); - } -} - -__jsonConst(SOCK) {} -__toJson(SOCK) {} -__clear(SOCK) {} + int reUse = 1; /* TODO: make this configurable */ - -void -sock_initServer(SOCK this, int backlog) -{ - struct sockaddr_in addr; /* Local address */ - int reUse = 1; /* TODO: make this configurable */ + this->logger = va_arg(* params, LOGGER); + this->port = va_arg(* params, int); /* Create socket for incoming connections */ if (-1 == (this->handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { @@ -48,66 +30,20 @@ sock_initServer(SOCK this, int backlog) exit(EXIT_FAILURE); } - /* Make the socket REUSE a TIME_WAT socket */ + /* Make the socket REUSE a TIME_WAIT socket */ setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof (reUse)); - - /* Construct local address structure */ - memset(&addr, 0, sizeof(addr)); /* Zero out structure */ - - addr.sin_family = AF_INET; /* Internet address family */ - addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ - addr.sin_port = htons(this->port); /* Local port */ - - /* Bind to the local address */ - if (-1 == bind(this->handle, (struct sockaddr *) &addr, sizeof(addr))) { - logger_log(this->logger, LOGGER_CRIT, - "error binding socket: %s - service terminated", - strerror(errno)); - exit(EXIT_FAILURE); - } - - /* Mark the socket so it will listen for incoming connections */ - if (-1 == listen(this->handle, backlog)) { - logger_log(this->logger, LOGGER_CRIT, - "error binding socket: %s - service terminated", - strerror(errno)); - exit(EXIT_FAILURE); - } } -SOCK -sock_accept(SOCK this, char remoteAddr[16]) +__destruct(SOCK) { - SOCK sock; /* Socket for client */ - struct sockaddr_in addr; /* Client address */ - unsigned int len; /* Length of client address data structure */ - - /* Set the size of the in-out parameter */ - len = sizeof(addr); - - sock = new(SOCK, this->logger, this->port); - /** - * @TODO: change port to remote port on success - */ - - /* Wait for a client to connect */ - if (-1 == (sock->handle = accept(this->handle, (struct sockaddr *) &addr, &len))) { - logger_log(this->logger, LOGGER_WARNING, - "error acception connection: %s", strerror(errno)); - } else { - strncpy (remoteAddr, inet_ntoa(addr.sin_addr), sizeof(remoteAddr)-1); - } - - /* clntSock is connected to a client! */ - /** - * @TODO add verbosity level to logger - */ -// if (0 != this->logger->verbose) { - logger_log(this->logger, LOGGER_INFO, - "handling client %s\n", inet_ntoa(addr.sin_addr)); -// } - - return sock; + if (0 != this->handle) { + shutdown(this->handle, SHUT_RDWR); + close(this->handle); + } } +__jsonConst(SOCK) {} +__toJson(SOCK) {} +__clear(SOCK) {} + // vim: set ts=4 sw=4: diff --git a/src/socket_accept.c b/src/socket_accept.c new file mode 100644 index 0000000..ba7a15a --- /dev/null +++ b/src/socket_accept.c @@ -0,0 +1,50 @@ +#include /* for printf() and fprintf() */ +#include /* SO_REUSEADDR */ +#include /* for socket(), bind(), and connect() */ +#include /* for sockaddr_in and inet_ntoa() */ +#include /* for atoi() and exit() */ +#include /* for memset() */ +#include /* for close() */ +#include /* for errno */ +#include + +#include "logger.h" +#include "cclass.h" +#include "socket.h" + +SOCK +sock_accept(SOCK this, char remoteAddr[16]) +{ + SOCK sock; /* Socket for client */ + unsigned int len; /* Length of client address data structure */ + + /* Set the size of the in-out parameter */ + len = sizeof(this->addr); + + sock = new(SOCK, this->logger, this->port); + /** + * @TODO: change port to remote port on success + */ + + /* Wait for a client to connect */ + sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len); + if (-1 == sock->handle) { + logger_log(this->logger, LOGGER_WARNING, + "error acception connection: %s", strerror(errno)); + } else { + strncpy (remoteAddr, inet_ntoa((sock->addr).sin_addr), sizeof(remoteAddr)-1); + } + + /* clntSock is connected to a client! */ + /** + * @TODO add verbosity level to logger + */ +// if (0 != this->logger->verbose) { + logger_log(this->logger, LOGGER_INFO, + "handling client %s\n", inet_ntoa((this->addr).sin_addr)); +// } + + return sock; +} + +// vim: set ts=4 sw=4: diff --git a/src/socket_connect.c b/src/socket_connect.c new file mode 100644 index 0000000..41ed76b --- /dev/null +++ b/src/socket_connect.c @@ -0,0 +1,31 @@ +#include /* for printf() and fprintf() */ +#include /* SO_REUSEADDR */ +#include /* for socket(), bind(), and connect() */ +#include /* for sockaddr_in and inet_ntoa() */ +#include /* for atoi() and exit() */ +#include /* for memset() */ +#include /* for close() */ +#include /* for errno */ +#include + +#include "logger.h" +#include "cclass.h" +#include "socket.h" + + +void +sock_connect(SOCK this, const char * addr) +{ + inet_pton(AF_INET, addr, &((this->addr).sin_addr)); + (this->addr).sin_family = AF_INET; /* Internet address family */ + (this->addr).sin_port = htons(this->port); /* Local port */ + + if (-1 == connect(this->handle, (struct sockaddr*) &(this->addr), sizeof(this->addr))) { + logger_log(this->logger, LOGGER_CRIT, + "error connection socket: %s - service terminated", + strerror(errno)); + exit(EXIT_FAILURE); + } +} + +// vim: set ts=4 sw=4: diff --git a/src/socket_listen.c b/src/socket_listen.c new file mode 100644 index 0000000..847816e --- /dev/null +++ b/src/socket_listen.c @@ -0,0 +1,40 @@ +#include /* for printf() and fprintf() */ +#include /* SO_REUSEADDR */ +#include /* for socket(), bind(), and connect() */ +#include /* for sockaddr_in and inet_ntoa() */ +#include /* for atoi() and exit() */ +#include /* for memset() */ +#include /* for close() */ +#include /* for errno */ +#include + +#include "logger.h" +#include "cclass.h" +#include "socket.h" + + +void +sock_listen(SOCK this, int backlog) +{ + (this->addr).sin_family = AF_INET; /* Internet address family */ + (this->addr).sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ + (this->addr).sin_port = htons(this->port); /* Local port */ + + /* Bind to the local address */ + if (-1 == bind(this->handle, (struct sockaddr *) &(this->addr), sizeof(this->addr))) { + logger_log(this->logger, LOGGER_CRIT, + "error binding socket: %s - service terminated", + strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Mark the socket so it will listen for incoming connections */ + if (-1 == listen(this->handle, backlog)) { + logger_log(this->logger, LOGGER_CRIT, + "error binding socket: %s - service terminated", + strerror(errno)); + exit(EXIT_FAILURE); + } +} + +// vim: set ts=4 sw=4: diff --git a/tests/Makefile.am b/tests/Makefile.am index 7d4277c..1cb9e3f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,20 +4,18 @@ TESTS_ENVIRONMENT = valgrind --error-exitcode=123 --leak-check=full --quiet TESTS = cclassTest loggerTest socketTest serverTest check_PROGRAMS = cclassTest loggerTest socketTest serverTest -cclassTest_SOURCES = runtest.c cclassTest.c mock/class.c ../src/cclass.c -cclassTest_LDADD = $(LIBOBJS) +SOURCES = runtest.c ../src/cclass.c + +cclassTest_SOURCES = $(SOURCES) cclassTest.c mock/class.c cclassTest_CFLAGS = -Wall -ggdb -O0 -finline-functions -I ../include -I .. -I . -loggerTest_SOURCES = runtest.c loggerTest.c ../src/cclass.c ../src/logger.c -loggerTest_LDADD = $(LIBOBJS) +loggerTest_SOURCES = $(SOURCES) loggerTest.c ../src/logger.c loggerTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . -socketTest_SOURCES = runtest.c socketTest.c ../src/cclass.c ../src/logger.c ../src/socket.c -socketTest_LDADD = $(LIBOBJS) +socketTest_SOURCES = $(SOURCES) socketTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/socket_connect.c socketTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . -serverTest_SOURCES = runtest.c serverTest.c ../src/cclass.c ../src/logger.c ../src/socket.c ../src/server.c -serverTest_LDADD = $(LIBOBJS) +serverTest_SOURCES = $(SOURCES) serverTest.c ../src/logger.c ../src/socket.c ../src/socket_listen.c ../src/socket_accept.c ../src/server.c serverTest_CFLAGS = -Wall -ggdb -O0 -I ../include -I .. -I . EXTRA_DIST = runtest.h mock/class.h diff --git a/tests/runtest.c b/tests/runtest.c index 500f80d..b363cc8 100644 --- a/tests/runtest.c +++ b/tests/runtest.c @@ -67,7 +67,7 @@ main(int argc, char * argv[]) { size_t errors = 0; size_t failures = 0; - size_t assertions = 0; + // size_t assertions = 0; // @TODO find a way to count assertions size_t index; diff --git a/tests/socketTest.c b/tests/socketTest.c index a4da5db..a452121 100644 --- a/tests/socketTest.c +++ b/tests/socketTest.c @@ -1,5 +1,6 @@ #include #include +#include #include "runtest.h" #include "logger.h" @@ -37,6 +38,7 @@ __setUp() ASSERT_INSTANCE_OF(SOCK, sock); ASSERT_INSTANCE_OF(LOGGER, sock->logger); ASSERT_EQUAL(TEST_PORT, sock->port); + ASSERT_NOT_EQUAL(0, sock->handle); return TEST_OK; } @@ -69,11 +71,9 @@ int (* const tearDown)() = __tearDown; static int -testInitServer() +testListen() { - sock_initServer(sock, 10); - - ASSERT_NOT_NULL(sock->handle); + sock_listen(sock, 10); return TEST_OK; } @@ -82,13 +82,42 @@ static int testAccept() { - /* - * @TODO ... - */ + SOCK acc, con; + char addr[16]; + pid_t pid; + + sock_listen(sock, 10); + + pid = fork(); + + switch(pid) { + case 0: + con = new(SOCK, logger, TEST_PORT); + sleep(1); + sock_connect(con, "127.0.0.1"); + delete(&con); + __tearDown(); + exit(EXIT_SUCCESS); + break; + + case -1: + return TEST_FAILED; + + default: + acc = sock_accept(sock, addr); + } + + if (NULL != acc) { + ASSERT_OBJECT(acc); + delete(&acc); + } + + return TEST_OK; } const testfunc tests[] = { - testInitServer + testListen, + testAccept }; const size_t count = FUNCS_COUNT(tests);