1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/server/src/node.c

182 lines
3.5 KiB
C
Raw Normal View History

/** Nodes.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
*/
#include <string.h>
2014-12-05 12:39:52 +01:00
#include "node.h"
#include "cfg.h"
#include "utils.h"
2014-12-05 12:39:52 +01:00
/* Node types */
2015-03-31 14:36:30 +02:00
#include "file.h"
2014-12-05 12:39:52 +01:00
#include "socket.h"
#include "gtfpga.h"
#ifdef ENABLE_OPAL_ASYNC
2014-12-05 12:39:52 +01:00
#include "opal.h"
#endif
2014-12-05 12:39:52 +01:00
#define VTABLE(type, name, fnc) { type, name, \
fnc ## _parse, fnc ## _print, \
fnc ## _open, fnc ## _close, \
fnc ## _read, fnc ## _write }
#define VTABLE2(type, name, fnc) { type, name, \
fnc ## _parse, fnc ## _print, \
fnc ## _open, fnc ## _close, \
fnc ## _read, fnc ## _write, \
fnc ## _init, fnc ## _deinit }
2014-12-05 12:39:52 +01:00
/** Vtable for virtual node sub types */
struct node_vtable vtables[] = {
#ifdef ENABLE_OPAL_ASYNC
VTABLE2(OPAL_ASYNC, "opal", opal),
#endif
#ifdef ENABLE_GTFPGA
VTABLE2(GTFPGA, "gtfpga", gtfpga),
#endif
2015-03-31 14:36:30 +02:00
VTABLE(LOG_FILE, "file", file),
2014-12-05 12:39:52 +01:00
VTABLE(IEEE_802_3, "ieee802.3", socket),
VTABLE(IP, "ip", socket),
VTABLE(UDP, "udp", socket),
VTABLE(TCP, "tcp", socket),
VTABLE(TCPD, "tcpd", socket)
2014-12-05 12:39:52 +01:00
};
/** Linked list of nodes. */
struct list nodes;
2014-12-05 12:39:52 +01:00
int node_init(int argc, char *argv[])
{ INDENT
for (int i=0; i<ARRAY_LEN(vtables); i++) {
const struct node_vtable *vt = &vtables[i];
if (vt->refcnt && vt->init) {
if (vt->init(argc, argv))
error("Failed to initialize '%s' node type", vt->name);
else
info("Initializing '%s' node type", vt->name);
}
}
return 0;
}
int node_deinit()
{ INDENT
/* De-initialize node types */
for (int i=0; i<ARRAY_LEN(vtables); i++) {
struct node_vtable *vt = &vtables[i];
if (vt->refcnt && vt->deinit) {
if (vt->deinit())
error("Failed to de-initialize '%s' node type", vt->name);
else
info("De-initializing '%s' node type", vt->name);
}
}
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;
2014-12-05 12:39:52 +01:00
}
2014-12-05 12:39:52 +01:00
return NULL;
}
struct node_vtable * node_lookup_vtable(const char *str)
{
2014-12-05 12:39:52 +01:00
for (int i = 0; i < ARRAY_LEN(vtables); i++) {
if (!strcmp(vtables[i].name, str))
return &vtables[i];
}
2014-12-05 12:39:52 +01:00
return NULL;
}
2014-12-05 12:39:52 +01:00
int node_start(struct node *n)
2015-03-21 15:29:00 +01:00
{ INDENT
2015-03-18 16:16:44 +01:00
if (!n->refcnt) {
warn("Node '%s' is unused. Skipping...", n->name);
return -1;
2015-03-18 16:16:44 +01:00
}
2014-12-05 12:39:52 +01:00
char str[256];
node_print(n, str, sizeof(str));
debug(1, "Starting node '%s' of type '%s' (%s)", n->name, n->vt->name, str);
{ INDENT
return n->vt->open(n);
}
2014-12-05 12:39:52 +01:00
}
2014-12-05 12:39:52 +01:00
int node_start_defer(struct node *n)
{
struct socket *s = n->socket;
2014-12-05 12:39:52 +01:00
if (node_type(n) == TCPD) {
info("Wait for incoming TCP connection from node '%s'...", n->name);
s->sd = listen(s->sd2, 1);
if (s->sd < 0)
serror("Failed to listen on socket for node '%s'", n->name);
s->sd = accept(s->sd2, NULL, NULL);
if (s->sd < 0)
serror("Failed to accept on socket for node '%s'", n->name);
2014-12-05 12:39:52 +01:00
}
return 0;
}
int node_stop(struct node *n)
2015-03-21 15:29:00 +01:00
{ INDENT
2014-12-05 12:39:52 +01:00
int ret;
info("Stopping node '%s'", n->name);
{ INDENT
ret = n->vt->close(n);
}
return ret;
}
2015-03-21 15:29:00 +01:00
void node_reverse(struct node *n)
{
switch (n->vt->type) {
case IEEE_802_3:
case IP:
case UDP:
case TCP:
SWAP(n->socket->remote, n->socket->local);
break;
default: { }
}
2015-03-21 15:29:00 +01:00
}
struct node * node_create()
{
return alloc(sizeof(struct node));
}
void node_destroy(struct node *n)
{
switch (n->vt->type) {
case IEEE_802_3:
case IP:
case UDP:
case TCP:
free(n->socket->netem);
default: { }
}
free(n->socket);
free(n);
}