mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-23 00:00:01 +01:00
229 lines
7 KiB
C
229 lines
7 KiB
C
/** Nodes
|
||
*
|
||
* The S2SS server connects multiple nodes.
|
||
* There are multiple types of nodes:
|
||
* - simulators
|
||
* - servers
|
||
* - workstations
|
||
*
|
||
* @file
|
||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
||
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||
*
|
||
* @addtogroup node Node
|
||
* @{
|
||
*********************************************************************************/
|
||
|
||
#ifndef _NODE_H_
|
||
#define _NODE_H_
|
||
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <libconfig.h>
|
||
|
||
#include "msg.h"
|
||
#include "list.h"
|
||
|
||
/* Helper macros for virtual node type */
|
||
#define node_type(n) ((n)->vt->type)
|
||
#define node_print(n) ((n)->vt->print(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_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))
|
||
|
||
|
||
#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_type {
|
||
/** The unique name of this node. This must be allways the first member! */
|
||
char *name;
|
||
|
||
/** Node type */
|
||
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.‚
|
||
*
|
||
* @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);
|
||
|
||
/** Returns a string with a textual represenation of this node.
|
||
*
|
||
* @param n A pointer to the node structure
|
||
* @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.
|
||
* @retval 0 Success. Everything went well.
|
||
* @retval <0 Error. Something went wrong.
|
||
*/
|
||
int (*open) (struct node *n);
|
||
|
||
/** Close the connection to this node.
|
||
*
|
||
* @param n A pointer to the node.
|
||
* @retval 0 Success. Everything went well.
|
||
* @retval <0 Error. Something went wrong.
|
||
*/
|
||
int (*close)(struct node *n);
|
||
|
||
/** Receive multiple messages at once.
|
||
*
|
||
* Messages are received with a single recvmsg() syscall by
|
||
* using gathering techniques (struct iovec).
|
||
* The messages will be stored in a circular buffer / array @p m.
|
||
* 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 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.
|
||
* @param cnt The number of messages which should be sent.
|
||
* @return The number of messages actually received.
|
||
*/
|
||
int (*read) (struct node *n, struct msg *pool, int poolsize, int first, int cnt);
|
||
|
||
/** Send multiple messages in a single datagram / packet.
|
||
*
|
||
* Messages are sent with a single sendmsg() syscall by
|
||
* using gathering techniques (struct iovec).
|
||
* 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 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.
|
||
* @param cnt The number of messages which should be sent.
|
||
* @return The number of messages actually sent.
|
||
*/
|
||
int (*write)(struct node *n, struct msg *pool, int poolsize, int first, int cnt);
|
||
|
||
int (*init)(int argc, char *argv[], struct settings *set);
|
||
int (*deinit)();
|
||
|
||
int refcnt;
|
||
};
|
||
|
||
/** The data structure for a node.
|
||
*
|
||
* Every entity which exchanges messages is represented by a node.
|
||
* Nodes can be remote machines and simulators or locally running processes.
|
||
*/
|
||
struct node
|
||
{
|
||
/** A short identifier of the node, only used for configuration and logging */
|
||
char *name;
|
||
/** How many paths are sending / receiving from this node? */
|
||
int refcnt;
|
||
/** Number of messages to send / recv at once (scatter / gather) */
|
||
int combine;
|
||
/** CPU Affinity of this node */
|
||
int affinity;
|
||
|
||
/** C++ like virtual function call table */
|
||
struct node_type * vt;
|
||
/** Virtual data (used by vtable functions) */
|
||
union {
|
||
struct socket *socket;
|
||
struct opal *opal;
|
||
struct gtfpga *gtfpga;
|
||
struct file *file;
|
||
struct ngsi *ngsi;
|
||
};
|
||
|
||
/** A pointer to the libconfig object which instantiated this node */
|
||
config_setting_t *cfg;
|
||
};
|
||
|
||
/** Initialize node type subsystems.
|
||
*
|
||
* These routines are only called once per type (not per node instance).
|
||
* See node_vtable::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
|
||
*/
|
||
int node_deinit();
|
||
|
||
/** Connect and bind the UDP socket of this node.
|
||
*
|
||
* 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.
|
||
*/
|
||
int node_start(struct node *n);
|
||
|
||
/** Deferred TCP connection setup
|
||
*
|
||
* @todo Dirty hack!
|
||
* We should check the address of the connecting node!
|
||
* We should preserve the original socket for proper shutdown.
|
||
*/
|
||
int node_start_defer(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();
|
||
|
||
/** Destroy node by freeing dynamically allocated memory.
|
||
*
|
||
* @param i A pointer to the interface structure.
|
||
*/
|
||
void node_destroy(struct node *n);
|
||
|
||
#endif /** _NODE_H_ @} */
|