diff --git a/server/include/file.h b/server/include/file.h index c414f9904..74b42498f 100644 --- a/server/include/file.h +++ b/server/include/file.h @@ -66,7 +66,7 @@ int file_deinit(); char * file_print(struct node *n); /** @see node_vtable::parse */ -int file_parse(config_setting_t *cfg, struct node *n); +int file_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::open */ int file_open(struct node *n); diff --git a/server/include/gtfpga.h b/server/include/gtfpga.h index 9f3ce908e..86a49f94e 100644 --- a/server/include/gtfpga.h +++ b/server/include/gtfpga.h @@ -55,7 +55,7 @@ int gtfpga_init(int argc, char * argv[], struct settings *set); int gtfpga_deinit(); /** @see node_vtable::parse */ -int gtfpga_parse(config_setting_t *cfg, struct node *n); +int gtfpga_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::print */ char * gtfpga_print(struct node *n); diff --git a/server/include/ngsi.h b/server/include/ngsi.h index 2603502a0..b41aa6d65 100644 --- a/server/include/ngsi.h +++ b/server/include/ngsi.h @@ -72,7 +72,7 @@ int ngsi_init(int argc, char *argv[], struct settings *set); int ngsi_deinit(); /** @see node_vtable::parse */ -int ngsi_parse(config_setting_t *cfg, struct node *n); +int ngsi_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::print */ char * ngsi_print(struct node *n); diff --git a/server/include/node.h b/server/include/node.h index 4abc81e50..7c3de43d3 100644 --- a/server/include/node.h +++ b/server/include/node.h @@ -27,16 +27,6 @@ #include "list.h" /* Helper macros for virtual node type */ -#define node_type(n) ((n)->_vt->type) -#define node_parse(n, cfg) ((n)->_vt->parse(cfg, n)) - -#define node_read(n, p, ps, f, c) ((n)->_vt->read(n, p, ps, f, c)) -#define node_write(n, p, ps, f, c) ((n)->_vt->write(n, p, ps, f, c)) - -#define node_open(n) ((n)->_vt->open(n)) -#define node_close(n) ((n)->_vt->close(n)) - - #define REGISTER_NODE_TYPE(type, name, fnc) \ __attribute__((constructor)) void __register_node_ ## fnc () { \ static struct node_type t = { name, type, \ @@ -55,6 +45,18 @@ struct node_type { const char *name; /** A list of all existing nodes of this type. */ struct list instances; + + /** Global initialization per node type. + * + * This callback is invoked once per node-type. + * + * @param argc Number of arguments passed to the server executable (see main()). + * @param argv Array of arguments passed to the server executable (see main()). + * @param set Global settings. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*init)(int argc, char *argv[], struct settings *set); enum { BSD_SOCKET, /**< BSD Socket API */ @@ -63,26 +65,46 @@ struct node_type { GTFPGA, /**< Xilinx ML507 GTFPGA card */ NGSI /**< NGSI 9/10 HTTP RESTful API (FIRWARE ContextBroker) */ } type; /**< Node type */ + /** Global de-initialization per node type. + * + * This callback is invoked once per node-type. + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*deinit)(); + + /** Allocate memory for an instance of this type. + * + * @return A pointer to the node-type specific private data. + */ + void * (*create)(); + + /** Free memory of an instance of this type. + * + * @param n A pointer to the node object. + */ + int (*destroy)(struct node *n); /** Parse node connection details.‚ * + * @param n A pointer to the node object. * @param cfg A libconfig object pointing to the node. - * @param n A pointer to the node structure which should be parsed. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ - int (*parse)(config_setting_t *cfg, struct node *n); + int (*parse)(struct node *n, config_setting_t *cfg); /** Returns a string with a textual represenation of this node. * - * @param n A pointer to the node structure + * @param n A pointer to the node object. * @return A pointer to a dynamically allocated string. Must be freed(). */ char * (*print)(struct node *n); /** Opens the connection to this node. * - * @param n A pointer to the node. + * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ @@ -90,7 +112,7 @@ struct node_type { /** Close the connection to this node. * - * @param n A pointer to the node. + * @param n A pointer to the node object. * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ @@ -104,7 +126,7 @@ struct node_type { * Indexes used to address @p m will wrap around after len messages. * Some node types might only support to receive one message at a time. * - * @param n A pointer to the node where the messages should be sent to. + * @param n A pointer to the node object. * @param pool A pointer to an array of messages which should be sent. * @param poolsize The length of the message array. * @param first The index of the first message which should be sent. @@ -120,7 +142,7 @@ struct node_type { * The messages have to be stored in a circular buffer / array m. * So the indexes will wrap around after len. * - * @param n A pointer to the node where the messages should be sent to. + * @param n A pointer to the node object. * @param pool A pointer to an array of messages which should be sent. * @param poolsize The length of the message array. * @param first The index of the first message which should be sent. @@ -128,29 +150,14 @@ struct node_type { * @return The number of messages actually sent. */ int (*write)(struct node *n, struct msg *pool, int poolsize, int first, int cnt); - - /** Global initialization per node type. - * - * This callback is invoked once per node-type. - * - * @param argc Number of arguments passed to the server executable (see main()). - * @param argv Array of arguments passed to the server executable (see main()). - * @param set Global settings. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*init)(int argc, char *argv[], struct settings *set); - /** Global de-initialization per node type. + /** Reverse source and destination of a node. * - * This callback is invoked once per node-type. + * This is not supported by all node types! * - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. + * @param n A pointer to the node object. */ - int (*deinit)(); - - int refcnt; /**< Reference counter: how many nodes are using this node-type? */ + int (*reverse)(struct node *n); }; /** The data structure for a node. @@ -179,58 +186,72 @@ struct node config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this node */ }; -/** Initialize node type subsystems. +/** Initialize all registered node type subsystems. * - * These routines are only called once per type (not per node instance). - * See node_vtable::init + * @see node_type::init */ int node_init(int argc, char *argv[], struct settings *set); /** De-initialize node type subsystems. * - * These routines are only called once per type (not per node instance). - * See node_vtable::deinit + * @see node_type::deinit */ int node_deinit(); -/** Connect and bind the UDP socket of this node. +/** Create a node by allocating dynamic memory. * - * Depending on the type (vtable) of this node, - * a socket is opened, shmem region registred... - * - * @param n A pointer to the node structure - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. + * @see node_type::create + * @param vt A pointer to the node-type table of virtual functions. */ -int node_start(struct node *n); - -/** Return a pointer to a string which should be used to print this node */ -char * node_print(struct node *n); - -/** Stops a node. - * - * Depending on the type (vtable) of this node, - * a socket is closed, shmem region released... - * - * @param n A pointer to the node structure - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int node_stop(struct node *n); - -/** Reverse local and remote socket address. - * This is usefull for the helper programs: send, receive, test - * because they usually use the same configuration file as the - * server and therefore the direction needs to be swapped. */ -void node_reverse(struct node *n); - -/** Create a node by allocating dynamic memory. */ struct node * node_create(struct node_type *vt); /** Destroy node by freeing dynamically allocated memory. * - * @param i A pointer to the interface structure. + * @see node_type::destroy */ void node_destroy(struct node *n); +/** Start operation of a node. + * + * @see node_type::open + */ +int node_start(struct node *n); + +/** Stops operation of a node. + * + * @see node_type::close + */ +int node_stop(struct node *n); + +/** Parse node connection details. + * + * @see node_type::parse + */ +int node_parse(struct node *n, config_setting_t *cfg); + +/** Return a pointer to a string which should be used to print this node + * + * @see node_type::print + * @param i A pointer to the interface structure. + */ +char * node_print(struct node *n); + +/** Receive multiple messages at once. + * + * @see node_type::read + */ +int node_read(struct node *n, struct msg *pool, int poolsize, int first, int cnt); + +/** Send multiple messages in a single datagram / packet. + * + * @see node_type::write + */ +int node_write(struct node *n, struct msg *pool, int poolsize, int first, int cnt); + +/** Reverse local and remote socket address. + * + * @see node_type::reverse + */ +int node_reverse(struct node *n); + #endif /** _NODE_H_ @} */ diff --git a/server/include/opal.h b/server/include/opal.h index 88994c8e1..dc039c27b 100644 --- a/server/include/opal.h +++ b/server/include/opal.h @@ -74,7 +74,7 @@ int opal_init(int argc, char *argv[], struct settings *set); int opal_deinit(); /** @see node_vtable::parse */ -int opal_parse(config_setting_t *cfg, struct node *n); +int opal_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::print */ char * opal_print(struct node *n); diff --git a/server/include/socket.h b/server/include/socket.h index ee8cb65e7..3ee306748 100644 --- a/server/include/socket.h +++ b/server/include/socket.h @@ -78,7 +78,7 @@ int socket_write(struct node *n, struct msg *pool, int poolsize, int first, int int socket_read(struct node *n, struct msg *pool, int poolsize, int first, int cnt); /** @see node_vtable::parse */ -int socket_parse(config_setting_t *cfg, struct node *n); +int socket_parse(struct node *n, config_setting_t *cfg); /** @see node_vtable::print */ char * socket_print(struct node *n); diff --git a/server/src/cfg.c b/server/src/cfg.c index 2966c5b25..9d2a582be 100644 --- a/server/src/cfg.c +++ b/server/src/cfg.c @@ -18,17 +18,6 @@ #include "path.h" #include "hooks.h" -#include "file.h" -#ifdef ENABLE_SOCKET - #include "socket.h" -#endif -#ifdef ENABLE_GTFPGA - #include "gtfpga.h" -#endif -#ifdef ENABLE_OPAL_ASYNC - #include "opal.h" -#endif - int config_parse(const char *filename, config_t *cfg, struct settings *set, struct list *nodes, struct list *paths) { diff --git a/server/src/file.c b/server/src/file.c index 8fe33ad5a..c0241f50b 100644 --- a/server/src/file.c +++ b/server/src/file.c @@ -26,6 +26,15 @@ int file_deinit() return 0; /* nothing todo here */ } +int file_reverse(struct node *n) +{ + struct file *f = n->file; + + SWAP(f->read, f->write); + + return 0; +} + static char * file_format_name(const char *format, struct timespec *ts) { struct tm tm; @@ -69,7 +78,7 @@ static int file_parse_direction(config_setting_t *cfg, struct file *f, int d) return 0; } -int file_parse(config_setting_t *cfg, struct node *n) +int file_parse(struct node *n, config_setting_t *cfg) { struct file *f = alloc(sizeof(struct file)); diff --git a/server/src/gtfpga.c b/server/src/gtfpga.c index ecdcc1167..9a9d6a70c 100644 --- a/server/src/gtfpga.c +++ b/server/src/gtfpga.c @@ -56,7 +56,7 @@ int gtfpga_deinit() return 0; } -int gtfpga_parse(config_setting_t *cfg, struct node *n) +int gtfpga_parse(struct node *n, config_setting_t *cfg) { struct gtfpga *g = alloc(sizeof(struct gtfpga)); diff --git a/server/src/ngsi.c b/server/src/ngsi.c index a445fdbd4..51338fc23 100644 --- a/server/src/ngsi.c +++ b/server/src/ngsi.c @@ -223,7 +223,7 @@ static int ngsi_parse_entity(json_t *entity, struct ngsi *i, struct msg *pool, i return cnt; } -static int ngsi_parse_mapping(config_setting_t *cfg, struct list *mapping) +static int ngsi_parse_mapping(struct list *mapping, config_setting_t *cfg) { if (!config_setting_is_array(cfg)) return -1; @@ -423,7 +423,7 @@ int ngsi_deinit() return 0; } -int ngsi_parse(config_setting_t *cfg, struct node *n) +int ngsi_parse(struct node *n, config_setting_t *cfg) { struct ngsi *i = alloc(sizeof(struct ngsi)); @@ -452,7 +452,7 @@ int ngsi_parse(config_setting_t *cfg, struct node *n) if (!cfg_mapping) cerror(cfg, "Missing mapping for node '%s", n->name); - if (ngsi_parse_mapping(cfg_mapping, &i->mapping)) + if (ngsi_parse_mapping(&i->mapping, cfg_mapping)) cerror(cfg_mapping, "Invalid mapping for NGSI node '%s'", n->name); n->ngsi = i; @@ -469,6 +469,15 @@ char * ngsi_print(struct node *n) i->endpoint, i->timeout, list_length(&i->mapping)); } +int ngsi_destroy(struct node *n) +{ + struct ngsi *i = n->ngsi; + + list_destroy(&i->mapping); + + return 0; +} + int ngsi_open(struct node *n) { struct ngsi *i = n->ngsi; diff --git a/server/src/node.c b/server/src/node.c index 8c360ebb0..cb16c041b 100644 --- a/server/src/node.c +++ b/server/src/node.c @@ -12,27 +12,33 @@ #include "cfg.h" #include "utils.h" -/* Node types */ -#include "file.h" -#ifdef ENABLE_GTFPGA - #include "gtfpga.h" -#endif -#ifdef ENABLE_OPAL_ASYNC - #include "opal.h" -#endif -#ifdef ENABLE_SOCKET - #include "socket.h" - #include - #include -#endif -#ifdef ENABLE_NGSI - #include "ngsi.h" - #include -#endif - /** Vtable for virtual node sub types */ struct list node_types = LIST_INIT(NULL); +int node_parse(struct node *n, config_setting_t *cfg) +{ + return n->_vt->parse ? n->_vt->parse(n, cfg) : -1; +} + +int node_read(struct node *n, struct msg *p, int ps, int f, int c) +{ + return n->_vt->read ? n->_vt->read(n, p, ps, f, c) : -1; +} + +int node_write(struct node *n, struct msg *p, int ps, int f, int c) +{ + return n->_vt->write ? n->_vt->write(n, p, ps, f, c) : -1; +} + +int node_open(struct node *n) +{ + return n->_vt->open ? n->_vt->open(n) : -1; +} +int node_close(struct node *n) +{ + return n->_vt->close ? n->_vt->close(n) : -1; +} + int node_init(int argc, char *argv[], struct settings *set) { INDENT list_foreach(const struct node_type *vt, &node_types) { @@ -88,19 +94,9 @@ char * node_print(struct node *n) return n->_print; } -void node_reverse(struct node *n) +int node_reverse(struct node *n) { - switch (node_type(n)) { -#ifdef ENABLE_SOCKET - case BSD_SOCKET: - SWAP(n->socket->remote, n->socket->local); - break; -#endif - case LOG_FILE: - SWAP(n->file->read, n->file->write); - break; - default: { } - } + return n->_vt->reverse ? n->_vt->reverse(n) : -1; } struct node * node_create(struct node_type *vt) @@ -116,20 +112,8 @@ struct node * node_create(struct node_type *vt) void node_destroy(struct node *n) { - switch (node_type(n)) { -#ifdef ENABLE_NGSI - case NGSI: - list_destroy(&n->ngsi->mapping); - break; -#endif -#ifdef ENABLE_SOCKET - case BSD_SOCKET: - rtnl_qdisc_put(n->socket->tc_qdisc); - rtnl_cls_put(n->socket->tc_classifier); - break; -#endif - default: { } - } + if (n->_vt->destroy) + n->_vt->destroy(n); free(n->_print); free(n->socket); diff --git a/server/src/opal.c b/server/src/opal.c index 29c03ad77..aa875eae8 100644 --- a/server/src/opal.c +++ b/server/src/opal.c @@ -128,7 +128,7 @@ int opal_print_global(struct opal_global *g) return 0; } -int opal_parse(config_setting_t *cfg, struct node *n) +int opal_parse(struct node *n, config_setting_t *cfg) { struct opal *o = alloc(sizeof(struct opal)); diff --git a/server/src/socket.c b/server/src/socket.c index 76f88de93..3ef719070 100644 --- a/server/src/socket.c +++ b/server/src/socket.c @@ -157,6 +157,15 @@ int socket_open(struct node *n) return 0; } +int socket_reverse(struct node *n) +{ + struct socket *s = n->socket; + + SWAP(s->remote, s->local); + + return 0; +} + int socket_close(struct node *n) { struct socket *s = n->socket; @@ -167,6 +176,16 @@ int socket_close(struct node *n) return 0; } +int socket_destroy(struct node *n) +{ + struct socket *s = n->socket; + + rtnl_qdisc_put(s->tc_qdisc); + rtnl_cls_put(s->tc_classifier); + + return 0; +} + int socket_read(struct node *n, struct msg *pool, int poolsize, int first, int cnt) { struct socket *s = n->socket; @@ -270,7 +289,7 @@ int socket_write(struct node *n, struct msg *pool, int poolsize, int first, int return sent; } -int socket_parse(config_setting_t *cfg, struct node *n) +int socket_parse(struct node *n, config_setting_t *cfg) { const char *local, *remote, *layer; int ret;