Browse Source

checkpoint before running some sed

Caleb James DeLisle 9 years ago
parent
commit
f8c4656984

+ 17 - 79
admin/angel/Core.c

@@ -24,19 +24,9 @@
 #include "crypto/AddressCalc.h"
 #include "crypto/random/Random.h"
 #include "crypto/random/libuv/LibuvEntropyProvider.h"
-#include "dht/ReplyModule.h"
-#include "dht/EncodingSchemeModule.h"
-#include "dht/SerializationModule.h"
-#include "dht/dhtcore/RouterModule.h"
-#include "dht/dhtcore/RouterModule_admin.h"
-#include "dht/dhtcore/RumorMill.h"
-#include "dht/dhtcore/SearchRunner.h"
-#include "dht/dhtcore/SearchRunner_admin.h"
-#include "dht/dhtcore/NodeStore_admin.h"
-#include "dht/dhtcore/Janitor.h"
-#include "dht/dhtcore/Router_new.h"
-#include "dht/DHTCoreInterface.h"
+#include "dht/Pathfinder.h"
 #include "exception/Jmp.h"
+#include "interface/Iface.h"
 #include "interface/addressable/AddrInterface.h"
 #include "interface/addressable/UDPAddrInterface.h"
 #include "interface/UDPInterface_admin.h"
@@ -87,17 +77,6 @@
 // Failsafe: abort if more than 2^23 bytes are allocated (8MB)
 #define ALLOCATOR_FAILSAFE (1<<23)
 
-/** The number of milliseconds between attempting local maintenance searches. */
-#define LOCAL_MAINTENANCE_SEARCH_MILLISECONDS 1000
-
-/**
- * The number of milliseconds to pass between global maintainence searches.
- * These are searches for random targets which are used to discover new nodes.
- */
-#define GLOBAL_MAINTENANCE_SEARCH_MILLISECONDS 30000
-
-#define RUMORMILL_CAPACITY 64
-
 /**
  * The worst possible packet overhead.
  * assuming the packet needs to be handed off to another node
@@ -368,80 +347,41 @@ void Core_init(struct Allocator* alloc,
         logger = adminLogger;
     }
 
-    // EventEmitter
-    struct EventEmitter* eventEmitter = EventEmitter_new(alloc, logger);
-
     // CryptoAuth
     struct Address* addr = Allocator_calloc(alloc, sizeof(struct Address), 1);
     addr->protocolVersion = Version_CURRENT_PROTOCOL;
     parsePrivateKey(privateKey, addr, eh);
     struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand);
 
+    // EventEmitter
+    struct EventEmitter* eventEmitter = EventEmitter_new(alloc, logger, cryptoAuth->publicKey);
+
     /*struct Sockaddr* myAddr = */Sockaddr_fromBytes(addr->ip6.bytes, Sockaddr_AF_INET6, alloc);
 
     struct SwitchCore* switchCore = SwitchCore_new(logger, alloc, eventBase);
-    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(alloc);
-    ReplyModule_register(registry, alloc);
-
-    struct RumorMill* rumorMill = RumorMill_new(alloc, addr, RUMORMILL_CAPACITY, logger, "extern");
-
-    struct NodeStore* nodeStore = NodeStore_new(addr, alloc, eventBase, logger, rumorMill);
-
-    struct RouterModule* routerModule = RouterModule_register(registry,
-                                                              alloc,
-                                                              addr->key,
-                                                              eventBase,
-                                                              logger,
-                                                              rand,
-                                                              nodeStore);
-
-    struct SearchRunner* searchRunner = SearchRunner_new(nodeStore,
-                                                         logger,
-                                                         eventBase,
-                                                         routerModule,
-                                                         addr->ip6.bytes,
-                                                         rumorMill,
-                                                         alloc);
-
-    Janitor_new(LOCAL_MAINTENANCE_SEARCH_MILLISECONDS,
-                GLOBAL_MAINTENANCE_SEARCH_MILLISECONDS,
-                routerModule,
-                nodeStore,
-                searchRunner,
-                rumorMill,
-                logger,
-                alloc,
-                eventBase,
-                rand);
-
-    EncodingSchemeModule_register(registry, logger, alloc);
-
-    SerializationModule_register(registry, logger, alloc);
 
     struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand, hermes);
 
-    struct Router* router = Router_new(routerModule, nodeStore, searchRunner, alloc);
-
     struct SessionManager* sessionManager =
         SessionManager_new(alloc, eventBase, cryptoAuth, rand, logger, eventEmitter);
 
     struct SwitchAdapter* switchAdapter = SwitchAdapter_new(alloc, logger);
-    Interface_plumb(&sessionManager->switchIf, &switchAdapter->sessionManagerIf);
+    Iface_plumb(&sessionManager->switchIf, &switchAdapter->sessionManagerIf);
     SwitchCore_setRouterInterface(&switchAdapter->switchIf, switchCore);
 
-    struct ControlHandler* controlHandler = ControlHandler_new(alloc, logger, router, addr);
-    Interface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf);
-
-    /*struct DHTCoreInterface* dhtCore =*/ DHTCoreInterface_register(alloc, logger, registry);
-    // TODO...
+    struct ControlHandler* controlHandler =
+        ControlHandler_new(alloc, logger, eventEmitter, addr->key);
+    Iface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf);
 
     struct SwitchPinger* sp = SwitchPinger_new(eventBase, rand, logger, addr, alloc);
-    Interface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf);
+    Iface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf);
 
     // Interfaces.
     struct InterfaceController* ifController =
-        InterfaceController_new(cryptoAuth, switchCore, router, rumorMill,
-                                logger, eventBase, sp, rand, alloc);
+        InterfaceController_new(cryptoAuth, switchCore,
+                                logger, eventBase, sp, rand, alloc, eventEmitter);
+
+    Pathfinder_register(alloc, logger, eventBase, rand, admin, eventEmitter);
 
     // ------------------- DNS -------------------------//
 
@@ -453,20 +393,18 @@ void Core_init(struct Allocator* alloc,
     Assert_true(!Sockaddr_parse("[fc00::1]:53", &rainflyAddr));
     struct PacketHeaderToUDPAddrInterface* magicUDP =
         PacketHeaderToUDPAddrInterface_new(alloc, &rainflyAddr.addr);
-//    Interface_plumb(&magicUDP->headerIf, &dtAAAAAAAAAAAAAA->magicIf);
+//    Iface_plumb(&magicUDP->headerIf, &dtAAAAAAAAAAAAAA->magicIf);
     DNSServer_new(&magicUDP->udpIf, logger, rainfly);
 
 
     // ------------------- Register RPC functions ----------------------- //
-    InterfaceController_admin_register(ifController, nodeStore, admin, alloc);
+    InterfaceController_admin_register(ifController, admin, alloc);
     SwitchPinger_admin_register(sp, admin, alloc);
     UDPInterface_admin_register(eventBase, alloc, logger, admin, ifController);
 #ifdef HAS_ETH_INTERFACE
     ETHInterface_admin_register(eventBase, alloc, logger, admin, ifController, hermes);
 #endif
-    NodeStore_admin_register(nodeStore, admin, alloc);
-    RouterModule_admin_register(routerModule, router, admin, alloc);
-    SearchRunner_admin_register(searchRunner, admin, alloc);
+
     AuthorizedPasswords_init(admin, cryptoAuth, alloc);
     Admin_registerFunction("ping", adminPing, admin, false, NULL, admin);
 //    Core_admin_register(myAddr, dtAAAAAAAAAAAAAA, logger, ipTun, alloc, admin, eventBase);

+ 2 - 3
admin/angel/cjdroute2.c

@@ -20,12 +20,11 @@
 #include "admin/AuthorizedPasswords.h"
 #include "admin/Configurator.h"
 #include "benc/Int.h"
+#include "benc/List.h"
+#include "benc/Dict.h"
 #include "crypto/AddressCalc.h"
 #include "crypto/CryptoAuth.h"
 #include "crypto/CryptoAuth_benchmark.h"
-#include "dht/ReplyModule.h"
-#include "dht/SerializationModule.h"
-#include "dht/dhtcore/RouterModule_admin.h"
 #include "exception/Except.h"
 #include "interface/Interface.h"
 #include "interface/UDPInterface_admin.h"

+ 2 - 2
dht/DHTCoreInterface.c

@@ -56,10 +56,10 @@ static int incomingFromDHT(struct DHTMessage* dmessage, void* vcim)
 
     Log_debug(cim->log, "Outgoing DHT");
 
-    return Interface_send(&cim->pub.coreIf, msg);
+    return Iface_send(&cim->pub.coreIf, msg);
 }
 
-static int incomingFromCore(struct Interface_Two* coreIf, struct Message* msg)
+static Iface_DEFUN incomingFromCore(struct Iface* coreIf, struct Message* msg)
 {
     struct DHTCoreInterface_pvt* cim = Identity_check((struct DHTCoreInterface_pvt*) coreIf);
 

+ 2 - 2
dht/DHTCoreInterface.h

@@ -16,7 +16,7 @@
 #define DHTCoreInterface_H
 
 #include "dht/DHTModuleRegistry.h"
-#include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "util/log/Log.h"
 #include "util/Linker.h"
@@ -28,7 +28,7 @@ struct DHTCoreInterface
      * Communicates with the core.
      * Content: [ struct Address ][ content... ]
      */
-    struct Interface_Two coreIf;
+    struct Iface coreIf;
 };
 
 struct DHTCoreInterface* DHTCoreInterface_register(struct Allocator* alloc,

+ 347 - 0
dht/Pathfinder.c

@@ -0,0 +1,347 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "dht/Pathfinder.h"
+#include "dht/DHTModule.h"
+#include "dht/Address.h"
+#include "wire/DataHeader.h"
+#include "wire/RouteHeader.h"
+#include "dht/ReplyModule.h"
+#include "dht/EncodingSchemeModule.h"
+#include "dht/SerializationModule.h"
+#include "dht/dhtcore/RouterModule.h"
+#include "dht/dhtcore/RouterModule_admin.h"
+#include "dht/dhtcore/RumorMill.h"
+#include "dht/dhtcore/SearchRunner.h"
+#include "dht/dhtcore/SearchRunner_admin.h"
+#include "dht/dhtcore/NodeStore_admin.h"
+#include "dht/dhtcore/Janitor.h"
+#include "dht/dhtcore/Router_new.h"
+#include "util/AddrTools.h"
+#include "wire/Error.h"
+#include "util/CString.h"
+
+///////////////////// [ Address ][ content... ]
+
+/** The number of milliseconds between attempting local maintenance searches. */
+#define LOCAL_MAINTENANCE_SEARCH_MILLISECONDS 1000
+
+/**
+ * The number of milliseconds to pass between global maintainence searches.
+ * These are searches for random targets which are used to discover new nodes.
+ */
+#define GLOBAL_MAINTENANCE_SEARCH_MILLISECONDS 30000
+
+#define RUMORMILL_CAPACITY 64
+
+struct Pathfinder_pvt
+{
+    struct Pathfinder pub;
+    struct Iface eventIf;
+    struct DHTModule dhtModule;
+    struct Allocator* alloc;
+    struct Log* log;
+    struct EventBase* base;
+    struct Random* rand;
+    struct Admin* admin;
+    struct EventEmitter* ee;
+
+    #define Pathfinder_pvt_state_INITIALIZING 0
+    #define Pathfinder_pvt_state_RUNNING 1
+    int state;
+
+    // After begin connected, these fields will be filled.
+    struct Address myAddr;
+    struct DHTModuleRegistry* registry;
+
+    Identity
+};
+
+static int incomingFromDHT(struct DHTMessage* dmessage, void* vpf)
+{
+    struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vpf);
+    struct Message* msg = dmessage->binMessage;
+    struct Address* addr = dmessage->address;
+
+    // Sanity check (make sure the addr was actually calculated)
+    Assert_true(addr->ip6.bytes[0] == 0xfc && addr->padding == 0);
+
+    Message_shift(msg, Event_Msg_MIN_SIZE, NULL);
+    struct Event_Msg* emsg = (struct Event_Msg*) msg->bytes;
+    Bits_memset(emsg, 0, Event_Msg_MIN_SIZE);
+
+    DataHeader_setVersion(&emsg->data, DataHeader_CURRENT_VERSION);
+    DataHeader_setContentType(&emsg->data, ContentType_CJDHT);
+
+    Bits_memcpyConst(emsg->route.ip6, addr->ip6.bytes, 16);
+    emsg->route.version_be = Endian_hostToBigEndian32(addr->protocolVersion);
+    emsg->route.sh.label_be = Endian_hostToBigEndian64(addr->path);
+    Bits_memcpyConst(emsg->route.publicKey, addr->key, 32);
+
+    Message_push32(msg, Event_Pathfinder_SENDMSG, NULL);
+
+    Log_debug(pf->log, "Outgoing DHT");
+
+    Iface_send(&pf->eventIf, msg);
+    return 0;
+}
+
+static Iface_DEFUN connected(struct Pathfinder_pvt* pf, struct Message* msg)
+{
+    struct Event_Core_Connect conn;
+    Message_pop(msg, &conn, Event_Core_Connect_SIZE, NULL);
+    Assert_true(!msg->length);
+
+    Bits_memcpyConst(pf->myAddr.key, conn.publicKey, 32);
+    Address_getPrefix(&pf->myAddr);
+    pf->myAddr.path = 1;
+
+    // begin
+
+    pf->registry = DHTModuleRegistry_new(pf->alloc);
+    ReplyModule_register(pf->registry, pf->alloc);
+
+    struct RumorMill* rumorMill =
+        RumorMill_new(pf->alloc, &pf->myAddr, RUMORMILL_CAPACITY, pf->log, "extern");
+
+    struct NodeStore* nodeStore =
+        NodeStore_new(&pf->myAddr, pf->alloc, pf->base, pf->log, rumorMill);
+
+    struct RouterModule* routerModule = RouterModule_register(pf->registry,
+                                                              pf->alloc,
+                                                              pf->myAddr.key,
+                                                              pf->base,
+                                                              pf->log,
+                                                              pf->rand,
+                                                              nodeStore);
+
+    struct SearchRunner* searchRunner = SearchRunner_new(nodeStore,
+                                                         pf->log,
+                                                         pf->base,
+                                                         routerModule,
+                                                         pf->myAddr.ip6.bytes,
+                                                         rumorMill,
+                                                         pf->alloc);
+
+    Janitor_new(LOCAL_MAINTENANCE_SEARCH_MILLISECONDS,
+                GLOBAL_MAINTENANCE_SEARCH_MILLISECONDS,
+                routerModule,
+                nodeStore,
+                searchRunner,
+                rumorMill,
+                pf->log,
+                pf->alloc,
+                pf->base,
+                pf->rand);
+
+    EncodingSchemeModule_register(pf->registry, pf->log, pf->alloc);
+
+    SerializationModule_register(pf->registry, pf->log, pf->alloc);
+
+    DHTModuleRegistry_register(&pf->dhtModule, pf->registry);
+
+    // Now the admin stuff...
+    if (pf->admin) {
+        struct Router* router = Router_new(routerModule, nodeStore, searchRunner, pf->alloc);
+        NodeStore_admin_register(nodeStore, pf->admin, pf->alloc);
+        RouterModule_admin_register(routerModule, router, pf->admin, pf->alloc);
+        SearchRunner_admin_register(searchRunner, pf->admin, pf->alloc);
+    }
+
+    pf->state = Pathfinder_pvt_state_RUNNING;
+
+    return NULL;
+}
+
+static void addressForNode(struct Address* addrOut, struct Message* msg)
+{
+    struct Event_Node node;
+    Message_pop(msg, &node, Event_Node_SIZE, NULL);
+    Assert_true(!msg->length);
+    addrOut->protocolVersion = Endian_bigEndianToHost32(node.version_be);
+    addrOut->path = Endian_bigEndianToHost64(node.path_be);
+    Bits_memcpyConst(addrOut->key, node.publicKey, 32);
+    Bits_memcpyConst(addrOut->ip6.bytes, node.ip6, 16);
+}
+
+static Iface_DEFUN switchErr(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Event_Core_SwitchErr switchErr;
+    Message_pop(msg, &switchErr, Event_Core_SwitchErr_MIN_SIZE, NULL);
+
+    uint8_t pathStr[20];
+    AddrTools_printPath(pathStr, Endian_bigEndianToHost64(switchErr.sh.label_be));
+    int err = Endian_bigEndianToHost32(switchErr.ctrlErr.errorType_be);
+    Log_debug(pf->log, "switch err from [%s] type [%s][%d]", pathStr, Error_strerror(err), err);
+    return NULL;
+}
+
+static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    uint8_t addr[16];
+    Message_pop(msg, addr, 16, NULL);
+    Assert_true(!msg->length);
+    uint8_t printedAddr[40];
+    AddrTools_printIp(printedAddr, addr);
+    Log_debug(pf->log, "Search req [%s]", printedAddr);
+    return NULL;
+}
+
+static Iface_DEFUN peer(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    addressForNode(&addr, msg);
+    String* str = Address_toString(&addr, msg->alloc);
+    Log_debug(pf->log, "Peer [%s]", str->bytes);
+    return NULL;
+}
+
+static Iface_DEFUN peerGone(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    addressForNode(&addr, msg);
+    String* str = Address_toString(&addr, msg->alloc);
+    Log_debug(pf->log, "Peer gone [%s]", str->bytes);
+    return NULL;
+}
+
+static Iface_DEFUN session(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    addressForNode(&addr, msg);
+    String* str = Address_toString(&addr, msg->alloc);
+    Log_debug(pf->log, "Session [%s]", str->bytes);
+    return NULL;
+}
+
+static Iface_DEFUN sessionEnded(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    addressForNode(&addr, msg);
+    String* str = Address_toString(&addr, msg->alloc);
+    Log_debug(pf->log, "Session ended [%s]", str->bytes);
+    return NULL;
+}
+
+static Iface_DEFUN discoveredPath(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    addressForNode(&addr, msg);
+    String* str = Address_toString(&addr, msg->alloc);
+    Log_debug(pf->log, "Discovered path [%s]", str->bytes);
+    return NULL;
+}
+
+static Iface_DEFUN handlePing(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    Log_debug(pf->log, "Received ping");
+    Message_push32(msg, Event_Pathfinder_PONG, NULL);
+    return Iface_next(&pf->eventIf, msg);
+}
+
+static Iface_DEFUN handlePong(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    Log_debug(pf->log, "Received pong");
+    return NULL;
+}
+
+static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf)
+{
+    struct Address addr;
+    struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes;
+    Message_shift(msg, -(RouteHeader_SIZE + DataHeader_SIZE), NULL);
+    Bits_memcpyConst(addr.ip6.bytes, hdr->ip6, 16);
+    Bits_memcpyConst(addr.key, hdr->publicKey, 32);
+    addr.protocolVersion = Endian_bigEndianToHost32(hdr->version_be);
+    addr.padding = 0;
+    addr.path = Endian_bigEndianToHost64(hdr->sh.label_be);
+
+    Log_debug(pf->log, "Incoming DHT");
+
+    struct DHTMessage dht = {
+        .address = &addr,
+        .binMessage = msg,
+        .allocator = msg->alloc
+    };
+
+    DHTModuleRegistry_handleIncoming(&dht, pf->registry);
+
+    return NULL;
+}
+
+static Iface_DEFUN incomingFromEventIf(struct Iface* eventIf, struct Message* msg)
+{
+    struct Pathfinder_pvt* pf = Identity_containerOf(eventIf, struct Pathfinder_pvt, eventIf);
+    enum Event_Core ev = Message_pop32(msg, NULL);
+    if (Pathfinder_pvt_state_INITIALIZING == pf->state) {
+        Assert_true(ev == Event_Core_CONNECT);
+        return connected(pf, msg);
+    }
+    switch (ev) {
+        case Event_Core_SWITCH_ERR: return switchErr(msg, pf);
+        case Event_Core_SEARCH_REQ: return searchReq(msg, pf);
+        case Event_Core_PEER: return peer(msg, pf);
+        case Event_Core_PEER_GONE: return peerGone(msg, pf);
+        case Event_Core_SESSION: return session(msg, pf);
+        case Event_Core_SESSION_ENDED: return sessionEnded(msg, pf);
+        case Event_Core_DISCOVERED_PATH: return discoveredPath(msg, pf);
+        case Event_Core_MSG: return incomingMsg(msg, pf);
+        case Event_Core_PING: return handlePing(msg, pf);
+        case Event_Core_PONG: return handlePong(msg, pf);
+        default:;
+    }
+    Assert_failure("unexpected event [%d]", ev);
+}
+
+static void sendEvent(struct Pathfinder_pvt* pf, enum Event_Pathfinder ev, void* data, int size)
+{
+    struct Allocator* alloc = Allocator_child(pf->alloc);
+    struct Message* msg = Message_new(0, 512+size, alloc);
+    Message_push(msg, data, size, NULL);
+    Message_push32(msg, ev, NULL);
+    Iface_send(&pf->eventIf, msg);
+    Allocator_free(alloc);
+}
+
+struct Pathfinder* Pathfinder_register(struct Allocator* alloc,
+                                       struct Log* log,
+                                       struct EventBase* base,
+                                       struct Random* rand,
+                                       struct Admin* admin,
+                                       struct EventEmitter* ee)
+{
+    struct Pathfinder_pvt* pf = Allocator_calloc(alloc, sizeof(struct Pathfinder_pvt), 1);
+    pf->alloc = alloc;
+    pf->log = log;
+    pf->base = base;
+    pf->rand = rand;
+    pf->admin = admin;
+    pf->ee = ee;
+    Identity_set(pf);
+
+    pf->eventIf.send = incomingFromEventIf;
+    EventEmitter_regPathfinderIface(ee, &pf->eventIf);
+
+    pf->dhtModule.context = pf;
+    pf->dhtModule.handleOutgoing = incomingFromDHT;
+
+    struct Event_Pathfinder_Connect conn = {
+        .superiority_be = Endian_hostToBigEndian32(1),
+        .version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL)
+    };
+    CString_strncpy(conn.userAgent, "Cjdns internal pathfinder", 64);
+    sendEvent(pf, Event_Pathfinder_CONNECT, &conn, Event_Pathfinder_Connect_SIZE);
+
+    return &pf->pub;
+}

