Browse Source

changed class tool. Now multiple interface per class are supported as well as simple inheritence.

master
Georg Hopp 14 years ago
parent
commit
2d6305c3d6
  1. 98
      include/cclass.h
  2. 81
      include/class.h
  3. 39
      include/interface.h
  4. 30
      include/interface/class.h
  5. 22
      include/interface/logger.h
  6. 49
      include/logger.h
  7. 14
      include/server.h
  8. 20
      include/socket.h
  9. 119
      src/cclass.c
  10. 28
      src/class.c
  11. 6
      src/daemonize.c
  12. 45
      src/interface.c
  13. 43
      src/interface/class.c
  14. 37
      src/interface/logger.c
  15. 35
      src/logger.c
  16. 11
      src/logger/add.c
  17. 30
      src/logger/log.c
  18. 16
      src/logger/stderr.c
  19. 31
      src/logger/syslog.c
  20. 29
      src/server.c
  21. 3
      src/server/close_conn.c
  22. 34
      src/server/run.c
  23. 63
      src/socket.c
  24. 24
      src/socket/accept.c
  25. 15
      src/socket/connect.c
  26. 17
      src/socket/listen.c
  27. 10
      src/testserver.c

98
include/cclass.h

@ -1,98 +0,0 @@
/**
* \file
* cclass.h: basic "class-like" handling of code and data structures
* Copyright (C) 2011 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CCLASS_H__
#define __CCLASS_H__
#include <stdarg.h>
#include <sys/types.h>
#include <json/json.h>
#define CCLASS_MAGIC 0xFEFE
typedef void (* ctor)(void *, va_list *);
typedef void (* clr)(void *);
typedef void (* dtor)(void *);
typedef void (* jCtor)(void *, struct json_object *);
typedef void (* jTo)(void *, struct json_object **);
typedef struct _CCLASS {
const int magic;
size_t size;
ctor __construct;
clr __clear;
dtor __destruct;
jCtor __jsonConst;
jTo __toJson;
} * CCLASS;
#define CCLASS_SIZE sizeof(struct _CCLASS)
#define CCLASS_PTR_SIZE sizeof(CCLASS)
#define __construct(_class) \
static void __construct(_class this, va_list * params)
#define __clear(_class) \
static void __clear(_class this)
#define __destruct(_class) \
static void __destruct(_class this)
#define __jsonConst(_class) \
static void __jsonConst(_class this, struct json_object * json)
#define __toJson(_class) \
static void __toJson(_class this, struct json_object ** json)
#define CLASS(_class) \
struct _##_class; \
typedef struct _##_class * _class; \
extern const CCLASS const __##_class; \
struct _##_class
#define INIT_CLASS(_class) \
__construct(_class); \
__clear(_class); \
__destruct(_class); \
__jsonConst(_class); \
__toJson(_class); \
static const struct _CCLASS _cclass = { \
CCLASS_MAGIC, \
sizeof(struct _##_class), \
(ctor)__construct, \
(clr)__clear, \
(dtor)__destruct, \
(jCtor)__jsonConst, \
(jTo)__toJson \
}; const CCLASS __##_class = (const CCLASS)&_cclass
void * _new(const CCLASS _class, ...);
#define new(_class, ...) _new((__##_class), __VA_ARGS__)
void * _newFromJson(const CCLASS _class, struct json_object * json);
#define newFromJson(_class, json) _newFromJson((__##_class), (json))
int _instanceOf(const CCLASS _class, void * _object);
#define instanceOf(_class, object) _instanceOf((__##_class), (object))
void clear(void * _object);
void delete(void * _object);
void toJson(void * _object, struct json_object ** json);
int isObject(void * _object);
#endif//__CCLASS_H__
// vim: set et ts=4 sw=4:

81
include/class.h

@ -0,0 +1,81 @@
#ifndef __CLASS_H__
#define __CLASS_H__
#include <stdarg.h>
#include <sys/types.h>
#include <string.h>
#include <assert.h>
#include "interface.h"
#define _ISOC99_SOURCE
#define CLASS_MAGIC 0xFEFE
#define CLASS(name) \
struct c_##name; \
typedef struct c_##name * name; \
extern struct class * const _##name; \
struct c_##name
#define EXTENDS(parent) \
const char _[sizeof(struct c_##parent)]
#define _NULL NULL
#define CREATE_CLASS(name,_parent,...) \
static struct class c_##name; \
static void _classInit_(void) { \
c_##name.parent = _##_parent; \
c_##name.init = NULL; \
} \
static struct class c_##name = { \
CLASS_MAGIC, \
NULL, \
sizeof(struct c_##name), \
_classInit_, \
INIT_IMPL(__VA_ARGS__) \
}; struct class * const _##name = &c_##name
/**
* @TODO: actually i use gcc feature ## for variadoc... think about
* a way to make this standard.
*/
#define CALL(object,_iface,method,...) \
do { \
class_ptr class = class_getClass((object)); \
struct i_##_iface * iface; \
if (class->init) class->init(); \
iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
while ((NULL == iface || NULL == iface->method) && HAS_PARENT(class)) { \
class = class->parent; \
if (class->init) class->init(); \
iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
}; \
assert(NULL != iface->method); \
iface->method(object, ##__VA_ARGS__); \
} while(0)
#define IFACE_GET(class,iface) (interfaceGet(&((class)->impl),(iface)))
#define IFACE_EXISTS(class,iface) (NULL != IFACE_GET((class),(iface)))
#define HAS_PARENT(class) (NULL != ((class)->parent))
typedef void (* fptr_classInit)(void);
struct class;
typedef struct class * class_ptr;
struct class {
const int magic;
class_ptr parent;
size_t object_size;
fptr_classInit init;
struct iface_impl impl;
};
extern inline void * class_getInterface(class_ptr *, iface_ptr);
extern inline class_ptr class_getClass(void *);
#endif // __CLASS_H__
// vim: set ts=4 sw=4:

39
include/interface.h

@ -0,0 +1,39 @@
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
#include <sys/types.h>
#define MAX_IFACE 32 // ATTENTION: every iface_impl will use MAX_IFACE * sizeof(void*)
#define IFACE(name) ((const struct i_##name const*)&i_##name##_impl)
#define INIT_IFACE(name,...) \
static const struct i_##name i_##name##_impl = {&i_##name,__VA_ARGS__}
#define NUMARGS(...) (sizeof((const void*[]){__VA_ARGS__})/sizeof(void*))
#define INIT_IMPL(...) {NUMARGS(__VA_ARGS__), 0, {__VA_ARGS__}}
#define CREATE_IMPL(...) \
static struct iface_impl iface_impl = INIT_IMPL(__VA_ARGS__)
#define METHOD_GET(iface,method) (iface->method)
struct interface {
const char * name;
const size_t nmethods;
};
typedef const struct interface * iface_ptr;
struct iface_impl {
const size_t nimpl; // number of interface implementations
char simpl; // implementations sorted??
const void * impl[MAX_IFACE]; // implementations
};
typedef struct iface_impl * iface_impl_ptr;
extern struct interface * interfaceGet(iface_impl_ptr, const iface_ptr);
#endif // __INTERFACE_H__
// vim: set ts=4 sw=4:

30
include/interface/class.h

@ -0,0 +1,30 @@
#ifndef __INTERFACE_CLASS_H__
#define __INTERFACE_CLASS_H__
#include <stdarg.h>
#include "class.h"
#include "interface.h"
typedef void (* fptr_ctor)(void *, va_list *);
typedef void (* fptr_dtor)(void *);
typedef void (* fptr_clone)(void *, const void * const);
extern const struct interface i_Class;
struct i_Class {
const struct interface * const _;
fptr_ctor ctor;
fptr_dtor dtor;
fptr_clone clone;
};
extern inline void * classNew(class_ptr, ...);
extern inline void classDelete(void **);
#define new(class,...) classNew(_##class, __VA_ARGS__)
#define delete(object) classDelete((void **)(object))
#endif // __INTERFACE_CLASS_H__
// vim: set ts=4 sw=4:

22
include/interface/logger.h

@ -0,0 +1,22 @@
#ifndef __INTERFACE_LOGGER_H__
#define __INTERFACE_LOGGER_H__
#include <stdarg.h>
#include "interface.h"
#include "logger.h"
typedef void (* fptr_log)(void *, logger_level, const char * const);
extern const struct interface i_Logger;
struct i_Logger {
const struct interface * const _;
fptr_log log;
};
extern inline void loggerLog(void *, logger_level, const char * const, ...);
#endif // __INTERFACE_LOGGER_H__
// vim: set ts=4 sw=4:

49
include/logger.h

@ -1,34 +1,33 @@
#ifndef __LOGGER_H__ #ifndef __LOGGER_H__
#define __LOGGER_H__ #define __LOGGER_H__
#include "cclass.h"
#define LOGGER_EMERG 0
#define LOGGER_ALERT 1
#define LOGGER_CRIT 2
#define LOGGER_ERR 3
#define LOGGER_WARNING 4
#define LOGGER_NOTICE 5
#define LOGGER_INFO 6
#define LOGGER_DEBUG 7
#define MAX_LOG_FNCTS 10
typedef void (*logger_logfnct)(int level, const char * msg);
CLASS(LOGGER) {
logger_logfnct logfncts[MAX_LOG_FNCTS];
unsigned int logfncts_count;
#include "class.h"
typedef enum logger_level {
LOGGER_DEBUG=0,
LOGGER_INFO,
LOGGER_NOTICE,
LOGGER_WARNING,
LOGGER_ERR,
LOGGER_CRIT,
LOGGER_ALERT,
LOGGER_EMERG
} logger_level;
extern const char * const logger_level_str[];
CLASS(Logger) {
logger_level min_level;
}; };
void logger_log(LOGGER this, int level, const char * msg, ...)
__attribute__((format (printf, 3, 4)));
CLASS(LoggerStderr) {
EXTENDS(Logger);
};
void logger_add(LOGGER this, logger_logfnct logfunc);
CLASS(LoggerSyslog) {
EXTENDS(Logger);
};
#endif /* __LOGGER_H__ */
#endif // __LOGGER_H__
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

14
include/server.h

@ -4,9 +4,9 @@
#include <stdio.h> /* for printf() and fprintf() */ #include <stdio.h> /* for printf() and fprintf() */
#include <poll.h> /* for select system call and related */ #include <poll.h> /* for select system call and related */
#include "class.h"
#include "socket.h" #include "socket.h"
#include "logger.h" #include "logger.h"
#include "cclass.h"
#define POLL_FD_NSIZE 1024 #define POLL_FD_NSIZE 1024
#define POLL_FD_SIZE (sizeof(struct pollfd) * POLL_FD_NSIZE) #define POLL_FD_SIZE (sizeof(struct pollfd) * POLL_FD_NSIZE)
@ -23,14 +23,14 @@
typedef void (*server_read_hook)(const char *, size_t); typedef void (*server_read_hook)(const char *, size_t);
CLASS(SERVER) {
LOGGER logger;
SOCK sock;
CLASS(Server) {
Logger logger;
Sock sock;
nfds_t nfds; nfds_t nfds;
struct pollfd fds[POLL_FD_NSIZE]; struct pollfd fds[POLL_FD_NSIZE];
struct { struct {
SOCK sock;
Sock sock;
char * wbuf; char * wbuf;
char * rbuf; char * rbuf;
unsigned int rpos; unsigned int rpos;
@ -40,8 +40,8 @@ CLASS(SERVER) {
server_read_hook read_hook; server_read_hook read_hook;
}; };
void server_run(SERVER this);
void server_close_conn(SERVER this, unsigned int handle);
void serverRun(Server this);
void serverCloseConn(Server this, unsigned int handle);
#endif // __SERVER_H__ #endif // __SERVER_H__

20
include/socket.h

@ -1,23 +1,23 @@
#ifndef __SOCKET_H__ #ifndef __SOCKET_H__
#define __SOCKET_H__ #define __SOCKET_H__
#include <arpa/inet.h> /* for in_port_t */
#include <arpa/inet.h> /* for in_port_t */
#include "class.h"
#include "logger.h" #include "logger.h"
#include "cclass.h"
CLASS(SOCK) {
LOGGER logger;
CLASS(Sock) {
Logger log;
in_port_t port; in_port_t port;
struct sockaddr_in addr; struct sockaddr_in addr;
int handle; /* socket handle for server */
int handle;
}; };
void sock_connect(SOCK this, const char * addr);
void sock_listen(SOCK this, int backlog);
SOCK sock_accept(SOCK this, char remoteAddr[16]);
void socketConnect(Sock this, const char * addr);
void socketListen(Sock this, int backlog);
Sock socketAccept(Sock this, char remoteAddr[16]);
#endif /* __SOCKET_H__ */
#endif // __SOCKET_H__
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

119
src/cclass.c

@ -1,119 +0,0 @@
/**
* \file
* cclass.c: basic "class-like" handling of code and data structures
* Copyright (C) 2011 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <json/json.h>
#include "cclass.h"
#undef __construct
#undef __clear
#undef __destruct
#undef __jsonConst
#undef __toJson
void *
_new(const CCLASS _class, ...)
{
const CCLASS class = _class;
void * object = calloc(1, class->size + sizeof(void *));
* (const struct _CCLASS **)object = class;
object += sizeof(CCLASS);
if (class->__construct) {
va_list params;
va_start(params, _class);
class->__construct(object, &params);
va_end(params);
}
return object;
}
void *
_newFromJson(const CCLASS _class, struct json_object * json)
{
const CCLASS class = _class;
void * object = calloc(1, class->size + sizeof(CCLASS));
* (const struct _CCLASS **) object = class;
object += sizeof(CCLASS);
if (class->__jsonConst && json) {
class->__jsonConst(object, json);
}
return object;
}
int
_instanceOf(const CCLASS _class, void * _object)
{
const CCLASS * class = _object - sizeof(CCLASS);
return (class && _class == *class);
}
void
clear(void * _object)
{
const CCLASS * class = _object - sizeof(CCLASS);
if (_object && *class && (*class)->__clear) {
(*class)->__clear(_object);
}
}
void
delete(void ** _object)
{
const CCLASS * class = (*_object) - sizeof(CCLASS);
if (*_object && *class && (*class)->__destruct) {
(*class)->__destruct(*_object);
}
free((void *)class);
*_object = NULL;
}
void
toJson(void * _object, struct json_object ** json)
{
const CCLASS * class = _object - sizeof(CCLASS);
if (_object && *class && (*class)->__toJson) {
(*class)->__toJson(_object, json);
}
}
int
isObject(void * _object)
{
const CCLASS * class = _object - sizeof(CCLASS);
return (_object && (*class) && CCLASS_MAGIC == (*class)->magic);
}
// vim: set et ts=4 sw=4:

28
src/class.c

@ -0,0 +1,28 @@
#include <stdarg.h>
#include <stdlib.h>
#include "class.h"
#include "interface.h"
inline
void *
class_getInterface(class_ptr * class, iface_ptr _iface)
{
void * iface = (void *)IFACE_GET(*class, _iface);
while(NULL == iface && HAS_PARENT(*class)) {
*class = (*class)->parent;
iface = (void *)IFACE_GET(*class, _iface);
}
return iface;
}
inline
class_ptr
class_getClass(void * object)
{
return *(class_ptr *)(object - sizeof(void*));
}
// vim: set ts=4 sw=4:

6
src/daemonize.c

@ -17,7 +17,7 @@ void daemonize(void) {
setsid(); setsid();
/* connect all standard streams to /dev/null */ /* connect all standard streams to /dev/null */
freopen("/dev/null", "w", stderr);
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
stderr = freopen("/dev/null", "w", stderr);
stdin = freopen("/dev/null", "r", stdin);
stdout = freopen("/dev/null", "w", stdout);
} }

45
src/interface.c

@ -0,0 +1,45 @@
#include <sys/types.h>
#include <stdlib.h>
#include "interface.h"
#ifndef TRUE
#define TRUE 1
#endif // TRUE
static
inline
int
comp(const void * _a, const void * _b)
{
const struct interface * a = **(const struct interface ***)_a;
const struct interface * b = **(const struct interface ***)_b;
return ((a)<(b))? -1 : ((a)>(b))? 1 : 0;
}
/**
* this one is important in selector functions to get the correct interface
* implementation of a class.
*/
struct interface *
interfaceGet(iface_impl_ptr iface_impl, const iface_ptr _iface)
{
const iface_ptr * iface = &_iface;
void * dummy;
if (! iface_impl->simpl) {
qsort((void**)(iface_impl->impl), iface_impl->nimpl, sizeof(iface_ptr), comp);
iface_impl->simpl=TRUE;
}
dummy = bsearch(
&iface,
iface_impl->impl,
iface_impl->nimpl,
sizeof(iface_ptr),
comp);
return dummy? *(struct interface **)dummy : dummy;
}
// vim: set ts=4 sw=4:

43
src/interface/class.c

@ -0,0 +1,43 @@
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include "class.h"
#include "interface/class.h"
const
struct interface i_Class = {
"class",
3
};
inline
void *
classNew(class_ptr class, ...)
{
void * object = calloc(1, class->object_size + sizeof(void*));
va_list params;
if (class->init) class->init();
* (class_ptr *)object = class;
object += sizeof(void*);
va_start(params, class);
CALL(object, Class, ctor, &params);
va_end(params);
return object;
}
inline
void
classDelete(void ** object)
{
CALL(*object, Class, dtor);
free(*object - sizeof(void*));
*object = NULL;
}
// vim: set ts=4 sw=4:

37
src/interface/logger.c

@ -0,0 +1,37 @@
#include <stdlib.h>
#include "logger.h"
#include "interface/logger.h"
const struct interface i_Logger = {
"logger",
1
};
inline
void
loggerLog(void * _object, logger_level level, const char * const fmt, ...) {
Logger object = _object;
if (level >= object->min_level) {
char * msg = NULL;
size_t msg_size = 0;
va_list params;
va_start(params, fmt);
msg_size = vsnprintf(msg, msg_size, fmt, params);
va_end(params);
msg = malloc(msg_size + 1);
va_start(params, fmt);
vsnprintf(msg, msg_size + 1, fmt, params);
va_end(params);
CALL(_object, Logger, log, level, msg);
free(msg);
}
}
// vim: set ts=4 sw=4:

35
src/logger.c

@ -1,18 +1,33 @@
#include "logger.h"
#include <stdarg.h>
extern void logger_syslog(int level, const char * msg);
#include "logger.h"
#include "interface/class.h"
#include "interface/logger.h"
INIT_CLASS(LOGGER);
const
char * const
logger_level_str[] = {
"DEBUG",
"INFO",
"NOTICE",
"WARNING",
"ERR",
"CRIT",
"ALERT",
"EMERG"
};
__construct(LOGGER)
static
void
ctor(void * _this, va_list * params)
{ {
this->logfncts[0] = logger_syslog;
this->logfncts_count = 1;
Logger this = _this;
this->min_level = va_arg(*params, int);
} }
__destruct(LOGGER) {}
__jsonConst(LOGGER) {}
__toJson(LOGGER) {}
__clear(LOGGER) {}
static void dtor(void * _this) {}
INIT_IFACE(Class, ctor, dtor, NULL);
CREATE_CLASS(Logger, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

11
src/logger/add.c

@ -1,11 +0,0 @@
#include "logger.h"
void
logger_add(LOGGER this, logger_logfnct logfunc) {
if (this->logfncts_count < MAX_LOG_FNCTS) {
this->logfncts[this->logfncts_count] = logfunc;
this->logfncts_count++;
}
}
// vim: set ts=4 sw=4:

30
src/logger/log.c

@ -1,30 +0,0 @@
#define _ISOC99_SOURCE
#include <stdio.h>
#include <string.h>
#include "logger.h"
void
logger_log(LOGGER this, int level, const char * message, ...) {
va_list args;
char buffer[1025];
logger_logfnct * logfnct;
int maxBuf = sizeof(buffer)/sizeof(buffer[0]);
memset(buffer, 0, maxBuf);
va_start(args, message);
vsnprintf(buffer, 1024, message, args);
va_end(args);
logfnct = this->logfncts;
while (NULL != *logfnct) {
(*logfnct)(level, buffer);
logfnct++;
}
}
// vim: set ts=4 sw=4:

16
src/logger/stderr.c

@ -0,0 +1,16 @@
#include <stdio.h>
#include "logger.h"
#include "interface/logger.h"
static
void
logStderr(void * this, logger_level level, const char * const msg)
{
fprintf(stderr, "[%s] %s\n", logger_level_str[level], msg);
}
INIT_IFACE(Logger, logStderr);
CREATE_CLASS(LoggerStderr, Logger, IFACE(Logger));
// vim: set ts=4 sw=4:

31
src/logger/syslog.c

@ -1,20 +1,29 @@
#include <syslog.h> #include <syslog.h>
const int priority[] = {
LOG_USER | LOG_EMERG,
LOG_USER | LOG_ALERT,
LOG_USER | LOG_CRIT,
LOG_USER | LOG_ERR,
LOG_USER | LOG_WARNING,
LOG_USER | LOG_NOTICE,
LOG_USER | LOG_INFO,
LOG_USER | LOG_DEBUG
#include "logger.h"
#include "interface/logger.h"
static
const
int syslog_priority[] = {
LOG_USER | LOG_DEBUG,
LOG_USER | LOG_INFO,
LOG_USER | LOG_NOTICE,
LOG_USER | LOG_WARNING,
LOG_USER | LOG_ERR,
LOG_USER | LOG_CRIT,
LOG_USER | LOG_ALERT,
LOG_USER | LOG_EMERG
}; };
static
void void
logger_syslog(int level, const char * msg)
logSyslog(void * this, logger_level level, const char * const msg)
{ {
syslog(priority[level], "%s", msg);
syslog(syslog_priority[level], "[%s] %s", logger_level_str[level], msg);
} }
INIT_IFACE(Logger, logSyslog);
CREATE_CLASS(LoggerSyslog, Logger, IFACE(Logger));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

29
src/server.c

@ -2,34 +2,38 @@
#include <string.h> /* for memset and stuff */ #include <string.h> /* for memset and stuff */
#include <stdlib.h> /* for getopt */ #include <stdlib.h> /* for getopt */
#include "class.h"
#include "server.h" #include "server.h"
#include "socket.h" #include "socket.h"
#include "server.h"
#include "logger.h" #include "logger.h"
#include "cclass.h"
INIT_CLASS(SERVER);
#include "interface/class.h"
__construct(SERVER)
static
void
ctor(void * _this, va_list * params)
{ {
Server this = _this;
in_port_t port; in_port_t port;
unsigned int backlog; unsigned int backlog;
this->logger = va_arg(* params, LOGGER);
this->logger = va_arg(* params, Logger);
port = va_arg(* params, int); port = va_arg(* params, int);
backlog = va_arg(* params, unsigned int); backlog = va_arg(* params, unsigned int);
this->sock = new(SOCK, this->logger, port);
sock_listen(this->sock, backlog);
this->sock = new(Sock, this->logger, port);
socketListen(this->sock, backlog);
(this->fds)[0].fd = this->sock->handle; (this->fds)[0].fd = this->sock->handle;
(this->fds)[0].events = POLLIN; (this->fds)[0].events = POLLIN;
this->nfds = 1; this->nfds = 1;
} }
__destruct(SERVER)
static
void
dtor(void * _this)
{ {
int i;
Server this = _this;
int i;
for (i=1; i<this->nfds; i++) { for (i=1; i<this->nfds; i++) {
/* /*
@ -41,8 +45,7 @@ __destruct(SERVER)
delete(&this->sock); delete(&this->sock);
} }
__jsonConst(SERVER) {}
__toJson(SERVER) {}
__clear(SERVER) {}
INIT_IFACE(Class, ctor, dtor, NULL);
CREATE_CLASS(Server, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

3
src/server/close_conn.c

@ -1,9 +1,10 @@
#include <string.h> #include <string.h>
#include "server.h" #include "server.h"
#include "interface/class.h"
void void
server_close_conn(SERVER this, unsigned int i)
serverCloseConn(Server this, unsigned int i)
{ {
delete(&((this->conns)[i].sock)); delete(&((this->conns)[i].sock));
CLEAR_CONN(this, i); CLEAR_CONN(this, i);

34
src/server/run.c

@ -4,17 +4,18 @@
#include <errno.h> /* for errno */ #include <errno.h> /* for errno */
#include <unistd.h> #include <unistd.h>
#include "include/logger.h"
#include "include/server.h"
#include "include/socket.h"
#include "include/signalHandling.h"
#include "server.h"
#include "socket.h"
#include "logger.h"
#include "signalHandling.h"
#include "interface/class.h"
#undef MAX #undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y)) #define MAX(x,y) ((x) > (y) ? (x) : (y))
static static
int int
server_poll(SERVER this) {
serverPoll(Server this) {
int events; int events;
/* /*
@ -30,7 +31,7 @@ server_poll(SERVER this) {
/* Fallthrough */ /* Fallthrough */
case EINTR: case EINTR:
logger_log(this->logger, LOGGER_CRIT,
loggerLog(this->logger, LOGGER_CRIT,
"poll systemcall failed: [%s] - service terminated", "poll systemcall failed: [%s] - service terminated",
strerror(errno)); strerror(errno));
//exit(EXIT_FAILURE); /* @TODO do real shutdown here */ //exit(EXIT_FAILURE); /* @TODO do real shutdown here */
@ -42,13 +43,13 @@ server_poll(SERVER this) {
static static
void void
server_handle_accept(SERVER this)
serverHandleAccept(Server this)
{ {
if (0 != ((this->fds)[0].revents & POLLIN)) { if (0 != ((this->fds)[0].revents & POLLIN)) {
char remoteAddr[16] = ""; char remoteAddr[16] = "";
SOCK acc;
Sock acc;
acc = sock_accept(this->sock, remoteAddr);
acc = socketAccept(this->sock, remoteAddr);
if (-1 != acc->handle) { if (-1 != acc->handle) {
(this->conns)[this->nfds].sock = acc; // save the socket handle (this->conns)[this->nfds].sock = acc; // save the socket handle
@ -65,7 +66,7 @@ server_handle_accept(SERVER this)
static static
int int
server_read(SERVER this)
serverRead(Server this)
{ {
unsigned int i; unsigned int i;
size_t _read; size_t _read;
@ -85,7 +86,8 @@ server_read(SERVER this)
* read failure / close connection * read failure / close connection
* FALLTHROUGH * FALLTHROUGH
*/ */
server_close_conn(this, i);
loggerLog(this->logger, LOGGER_INFO, "connection closed...");
serverCloseConn(this, i);
break; break;
default: default:
@ -102,12 +104,12 @@ server_read(SERVER this)
} }
void void
server_run(SERVER this)
serverRun(Server this)
{ {
/* /*
* @TODO again...add verbosity to logger.... * @TODO again...add verbosity to logger....
*/ */
logger_log(this->logger, LOGGER_INFO, "service started");
loggerLog(this->logger, LOGGER_INFO, "service started");
while (!doShutdown) /* until error or signal */ while (!doShutdown) /* until error or signal */
{ {
@ -116,16 +118,16 @@ server_run(SERVER this)
* @TODO take return value of poll into account with * @TODO take return value of poll into account with
* further handling! * further handling!
*/ */
events = server_poll(this);
events = serverPoll(this);
if (doShutdown) break; if (doShutdown) break;
/* /*
* handle accept * handle accept
*/ */
server_handle_accept(this);
serverHandleAccept(this);
/* handle reads */ /* handle reads */
server_read(this);
serverRead(this);
} }
} }

63
src/socket.c

@ -1,49 +1,46 @@
#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 <errno.h>
#include <stdlib.h>
#include "logger.h"
#include "cclass.h"
#include "socket.h" #include "socket.h"
#include "logger.h"
#include "interface/class.h"
#include "interface/logger.h"
INIT_CLASS(SOCK);
__construct(SOCK)
static
void
ctor(void * _this, va_list * params)
{ {
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))) {
logger_log(this->logger, LOGGER_CRIT,
"error opening socket: %s - service terminated",
strerror(errno));
exit(EXIT_FAILURE);
}
Sock this = _this;
int reUse = 1; /* TODO: make this configurable */
this->log = 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))) {
loggerLog(this->log, LOGGER_CRIT,
"error opening socket: %s - service terminated",
strerror(errno));
exit(EXIT_FAILURE);
}
/* Make the socket REUSE a TIME_WAIT socket */
setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof (reUse));
/* Make the socket REUSE a TIME_WAIT socket */
setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof (reUse));
} }
__destruct(SOCK)
static
void
dtor(void * _this)
{ {
Sock this = _this;
if (0 != this->handle) { if (0 != this->handle) {
shutdown(this->handle, SHUT_RDWR); shutdown(this->handle, SHUT_RDWR);
close(this->handle); close(this->handle);
} }
} }
__jsonConst(SOCK) {}
__toJson(SOCK) {}
__clear(SOCK) {}
INIT_IFACE(Class, ctor, dtor, NULL);
CREATE_CLASS(Sock, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

24
src/socket/accept.c

@ -1,27 +1,19 @@
#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 <errno.h> /* for errno */
#include <stdarg.h>
#include "logger.h"
#include "cclass.h"
#include "socket.h" #include "socket.h"
#include "interface/class.h"
#include "interface/logger.h"
SOCK
sock_accept(SOCK this, char remoteAddr[16])
Sock
socketAccept(Sock this, char remoteAddr[16])
{ {
SOCK sock; /* Socket for client */
Sock sock; /* Socket for client */
unsigned int len; /* Length of client address data structure */ unsigned int len; /* Length of client address data structure */
/* Set the size of the in-out parameter */ /* Set the size of the in-out parameter */
len = sizeof(this->addr); len = sizeof(this->addr);
sock = new(SOCK, this->logger, this->port);
sock = new(Sock, this->log, this->port);
/** /**
* @TODO: change port to remote port on success * @TODO: change port to remote port on success
*/ */
@ -29,10 +21,10 @@ sock_accept(SOCK this, char remoteAddr[16])
/* Wait for a client to connect */ /* Wait for a client to connect */
sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len); sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len);
if (-1 == sock->handle) { if (-1 == sock->handle) {
logger_log(this->logger, LOGGER_WARNING,
loggerLog(this->log, LOGGER_WARNING,
"error acception connection: %s", strerror(errno)); "error acception connection: %s", strerror(errno));
} else { } else {
logger_log(this->logger, LOGGER_INFO,
loggerLog(this->log, LOGGER_INFO,
"handling client %s\n", inet_ntoa((sock->addr).sin_addr)); "handling client %s\n", inet_ntoa((sock->addr).sin_addr));
} }

15
src/socket/connect.c

@ -1,27 +1,20 @@
#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 <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <errno.h> /* for errno */ #include <errno.h> /* for errno */
#include <stdarg.h>
#include "logger.h"
#include "cclass.h"
#include "socket.h" #include "socket.h"
#include "interface/class.h"
#include "interface/logger.h"
void void
sock_connect(SOCK this, const char * addr)
socketConnect(Sock this, const char * addr)
{ {
inet_pton(AF_INET, addr, &((this->addr).sin_addr)); inet_pton(AF_INET, addr, &((this->addr).sin_addr));
(this->addr).sin_family = AF_INET; /* Internet address family */ (this->addr).sin_family = AF_INET; /* Internet address family */
(this->addr).sin_port = htons(this->port); /* Local port */ (this->addr).sin_port = htons(this->port); /* Local port */
if (-1 == connect(this->handle, (struct sockaddr*) &(this->addr), sizeof(this->addr))) { if (-1 == connect(this->handle, (struct sockaddr*) &(this->addr), sizeof(this->addr))) {
logger_log(this->logger, LOGGER_CRIT,
loggerLog(this->log, LOGGER_CRIT,
"error connection socket: %s - service terminated", "error connection socket: %s - service terminated",
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

17
src/socket/listen.c

@ -1,20 +1,13 @@
#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 <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <errno.h> /* for errno */ #include <errno.h> /* for errno */
#include <stdarg.h>
#include "logger.h"
#include "cclass.h"
#include "socket.h" #include "socket.h"
#include "interface/class.h"
#include "interface/logger.h"
void void
sock_listen(SOCK this, int backlog)
socketListen(Sock this, int backlog)
{ {
(this->addr).sin_family = AF_INET; /* Internet address family */ (this->addr).sin_family = AF_INET; /* Internet address family */
(this->addr).sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ (this->addr).sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
@ -22,7 +15,7 @@ sock_listen(SOCK this, int backlog)
/* Bind to the local address */ /* Bind to the local address */
if (-1 == bind(this->handle, (struct sockaddr *) &(this->addr), sizeof(this->addr))) { if (-1 == bind(this->handle, (struct sockaddr *) &(this->addr), sizeof(this->addr))) {
logger_log(this->logger, LOGGER_CRIT,
loggerLog(this->log, LOGGER_CRIT,
"error binding socket: %s - service terminated", "error binding socket: %s - service terminated",
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -30,7 +23,7 @@ sock_listen(SOCK this, int backlog)
/* Mark the socket so it will listen for incoming connections */ /* Mark the socket so it will listen for incoming connections */
if (-1 == listen(this->handle, backlog)) { if (-1 == listen(this->handle, backlog)) {
logger_log(this->logger, LOGGER_CRIT,
loggerLog(this->log, LOGGER_CRIT,
"error binding socket: %s - service terminated", "error binding socket: %s - service terminated",
strerror(errno)); strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

10
src/testserver.c

@ -3,7 +3,9 @@
#include <string.h> #include <string.h>
#include "server.h" #include "server.h"
#include "logger.h"
#include "signalHandling.h" #include "signalHandling.h"
#include "interface/class.h"
static void static void
read_hook(const char * _buffer, size_t size) read_hook(const char * _buffer, size_t size)
@ -11,7 +13,7 @@ read_hook(const char * _buffer, size_t size)
char buffer[1025]; char buffer[1025];
memset(buffer, 0, 1025); memset(buffer, 0, 1025);
snprintf(buffer, size, _buffer);
snprintf(buffer, 1025>size? size : 1024, "%s", _buffer);
printf("%s\n", buffer); printf("%s\n", buffer);
} }
@ -19,13 +21,13 @@ read_hook(const char * _buffer, size_t size)
int int
main() main()
{ {
LOGGER logger = new(LOGGER, NULL);
SERVER server = new(SERVER, logger, 11212, SOMAXCONN);
Logger logger = new(LoggerStderr, LOGGER_INFO);
Server server = new(Server, logger, 11212, SOMAXCONN);
server->read_hook = read_hook; server->read_hook = read_hook;
init_signals(); init_signals();
server_run(server);
serverRun(server);
delete(&server); delete(&server);
delete(&logger); delete(&logger);

Loading…
Cancel
Save