123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /* 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 "crypto/AddressCalc.h"
- #include "crypto/CryptoAuth_pvt.h"
- #include "interface/InterfaceController.h"
- #include "dht/dhtcore/RumorMill.h"
- #include "dht/dhtcore/Router.h"
- #include "memory/Allocator.h"
- #include "net/SwitchPinger.h"
- #include "util/Base32.h"
- #include "util/Bits.h"
- #include "util/events/Time.h"
- #include "util/events/Timeout.h"
- #include "util/Identity.h"
- #include "util/version/Version.h"
- #include "util/AddrTools.h"
- #include "wire/Error.h"
- #include "wire/Message.h"
- #include <stddef.h> // offsetof
- /** After this number of milliseconds, a node will be regarded as unresponsive. */
- #define UNRESPONSIVE_AFTER_MILLISECONDS (20*1024)
- /**
- * After this number of milliseconds without a valid incoming message,
- * a peer is "lazy" and should be pinged.
- */
- #define PING_AFTER_MILLISECONDS (3*1024)
- /** How often to ping "lazy" peers, "unresponsive" peers are only pinged 20% of the time. */
- #define PING_INTERVAL_MILLISECONDS 1024
- /** The number of milliseconds to wait for a ping response. */
- #define TIMEOUT_MILLISECONDS (2*1024)
- /**
- * The number of seconds to wait before an unresponsive peer
- * making an incoming connection is forgotten.
- */
- #define FORGET_AFTER_MILLISECONDS (256*1024)
- /*--------------------Structs--------------------*/
- #define Map_NAME OfIFCPeerByExernalIf
- #define Map_ENABLE_HANDLES
- #define Map_KEY_TYPE struct Interface*
- #define Map_VALUE_TYPE struct InterfaceController_Peer*
- #include "util/Map.h"
- struct InterfaceController_pvt
- {
- /** Public functions and fields for this ifcontroller. */
- struct InterfaceController pub;
- /** Used to get a peer by its handle. */
- struct Map_OfIFCPeerByExernalIf peerMap;
- struct Allocator* const allocator;
- struct CryptoAuth* const ca;
- /** Switch for adding nodes when they are discovered. */
- struct SwitchCore* const switchCore;
- struct Router* const router;
- struct Random* const rand;
- struct RumorMill* const rumorMill;
- struct Log* const logger;
- struct EventBase* const eventBase;
- /** After this number of milliseconds, a neoghbor will be regarded as unresponsive. */
- uint32_t unresponsiveAfterMilliseconds;
- /** The number of milliseconds to wait before pinging. */
- uint32_t pingAfterMilliseconds;
- /** The number of milliseconds to let a ping go before timing it out. */
- uint32_t timeoutMilliseconds;
- /** After this number of milliseconds, an incoming connection is forgotten entirely. */
- uint32_t forgetAfterMilliseconds;
- /** The timeout event to use for pinging potentially unresponsive neighbors. */
- struct Timeout* const pingInterval;
- /** For pinging lazy/unresponsive nodes. */
- struct SwitchPinger* const switchPinger;
- /** A password which is generated per-startup and sent out in beacon messages. */
- uint8_t beaconPassword[Headers_Beacon_PASSWORD_LEN];
- Identity
- };
- //---------------//
- static inline struct InterfaceController_pvt* ifcontrollerForPeer(
- struct InterfaceController_Peer* ep)
- {
- return Identity_check((struct InterfaceController_pvt*) ep->switchIf.senderContext);
- }
- static void onPingResponse(struct SwitchPinger_Response* resp, void* onResponseContext)
- {
- if (SwitchPinger_Result_OK != resp->res) {
- return;
- }
- struct InterfaceController_Peer* ep =
- Identity_check((struct InterfaceController_Peer*) onResponseContext);
- struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);
- struct Address addr;
- Bits_memset(&addr, 0, sizeof(struct Address));
- Bits_memcpyConst(addr.key, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
- addr.path = ep->switchLabel;
- addr.protocolVersion = resp->version;
- #ifdef Log_DEBUG
- uint8_t addrStr[60];
- Address_print(addrStr, &addr);
- uint8_t key[56];
- Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
- #endif
- if (!Version_isCompatible(Version_CURRENT_PROTOCOL, resp->version)) {
- Log_debug(ic->logger, "got switch pong from node [%s] with incompatible version [%d]",
- key, resp->version);
- } else {
- Log_debug(ic->logger, "got switch pong from node [%s] with version [%d]",
- key, resp->version);
- }
- 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, &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, &addr);
- } else {
- Log_debug(ic->logger, "link exists");
- }
- ep->timeOfLastPing = Time_currentTimeMilliseconds(ic->eventBase);
- #ifdef Log_DEBUG
- // This will be false if it times out.
- //Assert_true(label == ep->switchLabel);
- uint8_t path[20];
- AddrTools_printPath(path, resp->label);
- uint8_t sl[20];
- AddrTools_printPath(sl, ep->switchLabel);
- Log_debug(ic->logger, "Received [%s] from lazy endpoint [%s] [%s]",
- SwitchPinger_resultString(resp->res)->bytes, path, sl);
- #endif
- }
- /*
- * Send a ping packet to one of the endpoints.
- */
- static void sendPing(struct InterfaceController_Peer* ep)
- {
- struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);
- ep->pingCount++;
- struct SwitchPinger_Ping* ping =
- SwitchPinger_newPing(ep->switchLabel,
- String_CONST(""),
- ic->timeoutMilliseconds,
- onPingResponse,
- ic->allocator,
- ic->switchPinger);
- #ifdef Log_DEBUG
- uint8_t key[56];
- Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
- #endif
- if (!ping) {
- Log_debug(ic->logger, "Failed to ping [%s.k], out of ping slots", key);
- return;
- } else {
- Log_debug(ic->logger, "SwitchPing [%s.k]", key);
- }
- ping->onResponseContext = ep;
- }
- /**
- * Check the table for nodes which might need to be pinged, ping a node if necessary.
- * If a node has not responded in unresponsiveAfterMilliseconds then mark them as unresponsive
- * and if the connection is incoming and the node has not responded in forgetAfterMilliseconds
- * then drop them entirely.
- * This is called every PING_INTERVAL_MILLISECONDS but pingCallback is a misleading name.
- */
- static void pingCallback(void* vic)
- {
- struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) vic);
- if (!ic->peerMap.count) { return; }
- uint64_t now = Time_currentTimeMilliseconds(ic->eventBase);
- // scan for endpoints have not sent anything recently.
- uint32_t startAt = Random_uint32(ic->rand) % ic->peerMap.count;
- for (uint32_t i = startAt, count = 0; (!count || i != startAt) && count <= ic->peerMap.count;) {
- i = (i + 1) % ic->peerMap.count;
- count++;
- struct InterfaceController_Peer* ep = ic->peerMap.values[i];
- if (now < ep->timeOfLastMessage + ic->pingAfterMilliseconds) {
- if (now < ep->timeOfLastPing + ic->pingAfterMilliseconds) {
- // Possibly an out-of-date node which is mangling packets, don't ping too often
- // because it causes the RumorMill to be filled with this node over and over.
- continue;
- }
- struct Node_Link* link = Router_linkForPath(ic->router, ep->switchLabel);
- // It exists, it's parent is the self-node, and it's label is equal to the switchLabel.
- if (link
- && Node_getBestParent(link->child)
- && Node_getBestParent(link->child)->parent->address.path == 1
- && Node_getBestParent(link->child)->cannonicalLabel == ep->switchLabel)
- {
- continue;
- }
- }
- #ifdef Log_DEBUG
- uint8_t key[56];
- Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
- #endif
- if (ep->isIncomingConnection
- && now > ep->timeOfLastMessage + ic->forgetAfterMilliseconds)
- {
- Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] "
- "seconds, dropping connection",
- key, ic->forgetAfterMilliseconds / 1024);
- Allocator_free(ep->external->allocator);
- continue;
- }
- bool unresponsive = (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds);
- if (unresponsive) {
- // our link to the peer is broken...
- Router_disconnectedPeer(ic->router, ep->switchLabel);
- // Lets skip 87% of pings when they're really down.
- if (ep->pingCount % 8) {
- ep->pingCount++;
- continue;
- }
- ep->state = InterfaceController_PeerState_UNRESPONSIVE;
- }
- #ifdef Log_DEBUG
- uint32_t lag = (now - ep->timeOfLastMessage) / 1024;
- Log_debug(ic->logger,
- "Pinging %s peer [%s.k] lag [%u]",
- (unresponsive ? "unresponsive" : "lazy"), key, lag);
- #endif
- sendPing(ep);
- // we only ping one node
- return;
- }
- }
- /** If there's already an endpoint with the same public key, merge the new one with the old one. */
- static void moveEndpointIfNeeded(struct InterfaceController_Peer* ep,
- struct InterfaceController_pvt* ic)
- {
- Log_debug(ic->logger, "Checking for old sessions to merge with.");
- uint8_t* key = CryptoAuth_getHerPublicKey(ep->cryptoAuthIf);
- for (uint32_t i = 0; i < ic->peerMap.count; i++) {
- struct InterfaceController_Peer* thisEp = ic->peerMap.values[i];
- uint8_t* thisKey = CryptoAuth_getHerPublicKey(thisEp->cryptoAuthIf);
- if (thisEp != ep && !Bits_memcmp(thisKey, key, 32)) {
- Log_info(ic->logger, "Moving endpoint to merge new session with old.");
- // flush out the new entry if needed.
- Router_disconnectedPeer(ic->router, ep->switchLabel);
- ep->switchLabel = thisEp->switchLabel;
- SwitchCore_swapInterfaces(&thisEp->switchIf, &ep->switchIf);
- Allocator_free(thisEp->external->allocator);
- return;
- }
- }
- }
- // Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch.
- static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cryptoAuthIf)
- {
- struct InterfaceController_Peer* ep =
- Identity_check((struct InterfaceController_Peer*) cryptoAuthIf->receiverContext);
- struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);
- // nonce added by the CryptoAuth session.
- Message_pop(msg, NULL, 4, NULL);
- ep->bytesIn += msg->length;
- int caState = CryptoAuth_getState(cryptoAuthIf);
- if (ep->state < InterfaceController_PeerState_ESTABLISHED) {
- // EP states track CryptoAuth states...
- ep->state = caState;
- if (caState == CryptoAuth_ESTABLISHED) {
- moveEndpointIfNeeded(ep, ic);
- } 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
- // directs it to *this* router.
- if (msg->length < 8 || msg->bytes[7] != 1) {
- Log_info(ic->logger, "DROP message because CA is not established.");
- return Error_NONE;
- } else {
- // When a "server" gets a new connection from a "client" the router doesn't
- // know about that client so if the client sends a packet to the server, the
- // server will be unable to handle it until the client has sent inter-router
- // communication to the server. Here we will ping the client so when the
- // server gets the ping response, it will insert the client into its table
- // and know its version.
- // prevent DoS by limiting the number of times this can be called per second
- // limit it to 7, this will affect innocent packets but it doesn't matter much
- // since this is mostly just an optimization and for keeping the tests happy.
- if ((ep->pingCount + 1) % 7) {
- sendPing(ep);
- }
- }
- }
- } else if (ep->state == InterfaceController_PeerState_UNRESPONSIVE
- && caState == CryptoAuth_ESTABLISHED)
- {
- ep->state = InterfaceController_PeerState_ESTABLISHED;
- } else {
- ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase);
- }
- Identity_check(ep);
- Assert_true(!(msg->capacity % 4));
- return Interface_receiveMessage(&ep->switchIf, msg);
- }
- // This is directly called from SwitchCore, message is not encrypted.
- static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf)
- {
- struct InterfaceController_Peer* ep =
- Identity_check((struct InterfaceController_Peer*) switchIf);
- ep->bytesOut += msg->length;
- struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep);
- uint8_t ret;
- uint64_t now = Time_currentTimeMilliseconds(ic->eventBase);
- if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) {
- // TODO(cjd): This is a hack because if the time of last message exceeds the
- // unresponsive time, we need to send back an error and that means
- // mangling the message which would otherwise be in the queue.
- struct Allocator* tempAlloc = Allocator_child(ic->allocator);
- struct Message* toSend = Message_clone(msg, tempAlloc);
- ret = Interface_sendMessage(ep->cryptoAuthIf, toSend);
- Allocator_free(tempAlloc);
- } else {
- ret = Interface_sendMessage(ep->cryptoAuthIf, msg);
- }
- // TODO(cjd): this is not quite right
- // We don't always trust the UDP interface to be accurate
- // short spurious failures and packet-backup should not cause us to treat a link as dead
- if (ret == Error_UNDELIVERABLE) {
- ret = 0;
- }
- // If this node is unresponsive then return an error.
- if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) {
- return ret ? ret : Error_UNDELIVERABLE;
- } else {
- /* Way way way too much noise
- Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.",
- (now - ep->timeOfLastMessage));
- */
- }
- return Error_NONE;
- }
- static int closeInterface(struct Allocator_OnFreeJob* job)
- {
- struct InterfaceController_Peer* toClose =
- Identity_check((struct InterfaceController_Peer*) job->userData);
- struct InterfaceController_pvt* ic = ifcontrollerForPeer(toClose);
- // flush the peer from the table...
- Router_disconnectedPeer(ic->router, toClose->switchLabel);
- int index = Map_OfIFCPeerByExernalIf_indexForHandle(toClose->handle, &ic->peerMap);
- Assert_true(index >= 0);
- Map_OfIFCPeerByExernalIf_remove(index, &ic->peerMap);
- return 0;
- }
- int InterfaceController_registerPeer(struct InterfaceController* ifController,
- uint8_t herPublicKey[32],
- String* password,
- bool requireAuth,
- bool isIncomingConnection,
- struct Interface* externalInterface)
- {
- // This function is overridden by some tests...
- if (ifController->registerPeer) {
- return ifController->registerPeer(ifController, herPublicKey, password, requireAuth,
- isIncomingConnection, externalInterface);
- }
- struct InterfaceController_pvt* ic =
- Identity_check((struct InterfaceController_pvt*) ifController);
- if (Map_OfIFCPeerByExernalIf_indexForKey(&externalInterface, &ic->peerMap) > -1) {
- return 0;
- }
- Log_debug(ic->logger, "registerPeer [%p] total [%u]",
- (void*)externalInterface, ic->peerMap.count);
- uint8_t ip6[16];
- if (herPublicKey) {
- AddressCalc_addressForPublicKey(ip6, herPublicKey);
- if (!AddressCalc_validAddress(ip6)) {
- return InterfaceController_registerPeer_BAD_KEY;
- }
- if (!Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) {
- // can't link with yourself, wiseguy
- return InterfaceController_registerPeer_BAD_KEY;
- }
- } else {
- Assert_true(requireAuth);
- }
- struct Allocator* epAllocator = externalInterface->allocator;
- struct InterfaceController_Peer* ep =
- Allocator_calloc(epAllocator, sizeof(struct InterfaceController_Peer), 1);
- ep->bytesOut = 0;
- ep->bytesIn = 0;
- ep->external = externalInterface;
- int setIndex = Map_OfIFCPeerByExernalIf_put(&externalInterface, &ep, &ic->peerMap);
- ep->handle = ic->peerMap.handles[setIndex];
- Identity_set(ep);
- Allocator_onFree(epAllocator, closeInterface, ep);
- // If the other end need needs to supply a valid password to connect
- // we will set the connection state to UNAUTHENTICATED so that if the
- // packet is invalid, the connection will be dropped right away.
- if (requireAuth) {
- ep->state = InterfaceController_PeerState_UNAUTHENTICATED;
- }
- ep->cryptoAuthIf = CryptoAuth_wrapInterface(externalInterface,
- herPublicKey,
- NULL,
- requireAuth,
- "outer",
- ic->ca);
- ep->cryptoAuthIf->receiveMessage = receivedAfterCryptoAuth;
- ep->cryptoAuthIf->receiverContext = ep;
- // Always use authType 1 until something else comes along, then we'll have to refactor.
- if (password) {
- CryptoAuth_setAuth(password, 1, ep->cryptoAuthIf);
- }
- ep->isIncomingConnection = isIncomingConnection;
- Bits_memcpyConst(&ep->switchIf, (&(struct Interface) {
- .sendMessage = sendFromSwitch,
- // ifcontrollerForPeer uses this.
- // sendFromSwitch relies on the fact that the
- // switchIf is the same memory location as the Peer.
- .senderContext = ic,
- .allocator = epAllocator
- }), sizeof(struct Interface));
- int ret = SwitchCore_addInterface(&ep->switchIf, 0, &ep->switchLabel, ic->switchCore);
- if (ret) {
- return (ret == SwitchCore_addInterface_OUT_OF_SPACE)
- ? InterfaceController_registerPeer_OUT_OF_SPACE
- : InterfaceController_registerPeer_INTERNAL;
- }
- // We want the node to immedietly be pinged but we don't want it to appear unresponsive because
- // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to
- // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node".
- ep->timeOfLastMessage =
- Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1;
- if (herPublicKey) {
- #ifdef Log_INFO
- uint8_t printAddr[60];
- AddrTools_printIp(printAddr, ip6);
- Log_info(ic->logger, "Adding peer [%s]", printAddr);
- #endif
- } else {
- Log_info(ic->logger, "Adding peer with unknown key");
- }
- // We can't just add the node directly to the routing table because we do not know
- // the version. We'll send it a switch ping and when it responds, we will know it's
- // key (if we don't already) and version number.
- sendPing(ep);
- return 0;
- }
- struct InterfaceController_Peer* InterfaceController_getPeer(struct InterfaceController* ifc,
- struct Interface* iface)
- {
- if (ifc->getPeer) { return ifc->getPeer(ifc, iface); }
- struct Interface* cryptoAuthIf = CryptoAuth_getConnectedInterface(iface);
- return Identity_check((struct InterfaceController_Peer*) cryptoAuthIf->receiverContext);
- }
- void InterfaceController_populateBeacon(struct InterfaceController* ifc,
- struct Headers_Beacon* beacon)
- {
- struct InterfaceController_pvt* ic = Identity_check((struct InterfaceController_pvt*) ifc);
- beacon->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
- Bits_memcpyConst(beacon->password, ic->beaconPassword, Headers_Beacon_PASSWORD_LEN);
- Bits_memcpyConst(beacon->publicKey, ic->ca->publicKey, 32);
- }
- int InterfaceController_getPeerStats(struct InterfaceController* ifController,
- struct Allocator* alloc,
- struct InterfaceController_peerStats** statsOut)
- {
- struct InterfaceController_pvt* ic =
- Identity_check((struct InterfaceController_pvt*) ifController);
- int count = ic->peerMap.count;
- struct InterfaceController_peerStats* stats =
- Allocator_malloc(alloc, sizeof(struct InterfaceController_peerStats)*count);
- for (int i = 0; i < count; i++) {
- struct InterfaceController_Peer* peer = ic->peerMap.values[i];
- struct InterfaceController_peerStats* s = &stats[i];
- s->pubKey = CryptoAuth_getHerPublicKey(peer->cryptoAuthIf);
- s->bytesOut = peer->bytesOut;
- s->bytesIn = peer->bytesIn;
- s->timeOfLastMessage = peer->timeOfLastMessage;
- s->state = peer->state;
- s->switchLabel = peer->switchLabel;
- s->isIncomingConnection = peer->isIncomingConnection;
- s->user = NULL;
- if (s->isIncomingConnection) {
- s->user = CryptoAuth_getUser(peer->cryptoAuthIf);
- }
- struct ReplayProtector* rp = CryptoAuth_getReplayProtector(peer->cryptoAuthIf);
- s->duplicates = rp->duplicates;
- s->lostPackets = rp->lostPackets;
- s->receivedOutOfRange = rp->receivedOutOfRange;
- }
- *statsOut = stats;
- return count;
- }
- int InterfaceController_disconnectPeer(struct InterfaceController* ifController,
- uint8_t herPublicKey[32])
- {
- struct InterfaceController_pvt* ic =
- Identity_check((struct InterfaceController_pvt*) ifController);
- for (uint32_t i = 0; i < ic->peerMap.count; i++) {
- struct InterfaceController_Peer* peer = ic->peerMap.values[i];
- if (!Bits_memcmp(herPublicKey, CryptoAuth_getHerPublicKey(peer->cryptoAuthIf), 32)) {
- Allocator_free(peer->external->allocator);
- return 0;
- }
- }
- return InterfaceController_disconnectPeer_NOTFOUND;
- }
- 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 InterfaceController_pvt* out =
- Allocator_malloc(allocator, sizeof(struct InterfaceController_pvt));
- Bits_memcpyConst(out, (&(struct InterfaceController_pvt) {
- .peerMap = {
- .allocator = allocator
- },
- .allocator = allocator,
- .ca = ca,
- .rand = rand,
- .switchCore = switchCore,
- .router = router,
- .rumorMill = rumorMill,
- .logger = logger,
- .eventBase = eventBase,
- .switchPinger = switchPinger,
- .unresponsiveAfterMilliseconds = UNRESPONSIVE_AFTER_MILLISECONDS,
- .pingAfterMilliseconds = PING_AFTER_MILLISECONDS,
- .timeoutMilliseconds = TIMEOUT_MILLISECONDS,
- .forgetAfterMilliseconds = FORGET_AFTER_MILLISECONDS,
- .pingInterval = (switchPinger)
- ? Timeout_setInterval(pingCallback,
- out,
- PING_INTERVAL_MILLISECONDS,
- eventBase,
- allocator)
- : NULL
- }), sizeof(struct InterfaceController_pvt));
- Identity_set(out);
- // Add the beaconing password.
- Random_bytes(rand, out->beaconPassword, Headers_Beacon_PASSWORD_LEN);
- String strPass = { .bytes=(char*)out->beaconPassword, .len=Headers_Beacon_PASSWORD_LEN };
- int ret = CryptoAuth_addUser(&strPass, 1, String_CONST("Local Peers"), ca);
- if (ret) {
- Log_warn(logger, "CryptoAuth_addUser() returned [%d]", ret);
- }
- return &out->pub;
- }
|