+ 40 - 0
dht/Pathfinder.h

@@ -0,0 +1,40 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef Pathfinder_H
+#define Pathfinder_H
+
+#include "interface/Iface.h"
+#include "memory/Allocator.h"
+#include "util/log/Log.h"
+#include "util/events/EventBase.h"
+#include "crypto/random/Random.h"
+#include "admin/Admin.h"
+#include "net/EventEmitter.h"
+#include "util/Linker.h"
+Linker_require("dht/Pathfinder.c")
+
+struct Pathfinder
+{
+    int unused;
+};
+
+struct Pathfinder* Pathfinder_register(struct Allocator* alloc,
+                                       struct Log* logger,
+                                       struct EventBase* base,
+                                       struct Random* rand,
+                                       struct Admin* admin,
+                                       struct EventEmitter* ee);
+
+#endif

+ 106 - 0
interface/Iface.h

@@ -0,0 +1,106 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef Iface_H
+#define Iface_H
+
+#include <stdint.h>
+
+#include "wire/Message.h"
+
+struct Iface;
+
+/**
+ * @param thisInterface the interface which contains the sendMessage function pointer.
+ * @param message the message
+ */
+typedef struct Iface* (* Iface_Callback)(struct Iface* thisInterface, struct Message* message);
+
+#define Iface_DEFUN __attribute__ ((warn_unused_result)) struct Iface*
+
+struct Iface
+{
+    /** Send a message through this interface. */
+    Iface_Callback send;
+
+    #ifdef PARANOIA
+        /** This is for checking currentMsg Iface_next() has not been called incorrectly. */
+        struct Message* currentMsg;
+    #endif
+
+    /** Interface to which this one is connected (if connected) */
+    struct Iface* connectedIf;
+};
+
+static inline void Iface_send(struct Iface* iface, struct Message* msg)
+{
+    do {
+        struct Iface* conn = iface->connectedIf;
+        if (!conn) { return; }
+        #ifdef PARANOIA
+            Assert_true(conn->send);
+            Assert_true(msg);
+            msg->currentIface = iface;
+            iface->currentMsg = msg;
+        #endif
+        iface = conn->send(conn, msg);
+        #ifdef PARANOIA
+            msg->currentIface = NULL;
+            iface->currentMsg = NULL;
+        #endif
+    } while (iface);
+}
+
+/**
+ * This is a hack high-performance version of Iface_send() which can only be used as a tail call.
+ * You MUST pass the same msg which was passed to you, otherwise it will fail.
+ */
+static inline Iface_DEFUN Iface_next(struct Iface* iface, struct Message* msg)
+{
+    #ifdef PARANOIA
+        Assert_true(msg->currentIface);
+        Assert_true(msg->currentIface->currentMsg == msg);
+    #endif
+
+    #ifdef STUPID_OPTIMIZATIONS
+        return iface;
+    #endif
+
+    Iface_send(iface, msg);
+    return NULL;
+}
+
+#define Iface_CALL(func, msg, ...) \
+    do {                                                      \
+        struct Iface* Iface_x = func(msg, __VA_ARGS__);       \
+        if (Iface_x) { Iface_send(Iface_x, msg); }            \
+    } while (0)
+
+static inline void Iface_plumb(struct Iface* a, struct Iface* b)
+{
+    Assert_true(!a->connectedIf);
+    Assert_true(!b->connectedIf);
+    a->connectedIf = b;
+    b->connectedIf = a;
+}
+
+static inline void Iface_unplumb(struct Iface* a)
+{
+    Assert_true(a->connectedIf);
+    Assert_true(a->connectedIf->connectedIf == a);
+    a->connectedIf->connectedIf = NULL;
+    a->connectedIf = NULL;
+}
+
+#endif

+ 2 - 53
interface/Interface.h

@@ -19,6 +19,8 @@
 
 #include "wire/Message.h"
 
+/// OLD: use interface/Iface.h instead!
+
 #define Interface_ERROR_WRONG_STATE 256
 
 struct Interface;
@@ -85,57 +87,4 @@ static inline uint8_t Interface_sendMessage(struct Interface* iface, struct Mess
     return iface->sendMessage(msg, iface);
 }
 
-
-
-typedef int Interface_Ret;
-
-#define Interface_RET 0
-
-struct Interface_Two;
-
-/**
- * @param thisInterface the interface which contains the sendMessage function pointer.
- * @param message the message
- */
-typedef Interface_RetVal (* Interface_Callback2)(struct Interface_Two* thisInterface,
-                                                 struct Message* message);
-
-struct Interface_Two
-{
-    /**
-     * Send a message through this interface.
-     *
-     * @return 0 If all goes well, non-zero in case of an error.
-     *           See Error.h for more information about interface error codes.
-     */
-    Interface_Callback2 send;
-
-    /** Interface to which this one is connected (if connected) */
-    struct Interface_Two* connectedIf;
-};
-
-static inline int Interface_send(struct Interface_Two* iface, struct Message* msg)
-{
-    struct Interface_Two* conn = iface->connectedIf;
-    if (!conn) { return Interface_ERROR_WRONG_STATE; }
-    Assert_true(conn->send);
-    return conn->send(conn, msg);
-}
-
-static inline void Interface_plumb(struct Interface_Two* a, struct Interface_Two* b)
-{
-    Assert_true(!a->connectedIf);
-    Assert_true(!b->connectedIf);
-    a->connectedIf = b;
-    b->connectedIf = a;
-}
-
-static inline void Interface_unplumb(struct Interface_Two* a)
-{
-    Assert_true(a->connectedIf);
-    Assert_true(a->connectedIf->connectedIf == a);
-    a->connectedIf->connectedIf = NULL;
-    a->connectedIf = NULL;
-}
-
 #endif

+ 62 - 59
interface/InterfaceController.c

@@ -14,11 +14,12 @@
  */
 #include "crypto/AddressCalc.h"
 #include "crypto/CryptoAuth_pvt.h"
+#include "interface/Iface.h"
 #include "interface/InterfaceController.h"
-#include "dht/dhtcore/RumorMill.h"
-#include "dht/dhtcore/Router.h"
 #include "memory/Allocator.h"
 #include "net/SwitchPinger.h"
+#include "net/Event.h"
+#include "net/EventEmitter.h"
 #include "util/Base32.h"
 #include "util/Bits.h"
 #include "util/events/Time.h"
@@ -77,13 +78,13 @@ static inline int Map_EndpointsBySockaddr_compare(struct Sockaddr** keyA, struct
 }
 // ---------------- EndMap ----------------
 
-#define ArrayList_TYPE struct Iface
+#define ArrayList_TYPE struct PeerIface
 #define ArrayList_NAME OfIfaces
 #include "util/ArrayList.h"
 
 struct InterfaceController_pvt;
 
-struct Iface
+struct PeerIface
 {
     String* name;
     int beaconState;
@@ -106,7 +107,7 @@ struct Peer
     struct Interface* cryptoAuthIf;
 
     /** The interface which this peer belongs to. */
-    struct Iface* ici;
+    struct PeerIface* ici;
 
     /** The address within the interface of this peer. */
     struct Sockaddr* lladdr;
@@ -162,7 +163,7 @@ struct InterfaceController_pvt
     struct EventBase* const eventBase;
 
     /** For communicating with the Pathfinder. */
-    struct Interface_Two eventEmitterIf;
+    struct Iface eventEmitterIf;
 
     /** After this number of milliseconds, a neoghbor will be regarded as unresponsive. */
     uint32_t unresponsiveAfterMilliseconds;
@@ -195,21 +196,24 @@ struct InterfaceController_pvt
     Identity
 };
 
-static void sendEvent(struct InterfaceController_pvt* ic, enum Event_Core ev, struct Peer* p)
+static void sendPeer(struct InterfaceController_pvt* ic,
+                     uint32_t pathfinderId,
+                     enum Event_Core ev,
+                     struct Peer* peer,
+                     struct Allocator* parentAlloc)
 {
-        /**
-     * Emitted when a peer connects (becomes state ESTABLISHED) or
-     * emitted for every peer if Event_Pathfinder_PEERS is sent.
-     * (emitted by: InterfaceController.c)
-     */
-    Event_Core_PEER,
-
-    /**
-     * Emitted when a peer disconnects (or becomes state UNRESPONSIVE)
-     * (emitted by: InterfaceController.c)
-     */
-    Event_Core_PEER_GONE,
-
+    struct Allocator* alloc = Allocator_child(parentAlloc);
+    struct Message* msg = Message_new(Event_Node_SIZE, 512, alloc);
+    struct Event_Node* node = (struct Event_Node*) msg->bytes;
+    Bits_memcpyConst(node->ip6, peer->addr.ip6.bytes, 16);
+    Bits_memcpyConst(node->publicKey, peer->addr.key, 32);
+    node->path_be = Endian_hostToBigEndian64(peer->addr.path);
+    node->metric_be = 0xffffffff;
+    node->version_be = Endian_hostToBigEndian32(peer->addr.protocolVersion);
+    Message_push32(msg, pathfinderId, NULL);
+    Message_push32(msg, ev, NULL);
+    Iface_send(&ic->eventEmitterIf, msg);
+    Allocator_free(alloc);
 }
 
 static void onPingResponse(struct SwitchPinger_Response* resp, void* onResponseContext)
@@ -241,18 +245,8 @@ static void onPingResponse(struct SwitchPinger_Response* resp, void* onResponseC
         return;
     }
 
-    if (!ep->timeOfLastPing) {
-        // We've never heard from this machine before (or we've since forgotten about it)
-        // This is here because we want the tests to function without the janitor present.
-        // Other than that, it just makes a slightly more synchronous/guaranteed setup.
-        Router_sendGetPeers(ic->router, &ep->addr, 0, 0, ic->allocator);
-    }
-
-    struct Node_Link* link = Router_linkForPath(ic->router, resp->label);
-    if (!link || !Node_getBestParent(link->child)) {
-        RumorMill_addNode(ic->rumorMill, &ep->addr);
-    } else {
-        Log_debug(ic->logger, "link exists");
+    if (ep->state == InterfaceController_PeerState_ESTABLISHED) {
+        sendPeer(ic, 0xffffffff, Event_Core_PEER, ep, ep->externalIf.allocator);
     }
 
     ep->timeOfLastPing = Time_currentTimeMilliseconds(ic->eventBase);
@@ -296,7 +290,7 @@ static void sendPing(struct Peer* ep)
     }
 }
 
-static void iciPing(struct Iface* ici, struct InterfaceController_pvt* ic)
+static void iciPing(struct PeerIface* ici, struct InterfaceController_pvt* ic)
 {
     if (!ici->peerMap.count) { return; }
     uint64_t now = Time_currentTimeMilliseconds(ic->eventBase);
@@ -326,6 +320,7 @@ static void iciPing(struct Iface* ici, struct InterfaceController_pvt* ic)
             Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] "
                                   "seconds, dropping connection",
                                   key, ic->forgetAfterMilliseconds / 1024);
+            sendPeer(ic, 0xffffffff, Event_Core_PEER_GONE, ep, ep->externalIf.allocator);
             Allocator_free(ep->externalIf.allocator);
             continue;
         }
@@ -333,7 +328,7 @@ static void iciPing(struct Iface* ici, struct InterfaceController_pvt* ic)
         bool unresponsive = (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds);
         if (unresponsive) {
             // our link to the peer is broken...
-            Router_disconnectedPeer(ic->router, ep->addr.path);
+            sendPeer(ic, 0xffffffff, Event_Core_PEER_GONE, ep, ep->externalIf.allocator);
 
             // Lets skip 87% of pings when they're really down.
             if (ep->pingCount % 8) {
@@ -368,7 +363,7 @@ static void pingCallback(void* vic)
 {
     struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) vic);
     for (int i = 0; i < ic->icis->length; i++) {
-        struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, i);
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, i);
         iciPing(ici, ic);
     }
 }
