+#include "system.h"
+
+#include "control_common.h"
+#include "hash.h"
+#include "logger.h"
+#include "net.h"
+#include "netutl.h"
+#include "node.h"
+#include "splay_tree.h"
+#include "utils.h"
+#include "xalloc.h"
+
+#include "ed25519/sha512.h"
+
+splay_tree_t *node_tree;
+static splay_tree_t *node_id_tree;
+static splay_tree_t *node_udp_tree;
+
+node_t *myself;
+
+static int node_compare(const node_t *a, const node_t *b) {
+ return strcmp(a->name, b->name);
+}
+
+static int node_id_compare(const node_t *a, const node_t *b) {
+ return memcmp(&a->id, &b->id, sizeof(node_id_t));
+}
+
+static int node_udp_compare(const node_t *a, const node_t *b) {
+ int result = sockaddrcmp(&a->address, &b->address);
+ if (result)
+ return result;
+ return (a->name && b->name) ? strcmp(a->name, b->name) : 0;
+}
+
+void init_nodes(void) {
+ node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
+ node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
+ node_udp_tree = splay_alloc_tree((splay_compare_t) node_udp_compare, NULL);
+}
+
+void exit_nodes(void) {
+ splay_delete_tree(node_udp_tree);
+ splay_delete_tree(node_id_tree);
+ splay_delete_tree(node_tree);
+}
+
+node_t *new_node(void) {
+ node_t *n = xzalloc(sizeof *n);
+
+ if(replaywin) n->late = xzalloc(replaywin);
+ n->subnet_tree = new_subnet_tree();
+ n->edge_tree = new_edge_tree();
+ n->mtu = MTU;
+ n->maxmtu = MTU;
+
+ return n;
+}
+
+void free_node(node_t *n) {
+ if(n->subnet_tree)
+ free_subnet_tree(n->subnet_tree);