Browse Source

more work on socket handling stuff... @TODO think about renaming it to connection as it only handles TCP sockets

master
Georg Hopp 14 years ago
parent
commit
c6635e3904
  1. 3
      include/socket.h
  2. 2
      src/server.c
  3. 90
      src/socket.c
  4. 50
      src/socket_accept.c
  5. 31
      src/socket_connect.c
  6. 40
      src/socket_listen.c
  7. 14
      tests/Makefile.am
  8. 2
      tests/runtest.c
  9. 45
      tests/socketTest.c

3
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__ */

2
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));

90
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:

50
src/socket_accept.c

@ -0,0 +1,50 @@
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/types.h> /* SO_REUSEADDR */
#include <sys/socket.h> /* for socket(), bind(), and connect() */
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <errno.h> /* for errno */
#include <stdarg.h>
#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:

31
src/socket_connect.c

@ -0,0 +1,31 @@
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/types.h> /* SO_REUSEADDR */
#include <sys/socket.h> /* for socket(), bind(), and connect() */
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <errno.h> /* for errno */
#include <stdarg.h>
#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:

40
src/socket_listen.c

@ -0,0 +1,40 @@
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/types.h> /* SO_REUSEADDR */
#include <sys/socket.h> /* for socket(), bind(), and connect() */
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <errno.h> /* for errno */
#include <stdarg.h>
#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:

14
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

2
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;

45
tests/socketTest.c

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#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);

Loading…
Cancel
Save