diff --git a/server/include/hooks.h b/server/include/hooks.h index 0203663cc..5af8b486a 100644 --- a/server/include/hooks.h +++ b/server/include/hooks.h @@ -21,11 +21,19 @@ #include +#define REGISTER_HOOK(name, prio, fnc, type) \ +__attribute__((constructor)) void __register_ ## fnc () { \ + static struct hook h = { name, prio, fnc, type }; \ + list_push(&hooks, &h); \ +} + /* The configuration of hook parameters is done in "config.h" */ /* Forward declarations */ struct path; +extern struct list hooks; + /** Callback type of hook function * * @param p The path which is processing this message. @@ -50,24 +58,20 @@ enum hook_type { /** Descriptor for user defined hooks. See hook_list[]. */ struct hook { + /** The unique name of this hook. This must be the first member! */ + const char *name; int priority; hook_cb_t callback; - const char *name; enum hook_type type; }; -/** Get a function pointer of a hook function by its name - * - * @param name The name of the requested hook - * @retval NULL There is no hook registred with name. - * @retval >0 A function pointer to the requested hook_cb_t hook. - */ -const struct hook * hook_lookup(const char *name); - +struct hook * hook_lookup(const char *name); /* The following prototypes are example hooks */ -/** Example hook: Print the message. */ +/** Example hook: Print the message. + * @example + */ int hook_print(struct path *p); /** Example hook: Drop messages. */ diff --git a/server/include/list.h b/server/include/list.h index c04541fa7..2cb57ddcd 100644 --- a/server/include/list.h +++ b/server/include/list.h @@ -49,6 +49,8 @@ struct opal; * @param data A pointer to the data which should be freed. */ typedef void (*dtor_cb_t)(void *data); + +typedef int (*cmp_cb_t)(void *, void *); struct list { struct list_elm *head, *tail; @@ -62,11 +64,13 @@ struct list_elm { union { void *ptr; struct node *node; + struct node_type *type; struct path *path; struct interface *interface; struct socket *socket; struct opal *opal; struct gtfpga *gtfpga; + struct hook *hook; } /* anonymous */; int priority; @@ -81,6 +85,12 @@ void list_push(struct list *l, void *p); void list_insert(struct list *l, int prio, void *p); -struct list_elm * list_search(struct list *l, int (*cmp)(void *)); +/** Search the list for an element whose first element is a character array which matches name. + * + * @see Only possible because of ยง1424 of http://c0x.coding-guidelines.com/6.7.2.1.html + */ +void * list_lookup(const struct list *l, const char *name); + +void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx); #endif /* _LIST_H_ */ diff --git a/server/include/node.h b/server/include/node.h index fda53823f..307bf8f75 100644 --- a/server/include/node.h +++ b/server/include/node.h @@ -23,11 +23,6 @@ #include "msg.h" #include "list.h" -/** Static node initialization */ -#define NODE_INIT(n) { \ - .name = n \ -} - /* Helper macros for virtual node type */ #define node_type(n) ((n)->vt->type) #define node_print(n, b, l) ((n)->vt->print(n, b, l)) @@ -38,20 +33,34 @@ #define node_read_single(n, m) ((n)->vt->read(n, m, 1, 0, 1)) #define node_write_single(n, m) ((n)->vt->write(n, m, 1, 0, 1)) -/** Node type: layer, protocol, listen/connect */ -enum node_type { - BSD_SOCKET, /**< BSD Socket API */ - LOG_FILE, /**< File IO */ - OPAL_ASYNC, /**< OPAL-RT Asynchronous Process Api */ - GTFPGA /**< Xilinx ML507 GTFPGA card */ -}; + +#define REGISTER_NODE_TYPE(type, name, fnc) \ +__attribute__((constructor)) void __register_node_ ## fnc () { \ + static struct node_type t = { name, type, \ + fnc ## _parse, fnc ## _print, \ + fnc ## _open, fnc ## _close, \ + fnc ## _read, fnc ## _write, \ + fnc ## _init, fnc ## _deinit };\ + list_push(&node_types, &t); \ +} + +extern struct list node_types; /** C++ like vtable construct for node_types * @todo Add comments */ -struct node_vtable { - const enum node_type type; - const char *name; +struct node_type { + /** The unique name of this node. This must be the first member! */ + char *name; + + /** Node type: layer, protocol, listen/connect */ + enum { + BSD_SOCKET, /**< BSD Socket API */ + LOG_FILE, /**< File IO */ + OPAL_ASYNC, /**< OPAL-RT Asynchronous Process Api */ + GTFPGA, /**< Xilinx ML507 GTFPGA card */ + NGSI /**< NGSI 9/10 HTTP RESTful API (FIRWARE ContextBroker) */ + } type; /** Parse node connection details for SOCKET type * diff --git a/server/src/cfg.c b/server/src/cfg.c index b56bb2177..8edd6ff2c 100644 --- a/server/src/cfg.c +++ b/server/src/cfg.c @@ -107,7 +107,7 @@ int config_parse_path(config_setting_t *cfg, cerror(cfg, "Invalid input node for path"); in = config_setting_get_string(cfg_in); - p->in = node_lookup_name(in, nodes); + p->in = list_lookup(nodes, in); if (!p->in) cerror(cfg_in, "Invalid input node '%s'", in); diff --git a/server/src/file.c b/server/src/file.c index 1b695eb9f..4ac657680 100644 --- a/server/src/file.c +++ b/server/src/file.c @@ -222,3 +222,5 @@ int file_write(struct node *n, struct msg *pool, int poolsize, int first, int cn return i; } + +REGISTER_NODE_TYPE(LOG_FILE, "file", file) \ No newline at end of file diff --git a/server/src/gtfpga.c b/server/src/gtfpga.c index 4f5c50103..9df180306 100644 --- a/server/src/gtfpga.c +++ b/server/src/gtfpga.c @@ -268,3 +268,4 @@ int gtfpga_write(struct node *n, struct msg *pool, int poolsize, int first, int return 0; } +REGISTER_NODE_TYPE(GTFPGA, "gtfpga", gtfpga) \ No newline at end of file diff --git a/server/src/hooks.c b/server/src/hooks.c index 8587fb8f8..d8b6e7199 100644 --- a/server/src/hooks.c +++ b/server/src/hooks.c @@ -23,32 +23,10 @@ /* Some hooks can be configured by constants in te file "config.h" */ -/** This is a static list of available hooks. - * - * It's used by hook_lookup to parse hook identfiers from the configuration file. - * The list must be terminated by NULL pointers! - */ -static const struct hook hook_list[] = { -/* Priority, Callback, Name, Type */ - { 99, hook_print, "print", HOOK_MSG }, - { 99, hook_decimate, "decimate", HOOK_POST }, - { 99, hook_tofixed, "tofixed", HOOK_MSG }, - { 99, hook_ts, "ts", HOOK_MSG }, - { 99, hook_fir, "fir", HOOK_POST }, - { 99, hook_dft, "dft", HOOK_POST } -}; - -const struct hook* hook_lookup(const char *name) -{ - for (int i=0; icurrent; @@ -60,6 +38,7 @@ int hook_print(struct path *p) return 0; } +REGISTER_HOOK("tofixed", 99, hook_tofixed, HOOK_MSG) int hook_tofixed(struct path *p) { struct msg *m = p->current; @@ -70,6 +49,7 @@ int hook_tofixed(struct path *p) return 0; } +REGISTER_HOOK("ts", 99, hook_ts, HOOK_MSG) int hook_ts(struct path *p) { struct msg *m = p->current; @@ -80,6 +60,7 @@ int hook_ts(struct path *p) return 0; } +REGISTER_HOOK("fir", 99, hook_fir, HOOK_POST) int hook_fir(struct path *p) { /** Simple FIR-LP: F_s = 1kHz, F_pass = 100 Hz, F_block = 300 @@ -108,12 +89,14 @@ int hook_fir(struct path *p) return 0; } +REGISTER_HOOK("decimate", 99, hook_decimate, HOOK_POST) int hook_decimate(struct path *p) { /* Only sent every HOOK_DECIMATE_RATIO'th message */ return p->received % HOOK_DECIMATE_RATIO; } +REGISTER_HOOK("dft", 99, hook_dft, HOOK_POST) int hook_dft(struct path *p) { return 0; /** @todo Implement */ diff --git a/server/src/list.c b/server/src/list.c index fc75b7464..5ef309b33 100644 --- a/server/src/list.c +++ b/server/src/list.c @@ -8,6 +8,8 @@ * Unauthorized copying of this file, via any medium is strictly prohibited. *********************************************************************************/ +#include + #include "utils.h" #include "list.h" @@ -103,11 +105,21 @@ void list_insert(struct list *l, int prio, void *p) pthread_mutex_unlock(&l->lock); } -struct list_elm * list_search(struct list *l, int (*cmp)(void *)) +void * list_lookup(const struct list *l, const char *name) { FOREACH(l, it) { - if (!cmp(it->ptr)) - return it; + if (!strcmp(*(char **) it->ptr, name)) + return it->ptr; + } + + return NULL; +} + +void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx) +{ + FOREACH(l, it) { + if (!cmp(it->ptr, ctx)) + return it->ptr; } return NULL; diff --git a/server/src/node.c b/server/src/node.c index 7ca13d463..cf5bc15db 100644 --- a/server/src/node.c +++ b/server/src/node.c @@ -27,30 +27,13 @@ #include #endif -#define VTABLE(type, name, fnc) { type, name, \ - fnc ## _parse, fnc ## _print, \ - fnc ## _open, fnc ## _close, \ - fnc ## _read, fnc ## _write, \ - fnc ## _init, fnc ## _deinit } - /** Vtable for virtual node sub types */ -struct node_vtable vtables[] = { -#ifdef ENABLE_OPAL_ASYNC - VTABLE(OPAL_ASYNC, "opal", opal), -#endif -#ifdef ENABLE_GTFPGA - VTABLE(GTFPGA, "gtfpga", gtfpga), -#endif -#ifdef ENABLE_SOCKET - VTABLE(BSD_SOCKET, "socket", socket), -#endif - VTABLE(LOG_FILE, "file", file) -}; +struct list node_types = LIST_INIT(NULL); int node_init(int argc, char *argv[], struct settings *set) { INDENT - for (int i=0; itype; if (vt->refcnt) { info("Initializing '%s' node type", vt->name); vt->init(argc, argv, set); @@ -63,8 +46,8 @@ int node_init(int argc, char *argv[], struct settings *set) int node_deinit() { INDENT /* De-initialize node types */ - for (int i=0; itype; if (vt->refcnt) { info("De-initializing '%s' node type", vt->name); vt->deinit(); @@ -73,26 +56,6 @@ int node_deinit() return 0; } -struct node * node_lookup_name(const char *str, struct list *nodes) -{ - FOREACH(nodes, it) { - if (!strcmp(str, it->node->name)) - return it->node; - } - - return NULL; -} - -struct node_vtable * node_lookup_vtable(const char *str) -{ - for (int i = 0; i < ARRAY_LEN(vtables); i++) { - if (!strcmp(vtables[i].name, str)) - return &vtables[i]; - } - - return NULL; -} - int node_start(struct node *n) { INDENT if (!n->refcnt) { diff --git a/server/src/opal.c b/server/src/opal.c index a04146da1..e3481aaa4 100644 --- a/server/src/opal.c +++ b/server/src/opal.c @@ -271,3 +271,5 @@ int opal_write(struct node *n, struct msg *pool, int poolsize, int first, int cn return 1; } + +REGISTER_NODE_TYPE(OPAL_ASYNC, "opal", opal) \ No newline at end of file diff --git a/server/src/receive.c b/server/src/receive.c index c5d274cf1..edf9e45ff 100644 --- a/server/src/receive.c +++ b/server/src/receive.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) config_init(&config); config_parse(argv[optind], &config, &set, &nodes, NULL); - node = node_lookup_name(argv[optind+1], &nodes); + node = list_lookup(&nodes, argv[optind+1]); if (!node) error("There's no node with the name '%s'", argv[optind+1]); diff --git a/server/src/send.c b/server/src/send.c index 06cc6ce79..4562d94fd 100644 --- a/server/src/send.c +++ b/server/src/send.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) config_init(&config); config_parse(argv[optind], &config, &set, &nodes, NULL); - node = node_lookup_name(argv[optind+1], &nodes); + node = list_lookup(&nodes, argv[optind+1]); if (!node) error("There's no node with the name '%s'", argv[optind+1]); diff --git a/server/src/socket.c b/server/src/socket.c index 31a95680f..ba864a746 100644 --- a/server/src/socket.c +++ b/server/src/socket.c @@ -452,3 +452,5 @@ int socket_parse_addr(const char *addr, struct sockaddr *saddr, enum socket_laye return ret; } + +REGISTER_NODE_TYPE(BSD_SOCKET, "socket", socket) \ No newline at end of file diff --git a/server/src/test.c b/server/src/test.c index 48bc6ed73..f20db8798 100644 --- a/server/src/test.c +++ b/server/src/test.c @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) config_init(&config); config_parse(argv[1], &config, &settings, &nodes, NULL); - node = node_lookup_name(argv[3], &nodes); + node = list_lookup(&nodes, argv[3]); if (!node) error("There's no node with the name '%s'", argv[3]);