diff --git a/server/include/node.h b/server/include/node.h index 78dba6987..2b97294be 100644 --- a/server/include/node.h +++ b/server/include/node.h @@ -131,4 +131,10 @@ struct node_vtable const * node_lookup_vtable(const char *str); */ struct node* node_lookup_name(const char *str, struct node *nodes); +/** 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. */ +int node_reverse(struct node *n); + #endif /* _NODE_H_ */ diff --git a/server/include/utils.h b/server/include/utils.h index 4e822af04..b4eb8a028 100644 --- a/server/include/utils.h +++ b/server/include/utils.h @@ -39,6 +39,12 @@ #define ARRAY_LEN(a) ( sizeof a / sizeof a[0] ) +#define SWAP(a, b) do { \ + __typeof__(a) tmp = a; \ + a = b; \ + b = tmp; \ + } while(0) + /** The log level which is passed as first argument to print() */ enum log_level { DEBUG, INFO, WARN, ERROR }; diff --git a/server/src/node.c b/server/src/node.c index 0b722f85e..216e200e2 100644 --- a/server/src/node.c +++ b/server/src/node.c @@ -105,3 +105,17 @@ int node_stop(struct node *n) return ret; } + +int 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: { } + } + return n->vt->open == socket_open; +} diff --git a/server/src/receive.c b/server/src/receive.c index 16738b864..18f131c0e 100644 --- a/server/src/receive.c +++ b/server/src/receive.c @@ -33,21 +33,36 @@ void quit(int sig, siginfo_t *si, void *ptr) exit(EXIT_SUCCESS); } +void usage(char *name) +{ + printf("Usage: %s CONFIG NODE\n", name); + printf(" CONFIG path to a configuration file\n"); + printf(" NODE name of the node which shoud be used\n\n"); + printf("Simulator2Simulator Server %s (built on %s %s)\n", + BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); + exit(EXIT_FAILURE); +} + int main(int argc, char *argv[]) { + char c; + int reverse = 0; + struct config_t config; - - if (argc != 3) { - printf("Usage: %s CONFIG NODE\n", argv[0]); - printf(" CONFIG path to a configuration file\n"); - printf(" NODE name of the node which shoud be used\n\n"); - printf("Simulator2Simulator Server %s (built on %s %s)\n", - BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); - printf(" Steffen Vogel \n"); - exit(EXIT_FAILURE); + + while ((c = getopt(argc, argv, "hr")) != -1) { + switch (c) { + case 'r': reverse = 1; break; + case 'h': + case '?': usage(argv[0]); + } } + if (argc - optind != 2) + usage(argv[0]); + /* Setup signals */ struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, @@ -59,11 +74,16 @@ int main(int argc, char *argv[]) sigaction(SIGINT, &sa_quit, NULL); config_init(&config); - config_parse(argv[1], &config, &set, &nodes, NULL); + config_parse(argv[optind], &config, &set, &nodes, NULL); - node = node_lookup_name(argv[2], nodes); + node = node_lookup_name(argv[optind+1], nodes); if (!node) - error("There's no node with the name '%s'", argv[2]); + error("There's no node with the name '%s'", argv[optind+1]); + + node->refcnt++; + + if (reverse) + node_reverse(node); node_start(node); node_start_defer(node); diff --git a/server/src/send.c b/server/src/send.c index 51db9cc99..2dd7bae2a 100644 --- a/server/src/send.c +++ b/server/src/send.c @@ -35,20 +35,36 @@ void quit(int sig, siginfo_t *si, void *ptr) exit(EXIT_SUCCESS); } +void usage(char *name) +{ + printf("Usage: %s [-r] CONFIG NODE\n", name); + printf(" -r swap local / remote address of socket based nodes)\n"); + printf(" CONFIG path to a configuration file\n"); + printf(" NODE name of the node which shoud be used\n"); + printf("Simulator2Simulator Server %s (built on %s %s)\n", + BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); + printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); + printf(" Steffen Vogel \n"); + exit(EXIT_FAILURE); +} + int main(int argc, char *argv[]) { + char c; + int reverse = 0; + struct config_t config; - - if (argc != 3) { - printf("Usage: %s CONFIG NODE\n", argv[0]); - printf(" CONFIG path to a configuration file\n"); - printf(" NODE name of the node which shoud be used\n\n"); - printf("Simulator2Simulator Server %s (built on %s %s)\n", - BLU(VERSION), MAG(__DATE__), MAG(__TIME__)); - printf(" Copyright 2014, Institute for Automation of Complex Power Systems, EONERC\n"); - printf(" Steffen Vogel \n"); - exit(EXIT_FAILURE); + + while ((c = getopt(argc, argv, "hr")) != -1) { + switch (c) { + case 'r': reverse = 1; break; + case 'h': + case '?': usage(argv[0]); + } } + + if (argc - optind != 2) + usage(argv[0]); /* Setup signals */ struct sigaction sa_quit = { @@ -61,11 +77,16 @@ int main(int argc, char *argv[]) sigaction(SIGINT, &sa_quit, NULL); config_init(&config); - config_parse(argv[1], &config, &set, &nodes, NULL); + config_parse(argv[optind], &config, &set, &nodes, NULL); - node = node_lookup_name(argv[2], nodes); + node = node_lookup_name(argv[optind+1], nodes); if (!node) - error("There's no node with the name '%s'", argv[2]); + error("There's no node with the name '%s'", argv[optind+1]); + + node->refcnt++; + + if (reverse) + node_reverse(node); node_start(node); node_start_defer(node);