@@ -376,15 +371,13 @@ static void pingCallback(void* vic)
 /** If there's already an endpoint with the same public key, merge the new one with the old one. */
 static void moveEndpointIfNeeded(struct Peer* ep)
 {
-    struct Iface* ici = ep->ici;
+    struct PeerIface* ici = ep->ici;
     Log_debug(ici->ic->logger, "Checking for old sessions to merge with.");
     for (uint32_t i = 0; i < ici->peerMap.count; i++) {
         struct Peer* thisEp = ici->peerMap.values[i];
         if (thisEp != ep && !Bits_memcmp(thisEp->addr.key, ep->addr.key, 32)) {
             Log_info(ici->ic->logger, "Moving endpoint to merge new session with old.");
 
-            // flush out the new entry if needed.
-            Router_disconnectedPeer(ici->ic->router, ep->addr.path);
             ep->addr.path = thisEp->addr.path;
             SwitchCore_swapInterfaces(&thisEp->switchIf, &ep->switchIf);
             Allocator_free(thisEp->externalIf.allocator);
@@ -415,6 +408,7 @@ static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cr
 
         if (caState == CryptoAuth_ESTABLISHED) {
             moveEndpointIfNeeded(ep);
+            sendPeer(ic, 0xffffffff, Event_Core_PEER, ep, ep->externalIf.allocator);
         } else {
             // prevent some kinds of nasty things which could be done with packet replay.
             // This is checking the message switch header and will drop it unless the label
@@ -496,14 +490,12 @@ static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf)
 static int closeInterface(struct Allocator_OnFreeJob* job)
 {
     struct Peer* toClose = Identity_check((struct Peer*) job->userData);
+    struct InterfaceController_pvt* ic = Identity_check(toClose->ici->ic);
 
-    struct InterfaceController_pvt* ic = Identity_check(ep->ici->ic);
-
-    // flush the peer from the table...
-    Router_disconnectedPeer(ic->router, toClose->addr.path);
+    sendPeer(ic, 0xffffffff, Event_Core_PEER_GONE, toClose, toClose->externalIf.allocator);
 
     int index = Map_EndpointsBySockaddr_indexForHandle(toClose->handle, &toClose->ici->peerMap);
-    Assert_true(index >= 0);
+    Assert_true(index >= 0 && toClose->ici->peerMap.values[index] == toClose);
     Map_EndpointsBySockaddr_remove(index, &toClose->ici->peerMap);
     return 0;
 }
@@ -532,7 +524,7 @@ static uint8_t sendAfterCryptoAuth(struct Message* msg, struct Interface* extern
 /**
  * Expects [ struct LLAddress ][ beacon ]
  */
-static uint8_t handleBeacon(struct Message* msg, struct Iface* ici)
+static uint8_t handleBeacon(struct Message* msg, struct PeerIface* ici)
 {
     struct InterfaceController_pvt* ic = ici->ic;
     if (!ici->beaconState) {
@@ -638,7 +630,9 @@ static uint8_t handleBeacon(struct Message* msg, struct Iface* ici)
 
     Log_info(ic->logger, "Added peer [%s] from beacon", printedAddr->bytes);
 
-    Router_sendGetPeers(ic->router, &ep->addr, 0, 0, ic->allocator);
+    // This should be safe because this is an outgoing request and we're sure the node will not
+    // be relocated by moveEndpointIfNeeded()
+    sendPeer(ic, 0xffffffff, Event_Core_PEER, ep, ep->externalIf.allocator);
     return 0;
 }
 
@@ -646,7 +640,7 @@ static uint8_t handleBeacon(struct Message* msg, struct Iface* ici)
  * Incoming message from someone we don't know, maybe someone responding to a beacon?
  * expects: [ struct LLAddress ][ content ]
  */
-static uint8_t handleUnexpectedIncoming(struct Message* msg, struct Iface* ici)
+static uint8_t handleUnexpectedIncoming(struct Message* msg, struct PeerIface* ici)
 {
     struct InterfaceController_pvt* ic = ici->ic;
 
@@ -708,7 +702,7 @@ static uint8_t handleUnexpectedIncoming(struct Message* msg, struct Iface* ici)
 
 static uint8_t handleIncomingFromWire(struct Message* msg, struct Interface* iface)
 {
-    struct Iface* ici = Identity_check((struct Iface*) iface->receiverContext);
+    struct PeerIface* ici = Identity_check((struct PeerIface*) iface->receiverContext);
 
     struct Sockaddr* lladdr = (struct Sockaddr*) msg->bytes;
     if (msg->length < Sockaddr_OVERHEAD || msg->length < lladdr->addrLen) {
@@ -757,8 +751,7 @@ int InterfaceController_regIface(struct InterfaceController* ifc,
 {
     struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);
 
-    struct Iface* ici =
-        Allocator_calloc(alloc, sizeof(struct Iface), 1);
+    struct PeerIface* ici = Allocator_calloc(alloc, sizeof(struct PeerIface), 1);
     ici->name = String_clone(name, alloc);
     ici->peerMap.allocator = alloc;
     ici->ic = ic;
@@ -780,7 +773,7 @@ static int freeAlloc(struct Allocator_OnFreeJob* job)
     return 0;
 }
 
-static void sendBeacon(struct Iface* ici, struct Allocator* tempAlloc)
+static void sendBeacon(struct PeerIface* ici, struct Allocator* tempAlloc)
 {
     if (ici->beaconState < InterfaceController_beaconState_newState_SEND) {
         Log_debug(ici->ic->logger, "sendBeacon(%s) -> beaconing disabled", ici->name->bytes);
@@ -816,7 +809,7 @@ static void beaconInterval(void* vIfController)
 
     struct Allocator* alloc = Allocator_child(ic->allocator);
     for (int i = 0; i < ic->icis->length; i++) {
-        struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, i);
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, i);
         sendBeacon(ici, alloc);
     }
     Allocator_free(alloc);
@@ -829,7 +822,7 @@ int InterfaceController_beaconState(struct InterfaceController* ifc,
                                     int newState)
 {
     struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);
-    struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);
+    struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);
     if (!ici) {
         return InterfaceController_beaconState_NO_SUCH_IFACE;
     }
@@ -864,7 +857,7 @@ int InterfaceController_bootstrapPeer(struct InterfaceController* ifc,
     Assert_true(herPublicKey);
     Assert_true(password);
 
-    struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);
+    struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, interfaceNumber);
 
     if (!ici) {
         return InterfaceController_bootstrapPeer_BAD_IFNUM;
@@ -952,7 +945,7 @@ int InterfaceController_getPeerStats(struct InterfaceController* ifController,
 
     int count = 0;
     for (int i = 0; i < ic->icis->length; i++) {
-        struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, i);
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, i);
         count += ici->peerMap.count;
     }
 
@@ -961,7 +954,7 @@ int InterfaceController_getPeerStats(struct InterfaceController* ifController,
 
     int xcount = 0;
     for (int j = 0; j < ic->icis->length; j++) {
-        struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, j);
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, j);
         for (int i = 0; i < (int)ici->peerMap.count; i++) {
             struct Peer* peer = Identity_check((struct Peer*) ici->peerMap.values[i]);
             struct InterfaceController_PeerStats* s = &stats[xcount];
@@ -997,7 +990,7 @@ int InterfaceController_disconnectPeer(struct InterfaceController* ifController,
         Identity_check((struct InterfaceController_pvt*) ifController);
 
     for (int j = 0; j < ic->icis->length; j++) {
-        struct Iface* ici = ArrayList_OfIfaces_get(ic->icis, j);
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, j);
         for (int i = 0; i < (int)ici->peerMap.count; i++) {
             struct Peer* peer = ici->peerMap.values[i];
             if (!Bits_memcmp(herPublicKey, CryptoAuth_getHerPublicKey(peer->cryptoAuthIf), 32)) {
@@ -1009,12 +1002,23 @@ int InterfaceController_disconnectPeer(struct InterfaceController* ifController,
     return InterfaceController_disconnectPeer_NOTFOUND;
 }
 
-static int incomingFromEventEmitterIf(struct Interface_Two* eventEmitterIf, struct Message* msg)
+static Iface_DEFUN incomingFromEventEmitterIf(struct Iface* eventEmitterIf, struct Message* msg)
 {
     struct InterfaceController_pvt* ic =
          Identity_containerOf(eventEmitterIf, struct InterfaceController_pvt, eventEmitterIf);
     Assert_true(Message_pop32(msg, NULL) == Event_Pathfinder_PEERS);
-    
+    uint32_t pathfinderId = Message_pop32(msg, NULL);
+    Assert_true(!msg->length);
+
+    for (int j = 0; j < ic->icis->length; j++) {
+        struct PeerIface* ici = ArrayList_OfIfaces_get(ic->icis, j);
+        for (int i = 0; i < (int)ici->peerMap.count; i++) {
+            struct Peer* peer = Identity_check((struct Peer*) ici->peerMap.values[i]);
+            if (peer->state != InterfaceController_PeerState_ESTABLISHED) { continue; }
+            sendPeer(ic, pathfinderId, Event_Core_PEER, peer, msg->alloc);
+        }
+    }
+    return NULL;
 }
 
 struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
@@ -1031,7 +1035,6 @@ struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
     Bits_memcpyConst(out, (&(struct InterfaceController_pvt) {
         .allocator = allocator,
         .ca = ca,
-        .ee = ee,
         .rand = rand,
         .switchCore = switchCore,
         .logger = logger,

+ 5 - 6
interface/InterfaceController.h

@@ -19,13 +19,13 @@
 #include "interface/Interface.h"
 #include "wire/Headers.h"
 #include "crypto/CryptoAuth.h"
-#include "dht/dhtcore/Router.h"
-#include "dht/dhtcore/RumorMill.h"
 #include "dht/Address.h"
-#include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "switch/SwitchCore.h"
 #include "net/SwitchPinger.h"
+#include "net/Event.h"
+#include "net/EventEmitter.h"
 #include "util/platform/Sockaddr.h"
 #include "util/log/Log.h"
 #include "util/Linker.h"
@@ -180,12 +180,11 @@ int InterfaceController_getPeerStats(struct InterfaceController* ic,
 
 struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
                                                     struct SwitchCore* switchCore,
-                                                    struct Router* router,
-                                                    struct RumorMill* rumorMill,
                                                     struct Log* logger,
                                                     struct EventBase* eventBase,
                                                     struct SwitchPinger* switchPinger,
                                                     struct Random* rand,
-                                                    struct Allocator* allocator);
+                                                    struct Allocator* allocator,
+                                                    struct EventEmitter* ee);
 
 #endif

+ 0 - 4
interface/InterfaceController_admin.c

@@ -19,7 +19,6 @@
 #include "benc/Int.h"
 #include "crypto/AddressCalc.h"
 #include "crypto/Key.h"
-#include "dht/dhtcore/NodeStore.h"
 #include "interface/InterfaceController.h"
 #include "interface/InterfaceController_admin.h"
 #include "util/AddrTools.h"
@@ -28,7 +27,6 @@ struct Context
 {
     struct Allocator* alloc;
     struct InterfaceController* ic;
-    struct NodeStore* store;
     struct Admin* admin;
     Identity
 };
@@ -171,14 +169,12 @@ static resetSession(Dict* args, void* vcontext, String* txid, struct Allocator*
 }*/
 
 void InterfaceController_admin_register(struct InterfaceController* ic,
-                                        struct NodeStore* nodeStore,
                                         struct Admin* admin,
                                         struct Allocator* alloc)
 {
     struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
         .alloc = alloc,
         .ic = ic,
-        .store = nodeStore,
         .admin = admin
     }));
     Identity_set(ctx);

+ 0 - 2
interface/InterfaceController_admin.h

@@ -16,14 +16,12 @@
 #define InterfaceController_admin_H
 
 #include "admin/Admin.h"
-#include "dht/dhtcore/NodeStore.h"
 #include "interface/InterfaceController.h"
 #include "memory/Allocator.h"
 #include "util/Linker.h"
 Linker_require("interface/InterfaceController_admin.c")
 
 void InterfaceController_admin_register(struct InterfaceController* ic,
-                                        struct NodeStore* store,
                                         struct Admin* admin,
                                         struct Allocator* alloc);
 

+ 8 - 6
interface/addressable/PacketHeaderToUDPAddrInterface.c

@@ -62,10 +62,11 @@ static uint8_t sendMessage(struct Message* message, struct Interface* iface)
 
     Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL);
 
-    return Interface_send(&context->pub.headerIf, message);
+    Iface_send(&context->pub.headerIf, message);
+    return 0;
 }
 
-static int incomingFromHeaderIf(struct Interface_Two* iface, struct Message* message)
+static Iface_DEFUN incomingFromHeaderIf(struct Iface* iface, struct Message* message)
 {
     struct PacketHeaderToUDPAddrInterface_pvt* context =
         Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*)
@@ -73,14 +74,14 @@ static int incomingFromHeaderIf(struct Interface_Two* iface, struct Message* mes
 
     if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) {
         // runt
-        return Error_NONE;
+        return NULL;
     }
 
     struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes;
 
     // udp
     if (ip->nextHeader != 17) {
-        return Error_NONE;
+        return NULL;
     }
 
     struct Allocator* alloc = Allocator_child(message->alloc);
@@ -94,13 +95,14 @@ static int incomingFromHeaderIf(struct Interface_Two* iface, struct Message* mes
 
     if (Sockaddr_getPort(context->pub.udpIf.addr) != Endian_bigEndianToHost16(udp->destPort_be)) {
         // not the right port
-        return Error_NONE;
+        return NULL;
     }
 
     Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL);
     Message_push(message, addr, addr->addrLen, NULL);
 
-    return Interface_receiveMessage(&context->pub.udpIf.generic, message);
+    Interface_receiveMessage(&context->pub.udpIf.generic, message);
+    return NULL;
 }
 
 struct PacketHeaderToUDPAddrInterface* PacketHeaderToUDPAddrInterface_new(struct Allocator* alloc,

+ 2 - 1
interface/addressable/PacketHeaderToUDPAddrInterface.h

@@ -16,6 +16,7 @@
 #define PacketHeaderToUDPAddrInterface_H
 
 #include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "interface/addressable/AddrInterface.h"
 #include "memory/Allocator.h"
 #include "util/platform/Sockaddr.h"
@@ -25,7 +26,7 @@ Linker_require("interface/addressable/PacketHeaderToUDPAddrInterface.c")
 struct PacketHeaderToUDPAddrInterface
 {
     struct AddrInterface udpIf;
-    struct Interface_Two headerIf;
+    struct Iface headerIf;
 };
 
 struct PacketHeaderToUDPAddrInterface* PacketHeaderToUDPAddrInterface_new(struct Allocator* alloc,

+ 5 - 0
memory/Allocator.h

@@ -145,6 +145,7 @@ struct Allocator_Allocation* Allocator_getAllocation(struct Allocator* alloc, in
  * @return a pointer to the newly allocated memory.
  * @see malloc()
  */
+__attribute__((alloc_size(2)))
 void* Allocator__malloc(struct Allocator* allocator,
                         unsigned long length,
                         const char* fileName,
@@ -163,6 +164,7 @@ void* Allocator__malloc(struct Allocator* allocator,
  * @return a pointer to the newly allocated memory.
  * @see calloc()
  */
+__attribute__((alloc_size(2,3)))
 void* Allocator__calloc(struct Allocator* alloc,
                         unsigned long length,
                         unsigned long count,
@@ -184,6 +186,7 @@ void* Allocator__calloc(struct Allocator* alloc,
  *             without freeing the entire allocator.
  * @return a pointer to the newly allocated memory.
  */
+__attribute__((alloc_size(3)))
 void* Allocator__realloc(struct Allocator* allocator,
                          const void* original,
                          unsigned long size,
@@ -202,6 +205,7 @@ void* Allocator__realloc(struct Allocator* allocator,
  *                the size of the new allocation will be sizeof(*content).
  * @return a pointer to the newly allocated memory.
  */
+__attribute__((alloc_size(3)))
 void* Allocator__clone(struct Allocator* allocator,
                        const void* toClone,
                        unsigned long length,
@@ -340,6 +344,7 @@ void Allocator_snapshot(struct Allocator* alloc, int includeAllocations);
 #ifndef Allocator_Provider_CONTEXT_TYPE
     #define Allocator_Provider_CONTEXT_TYPE void
 #endif
+__attribute__((alloc_size(3)))
 typedef void* (* Allocator_Provider)(Allocator_Provider_CONTEXT_TYPE* ctx,
                                      struct Allocator_Allocation* original,
                                      unsigned long size,

+ 41 - 42
net/ControlHandler.c

@@ -26,8 +26,8 @@ struct ControlHandler_pvt
     struct Log* log;
     struct Allocator* alloc;
     struct Router* router;
-    struct Address* myAddr;
-    struct Interface_Two eventIface;
+    uint8_t myPublicKey[32];
+    struct Iface eventIf;
     Identity
 };
 
@@ -35,33 +35,33 @@ struct ControlHandler_pvt
  * Expects [ Ctrl ][ Error ][ cause SwitchHeader ][ cause handle ][ cause etc.... ]
  */
 #define handleError_MIN_SIZE (Control_Header_SIZE + Control_Error_MIN_SIZE + SwitchHeader_SIZE + 4)
-static int handleError(struct ControlHandler_pvt* ch,
-                       struct Message* msg,
-                       uint64_t label,
-                       uint8_t* labelStr)
+static Iface_DEFUN handleError(struct Message* msg,
+                               struct ControlHandler_pvt* ch,
+                               uint64_t label,
+                               uint8_t* labelStr)
 {
     if (msg->length < handleError_MIN_SIZE) {
         Log_info(ch->log, "DROP runt error packet from [%s]", labelStr);
-        return 0;
+        return NULL;
     }
     Message_shift(msg, SwitchHeader_SIZE + 4, NULL);
     Message_push32(msg, Event_Core_SWITCH_ERR, NULL);
-    return Interface_sent(&ch->eventIf, msg);
+    return Iface_next(&ch->eventIf, msg);
 }
 
 /**
  * Expects [ SwitchHeader ][ Ctrl ][ (key)Ping ][ data etc.... ]
  */
 #define handlePing_MIN_SIZE (Control_Header_SIZE + Control_Ping_MIN_SIZE)
-static int handlePing(struct ControlHandler_pvt* ch,
-                      struct Message* msg,
-                      uint64_t label,
-                      uint8_t* labelStr,
-                      uint16_t messageType_be)
+static Iface_DEFUN handlePing(struct Message* msg,
+                              struct ControlHandler_pvt* ch,
+                              uint64_t label,
+                              uint8_t* labelStr,
+                              uint16_t messageType_be)
 {
     if (msg->length < handlePing_MIN_SIZE) {
         Log_info(ch->log, "DROP runt ping");
-        return 0;
+        return NULL;
     }
 
     struct Control* ctrl = (struct Control*) msg->bytes;
@@ -72,7 +72,7 @@ static int handlePing(struct ControlHandler_pvt* ch,
     uint32_t herVersion = Endian_bigEndianToHost32(ping->version_be);
     if (!Version_isCompatible(Version_CURRENT_PROTOCOL, herVersion)) {
         Log_debug(ch->log, "DROP ping from incompatible version [%d]", herVersion);
-        return 0;
+        return NULL;
     }
 
     if (messageType_be == Control_KEYPING_be) {
@@ -80,27 +80,27 @@ static int handlePing(struct ControlHandler_pvt* ch,
         if (msg->length < Control_KeyPing_HEADER_SIZE) {
             // min keyPing size is longer
             Log_debug(ch->log, "DROP runt keyPing");
-            return 0;
+            return NULL;
         }
         if (msg->length > Control_KeyPing_MAX_SIZE) {
             Log_debug(ch->log, "DROP long keyPing");
-            return 0;
+            return NULL;
         }
         if (ping->magic != Control_KeyPing_MAGIC) {
             Log_debug(ch->log, "DROP keyPing (bad magic)");
-            return 0;
+            return NULL;
         }
 
         struct Control_KeyPing* keyPing = (struct Control_KeyPing*) msg->bytes;
         keyPing->magic = Control_KeyPong_MAGIC;
         ctrl->header.type_be = Control_KEYPONG_be;
-        Bits_memcpyConst(keyPing->key, ch->myAddr->key, 32);
+        Bits_memcpyConst(keyPing->key, ch->myPublicKey, 32);
 
     } else if (messageType_be == Control_PING_be) {
         Log_debug(ch->log, "got switch ping from [%s]", labelStr);
         if (ping->magic != Control_Ping_MAGIC) {
             Log_debug(ch->log, "DROP ping (bad magic)");
-            return 0;
+            return NULL;
         }
         ping->magic = Control_Pong_MAGIC;
         ctrl->header.type_be = Control_PONG_be;
@@ -125,8 +125,7 @@ static int handlePing(struct ControlHandler_pvt* ch,
     SwitchHeader_setVersion(switchHeader, SwitchHeader_CURRENT_VERSION);
     switchHeader->label_be = Endian_hostToBigEndian64(label);
 
-    Interface_send(&ch->pub.coreIf, msg);
-    return 0;
+    return Iface_next(&ch->pub.coreIf, msg);
 }
 
 /**
@@ -139,7 +138,7 @@ static int handlePing(struct ControlHandler_pvt* ch,
  * @param switchIf the interface which leads to the switch.
  * @param isFormV8 true if the control message is in the form specified by protocol version 8+
  */
-static int incomingFromCore(struct Interface_Two* coreIf, struct Message* msg)
+static Iface_DEFUN incomingFromCore(struct Iface* coreIf, struct Message* msg)
 {
     struct ControlHandler_pvt* ch = Identity_check((struct ControlHandler_pvt*) coreIf);
 
@@ -152,61 +151,61 @@ static int incomingFromCore(struct Interface_Two* coreIf, struct Message* msg)
 
     if (msg->length < 4 + Control_Header_SIZE) {
         Log_info(ch->log, "DROP runt ctrl packet from [%s]", labelStr);
-        return Error_NONE;
+        return NULL;
     }
 
     Assert_true(Message_pop32(msg, NULL) == 0xffffffff);
 
     if (Checksum_engine(msg->bytes, msg->length)) {
         Log_info(ch->log, "DROP ctrl packet from [%s] with invalid checksum", labelStr);
-        return Error_NONE;
+        return NULL;
     }
 
     struct Control* ctrl = (struct Control*) msg->bytes;
 
     if (ctrl->header.type_be == Control_ERROR_be) {
-        return handleError(ch, msg, label, labelStr);
+        return handleError(msg, ch, label, labelStr);
 
     } else if (ctrl->header.type_be == Control_KEYPING_be
-            || ctrl->header.type_be == Control_PING_be) {
-        return handlePing(ch, msg, label, labelStr, ctrl->header.type_be);
+            || ctrl->header.type_be == Control_PING_be)
+    {
+        return handlePing(msg, ch, label, labelStr, ctrl->header.type_be);
 
     } else if (ctrl->header.type_be == Control_KEYPONG_be
-            || ctrl->header.type_be == Control_PONG_be) {
-            Log_debug(ch->log, "got switch pong from [%s]", labelStr);
-            // Shift back over the header
-            Message_shift(msg, 4 + SwitchHeader_SIZE, NULL);
-            return Interface_send(&ch->pub.switchPingerIf, msg);
-
+            || ctrl->header.type_be == Control_PONG_be)
+    {
+        Log_debug(ch->log, "got switch pong from [%s]", labelStr);
+        // Shift back over the header
+        Message_shift(msg, 4 + SwitchHeader_SIZE, NULL);
+        return Iface_next(&ch->pub.switchPingerIf, msg);
     }
 
     Log_info(ch->log, "DROP control packet of unknown type from [%s], type [%d]",
              labelStr, Endian_bigEndianToHost16(ctrl->header.type_be));
 
-    return 0;
+    return NULL;
 }
 
 // Forward from switch pinger directly to core.
-static int incomingFromSwitchPinger(struct Interface_Two* switchPingerIf, struct Message* msg)
+static Iface_DEFUN incomingFromSwitchPinger(struct Iface* switchPingerIf, struct Message* msg)
 {
     struct ControlHandler_pvt* ch =
-        Identity_check( (struct ControlHandler_pvt*) (&switchPingerIf[-1]) );
-    return Interface_send(&ch->pub.coreIf, msg);
+        Identity_containerOf(switchPingerIf, struct ControlHandler_pvt, pub.switchPingerIf);
+    return Iface_next(&ch->pub.coreIf, msg);
 }
 
 struct ControlHandler* ControlHandler_new(struct Allocator* alloc,
                                           struct Log* logger,
                                           struct EventEmitter* ee,
-                                          struct Address* myAddr)
+                                          uint8_t myPublicKey[32])
 {
     struct ControlHandler_pvt* ch = Allocator_calloc(alloc, sizeof(struct ControlHandler_pvt), 1);
     ch->alloc = alloc;
     ch->log = logger;
-    ch->router = router;
-    ch->myAddr = myAddr;
+    Bits_memcpyConst(ch->myPublicKey, myPublicKey, 32);
     ch->pub.coreIf.send = incomingFromCore;
     ch->pub.switchPingerIf.send = incomingFromSwitchPinger;
-    EventEmitter_regCore(ee, Event_Core_INVALID, &ch->eventIface)
+    EventEmitter_regCore(ee, &ch->eventIf, Event_Pathfinder_INVALID);
     Identity_set(ch);
     return &ch->pub;
 }

+ 3 - 3
net/ControlHandler.h

@@ -25,18 +25,18 @@ Linker_require("net/ControlHandler.c")
 struct ControlHandler
 {
     /** This interface expects and sends [ SwitchHeader ][ 0xffffffff ][ CTRL frame ] */
-    struct Interface_Two coreIf;
+    struct Iface coreIf;
 
     /**
      * This interface expects and sends [ SwitchHeader ][ 0xffffffff ][ CTRL frame ]
      * May send a pong or an error caused by a ping.
      */
-    struct Interface_Two switchPingerIf;
+    struct Iface switchPingerIf;
 };
 
 struct ControlHandler* ControlHandler_new(struct Allocator* alloc,
                                           struct Log* logger,
                                           struct EventEmitter* ee,
-                                          struct Address* myAddr);
+                                          uint8_t myPublicKey[32]);
 
 #endif

+ 9 - 9
net/ConverterV15.c

@@ -39,7 +39,7 @@ struct ConverterV15_pvt
  * Incoming packet with a SessionManager header followed by a ContentHeader and then whatever
  * content.
  */
-static int incomingFromUpperDistributorIf(struct Interface_Two* upperDistributorIf,
+static Iface_DEFUN incomingFromUpperDistributorIf(struct Iface* upperDistributorIf,
                                           struct Message* msg)
 {
     struct ConverterV15_pvt* conv =
@@ -55,7 +55,7 @@ static int incomingFromUpperDistributorIf(struct Interface_Two* upperDistributor
         // session thinks it's old
     } else {
         // nothing is known about a node, fuckit, assume it's new !
-        return Interface_send(&conv->pub.sessionManagerIf, msg);
+        return Iface_send(&conv->pub.sessionManagerIf, msg);
     }
 
     struct DataHeader* dh = (struct DataHeader*) &hdr[1];
@@ -83,7 +83,7 @@ static int incomingFromUpperDistributorIf(struct Interface_Two* upperDistributor
 
 
     if (type == ContentType_IPTUN) {
-        return Interface_send(&conv->pub.sessionManagerIf, msg);
+        return Iface_send(&conv->pub.sessionManagerIf, msg);
     }
 
     struct Headers_IP6Header* ip6 = (struct Headers_IP6Header*) &hdr[1];
@@ -116,7 +116,7 @@ static int incomingFromUpperDistributorIf(struct Interface_Two* upperDistributor
 
     //Log_debug(conv->log, "send [%s]", Hex_print(ip6, 32, msg->alloc));
 
-    return Interface_send(&conv->pub.sessionManagerIf, msg);
+    return Iface_send(&conv->pub.sessionManagerIf, msg);
 }
 
 //// --------------- Incoming, convert v15 to v16 --------------- ////
@@ -144,7 +144,7 @@ static inline bool tryConvertDHT(struct Message* msg, struct Headers_IP6Header*
  * Incoming packet with a SessionManager header and under that either an ipv6 or ipv4 header
  * depending on whether it's destine for TUN/DHT or IpTunnel.
  */
-static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf, struct Message* msg)
+static Iface_DEFUN incomingFromSessionManagerIf(struct Iface* sessionManagerIf, struct Message* msg)
 {
     struct ConverterV15_pvt* conv =
         Identity_containerOf(sessionManagerIf, struct ConverterV15_pvt, pub.sessionManagerIf);
@@ -165,7 +165,7 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
     int ipVer = Headers_getIpVersion(ipPtr);
     if (ipVer == DataHeader_CURRENT_VERSION) {
     Log_debug(conv->log, "0");
-        return Interface_send(&conv->pub.upperDistributorIf, msg);
+        return Iface_send(&conv->pub.upperDistributorIf, msg);
     }
 
     if (ipVer == 6) {
@@ -177,7 +177,7 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
         if (ip6->sourceAddr[0] == 0xfc && ip6->destinationAddr[0] == 0xfc) {
     Log_debug(conv->log, "tryConvertDHT()");
             if (tryConvertDHT(msg, ip6)) {
-                return Interface_send(&conv->pub.upperDistributorIf, msg);
+                return Iface_send(&conv->pub.upperDistributorIf, msg);
             }
     Log_debug(conv->log, "tryConvertDHT(fail)");
             Message_pop(msg, NULL, RouteHeader_SIZE + Headers_IP6Header_SIZE, NULL);
@@ -188,7 +188,7 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
             Message_push(msg, &dh, DataHeader_SIZE, NULL);
             Message_shift(msg, RouteHeader_SIZE, NULL);
             Bits_memmoveConst(msg->bytes, bih, RouteHeader_SIZE);
-            return Interface_send(&conv->pub.upperDistributorIf, msg);
+            return Iface_send(&conv->pub.upperDistributorIf, msg);
         }
     Log_debug(conv->log, "iptunnel?");
     } else if (ipVer != 4) {
@@ -206,7 +206,7 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
     Bits_memset(dh, 0, DataHeader_SIZE);
     dh->contentType_be = Endian_hostToBigEndian16(ContentType_IPTUN);
     dh->versionAndFlags = DataHeader_CURRENT_VERSION << 4;
-    return Interface_send(&conv->pub.upperDistributorIf, msg);
+    return Iface_send(&conv->pub.upperDistributorIf, msg);
 }
 
 struct ConverterV15* ConverterV15_new(struct Allocator* alloc,

+ 2 - 2
net/ConverterV15.h

@@ -29,10 +29,10 @@ Linker_require("net/ConverterV15.c")
 struct ConverterV15
 {
     /** talks v15 */
-    struct Interface_Two sessionManagerIf;
+    struct Iface sessionManagerIf;
 
     /** talks v16 */
-    struct Interface_Two upperDistributorIf;
+    struct Iface upperDistributorIf;
 };
 
 struct ConverterV15* ConverterV15_new(struct Allocator* alloc,

+ 7 - 7
net/Ducttape.c

@@ -110,7 +110,7 @@ static struct Ducttape_MessageHeader* getDtHeader(struct Message* message, bool
 
 // [ struct Address ][ content (benc) ]
 // see ducttape.h -> dhtIf
-static int incomingFromDHTInterface(struct Interface_Two* dhtIf, struct Message* msg)
+static Iface_DEFUN incomingFromDHTInterface(struct Iface* dhtIf, struct Message* msg)
 {
     struct Ducttape_pvt* ctx = Identity_containerOf(dhtIf, struct Ducttape_pvt, pub.dhtIf);
 
@@ -126,7 +126,7 @@ static int incomingFromDHTInterface(struct Interface_Two* dhtIf, struct Message*
         struct Allocator* alloc = Allocator_child(ctx->alloc);
         Allocator_adopt(alloc, msg->alloc);
         Message_push(msg, &addr, Address_SIZE, NULL);
-        Interface_send(dhtIf, msg);
+        Iface_send(dhtIf, msg);
         Allocator_free(alloc);
         return 0;
     }
@@ -275,7 +275,7 @@ static inline uint8_t incomingForMe(struct Message* message,
         // Shift off the UDP header.
         Message_shift(message, -Headers_UDPHeader_SIZE, NULL);
         Message_push(message, &addr, Address_SIZE, NULL);
-        return Interface_send(&context->pub.dhtIf, message);
+        return Iface_send(&context->pub.dhtIf, message);
     }
 
     if (!context->userIf) {
@@ -373,7 +373,7 @@ static inline bool isForMe(struct Message* message, struct Ducttape_pvt* context
     return (Bits_memcmp(header->destinationAddr, context->myAddr.ip6.bytes, 16) == 0);
 }
 
-static int incomingFromMagicInterface(struct Interface_Two* magicIf, struct Message* msg)
+static Iface_DEFUN incomingFromMagicInterface(struct Iface* magicIf, struct Message* msg)
 {
     struct Ducttape_pvt* ctx = Identity_containerOf(magicIf, struct Ducttape_pvt, pub.magicIf);
 
@@ -441,7 +441,7 @@ static inline uint8_t incomingFromTun(struct Message* message,
     }
 
     if (!Bits_memcmp(header->destinationAddr, FC_ONE, 16)) {
-        return Interface_send(&context->pub.magicIf, message);
+        return Iface_send(&context->pub.magicIf, message);
     }
 
     struct Ducttape_MessageHeader* dtHeader = getDtHeader(message, true);
@@ -890,7 +890,7 @@ static uint8_t incomingFromSwitch(struct Message* message, struct Interface* swi
     if (nonceOrHandle > 3) {
         if (nonceOrHandle == 0xffffffff) {
             Message_shift(message, SwitchHeader_SIZE, NULL);
-            return Interface_send(&context->pub.controlIf, message);
+            return Iface_send(&context->pub.controlIf, message);
         }
         Message_shift(message, -4, NULL);
 
@@ -957,7 +957,7 @@ static uint8_t incomingFromSwitch(struct Message* message, struct Interface* swi
     return 0;
 }
 
-static int incomingFromControlHandler(struct Interface_Two* controlIf, struct Message* message)
+static Iface_DEFUN incomingFromControlHandler(struct Iface* controlIf, struct Message* message)
 {
     struct Ducttape_pvt* ctx = Identity_containerOf(controlIf, struct Ducttape_pvt, pub.controlIf);
     Assert_true(ctx->pub.switchIf.receiveMessage);

+ 4 - 4
net/Ducttape.h

@@ -32,24 +32,24 @@ struct Ducttape
      * Interface which sends and receives (switch level) CTRL frames.
      * Content is: [ SwitchHeader ][ 0xffffffff ][ ctrl header ][ content... ]
      */
-    struct Interface_Two controlIf;
+    struct Iface controlIf;
 
     /**
      * Interface which receives and sends messages to other routers.
      * Content is: [ Address ][ content... ]
      */
-    struct Interface_Two dhtIf;
+    struct Iface dhtIf;
 
     /**
      * Interface which receives packets (from tun) that are addressed to "magic address" fc00::1
      * Content is: [ IPv6 header ][ content... ]
      */
-    struct Interface_Two magicIf;
+    struct Iface magicIf;
 
     /**
      * 
      */
-    struct Interface_Two tunIf;
+    struct Iface tunIf;
 
     struct Interface switchIf;
 

+ 52 - 38
net/Event.h

@@ -21,13 +21,6 @@
 #include "wire/SwitchHeader.h"
 #include "wire/Control.h"
 
-struct Event_Ip6
-{
-    uint8_t ipv6[16];
-};
-#define Event_Ip6_SIZE 16
-Assert_compileTime(sizeof(struct Event_Ip6) == Event_Ip6_SIZE);
-
 struct Event_Node
 {
     uint8_t ip6[16];
@@ -50,7 +43,9 @@ struct Event_Msg
     struct DataHeader data;
     // ...content follows...
 };
-#pragma GCC poison Event_Msg_SIZE // Contains more data...
+#define Event_Msg_MIN_SIZE (RouteHeader_SIZE + DataHeader_SIZE)
+Assert_compileTime(sizeof(struct Event_Msg) == Event_Msg_MIN_SIZE);
+#pragma GCC poison Event_Msg_SIZE
 
 struct Event_Ping
 {
@@ -136,7 +131,7 @@ enum Event_Pathfinder
 
     /**
      * Get all sessions.
-     * TODO
+     * (Received by: SessionManager.c)
      */
     Event_Pathfinder_SESSIONS,
 
@@ -155,18 +150,6 @@ enum Event_Pathfinder
     Event_Pathfinder_INVALID
 };
 
-static const int Event_Pathfinder_SIZES[] = {
-    [Event_Pathfinder_CONNECT]      = 4 + Event_Pathfinder_Connect_SIZE,
-    [Event_Pathfinder_SUPERIORITY]  = 4 + Event_Pathfinder_Superiority_SIZE,
-    [Event_Pathfinder_NODE]         = 4 + Event_Node_SIZE,
-    [Event_Pathfinder_SENDMSG]      = -(4 + (int)sizeof(struct Event_Msg)),
-    [Event_Pathfinder_PING]         = 4 + Event_Ping_SIZE,
-    [Event_Pathfinder_PONG]         = 4 + Event_Ping_SIZE,
-    [Event_Pathfinder_SESSIONS]     = 4,
-    [Event_Pathfinder_PEERS]        = 4,
-    [Event_Pathfinder_PATHFINDERS]  = 4
-};
-
 struct Event_FromPathfinder
 {
     enum Event_Pathfinder event_be;
@@ -189,10 +172,15 @@ struct Event_FromPathfinder
 
 enum Event_Core
 {
+    /**
+     * This message is sent in response to an Event_Pathfinder_CONNECT message and is
+     * guaranteed to be sent before any other message.
+     * (emitted by: EventEmitter.c)
+     */
+    Event_Core_CONNECT,
+
     /**
      * Emitted when a pathfinder connects or if Event_Pathfinder_PATHFINDERS is sent.
-     * This message is guaranteed to be sent before any other message and the first instance
-     * refers to "you" the pathfinder which just connected.
      * (emitted by: EventEmitter.c)
      */
     Event_Core_PATHFINDER,
@@ -203,18 +191,18 @@ enum Event_Core
      */
     Event_Core_PATHFINDER_GONE,
 
-    /**
-     * Emitted if the core wants the pathfinder to begin searching for a node.
-     * (emitted by: SessionManager.c)
-     */
-    Event_Core_SEARCH_REQ,
-
     /**
      * Emitted if a switch error is received, no matter what type of packet causes it.
      * (emitted by: ControlHandler.c)
      */
     Event_Core_SWITCH_ERR,
 
+    /**
+     * Emitted if the core wants the pathfinder to begin searching for a node.
+     * (emitted by: SessionManager.c)
+     */
+    Event_Core_SEARCH_REQ,
+
     /**
      * Emitted when a peer connects (becomes state ESTABLISHED) or
      * emitted for every peer if Event_Pathfinder_PEERS is sent.
@@ -229,16 +217,22 @@ enum Event_Core
     Event_Core_PEER_GONE,
 
     /**
-     * Emitted if a new session begins,
-     * emitted for every active session of Event_Pathfinder_SESSIONS is sent.
-     * TODO
+     * Emitted if a new session begins, also emitted for every active session of
+     * Event_Pathfinder_SESSIONS is sent.
+     * (emitted by: SessionManager.c)
      */ 
     Event_Core_SESSION,
 
-    /** Emitted when a session ends. TODO */
+    /**
+     * Emitted when a session ends.
+     * (emitted by: SessionManager.c)
+     */
     Event_Core_SESSION_ENDED,
 
-    /** Emitted when SessionManager sees an incoming packet with a new path. TODO */
+    /**
+     * Emitted when SessionManager sees an incoming packet with a new path.
+     * (emitted by: SessionManager.c)
+     */
     Event_Core_DISCOVERED_PATH,
 
     /** Emitted for each incoming DHT message. TODO */
@@ -246,6 +240,7 @@ enum Event_Core
 
     /**
      * Emitted from time to time in order to verify the pathfinder is alive.
+     * Must be responded to by an Event_Pathfinder_PONG.
      * (emitted by: EventEmitter.c)
      */
     Event_Core_PING,
@@ -259,6 +254,13 @@ enum Event_Core
     Event_Core_INVALID
 };
 
+struct Event_Core_SearchReq
+{
+    uint8_t ipv6[16];
+};
+#define Event_Core_SearchReq_SIZE 16
+Assert_compileTime(sizeof(struct Event_Core_SearchReq) == Event_Core_SearchReq_SIZE);
+
 struct Event_Core_Pathfinder
 {
     /** See struct Event_Pathfinder_Superiority for more information */
@@ -273,6 +275,17 @@ struct Event_Core_Pathfinder
 #define Event_Core_Pathfinder_SIZE 72
 Assert_compileTime(sizeof(struct Event_Core_Pathfinder) == Event_Core_Pathfinder_SIZE);
 
+struct Event_Core_Connect
+{
+    /** The public key of this cjdns node. */
+    uint8_t publicKey[32];
+
+    /** This pathfinder's ID. */
+    uint32_t pathfinderId_be;
+};
+#define Event_Core_Connect_SIZE 36
+Assert_compileTime(sizeof(struct Event_Core_Connect) == Event_Core_Connect_SIZE);
+
 struct Event_Core_SwitchErr
 {
     struct SwitchHeader sh;
@@ -281,10 +294,10 @@ struct Event_Core_SwitchErr
     struct Control_Error ctrlErr;
 };
 #pragma GCC poison Event_Core_SwitchErr_SIZE
-Assert_compileTime(sizeof(struct Event_Core_SwitchErr) ==
-    (SwitchHeader_SIZE + 4 + Control_Header_SIZE + Control_Error_MIN_SIZE));
+#define Event_Core_SwitchErr_MIN_SIZE \
+    (SwitchHeader_SIZE + 4 + Control_Header_SIZE + Control_Error_MIN_SIZE)
+Assert_compileTime(sizeof(struct Event_Core_SwitchErr) == Event_Core_SwitchErr_MIN_SIZE);
 
-#define Event_FromCore_MAGIC 0x1337babe
 struct Event_FromCore
 {
     enum Event_Core event_be;
@@ -293,10 +306,11 @@ struct Event_FromCore
     uint8_t target_be;
 
     union {
+        struct Event_Core_Connect connect;
         struct Event_Core_Pathfinder pathfinder;
         struct Event_Core_Pathfinder pathfinderGone;
-        struct Event_Ip6 searchReq;
         struct Event_Core_SwitchErr switchErr;
+        struct Event_Core_SearchReq searchReq;
         struct Event_Node peer;
         struct Event_Node peerGone;
         struct Event_Node session;

+ 105 - 38
net/EventEmitter.c

@@ -21,7 +21,7 @@
 
 #include <stdbool.h>
 
-#define ArrayList_TYPE struct Interface_Two*
+#define ArrayList_TYPE struct Iface*
 #define ArrayList_NAME Ifaces
 #include "util/ArrayList.h"
 
@@ -30,8 +30,9 @@
 struct Pathfinder
 {
     struct EventEmitter_pvt* ee;
-    struct Interface_Two iface;
+    struct Iface iface;
     struct Allocator* alloc;
+
     uint8_t userAgent[64];
 
     uint32_t superiority;
@@ -60,11 +61,12 @@ struct Pathfinder
 struct EventEmitter_pvt
 {
     struct EventEmitter pub;
-    struct Interface_Two trickIf;
+    struct Iface trickIf;
     struct Allocator* alloc;
     struct Log* log;
     struct ArrayList_Ifaces* listTable[Event_Pathfinder_INVALID];
     struct ArrayList_Pathfinders* pathfinders;
+    uint8_t publicKey[32];
     Identity
 };
 
@@ -83,26 +85,89 @@ static struct ArrayList_Ifaces* getHandlers(struct EventEmitter_pvt* ee,
 static void sendToPathfinder(struct Pathfinder* pf, struct Message* msg)
 {
     if (!pf || pf->state != Pathfinder_state_CONNECTED) { return; }
-    Interface_send(&pf->iface, msg);
+    Iface_send(&pf->iface, msg);
     if (pf->bytesSinceLastPing < 8192 && pf->bytesSinceLastPing + msg->length >= 8192) {
         struct Message* ping = Message_new(0, 512, msg->alloc);
         Message_push32(ping, pf->bytesSinceLastPing, NULL);
         Message_push32(ping, PING_MAGIC, NULL);
-        Interface_send(&pf->iface, ping);
+        Message_push32(ping, Event_Core_PING, NULL);
+        Iface_send(&pf->iface, ping);
+    }
+    pf->bytesSinceLastPing += msg->length;
+}
+
+static bool Event_Pathfinder_sizeOk(enum Event_Pathfinder ev, int size)
+{
+    switch (ev) {
+        case Event_Pathfinder_CONNECT:
+            return (size == 8 + Event_Pathfinder_Connect_SIZE);
+        case Event_Pathfinder_SUPERIORITY:
+            return (size == 8 + Event_Pathfinder_Superiority_SIZE);
+        case Event_Pathfinder_NODE:
+            return (size == 8 + Event_Node_SIZE);
+        case Event_Pathfinder_SENDMSG:
+            return (size >= 8 + Event_Msg_MIN_SIZE);
+        case Event_Pathfinder_PING:
+        case Event_Pathfinder_PONG:
+            return (size >= 8 + Event_Ping_SIZE);
+        case Event_Pathfinder_SESSIONS:
+        case Event_Pathfinder_PEERS:
+        case Event_Pathfinder_PATHFINDERS:
+            return (size == 8);
+        default:;
     }
-    pf->bytesSinceLastPing += messageClone->length;
+    Assert_failure("invalid event [%d]", ev);
 }
+// Forget to add the event here? :)
+Assert_compileTime(Event_Pathfinder_INVALID == 9);
 
-static int incomingFromCore(struct Interface_Two* trickIf, struct Message* msg)
+static bool Event_Core_sizeOk(enum Event_Core ev, int size)
+{
+    switch (ev) {
+        case Event_Core_CONNECT:
+            return (size == 8 + Event_Core_Connect_SIZE);
+
+        case Event_Core_PATHFINDER:
+        case Event_Core_PATHFINDER_GONE:
+            return (size == 8 + Event_Core_Pathfinder_SIZE);
+
+        case Event_Core_SWITCH_ERR:
+            return (size >= 8 + Event_Core_SwitchErr_MIN_SIZE);
+
+        case Event_Core_SEARCH_REQ:
+            return (size == 8 + Event_Core_SearchReq_SIZE);
+
+        case Event_Core_PEER:
+        case Event_Core_PEER_GONE:
+        case Event_Core_SESSION:
+        case Event_Core_SESSION_ENDED:
+        case Event_Core_DISCOVERED_PATH:
+            return (size == 8 + Event_Node_SIZE);
+
+        case Event_Core_MSG:
+            return (size >= 8 + Event_Msg_MIN_SIZE);
+
+        case Event_Core_PING:
+        case Event_Core_PONG:
+            return (size == 8 + Event_Ping_SIZE);
+        default:;
+    }
+    Assert_failure("invalid event [%d]", ev);
+}
+// Remember to add the event to this function too!
+Assert_compileTime(Event_Core_INVALID == 13);
+
+static Iface_DEFUN incomingFromCore(struct Iface* trickIf, struct Message* msg)
 {
     struct EventEmitter_pvt* ee = Identity_containerOf(trickIf, struct EventEmitter_pvt, trickIf);
-    Assert_true(msg->length >= 8);
     Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment");
     enum Event_Core ev = Message_pop32(msg, NULL);
+    Assert_true(Event_Core_sizeOk(ev, msg->length+4));
     uint32_t pathfinderNum = Message_pop32(msg, NULL);
     Message_push32(msg, ev, NULL);
     if (pathfinderNum != 0xffffffff) {
-        struct Pathfinder* pf = ArrayList_Pathfinders_get(ee->pathfinders, i)[0];
+        struct Pathfinder* pf = ArrayList_Pathfinders_get(ee->pathfinders, pathfinderNum)[0];
+        Assert_true(pf && pf->state == Pathfinder_state_CONNECTED);
         sendToPathfinder(pf, msg);
     } else {
         for (int i = 0; i < ee->pathfinders->length; i++) {
@@ -128,6 +193,7 @@ static struct Message* pathfinderMsg(enum Event_Core ev,
     pathfinder->superiority_be = Endian_hostToBigEndian32(pf->superiority);
     pathfinder->pathfinderId_be = Endian_hostToBigEndian32(pf->pathfinderId);
     Bits_memcpyConst(pathfinder->userAgent, pf->userAgent, 64);
+    Message_push32(msg, 0xffffffff, NULL);
     Message_push32(msg, ev, NULL);
     return msg;
 }
@@ -148,20 +214,26 @@ static int handleFromPathfinder(enum Event_Pathfinder ev,
             pf->version = Endian_bigEndianToHost32(connect.version_be);
             Bits_memcpyConst(pf->userAgent, connect.userAgent, 64);
             pf->state = Pathfinder_state_CONNECTED;
-            // fallthrough
+
+            struct Event_Core_Connect resp;
+            resp.pathfinderId_be = Endian_hostToBigEndian32(pf->pathfinderId);
+            Bits_memcpyConst(resp.publicKey, ee->publicKey, 32);
+            Message_push(msg, &resp, Event_Core_Connect_SIZE, NULL);
+            Message_push32(msg, pf->pathfinderId, NULL);
+            Message_push32(msg, Event_Core_CONNECT, NULL);
+            sendToPathfinder(pf, msg);
+            break;
         }
         case Event_Pathfinder_SUPERIORITY: {
-            if (Event_Pathfinder_SUPERIORITY == ev) {
-                Message_shift(msg, -8, NULL);
-                pf->superiority = Message_pop32(msg, NULL);
-            }
+            Message_shift(msg, -8, NULL);
+            pf->superiority = Message_pop32(msg, NULL);
             struct Message* resp = pathfinderMsg(Event_Core_PATHFINDER, pf, msg->alloc);
             incomingFromCore(&ee->trickIf, resp);
             break;
         }
 
         case Event_Pathfinder_PING: {
-            Interface_send(&pf->iface, msg);
+            Iface_send(&pf->iface, msg);
             break;
         }
         case Event_Pathfinder_PONG: {
@@ -192,62 +264,56 @@ static int handleFromPathfinder(enum Event_Pathfinder ev,
     return true;
 }
 
-static int incomingFromPathfinder(struct Interface_Two* iface, struct Message* msg)
+static Iface_DEFUN incomingFromPathfinder(struct Iface* iface, struct Message* msg)
 {
     struct Pathfinder* pf = Identity_containerOf(iface, struct Pathfinder, iface);
     struct EventEmitter_pvt* ee = Identity_check((struct EventEmitter_pvt*) pf->ee);
     if (msg->length < 4) {
         Log_debug(ee->log, "DROPPF runt");
-        return 0;
+        return NULL;
     }
     enum Event_Pathfinder ev = Message_pop32(msg, NULL);
     Message_push32(msg, pf->pathfinderId, NULL);
     Message_push32(msg, ev, NULL);
     if (ev < 0 || ev >= Event_Pathfinder_INVALID) {
         Log_debug(ee->log, "DROPPF invalid type [%d]", ev);
-        return 0;
+        return NULL;
     }
-    if (Event_Pathfinder_SIZES[ev] < 0) {
-        if (-(Event_Pathfinder_SIZES[ev]) > msg->length) {
-            Log_debug(ee->log, "DROPPF runt");
-            return 0;
-        }
-    } else if (Event_Pathfinder_SIZES[ev] != msg->length) {
-        Log_debug(ee->log, "DROPPF incorrect length for type [%d] expected [%d] got [%d]",
-                  ev, Event_Pathfinder_SIZES[ev], msg->length);
-        return 0;
+    if (!Event_Pathfinder_sizeOk(ev, msg->length)) {
+        Log_debug(ee->log, "DROPPF incorrect length[%d] for type [%d]", msg->length, ev);
+        return NULL;
     }
 
     if (pf->state == Pathfinder_state_DISCONNECTED && ev != Event_Pathfinder_CONNECT) {
         Log_debug(ee->log, "DROPPF disconnected and event != CONNECT event:[%d]", ev);
-        return 0;
-    } else if (pf->state == Pathfinder_state_CONNECTED) {
+        return NULL;
+    } else if (pf->state != Pathfinder_state_CONNECTED) {
         Log_debug(ee->log, "DROPPF error state");
-        return 0;
+        return NULL;
     }
 
-    if (handleFromPathfinder(ev, msg, ee, pf)) { return 0; }
+    if (handleFromPathfinder(ev, msg, ee, pf)) { return NULL; }
 
     struct ArrayList_Ifaces* handlers = getHandlers(ee, ev, false);
-    if (!handlers) { return 0; }
+    if (!handlers) { return NULL; }
     for (int i = 0; i < handlers->length; i++) {
         struct Message* messageClone = msg;
         if (handlers->length > i+1) {
             // if only one handler, no need to copy the message...
             messageClone = Message_clone(msg, msg->alloc);
         }
-        struct Interface_Two* iface = ArrayList_Ifaces_get(handlers, i)[0];
+        struct Iface* iface = ArrayList_Ifaces_get(handlers, i)[0];
         // We have to call this manually because we don't have an interface handy which is
         // actually plumbed with this one.
         Assert_true(iface);
         Assert_true(iface->send);
         iface->send(iface, messageClone);
     }
-    return 0;
+    return NULL;
 }
 
 void EventEmitter_regCore(struct EventEmitter* eventEmitter,
-                          struct Interface_Two* iface,
+                          struct Iface* iface,
                           enum Event_Pathfinder ev)
 {
     struct EventEmitter_pvt* ee = Identity_check((struct EventEmitter_pvt*) eventEmitter);
@@ -257,7 +323,7 @@ void EventEmitter_regCore(struct EventEmitter* eventEmitter,
     ArrayList_Ifaces_add(l, &iface);
 }
 
-void EventEmitter_regPathfinderIface(struct EventEmitter* emitter, struct Interface_Two* iface)
+void EventEmitter_regPathfinderIface(struct EventEmitter* emitter, struct Iface* iface)
 {
     struct EventEmitter_pvt* ee = Identity_check((struct EventEmitter_pvt*) emitter);
     struct Allocator* alloc = Allocator_child(ee->alloc);
@@ -265,7 +331,7 @@ void EventEmitter_regPathfinderIface(struct EventEmitter* emitter, struct Interf
     pf->ee = ee;
     pf->iface.send = incomingFromPathfinder;
     pf->alloc = alloc;
-    Interface_plumb(&pf->iface, iface);
+    Iface_plumb(&pf->iface, iface);
     Identity_set(pf);
     int i = 0;
     for (; i < ee->pathfinders->length; i++) {
@@ -275,13 +341,14 @@ void EventEmitter_regPathfinderIface(struct EventEmitter* emitter, struct Interf
     pf->pathfinderId = ArrayList_Pathfinders_put(ee->pathfinders, i, &pf);
 }
 
-struct EventEmitter* EventEmitter_new(struct Allocator* alloc, struct Log* log)
+struct EventEmitter* EventEmitter_new(struct Allocator* alloc, struct Log* log, uint8_t* publicKey)
 {
     struct EventEmitter_pvt* ee = Allocator_calloc(alloc, sizeof(struct EventEmitter_pvt), 1);
     ee->log = log;
     ee->alloc = alloc;
     ee->trickIf.send = incomingFromCore;
     ee->pathfinders = ArrayList_Pathfinders_new(ee->alloc);
+    Bits_memcpyConst(ee->publicKey, publicKey, 32);
     Identity_set(ee);
     return &ee->pub;
 }

+ 4 - 4
net/EventEmitter.h

@@ -15,7 +15,7 @@
 #ifndef EventEmitter_H
 #define EventEmitter_H
 
-#include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "net/Event.h"
 #include "util/log/Log.h"
@@ -33,11 +33,11 @@ struct EventEmitter
  * If you only intend to fire events, just register with Event_Pathfinder_INVALID.
  */
 void EventEmitter_regCore(struct EventEmitter* ee,
-                          struct Interface_Two* iface,
+                          struct Iface* iface,
                           enum Event_Pathfinder ev);
 
-void EventEmitter_regPathfinderIface(struct EventEmitter* ee, struct Interface_Two* iface);
+void EventEmitter_regPathfinderIface(struct EventEmitter* ee, struct Iface* iface);
 
-struct EventEmitter* EventEmitter_new(struct Allocator* alloc, struct Log* log);
+struct EventEmitter* EventEmitter_new(struct Allocator* alloc, struct Log* log, uint8_t* publicKey);
 
 #endif

+ 211 - 141
net/SessionManager.c

@@ -42,7 +42,7 @@ struct Ip6 {
 struct SessionManager_pvt
 {
     struct SessionManager pub;
-    struct Interface_Two eventIf;
+    struct Iface eventIf;
     struct Allocator* alloc;
     struct Map_BufferedMessages bufMap;
     struct Log* log;
@@ -77,14 +77,37 @@ struct SessionManager_pvt
 #define debugHandlesAndLabel0(logger, session, label, message) \
     debugHandlesAndLabel(logger, session, label, "%s", message)
 
+static void sendSession(struct SessionManager_pvt* sm,
+                        struct SessionTable_Session* sess,
+                        uint64_t path,
+                        uint32_t destPf,
+                        enum Event_Core ev,
+                        struct Allocator* alloc)
+{
+    struct Event_Node session = {
+        .path_be = path,
+        .metric_be = 0xffffffff,
+        .version_be = Endian_hostToBigEndian32(sess->version)
+    };
+    Bits_memcpyConst(session.ip6, sess->ip6, 16);
+    uint8_t* publicKey = CryptoAuth_getHerPublicKey(sess->internal);
+    Bits_memcpyConst(session.publicKey, publicKey, 32);
+
+    struct Message* msg = Message_new(0, Event_Node_SIZE + 512, alloc);
+    Message_push(msg, &session, Event_Node_SIZE, NULL);
+    Message_push32(msg, destPf, NULL);
+    Message_push32(msg, ev, NULL);
+    Iface_send(&sm->eventIf, msg);
+}
+
 static uint8_t incomingFromSwitchPostCryptoAuth(struct Message* msg, struct Interface* iface)
 {
-    struct SessionManager_pvt* bw = Identity_check((struct SessionManager_pvt*) iface->receiverContext);
+    struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) iface->receiverContext);
 
-    struct SessionTable_Session* session = bw->currentSession;
-    struct SwitchHeader* sh = bw->currentSwitchHeader;
-    bw->currentSession = NULL;
-    bw->currentSwitchHeader = NULL;
+    struct SessionTable_Session* session = sm->currentSession;
+    struct SwitchHeader* sh = sm->currentSwitchHeader;
+    sm->currentSession = NULL;
+    sm->currentSwitchHeader = NULL;
 
     // CryptoAuth exports the nonce...
     uint32_t nonce = ((uint32_t*)msg->bytes)[0];
@@ -100,14 +123,14 @@ static uint8_t incomingFromSwitchPostCryptoAuth(struct Message* msg, struct Inte
 
     if (currentMessageSetup) {
         Bits_memcpyConst(&header->sh, sh, SwitchHeader_SIZE);
-        debugHandlesAndLabel0(bw->log,
+        debugHandlesAndLabel0(sm->log,
                               session,
                               Endian_bigEndianToHost64(sh->label_be),
                               "received start message");
     } else {
         // RouteHeader is laid out such that no copy of switch header should be needed.
         Assert_true(&header->sh == sh);
-        debugHandlesAndLabel0(bw->log,
+        debugHandlesAndLabel0(sm->log,
                               session,
                               Endian_bigEndianToHost64(sh->label_be),
                               "received run message");
@@ -123,31 +146,58 @@ static uint8_t incomingFromSwitchPostCryptoAuth(struct Message* msg, struct Inte
         session->sendSwitchLabel = path;
     }
     if (path != session->recvSwitchLabel) {
-        session->recvSwitchLabel = path;
-        struct Message* eventMsg = Message_new(Event_Node_SIZE, 512, msg->alloc);
-        struct Event_Node* node = (struct Event_Node*) eventMsg->bytes;
-        Bits_memcpyConst(node->ip6, session->ip6, 16);
-        Bits_memcpyConst(node->publicKey, pubKey, 32);
-        node->path_be = sh->label_be;
-        node->metric_be = 0xffffffff;
-        node->version_be = header->version_be;
-        Message_push32(eventMsg, Event_Core_SEARCH_REQ, NULL);
-        Interface_send(&bw->eventIf, eventMsg);
+        sendSession(sm, session, path, 0xffffffff, Event_Core_DISCOVERED_PATH, msg->alloc);
     }
 
-    Interface_send(&bw->pub.insideIf, msg);
+    Iface_send(&sm->pub.insideIf, msg);
     // Never return errors here because they can cause unencrypted stuff to be returned as an error.
     return 0;
 }
 
-static int incomingFromSwitchIf(struct Interface_Two* iface, struct Message* msg)
+
+static int sessionCleanup(struct Allocator_OnFreeJob* job)
+{
+    struct SessionTable_Session* sess = job->userData;
+    void* vsm = SessionTable_getInterfaceContext(sess);
+    struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) vsm);
+    struct Allocator* alloc = Allocator_child(sm->alloc);
+    sendSession(sm, sess, sess->sendSwitchLabel, 0xffffffff, Event_Core_SESSION_ENDED, alloc);
+    Allocator_free(alloc);
+    return 0;
+}
+
+static struct SessionTable_Session* getSession(struct SessionManager_pvt* sm,
+                                               uint8_t ip6[16],
+                                               uint8_t pubKey[32],
+                                               uint32_t version,
+                                               uint64_t label)
 {
-    struct SessionManager_pvt* bw = Identity_containerOf(iface, struct SessionManager_pvt, pub.switchIf);
+    struct SessionTable_Session* sess = SessionTable_sessionForIp6(ip6, sm->pub.sessionTable);
+    if (sess) {
+        sess->version = (sess->version) ? sess->version : version;
+        sess->sendSwitchLabel = (sess->sendSwitchLabel) ? sess->sendSwitchLabel : label;
+    } else {
+        sess = SessionTable_getSession(ip6, pubKey, sm->pub.sessionTable);
+        sess->version = version;
+        sess->sendSwitchLabel = label;
+        Allocator_onFree(sess->external.allocator, sessionCleanup, sess);
+        struct Allocator* alloc = Allocator_child(sm->alloc);
+        sendSession(sm, sess, label, 0xffffffff, Event_Core_SESSION, alloc);
+        Allocator_free(alloc);
+    }
+    return sess;
+}
+
+
+static Iface_DEFUN incomingFromSwitchIf(struct Iface* iface, struct Message* msg)
+{
+    struct SessionManager_pvt* sm =
+        Identity_containerOf(iface, struct SessionManager_pvt, pub.switchIf);
 
     // SwitchHeader, handle, small cryptoAuth header
     if (msg->length < SwitchHeader_SIZE + 4 + 20) {
-        Log_debug(bw->log, "DROP runt");
-        return 0;
+        Log_debug(sm->log, "DROP runt");
+        return NULL;
     }
 
     struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
@@ -157,134 +207,131 @@ static int incomingFromSwitchIf(struct Interface_Two* iface, struct Message* msg
     uint32_t nonceOrHandle = Endian_bigEndianToHost32(((uint32_t*)msg->bytes)[0]);
     if (nonceOrHandle > 3) {
         // > 3 it's a handle.
-        session = SessionTable_sessionForHandle(nonceOrHandle, bw->pub.sessionTable);
+        session = SessionTable_sessionForHandle(nonceOrHandle, sm->pub.sessionTable);
         if (!session) {
-            Log_debug(bw->log, "DROP message with unrecognized handle");
-            return 0;
+            Log_debug(sm->log, "DROP message with unrecognized handle");
+            return NULL;
         }
         Message_shift(msg, -4, NULL);
     } else {
         // handle + big cryptoauth header
         if (msg->length < CryptoHeader_SIZE + 4) {
-            Log_debug(bw->log, "DROP runt");
-            return 0;
+            Log_debug(sm->log, "DROP runt");
+            return NULL;
         }
         union CryptoHeader* caHeader = (union CryptoHeader*) msg->bytes;
         uint8_t* herKey = caHeader->handshake.publicKey;
         uint8_t ip6[16];
         // a packet which claims to be "from us" causes problems
         if (!AddressCalc_addressForPublicKey(ip6, herKey)) {
-            Log_debug(bw->log, "DROP Handshake with non-fc key");
-            return 0;
+            Log_debug(sm->log, "DROP Handshake with non-fc key");
+            return NULL;
         }
 
-        if (!Bits_memcmp(herKey, bw->ca->publicKey, 32)) {
-            Log_debug(bw->log, "DROP Handshake from 'ourselves'");
-            return 0;
+        if (!Bits_memcmp(herKey, sm->ca->publicKey, 32)) {
+            Log_debug(sm->log, "DROP Handshake from 'ourselves'");
+            return NULL;
         }
 
-        session = SessionTable_getSession(ip6, herKey, bw->pub.sessionTable);
-
-        debugHandlesAndLabel(bw->log, session,
-                             Endian_bigEndianToHost64(switchHeader->label_be),
-                             "new session nonce[%d]", nonceOrHandle);
+        uint64_t label = Endian_bigEndianToHost64(switchHeader->label_be);
+        session = getSession(sm, ip6, herKey, 0, label);
+        debugHandlesAndLabel(sm->log, session, label, "new session nonce[%d]", nonceOrHandle);
     }
 
-    Assert_true(NULL == bw->currentSession);
-    Assert_true(NULL == bw->currentSwitchHeader);
-    bw->currentSession = session;
-    bw->currentSwitchHeader = switchHeader;
+    Assert_true(NULL == sm->currentSession);
+    Assert_true(NULL == sm->currentSwitchHeader);
+    sm->currentSession = session;
+    sm->currentSwitchHeader = switchHeader;
     // --> incomingFromSwitchPostCryptoAuth
     int ret = Interface_receiveMessage(&session->external, msg);
     if (ret) {
-        bw->currentSession = NULL;
-        bw->currentSwitchHeader = NULL;
+        sm->currentSession = NULL;
+        sm->currentSwitchHeader = NULL;
 
-        debugHandlesAndLabel(bw->log, session,
+        debugHandlesAndLabel(sm->log, session,
                              Endian_bigEndianToHost64(switchHeader->label_be),
                              "DROP Failed decrypting message NoH[%d] state[%s]",
                              nonceOrHandle,
                              CryptoAuth_stateString(CryptoAuth_getState(session->internal)));
-        return Error_AUTHENTICATION;
+        return NULL;
     }
-    Assert_true(NULL == bw->currentSession);
-    Assert_true(NULL == bw->currentSwitchHeader);
+    Assert_true(NULL == sm->currentSession);
+    Assert_true(NULL == sm->currentSwitchHeader);
 
-    return 0;
+    return NULL;
 }
 
 static void checkTimedOutBuffers(void* vSessionManager)
 {
-    struct SessionManager_pvt* bw = Identity_check((struct SessionManager_pvt*) vSessionManager);
-    for (int i = 0; i < (int)bw->bufMap.count; i++) {
-        struct BufferedMessage* buffered = bw->bufMap.values[i];
-        uint64_t lag = Time_currentTimeSeconds(bw->eventBase) - buffered->timeSent;
+    struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) vSessionManager);
+    for (int i = 0; i < (int)sm->bufMap.count; i++) {
+        struct BufferedMessage* buffered = sm->bufMap.values[i];
+        uint64_t lag = Time_currentTimeSeconds(sm->eventBase) - buffered->timeSent;
         if (lag < 10) { continue; }
-        Map_BufferedMessages_remove(i, &bw->bufMap);
+        Map_BufferedMessages_remove(i, &sm->bufMap);
         Allocator_free(buffered->alloc);
         i--;
     }
 }
 
-static int needsLookup(struct SessionManager_pvt* bw, struct Message* msg)
+static void needsLookup(struct SessionManager_pvt* sm, struct Message* msg)
 {
     struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
     if (Defined(Log_DEBUG)) {
         uint8_t ipStr[40];
         AddrTools_printIp(ipStr, header->ip6);
-        Log_debug(bw->log, "Buffering a packet to [%s] and beginning a search", ipStr);
+        Log_debug(sm->log, "Buffering a packet to [%s] and beginning a search", ipStr);
     }
-    int index = Map_BufferedMessages_indexForKey((struct Ip6*)header->ip6, &bw->bufMap);
+    int index = Map_BufferedMessages_indexForKey((struct Ip6*)header->ip6, &sm->bufMap);
     if (index > -1) {
-        struct BufferedMessage* buffered = bw->bufMap.values[index];
-        Map_BufferedMessages_remove(index, &bw->bufMap);
+        struct BufferedMessage* buffered = sm->bufMap.values[index];
+        Map_BufferedMessages_remove(index, &sm->bufMap);
         Allocator_free(buffered->alloc);
-        Log_debug(bw->log, "DROP message which needs lookup because new one received");
+        Log_debug(sm->log, "DROP message which needs lookup because new one received");
     }
-    if ((int)bw->bufMap.count >= bw->pub.maxBufferedMessages) {
-        checkTimedOutBuffers(bw);
-        if ((int)bw->bufMap.count >= bw->pub.maxBufferedMessages) {
-            Log_debug(bw->log, "DROP message needing lookup maxBufferedMessages ([%d]) is reached",
-                      bw->pub.maxBufferedMessages);
-            return 0;
+    if ((int)sm->bufMap.count >= sm->pub.maxBufferedMessages) {
+        checkTimedOutBuffers(sm);
+        if ((int)sm->bufMap.count >= sm->pub.maxBufferedMessages) {
+            Log_debug(sm->log, "DROP message needing lookup maxBufferedMessages ([%d]) is reached",
+                      sm->pub.maxBufferedMessages);
+            return;
         }
     }
-    struct Allocator* lookupAlloc = Allocator_child(bw->alloc);
+    struct Allocator* lookupAlloc = Allocator_child(sm->alloc);
     struct BufferedMessage* buffered =
         Allocator_calloc(lookupAlloc, sizeof(struct BufferedMessage), 1);
     buffered->msg = msg;
     buffered->alloc = lookupAlloc;
-    buffered->timeSent = Time_currentTimeSeconds(bw->eventBase);
+    buffered->timeSent = Time_currentTimeSeconds(sm->eventBase);
     Allocator_adopt(lookupAlloc, msg->alloc);
-    Assert_true(Map_BufferedMessages_put((struct Ip6*)header->ip6, &buffered, &bw->bufMap) > -1);
+    Assert_true(Map_BufferedMessages_put((struct Ip6*)header->ip6, &buffered, &sm->bufMap) > -1);
 
     struct Allocator* eventAlloc = Allocator_child(lookupAlloc);
     struct Message* eventMsg = Message_new(0, 512, eventAlloc);
     Message_push(eventMsg, header->ip6, 16, NULL);
+    Message_push32(eventMsg, 0xffffffff, NULL);
     Message_push32(eventMsg, Event_Core_SEARCH_REQ, NULL);
-    Interface_send(&bw->eventIf, eventMsg);
+    Iface_send(&sm->eventIf, eventMsg);
     Allocator_free(eventAlloc);
-
-    return 0;
 }
 
 static uint8_t readyToSendPostCryptoAuth(struct Message* msg, struct Interface* iface)
 {
-    struct SessionManager_pvt* bw = Identity_check((struct SessionManager_pvt*) iface->senderContext);
-    struct SwitchHeader* sh = bw->currentSwitchHeader;
-    struct SessionTable_Session* sess = bw->currentSession;
-    bw->currentSession = NULL;
-    bw->currentSwitchHeader = NULL;
+    struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) iface->senderContext);
+    struct SwitchHeader* sh = sm->currentSwitchHeader;
+    struct SessionTable_Session* sess = sm->currentSession;
+    sm->currentSession = NULL;
+    sm->currentSwitchHeader = NULL;
     if (CryptoAuth_getState(sess->internal) >= CryptoAuth_HANDSHAKE3) {
         //if (0) { // Noisy
-            debugHandlesAndLabel0(bw->log,
+            debugHandlesAndLabel0(sm->log,
                                   sess,
                                   Endian_bigEndianToHost64(sh->label_be),
                                   "sending run message");
         //}
         Message_push32(msg, sess->sendHandle, NULL);
     } else {
-        debugHandlesAndLabel0(bw->log,
+        debugHandlesAndLabel0(sm->log,
                               sess,
                               Endian_bigEndianToHost64(sh->label_be),
                               "sending start message");
@@ -294,18 +341,19 @@ static uint8_t readyToSendPostCryptoAuth(struct Message* msg, struct Interface*
     Message_shift(msg, SwitchHeader_SIZE, NULL);
     Assert_true((uint8_t*)sh == msg->bytes);
 
-    return Interface_send(&bw->pub.switchIf, msg);
+    Iface_send(&sm->pub.switchIf, msg);
+    return 0;
 }
 
-static int readyToSend(struct SessionManager_pvt* bw,
-                       struct SessionTable_Session* sess,
-                       struct Message* msg)
+static Iface_DEFUN readyToSend(struct Message* msg,
+                               struct SessionManager_pvt* sm,
+                               struct SessionTable_Session* sess)
 {
     struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
     Message_shift(msg, -RouteHeader_SIZE, NULL);
-    Assert_true(!bw->currentSession);
-    Assert_true(!bw->currentSwitchHeader);
-    bw->currentSession = sess;
+    Assert_true(!sm->currentSession);
+    Assert_true(!sm->currentSwitchHeader);
+    sm->currentSession = sess;
 
     CryptoAuth_resetIfTimeout(sess->internal);
     if (CryptoAuth_getState(sess->internal) < CryptoAuth_HANDSHAKE3) {
@@ -315,34 +363,40 @@ static int readyToSend(struct SessionManager_pvt* bw,
         // Copy back the SwitchHeader so it is not clobbered.
         Message_shift(msg, (CryptoHeader_SIZE + SwitchHeader_SIZE), NULL);
         Bits_memcpyConst(msg->bytes, &header->sh, SwitchHeader_SIZE);
-        bw->currentSwitchHeader = (struct SwitchHeader*) msg->bytes;
+        sm->currentSwitchHeader = (struct SwitchHeader*) msg->bytes;
         Message_shift(msg, -(CryptoHeader_SIZE + SwitchHeader_SIZE), NULL);
     } else {
-        bw->currentSwitchHeader = &header->sh;
+        sm->currentSwitchHeader = &header->sh;
     }
 
     // --> readyToSendPostCryptoAuth
-    int ret = Interface_sendMessage(sess->internal, msg);
+    Interface_sendMessage(sess->internal, msg);
+
+    Assert_true(!sm->currentSession);
+    Assert_true(!sm->currentSwitchHeader);
 
-    Assert_true(!bw->currentSession);
-    Assert_true(!bw->currentSwitchHeader);
-    return ret;
+    return NULL;
 }
 
-static int incomingFromInsideIf(struct Interface_Two* iface, struct Message* msg)
+static Iface_DEFUN incomingFromInsideIf(struct Iface* iface, struct Message* msg)
 {
-    struct SessionManager_pvt* bw = Identity_containerOf(iface, struct SessionManager_pvt, pub.insideIf);
+    struct SessionManager_pvt* sm =
+        Identity_containerOf(iface, struct SessionManager_pvt, pub.insideIf);
     Assert_true(msg->length >= RouteHeader_SIZE);
     struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
 
     struct SessionTable_Session* sess =
-        SessionTable_sessionForIp6(header->ip6, bw->pub.sessionTable);
+        SessionTable_sessionForIp6(header->ip6, sm->pub.sessionTable);
     if (!sess) {
         if (!Bits_isZero(header->publicKey, 32)) {
-            sess =
-                SessionTable_getSession(header->ip6, header->publicKey, bw->pub.sessionTable);
+            sess = getSession(sm,
+                              header->ip6,
+                              header->publicKey,
+                              Endian_bigEndianToHost32(header->version_be),
+                              Endian_hostToBigEndian64(sess->sendSwitchLabel));
         } else {
-            return needsLookup(bw, msg);
+            needsLookup(sm, msg);
+            return NULL;
         }
     }
 
@@ -353,10 +407,11 @@ static int incomingFromInsideIf(struct Interface_Two* iface, struct Message* msg
     } else if (sess->sendSwitchLabel) {
         header->sh.label_be = Endian_hostToBigEndian64(sess->sendSwitchLabel);
     } else {
-        return needsLookup(bw, msg);
+        needsLookup(sm, msg);
+        return NULL;
     }
 
-    return readyToSend(bw, sess, msg);
+    return readyToSend(msg, sm, sess);
 }
 
 /* too good to toss!
@@ -389,81 +444,96 @@ static uint32_t getEffectiveMetric(uint64_t nowMilliseconds,
 }
 */
 
-static Interface_Ret sessions(struct Interface_Two* iface, struct Message* msg)
+static Iface_DEFUN sessions(struct SessionManager_pvt* sm,
+                            uint32_t sourcePf,
+                            struct Allocator* tempAlloc)
 {
-    
+    struct SessionTable_HandleList* handles =
+        SessionTable_getHandleList(sm->pub.sessionTable, tempAlloc);
+    for (int i = 0; i < (int)handles->count; i++) {
+        struct SessionTable_Session* sess =
+            SessionTable_sessionForHandle(handles->handles[i], sm->pub.sessionTable);
+        struct Allocator* alloc = Allocator_child(tempAlloc);
+        sendSession(sm, sess, sess->sendSwitchLabel, sourcePf, Event_Core_SESSION, alloc);
+        Allocator_free(alloc);
+    }
+    return NULL;
 }
 
-static Interface_Ret incomingFromEventIf(struct Interface_Two* iface, struct Message* msg)
+static Iface_DEFUN incomingFromEventIf(struct Iface* iface, struct Message* msg)
 {
-    struct SessionManager_pvt* bw = Identity_containerOf(iface, struct SessionManager_pvt, eventIf);
+    struct SessionManager_pvt* sm = Identity_containerOf(iface, struct SessionManager_pvt, eventIf);
     enum Event_Pathfinder ev = Message_pop32(msg, NULL);
     uint32_t sourcePf = Message_pop32(msg, NULL);
     if (ev == Event_Pathfinder_SESSIONS) {
         Assert_true(!msg->length);
-        return sessions(bw, sourcePf);
+        return sessions(sm, sourcePf, msg->alloc);
     }
     Assert_true(ev == Event_Pathfinder_NODE);
 
     struct Event_Node node;
     Message_pop(msg, &node, Event_Node_SIZE, NULL);
     Assert_true(!msg->length);
-    int index = Map_BufferedMessages_indexForKey((struct Ip6*)node.ip6, &bw->bufMap);
+    int index = Map_BufferedMessages_indexForKey((struct Ip6*)node.ip6, &sm->bufMap);
     struct SessionTable_Session* sess;
     if (index == -1) {
-        sess = SessionTable_sessionForIp6(node.ip6, bw->pub.sessionTable);
+        sess = SessionTable_sessionForIp6(node.ip6, sm->pub.sessionTable);
         // If we discovered a node we're not interested in ...
-        if (!sess) { return Interface_RET; }
+        if (!sess) { return NULL; }
+        sess->sendSwitchLabel = Endian_bigEndianToHost64(node.path_be);
+        sess->version = Endian_bigEndianToHost32(node.version_be);
     } else {
-        sess = SessionTable_getSession(node.ip6, node.publicKey, bw->pub.sessionTable);
+        sess = getSession(sm,
+                          node.ip6,
+                          node.publicKey,
+                          Endian_bigEndianToHost32(node.version_be),
+                          Endian_bigEndianToHost64(node.path_be));
     }
 
-    sess->sendSwitchLabel = Endian_bigEndianToHost64(node.path_be);
-    sess->version = Endian_bigEndianToHost64(node.version_be);
-
     // Send what's on the buffer...
     if (index > -1) {
-        struct BufferedMessage* bm = bw->bufMap.values[index];
-        readyToSend(bw, sess, bm->msg);
-        Map_BufferedMessages_remove(index, &bw->bufMap);
+        struct BufferedMessage* bm = sm->bufMap.values[index];
+        Iface_CALL(readyToSend, bm->msg, sm, sess);
+        Map_BufferedMessages_remove(index, &sm->bufMap);
         Allocator_free(bm->alloc);
     }
-    return Interface_RET;
+    return NULL;
 }
 
 struct SessionManager* SessionManager_new(struct Allocator* alloc,
-                                  struct EventBase* eventBase,
-                                  struct CryptoAuth* cryptoAuth,
-                                  struct Random* rand,
-                                  struct Log* log,
-                                  struct EventEmitter* ee)
+                                          struct EventBase* eventBase,
+                                          struct CryptoAuth* cryptoAuth,
+                                          struct Random* rand,
+                                          struct Log* log,
+                                          struct EventEmitter* ee)
 {
-    struct SessionManager_pvt* bw = Allocator_calloc(alloc, sizeof(struct SessionManager_pvt), 1);
-    bw->alloc = alloc;
-    bw->pub.switchIf.send = incomingFromSwitchIf;
-    bw->pub.insideIf.send = incomingFromInsideIf;
-    bw->bufMap.allocator = alloc;
-    bw->log = log;
-    bw->ca = cryptoAuth;
-    bw->eventBase = eventBase;
-
-    bw->pub.metricHalflifeMilliseconds = SessionManager_METRIC_HALFLIFE_MILLISECONDS_DEFAULT;
-    bw->pub.maxBufferedMessages = SessionManager_MAX_BUFFERED_MESSAGES_DEFAULT;
-
-    bw->eventIf.send = incomingFromEventIf;
-    EventEmitter_regCore(ee, &bw->eventIf, Event_Pathfinder_NODE);
-
-    bw->pub.sessionTable = SessionTable_new(incomingFromSwitchPostCryptoAuth,
+    struct SessionManager_pvt* sm = Allocator_calloc(alloc, sizeof(struct SessionManager_pvt), 1);
+    sm->alloc = alloc;
+    sm->pub.switchIf.send = incomingFromSwitchIf;
+    sm->pub.insideIf.send = incomingFromInsideIf;
+    sm->bufMap.allocator = alloc;
+    sm->log = log;
+    sm->ca = cryptoAuth;
+    sm->eventBase = eventBase;
+
+    sm->pub.metricHalflifeMilliseconds = SessionManager_METRIC_HALFLIFE_MILLISECONDS_DEFAULT;
+    sm->pub.maxBufferedMessages = SessionManager_MAX_BUFFERED_MESSAGES_DEFAULT;
+
+    sm->eventIf.send = incomingFromEventIf;
+    EventEmitter_regCore(ee, &sm->eventIf, Event_Pathfinder_NODE);
+    EventEmitter_regCore(ee, &sm->eventIf, Event_Pathfinder_SESSIONS);
+
+    sm->pub.sessionTable = SessionTable_new(incomingFromSwitchPostCryptoAuth,
                                             readyToSendPostCryptoAuth,
-                                            bw,
+                                            sm,
                                             eventBase,
                                             cryptoAuth,
                                             rand,
                                             alloc);
 
-    Timeout_setInterval(checkTimedOutBuffers, bw, 10000, eventBase, alloc);
+    Timeout_setInterval(checkTimedOutBuffers, sm, 10000, eventBase, alloc);
 
-    Identity_set(bw);
+    Identity_set(sm);
 
-    return &bw->pub;
+    return &sm->pub;
 }

+ 2 - 2
net/SessionManager.h

@@ -37,7 +37,7 @@ Linker_require("net/SessionManager.c")
 struct SessionManager
 {
     /** Sends and handles packets prepped to/from switch. */
-    struct Interface_Two switchIf;
+    struct Iface switchIf;
 
     /**
      * Sends and handles packets with RouteHeader on top.
@@ -48,7 +48,7 @@ struct SessionManager
      * If these values are not known, the packet will be taken from the cache or a search will
      * be triggered.
      */
-    struct Interface_Two insideIf;
+    struct Iface insideIf;
 
     struct SessionTable* sessionTable;
 

+ 17 - 11
net/SessionTable.c

@@ -170,12 +170,11 @@ struct SessionTable_Session* SessionTable_sessionForIp6(uint8_t* lookupKey,
 }
 
 struct SessionTable_Session* SessionTable_getSession(uint8_t* lookupKey,
-                                                         uint8_t cryptoKey[32],
-                                                         struct SessionTable* sm)
+                                                     uint8_t cryptoKey[32],
+                                                     struct SessionTable* sm)
 {
     Assert_true(cryptoKey);
-    struct SessionTable_Session* sess = SessionTable_sessionForIp6(lookupKey, sm);
-    if (sess) { return sess; }
+    Assert_true(!SessionTable_sessionForIp6(lookupKey, sm));
 
     struct Allocator* ifAlloc = Allocator_child(sm->allocator);
     struct SessionTable_Session_pvt* ss =
@@ -232,8 +231,15 @@ uint8_t* SessionTable_getIp6(uint32_t handle, struct SessionTable* sm)
     return sm->ifaceMap.keys[index].bytes;
 }
 
+void* SessionTable_getInterfaceContext(struct SessionTable_Session* session)
+{
+    struct SessionTable_Session_pvt* sess =
+        Identity_check((struct SessionTable_Session_pvt*) session);
+    return sess->sm->interfaceContext;
+}
+
 struct SessionTable_HandleList* SessionTable_getHandleList(struct SessionTable* sm,
-                                                               struct Allocator* alloc)
+                                                           struct Allocator* alloc)
 {
     struct SessionTable_HandleList* out =
         Allocator_malloc(alloc, sizeof(struct SessionTable_HandleList));
@@ -248,12 +254,12 @@ struct SessionTable_HandleList* SessionTable_getHandleList(struct SessionTable*
 }
 
 struct SessionTable* SessionTable_new(Interface_Callback decryptedIncoming,
-                                          Interface_Callback encryptedOutgoing,
-                                          void* interfaceContext,
-                                          struct EventBase* eventBase,
-                                          struct CryptoAuth* cryptoAuth,
-                                          struct Random* rand,
-                                          struct Allocator* allocator)
+                                      Interface_Callback encryptedOutgoing,
+                                      void* interfaceContext,
+                                      struct EventBase* eventBase,
+                                      struct CryptoAuth* cryptoAuth,
+                                      struct Random* rand,
+                                      struct Allocator* allocator)
 {
     struct SessionTable* sm = Allocator_malloc(allocator, sizeof(struct SessionTable));
     Bits_memcpyConst(sm, (&(struct SessionTable) {

+ 2 - 0
net/SessionTable.h

@@ -133,4 +133,6 @@ uint8_t* SessionTable_getIp6(uint32_t handle, struct SessionTable* sm);
 struct SessionTable_HandleList* SessionTable_getHandleList(struct SessionTable* sm,
                                                                struct Allocator* alloc);
 
+void* SessionTable_getInterfaceContext(struct SessionTable_Session* session);
+
 #endif

+ 10 - 6
net/SwitchAdapter.c

@@ -34,18 +34,20 @@ struct Header {
 #define Header_SIZE 16
 Assert_compileTime(sizeof(struct Header) == Header_SIZE);
 
-static int incomingFromControlIf(struct Interface_Two* controlIf, struct Message* msg)
+static Iface_DEFUN incomingFromControlIf(struct Iface* controlIf, struct Message* msg)
 {
     struct SwitchAdapter_pvt* sa =
         Identity_containerOf(controlIf, struct SwitchAdapter_pvt, pub.controlIf);
-    return Interface_receiveMessage(&sa->pub.switchIf, msg);
+    Interface_receiveMessage(&sa->pub.switchIf, msg);
+    return NULL;
 }
 
-static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf, struct Message* msg)
+static Iface_DEFUN incomingFromSessionManagerIf(struct Iface* sessionManagerIf, struct Message* msg)
 {
     struct SwitchAdapter_pvt* sa =
         Identity_containerOf(sessionManagerIf, struct SwitchAdapter_pvt, pub.sessionManagerIf);
-    return Interface_receiveMessage(&sa->pub.switchIf, msg);
+    Interface_receiveMessage(&sa->pub.switchIf, msg);
+    return NULL;
 }
 
 static uint8_t incomingFromSwitchIf(struct Message* msg, struct Interface* switchIf)
@@ -65,9 +67,11 @@ static uint8_t incomingFromSwitchIf(struct Message* msg, struct Interface* switc
     hdr->sh.label_be = Bits_bitReverse64(hdr->sh.label_be);
 
     if (hdr->handle_be == 0xffffffff) {
-        return Interface_send(&sa->pub.controlIf, msg);
+        Iface_send(&sa->pub.controlIf, msg);
+        return 0;
     }
-    return Interface_send(&sa->pub.sessionManagerIf, msg);
+    Iface_send(&sa->pub.sessionManagerIf, msg);
+    return 0;
 }
 
 struct SwitchAdapter* SwitchAdapter_new(struct Allocator* alloc, struct Log* log)

+ 3 - 2
net/SwitchAdapter.h

@@ -16,6 +16,7 @@
 #define SwitchAdapter_H
 
 #include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "memory/Allocator.h"
 #include "util/log/Log.h"
 #include "util/Linker.h"
@@ -33,13 +34,13 @@ struct SwitchAdapter
      * Sends forth the packets with control headers (0xffffffff) under the switch header.
      * Directs all input to the switch.
      */
-    struct Interface_Two controlIf;
+    struct Iface controlIf;
 
     /**
      * Sends all packets which are not control frames.
      * Directs all input to the switch.
      */
-    struct Interface_Two sessionManagerIf;
+    struct Iface sessionManagerIf;
 };
 
 struct SwitchAdapter* SwitchAdapter_new(struct Allocator* alloc, struct Log* log);

+ 9 - 9
net/SwitchPinger.c

@@ -76,7 +76,7 @@ struct Ping
 };
 
 // incoming message from network, pointing to the beginning of the switch header.
-static int messageFromControlHandler(struct Interface_Two* iface, struct Message* msg)
+static Iface_DEFUN messageFromControlHandler(struct Iface* iface, struct Message* msg)
 {
     struct SwitchPinger_pvt* ctx = Identity_check((struct SwitchPinger_pvt*) iface);
     struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
@@ -103,12 +103,12 @@ static int messageFromControlHandler(struct Interface_Two* iface, struct Message
             ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
             if (pongHeader->magic != Control_Pong_MAGIC) {
                 Log_debug(ctx->logger, "dropped invalid switch pong");
-                return Error_INVALID;
+                return NULL;
             }
             Message_shift(msg, -Control_Pong_HEADER_SIZE, NULL);
         } else {
             Log_debug(ctx->logger, "got runt pong message, length: [%d]", msg->length);
-            return Error_INVALID;
+            return NULL;
         }
 
     } else if (ctrl->header.type_be == Control_KEYPONG_be) {
@@ -119,16 +119,16 @@ static int messageFromControlHandler(struct Interface_Two* iface, struct Message
             ctx->incomingVersion = Endian_bigEndianToHost32(pongHeader->version_be);
             if (pongHeader->magic != Control_KeyPong_MAGIC) {
                 Log_debug(ctx->logger, "dropped invalid switch key-pong");
-                return Error_INVALID;
+                return NULL;
             }
             Bits_memcpyConst(ctx->incomingKey, pongHeader->key, 32);
             Message_shift(msg, -Control_KeyPong_HEADER_SIZE, NULL);
         } else if (msg->length > Control_KeyPong_MAX_SIZE) {
             Log_debug(ctx->logger, "got overlong key-pong message, length: [%d]", msg->length);
-            return Error_INVALID;
+            return NULL;
         } else {
             Log_debug(ctx->logger, "got runt key-pong message, length: [%d]", msg->length);
-            return Error_INVALID;
+            return NULL;
         }
 
     } else if (ctrl->header.type_be == Control_ERROR_be) {
@@ -136,7 +136,7 @@ static int messageFromControlHandler(struct Interface_Two* iface, struct Message
         Assert_true((uint8_t*)&ctrl->content.error.errorType_be == msg->bytes);
         if (msg->length < (Control_Error_HEADER_SIZE + SwitchHeader_SIZE + Control_Header_SIZE)) {
             Log_debug(ctx->logger, "runt error packet");
-            return Error_NONE;
+            return NULL;
         }
 
         ctx->error = Message_pop32(msg, NULL);
@@ -171,7 +171,7 @@ static int messageFromControlHandler(struct Interface_Two* iface, struct Message
     String* msgStr = &(String) { .bytes = (char*) msg->bytes, .len = msg->length };
     Pinger_pongReceived(msgStr, ctx->pinger);
     Bits_memset(ctx->incomingKey, 0, 32);
-    return Error_NONE;
+    return NULL;
 }
 
 static void onPingResponse(String* data, uint32_t milliseconds, void* vping)
@@ -261,7 +261,7 @@ static void sendPing(String* data, void* sendPingContext)
         SwitchHeader_setVersion(switchHeader, 0);
     #endif
 
-    Interface_send(&p->context->pub.controlHandlerIf, msg);
+    Iface_send(&p->context->pub.controlHandlerIf, msg);
 }
 
 static String* RESULT_STRING_OK =             String_CONST_SO("pong");

+ 2 - 2
net/SwitchPinger.h

@@ -18,7 +18,7 @@
 #include "benc/String.h"
 #include "dht/Address.h"
 #include "crypto/random/Random.h"
-#include "interface/Interface.h"
+#include "interface/Iface.h"
 #include "util/events/EventBase.h"
 #include "util/log/Log.h"
 #include "util/Linker.h"
@@ -97,7 +97,7 @@ struct SwitchPinger_Ping
 
 struct SwitchPinger
 {
-    struct Interface_Two controlHandlerIf;
+    struct Iface controlHandlerIf;
 };
 
 String* SwitchPinger_resultString(enum SwitchPinger_Result result);

+ 10 - 10
net/TUNAdapter.c

@@ -27,29 +27,29 @@ struct UpperDistributor_pvt
     Identity
 };
 
-static int incomingFromDhtIf(struct Interface_Two* dhtIf, struct Message* msg)
+static Iface_DEFUN incomingFromDhtIf(struct Iface* dhtIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(dhtIf, struct UpperDistributor_pvt, pub.dhtIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
-static int incomingFromTunIf(struct Interface_Two* tunIf, struct Message* msg)
+static Iface_DEFUN incomingFromTunIf(struct Iface* tunIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(tunIf, struct UpperDistributor_pvt, pub.tunIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
-static int incomingFromIpTunnelIf(struct Interface_Two* ipTunnelIf, struct Message* msg)
+static Iface_DEFUN incomingFromIpTunnelIf(struct Iface* ipTunnelIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(ipTunnelIf, struct UpperDistributor_pvt, pub.ipTunnelIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
 
-static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf, struct Message* msg)
+static Iface_DEFUN incomingFromSessionManagerIf(struct Iface* sessionManagerIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(sessionManagerIf, struct UpperDistributor_pvt, pub.sessionManagerIf);
@@ -58,14 +58,14 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
     struct DataHeader* dh = (struct DataHeader*) &hdr[1];
     enum ContentType type = DataHeader_getContentType(dh);
     if (type <= ContentType_IP6_RAW) {
-        return Interface_send(&ud->pub.tunIf, msg);
+        return Iface_send(&ud->pub.tunIf, msg);
     }
     if (type == ContentType_CJDHT) {
         Log_debug(ud->log, "UD_incomingFromSessionManagerIf");
-        return Interface_send(&ud->pub.dhtIf, msg);
+        return Iface_send(&ud->pub.dhtIf, msg);
     }
     if (type == ContentType_IPTUN) {
-        return Interface_send(&ud->pub.ipTunnelIf, msg);
+        return Iface_send(&ud->pub.ipTunnelIf, msg);
     }
     Log_debug(ud->log, "DROP message with unknown type [%d]", type);
     return 0;

+ 3 - 3
net/TUNAdapter.h

@@ -27,11 +27,11 @@ Linker_require("net/UpperDistributor.c")
  */
 struct UpperDistributor
 {
-    struct Interface_Two sessionManagerIf;
+    struct Iface sessionManagerIf;
 
-    struct Interface_Two tunIf;
+    struct Iface tunIf;
 
-    struct Interface_Two ipTunnelIf;
+    struct Iface ipTunnelIf;
 };
 
 struct UpperDistributor* UpperDistributor_new(struct Allocator* alloc, struct Log* log);

+ 10 - 10
net/UpperDistributor.c

@@ -28,29 +28,29 @@ struct UpperDistributor_pvt
     Identity
 };
 
-static int incomingFromDhtIf(struct Interface_Two* dhtIf, struct Message* msg)
+static Iface_DEFUN incomingFromDhtIf(struct Iface* dhtIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(dhtIf, struct UpperDistributor_pvt, pub.dhtIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
-static int incomingFromTunIf(struct Interface_Two* tunIf, struct Message* msg)
+static Iface_DEFUN incomingFromTunIf(struct Iface* tunIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(tunIf, struct UpperDistributor_pvt, pub.tunIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
-static int incomingFromIpTunnelIf(struct Interface_Two* ipTunnelIf, struct Message* msg)
+static Iface_DEFUN incomingFromIpTunnelIf(struct Iface* ipTunnelIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(ipTunnelIf, struct UpperDistributor_pvt, pub.ipTunnelIf);
-    return Interface_send(&ud->pub.sessionManagerIf, msg);
+    return Iface_send(&ud->pub.sessionManagerIf, msg);
 }
 
 
-static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf, struct Message* msg)
+static Iface_DEFUN incomingFromSessionManagerIf(struct Iface* sessionManagerIf, struct Message* msg)
 {
     struct UpperDistributor_pvt* ud =
         Identity_containerOf(sessionManagerIf, struct UpperDistributor_pvt, pub.sessionManagerIf);
@@ -59,14 +59,14 @@ static int incomingFromSessionManagerIf(struct Interface_Two* sessionManagerIf,
     struct DataHeader* dh = (struct DataHeader*) &hdr[1];
     enum ContentType type = DataHeader_getContentType(dh);
     if (type <= ContentType_IP6_RAW) {
-        return Interface_send(&ud->pub.tunIf, msg);
+        return Iface_send(&ud->pub.tunIf, msg);
     }
     if (type == ContentType_CJDHT) {
         Log_debug(ud->log, "UD_incomingFromSessionManagerIf");
-        return Interface_send(&ud->pub.dhtIf, msg);
+        return Iface_send(&ud->pub.dhtIf, msg);
     }
     if (type == ContentType_IPTUN) {
-        return Interface_send(&ud->pub.ipTunnelIf, msg);
+        return Iface_send(&ud->pub.ipTunnelIf, msg);
     }
     Log_debug(ud->log, "DROP message with unknown type [%d]", type);
     return 0;

+ 4 - 4
net/UpperDistributor.h

@@ -27,13 +27,13 @@ Linker_require("net/UpperDistributor.c")
  */
 struct UpperDistributor
 {
-    struct Interface_Two sessionManagerIf;
+    struct Iface sessionManagerIf;
 
-    struct Interface_Two dhtIf;
+    struct Iface dhtIf;
 
-    struct Interface_Two tunIf;
+    struct Iface tunIf;
 
-    struct Interface_Two ipTunnelIf;
+    struct Iface ipTunnelIf;
 };
 
 struct UpperDistributor* UpperDistributor_new(struct Allocator* alloc, struct Log* log);

+ 12 - 41
test/TestFramework.c

@@ -34,6 +34,7 @@
 #include "net/SwitchPinger.h"
 #include "net/ControlHandler.h"
 #include "interface/InterfaceController.h"
+#include "interface/Iface.h"
 #include "tunnel/IpTunnel.h"
 #include "net/EventEmitter.h"
 #include "net/SessionManager.h"
@@ -126,70 +127,40 @@ struct TestFramework* TestFramework_setUp(char* privateKey,
     struct SwitchCore* switchCore = SwitchCore_new(logger, allocator, base);
     struct CryptoAuth* ca = CryptoAuth_new(allocator, (uint8_t*)privateKey, base, logger, rand);
 
-
-// allocator, myAddress, logger, base, publicKey, rand
-    do {
-
-    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator);
-    ReplyModule_register(registry, allocator);
-
-    struct RumorMill* rumorMill = RumorMill_new(allocator, myAddress, 64, logger, "");
-
-    struct NodeStore* nodeStore = NodeStore_new(myAddress, allocator, base, logger, rumorMill);
-
-    struct RouterModule* routerModule =
-        RouterModule_register(registry, allocator, publicKey, base, logger, rand, nodeStore);
-
-    struct SearchRunner* searchRunner = SearchRunner_new(nodeStore,
-                                                         logger,
-                                                         base,
-                                                         routerModule,
-                                                         myAddress->ip6.bytes,
-                                                         rumorMill,
-                                                         allocator);
-
-    EncodingSchemeModule_register(registry, logger, allocator);
-
-    SerializationModule_register(registry, logger, allocator);
-
-    struct Router* router = Router_new(routerModule, nodeStore, searchRunner, allocator);
-
-    } while (0);
+    struct EventEmitter* eventEmitter = EventEmitter_new(allocator, logger, publicKey);
 
     /*struct IpTunnel* ipTun = */IpTunnel_new(logger, base, allocator, rand, NULL);
 
-
-
-    struct EventEmitter* eventEmitter = EventEmitter_new(allocator, logger);
-
     struct SessionManager* sessionManager =
         SessionManager_new(allocator, base, ca, rand, logger, eventEmitter);
     struct SwitchAdapter* switchAdapter = SwitchAdapter_new(allocator, logger);
-    Interface_plumb(&switchAdapter->sessionManagerIf, &sessionManager->switchIf);
+    Iface_plumb(&switchAdapter->sessionManagerIf, &sessionManager->switchIf);
 
     SwitchCore_setRouterInterface(&switchAdapter->switchIf, switchCore);
 
     struct ConverterV15* v15conv =
         ConverterV15_new(allocator, logger, sessionManager->sessionTable, myAddress->ip6.bytes);
-    Interface_plumb(&v15conv->sessionManagerIf, &sessionManager->insideIf);
+    Iface_plumb(&v15conv->sessionManagerIf, &sessionManager->insideIf);
 
     struct UpperDistributor* upper = UpperDistributor_new(allocator, logger);
-    Interface_plumb(&v15conv->upperDistributorIf, &upper->sessionManagerIf);
+    Iface_plumb(&v15conv->upperDistributorIf, &upper->sessionManagerIf);
 
     struct DHTCoreInterface* dhtCore = DHTCoreInterface_register(allocator, logger, registry);
-    Interface_plumb(&dhtCore->coreIf, &upper->dhtIf);
+    Iface_plumb(&dhtCore->coreIf, &upper->dhtIf);
 
     struct ControlHandler* controlHandler =
         ControlHandler_new(allocator, logger, eventEmitter, myAddress);
-    Interface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf);
+    Iface_plumb(&controlHandler->coreIf, &switchAdapter->controlIf);
 
     struct SwitchPinger* sp = SwitchPinger_new(base, rand, logger, myAddress, allocator);
-    Interface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf);
+    Iface_plumb(&controlHandler->switchPingerIf, &sp->controlHandlerIf);
 
     // Interfaces.
     struct InterfaceController* ifController =
-        InterfaceController_new(ca, switchCore, router, rumorMill,
-                                logger, base, sp, rand, allocator);
+        InterfaceController_new(ca, switchCore, rumorMill,
+                                logger, base, sp, rand, allocator, eventEmitter);
+
+    Pathfinder_register(allocator, logger, base, rand, NULL, eventEmitter);
 
     struct TestFramework* tf = Allocator_clone(allocator, (&(struct TestFramework) {
         .alloc = allocator,

+ 5 - 0
wire/Message.h

@@ -37,6 +37,11 @@ struct Message
     /** Amount of bytes of storage space available in the message. */
     int32_t capacity;
 
+    #ifdef PARANOIA
+        /** This is used inside of Iface.h to support Iface_next() */
+        struct Iface* currentIface;
+    #endif
+
     /** The allocator which allocated space for this message. */
     struct Allocator* alloc;
 };