1
0

DefaultInterfaceController.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "crypto/AddressCalc.h"
  16. #include "crypto/CryptoAuth_pvt.h"
  17. #include "net/DefaultInterfaceController.h"
  18. #include "dht/dhtcore/RumorMill.h"
  19. #include "memory/Allocator.h"
  20. #include "net/SwitchPinger.h"
  21. #include "util/Base32.h"
  22. #include "util/Bits.h"
  23. #include "util/events/Time.h"
  24. #include "util/events/Timeout.h"
  25. #include "util/Identity.h"
  26. #include "util/version/Version.h"
  27. #include "util/AddrTools.h"
  28. #include "wire/Error.h"
  29. #include "wire/Message.h"
  30. #include <stddef.h> // offsetof
  31. /** After this number of milliseconds, a node will be regarded as unresponsive. */
  32. #define UNRESPONSIVE_AFTER_MILLISECONDS (20*1024)
  33. /**
  34. * After this number of milliseconds without a valid incoming message,
  35. * a peer is "lazy" and should be pinged.
  36. */
  37. #define PING_AFTER_MILLISECONDS (3*1024)
  38. /** How often to ping "lazy" peers, "unresponsive" peers are only pinged 20% of the time. */
  39. #define PING_INTERVAL_MILLISECONDS 1024
  40. /** The number of milliseconds to wait for a ping response. */
  41. #define TIMEOUT_MILLISECONDS (2*1024)
  42. /**
  43. * The number of seconds to wait before an unresponsive peer
  44. * making an incoming connection is forgotten.
  45. */
  46. #define FORGET_AFTER_MILLISECONDS (256*1024)
  47. /*--------------------Structs--------------------*/
  48. struct IFCPeer
  49. {
  50. /** The interface which is registered with the switch. */
  51. struct Interface switchIf;
  52. /** The internal (wrapped by CryptoAuth) interface. */
  53. struct Interface* cryptoAuthIf;
  54. /** The external (network side) interface. */
  55. struct Interface* external;
  56. /** The label for this endpoint, needed to ping the endpoint. */
  57. uint64_t switchLabel;
  58. /** Milliseconds since the epoch when the last *valid* message was received. */
  59. uint64_t timeOfLastMessage;
  60. /** Time when the last switch ping response was received from this node. */
  61. uint64_t timeOfLastPing;
  62. /** The handle which can be used to look up this endpoint in the endpoint set. */
  63. uint32_t handle;
  64. /** True if we should forget about the peer if they do not respond. */
  65. bool isIncomingConnection : 1;
  66. /**
  67. * If InterfaceController_PeerState_UNAUTHENTICATED, no permanent state will be kept.
  68. * During transition from HANDSHAKE to ESTABLISHED, a check is done for a registeration of a
  69. * node which is already registered in a different switch slot, if there is one and the
  70. * handshake completes, it will be moved.
  71. */
  72. int state : 31;
  73. // traffic counters
  74. uint64_t bytesOut;
  75. uint64_t bytesIn;
  76. Identity
  77. };
  78. #define Map_NAME OfIFCPeerByExernalIf
  79. #define Map_ENABLE_HANDLES
  80. #define Map_KEY_TYPE struct Interface*
  81. #define Map_VALUE_TYPE struct IFCPeer*
  82. #include "util/Map.h"
  83. struct Context
  84. {
  85. /** Public functions and fields for this ifcontroller. */
  86. struct InterfaceController pub;
  87. /** Used to get a peer by its handle. */
  88. struct Map_OfIFCPeerByExernalIf peerMap;
  89. struct Allocator* const allocator;
  90. struct CryptoAuth* const ca;
  91. /** Switch for adding nodes when they are discovered. */
  92. struct SwitchCore* const switchCore;
  93. /** Router needed to inject newly added nodes to bootstrap the system. */
  94. struct RouterModule* const routerModule;
  95. struct RumorMill* const rumorMill;
  96. struct Log* const logger;
  97. struct EventBase* const eventBase;
  98. /** After this number of milliseconds, a neoghbor will be regarded as unresponsive. */
  99. uint32_t unresponsiveAfterMilliseconds;
  100. /** The number of milliseconds to wait before pinging. */
  101. uint32_t pingAfterMilliseconds;
  102. /** The number of milliseconds to let a ping go before timing it out. */
  103. uint32_t timeoutMilliseconds;
  104. /** After this number of milliseconds, an incoming connection is forgotten entirely. */
  105. uint32_t forgetAfterMilliseconds;
  106. /** A counter to allow for 3/4 of all pings to be skipped when a node is definitely down. */
  107. uint32_t pingCount;
  108. /** The timeout event to use for pinging potentially unresponsive neighbors. */
  109. struct Timeout* const pingInterval;
  110. /** For pinging lazy/unresponsive nodes. */
  111. struct SwitchPinger* const switchPinger;
  112. /** A password which is generated per-startup and sent out in beacon messages. */
  113. uint8_t beaconPassword[Headers_Beacon_PASSWORD_LEN];
  114. Identity
  115. };
  116. //---------------//
  117. static inline struct Context* ifcontrollerForPeer(struct IFCPeer* ep)
  118. {
  119. return Identity_check((struct Context*) ep->switchIf.senderContext);
  120. }
  121. static void onPingResponse(enum SwitchPinger_Result result,
  122. uint64_t label,
  123. String* data,
  124. uint32_t millisecondsLag,
  125. uint32_t version,
  126. void* onResponseContext)
  127. {
  128. if (SwitchPinger_Result_OK != result) {
  129. return;
  130. }
  131. struct IFCPeer* ep = Identity_check((struct IFCPeer*) onResponseContext);
  132. struct Context* ic = ifcontrollerForPeer(ep);
  133. struct Address addr;
  134. Bits_memset(&addr, 0, sizeof(struct Address));
  135. Bits_memcpyConst(addr.key, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
  136. addr.path = ep->switchLabel;
  137. addr.protocolVersion = version;
  138. ep->timeOfLastPing = Time_currentTimeMilliseconds(ic->eventBase);
  139. #ifdef Log_DEBUG
  140. uint8_t addrStr[60];
  141. Address_print(addrStr, &addr);
  142. #endif
  143. if (!Version_isCompatible(Version_CURRENT_PROTOCOL, version)) {
  144. Log_debug(ic->logger, "got switch pong from node [%s] with incompatible version [%d]",
  145. addrStr, version);
  146. } else {
  147. Log_debug(ic->logger, "got switch pong from node with version [%d]", version);
  148. }
  149. struct Node_Two* nn = RouterModule_nodeForPath(label, ic->routerModule);
  150. if (!nn) {
  151. RumorMill_addNode(ic->rumorMill, &addr);
  152. } else if (!Node_getBestParent(nn)) {
  153. RouterModule_peerIsReachable(label, millisecondsLag, ic->routerModule);
  154. }
  155. #ifdef Log_DEBUG
  156. // This will be false if it times out.
  157. //Assert_true(label == ep->switchLabel);
  158. uint8_t path[20];
  159. AddrTools_printPath(path, label);
  160. uint8_t sl[20];
  161. AddrTools_printPath(sl, ep->switchLabel);
  162. Log_debug(ic->logger, "Received [%s] from lazy endpoint [%s] [%s]",
  163. SwitchPinger_resultString(result)->bytes, path, sl);
  164. #endif
  165. }
  166. // Called from the pingInteral timeout.
  167. static void pingCallback(void* vic)
  168. {
  169. struct Context* ic = Identity_check((struct Context*) vic);
  170. uint64_t now = Time_currentTimeMilliseconds(ic->eventBase);
  171. ic->pingCount++;
  172. // scan for endpoints have not sent anything recently.
  173. for (uint32_t i = 0; i < ic->peerMap.count; i++) {
  174. struct IFCPeer* ep = ic->peerMap.values[i];
  175. if (now < ep->timeOfLastMessage + ic->pingAfterMilliseconds) {
  176. if (now < ep->timeOfLastPing + ic->pingAfterMilliseconds) {
  177. // Possibly an out-of-date node which is mangling packets, don't ping too often
  178. // because it causes the RumorMill to be filled with this node over and over.
  179. continue;
  180. }
  181. // This is here because of a pathological state where the connection is in ESTABLISHED
  182. // state but the *direct peer* has somehow been dropped from the routing table
  183. // usually because of a call to NodeStore_brokenPath()
  184. struct Node_Two* peerNode = RouterModule_nodeForPath(ep->switchLabel, ic->routerModule);
  185. if (peerNode && Node_getBestParent(peerNode)) {
  186. continue;
  187. }
  188. }
  189. #ifdef Log_DEBUG
  190. uint8_t key[56];
  191. Base32_encode(key, 56, CryptoAuth_getHerPublicKey(ep->cryptoAuthIf), 32);
  192. #endif
  193. if (ep->isIncomingConnection
  194. && now > ep->timeOfLastMessage + ic->forgetAfterMilliseconds)
  195. {
  196. Log_debug(ic->logger, "Unresponsive peer [%s.k] has not responded in [%u] "
  197. "seconds, dropping connection",
  198. key, ic->forgetAfterMilliseconds / 1024);
  199. Allocator_free(ep->external->allocator);
  200. return;
  201. }
  202. bool unresponsive = (now > ep->timeOfLastMessage + ic->unresponsiveAfterMilliseconds);
  203. if (unresponsive) {
  204. // flush the peer from the table...
  205. RouterModule_brokenPath(ep->switchLabel, ic->routerModule);
  206. // Lets skip 87% of pings when they're really down.
  207. if (ic->pingCount % 8) {
  208. continue;
  209. }
  210. ep->state = InterfaceController_PeerState_UNRESPONSIVE;
  211. }
  212. struct SwitchPinger_Ping* ping =
  213. SwitchPinger_newPing(ep->switchLabel,
  214. String_CONST(""),
  215. ic->timeoutMilliseconds,
  216. onPingResponse,
  217. ic->allocator,
  218. ic->switchPinger);
  219. #ifdef Log_DEBUG
  220. uint32_t lag = (now - ep->timeOfLastMessage) / 1024;
  221. #endif
  222. if (!ping) {
  223. Log_debug(ic->logger,
  224. "Failed to ping %s peer [%s.k] lag [%u], out of ping slots.",
  225. (unresponsive ? "unresponsive" : "lazy"), key, lag);
  226. return;
  227. }
  228. ping->onResponseContext = ep;
  229. Log_debug(ic->logger,
  230. "Pinging %s peer [%s.k] lag [%u]",
  231. (unresponsive ? "unresponsive" : "lazy"), key, lag);
  232. }
  233. }
  234. /** If there's already an endpoint with the same public key, merge the new one with the old one. */
  235. static void moveEndpointIfNeeded(struct IFCPeer* ep, struct Context* ic)
  236. {
  237. Log_debug(ic->logger, "Checking for old sessions to merge with.");
  238. uint8_t* key = CryptoAuth_getHerPublicKey(ep->cryptoAuthIf);
  239. for (uint32_t i = 0; i < ic->peerMap.count; i++) {
  240. struct IFCPeer* thisEp = ic->peerMap.values[i];
  241. uint8_t* thisKey = CryptoAuth_getHerPublicKey(thisEp->cryptoAuthIf);
  242. if (thisEp != ep && !Bits_memcmp(thisKey, key, 32)) {
  243. Log_info(ic->logger, "Moving endpoint to merge new session with old.");
  244. ep->switchLabel = thisEp->switchLabel;
  245. SwitchCore_swapInterfaces(&thisEp->switchIf, &ep->switchIf);
  246. Allocator_free(thisEp->external->allocator);
  247. return;
  248. }
  249. }
  250. }
  251. // Incoming message which has passed through the cryptoauth and needs to be forwarded to the switch.
  252. static uint8_t receivedAfterCryptoAuth(struct Message* msg, struct Interface* cryptoAuthIf)
  253. {
  254. struct IFCPeer* ep = Identity_check((struct IFCPeer*) cryptoAuthIf->receiverContext);
  255. struct Context* ic = ifcontrollerForPeer(ep);
  256. ep->bytesIn += msg->length;
  257. if (ep->state < InterfaceController_PeerState_ESTABLISHED) {
  258. if (CryptoAuth_getState(cryptoAuthIf) >= CryptoAuth_HANDSHAKE3) {
  259. moveEndpointIfNeeded(ep, ic);
  260. ep->state = InterfaceController_PeerState_ESTABLISHED;
  261. } else {
  262. ep->state = InterfaceController_PeerState_HANDSHAKE;
  263. // prevent some kinds of nasty things which could be done with packet replay.
  264. // This is checking the message switch header and will drop it unless the label
  265. // directs it to *this* router.
  266. if (msg->length < 8 || msg->bytes[7] != 1) {
  267. Log_info(ic->logger, "DROP message because CA is not established.");
  268. return Error_NONE;
  269. } else {
  270. // When a "server" gets a new connection from a "client" the router doesn't
  271. // know about that client so if the client sends a packet to the server, the
  272. // server will be unable to handle it until the client has sent inter-router
  273. // communication to the server. Here we will ping the client so when the
  274. // server gets the ping response, it will insert the client into its table
  275. // and know its version.
  276. // prevent DoS by limiting the number of times this can be called per second
  277. // limit it to 7, this will affect innocent packets but it doesn't matter much
  278. // since this is mostly just an optimization and for keeping the tests happy.
  279. if ((ic->pingCount + 1) % 7) {
  280. pingCallback(ic);
  281. }
  282. }
  283. }
  284. } else if (ep->state == InterfaceController_PeerState_UNRESPONSIVE
  285. && CryptoAuth_getState(cryptoAuthIf) >= CryptoAuth_HANDSHAKE3)
  286. {
  287. ep->state = InterfaceController_PeerState_ESTABLISHED;
  288. } else {
  289. ep->timeOfLastMessage = Time_currentTimeMilliseconds(ic->eventBase);
  290. }
  291. return ep->switchIf.receiveMessage(msg, &ep->switchIf);
  292. }
  293. // This is directly called from SwitchCore, message is not encrypted.
  294. static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf)
  295. {
  296. struct IFCPeer* ep = Identity_check((struct IFCPeer*) switchIf);
  297. ep->bytesOut += msg->length;
  298. struct Context* ic = ifcontrollerForPeer(ep);
  299. uint8_t ret;
  300. uint64_t now = Time_currentTimeMilliseconds(ic->eventBase);
  301. if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) {
  302. // TODO(cjd): This is a hack because if the time of last message exceeds the
  303. // unresponsive time, we need to send back an error and that means
  304. // mangling the message which would otherwise be in the queue.
  305. struct Allocator* tempAlloc = Allocator_child(ic->allocator);
  306. struct Message* toSend = Message_clone(msg, tempAlloc);
  307. ret = Interface_sendMessage(ep->cryptoAuthIf, toSend);
  308. Allocator_free(tempAlloc);
  309. } else {
  310. ret = Interface_sendMessage(ep->cryptoAuthIf, msg);
  311. }
  312. // If this node is unresponsive then return an error.
  313. if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) {
  314. return ret ? ret : Error_UNDELIVERABLE;
  315. } else {
  316. /* Way way way too much noise
  317. Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.",
  318. (now - ep->timeOfLastMessage));
  319. */
  320. }
  321. return Error_NONE;
  322. }
  323. static int closeInterface(struct Allocator_OnFreeJob* job)
  324. {
  325. struct IFCPeer* toClose = Identity_check((struct IFCPeer*) job->userData);
  326. struct Context* ic = ifcontrollerForPeer(toClose);
  327. // flush the peer from the table...
  328. RouterModule_brokenPath(toClose->switchLabel, ic->routerModule);
  329. int index = Map_OfIFCPeerByExernalIf_indexForHandle(toClose->handle, &ic->peerMap);
  330. Assert_true(index >= 0);
  331. Map_OfIFCPeerByExernalIf_remove(index, &ic->peerMap);
  332. return 0;
  333. }
  334. static int registerPeer(struct InterfaceController* ifController,
  335. uint8_t herPublicKey[32],
  336. String* password,
  337. bool requireAuth,
  338. bool isIncomingConnection,
  339. struct Interface* externalInterface)
  340. {
  341. struct Context* ic = Identity_check((struct Context*) ifController);
  342. if (Map_OfIFCPeerByExernalIf_indexForKey(&externalInterface, &ic->peerMap) > -1) {
  343. return 0;
  344. }
  345. Log_debug(ic->logger, "registerPeer [%p] total [%u]",
  346. (void*)externalInterface, ic->peerMap.count);
  347. uint8_t ip6[16];
  348. if (herPublicKey) {
  349. AddressCalc_addressForPublicKey(ip6, herPublicKey);
  350. if (!AddressCalc_validAddress(ip6)) {
  351. return InterfaceController_registerPeer_BAD_KEY;
  352. }
  353. if (!Bits_memcmp(ic->ca->publicKey, herPublicKey, 32)) {
  354. // can't link with yourself, wiseguy
  355. return InterfaceController_registerPeer_BAD_KEY;
  356. }
  357. } else {
  358. Assert_true(requireAuth);
  359. }
  360. struct Allocator* epAllocator = externalInterface->allocator;
  361. struct IFCPeer* ep = Allocator_calloc(epAllocator, sizeof(struct IFCPeer), 1);
  362. ep->bytesOut = 0;
  363. ep->bytesIn = 0;
  364. ep->external = externalInterface;
  365. int setIndex = Map_OfIFCPeerByExernalIf_put(&externalInterface, &ep, &ic->peerMap);
  366. ep->handle = ic->peerMap.handles[setIndex];
  367. Identity_set(ep);
  368. Allocator_onFree(epAllocator, closeInterface, ep);
  369. // If the other end need not supply a valid password to connect
  370. // we will set the connection state to HANDSHAKE because we don't
  371. // want the connection to be trashed after the first invalid packet.
  372. if (!requireAuth) {
  373. ep->state = InterfaceController_PeerState_HANDSHAKE;
  374. }
  375. ep->cryptoAuthIf = CryptoAuth_wrapInterface(externalInterface,
  376. herPublicKey,
  377. NULL,
  378. requireAuth,
  379. "outer",
  380. ic->ca);
  381. ep->cryptoAuthIf->receiveMessage = receivedAfterCryptoAuth;
  382. ep->cryptoAuthIf->receiverContext = ep;
  383. // Always use authType 1 until something else comes along, then we'll have to refactor.
  384. if (password) {
  385. CryptoAuth_setAuth(password, 1, ep->cryptoAuthIf);
  386. }
  387. ep->isIncomingConnection = isIncomingConnection;
  388. Bits_memcpyConst(&ep->switchIf, (&(struct Interface) {
  389. .sendMessage = sendFromSwitch,
  390. // ifcontrollerForPeer uses this.
  391. // sendFromSwitch relies on the fact that the
  392. // switchIf is the same memory location as the Peer.
  393. .senderContext = ic,
  394. .allocator = epAllocator
  395. }), sizeof(struct Interface));
  396. int ret = SwitchCore_addInterface(&ep->switchIf, 0, &ep->switchLabel, ic->switchCore);
  397. if (ret) {
  398. return (ret == SwitchCore_addInterface_OUT_OF_SPACE)
  399. ? InterfaceController_registerPeer_OUT_OF_SPACE
  400. : InterfaceController_registerPeer_INTERNAL;
  401. }
  402. // We want the node to immedietly be pinged but we don't want it to appear unresponsive because
  403. // the pinger will only ping every (PING_INTERVAL * 8) so we set timeOfLastMessage to
  404. // (now - pingAfterMilliseconds - 1) so it will be considered a "lazy node".
  405. ep->timeOfLastMessage =
  406. Time_currentTimeMilliseconds(ic->eventBase) - ic->pingAfterMilliseconds - 1;
  407. if (herPublicKey) {
  408. #ifdef Log_INFO
  409. uint8_t printAddr[60];
  410. AddrTools_printIp(printAddr, ip6);
  411. Log_info(ic->logger, "Adding peer [%s]", printAddr);
  412. #endif
  413. // Kick the ping callback so that the node will be pinged ASAP.
  414. pingCallback(ic);
  415. }
  416. return 0;
  417. }
  418. static enum InterfaceController_PeerState getPeerState(struct Interface* iface)
  419. {
  420. struct Interface* cryptoAuthIf = CryptoAuth_getConnectedInterface(iface);
  421. struct IFCPeer* p = Identity_check((struct IFCPeer*) cryptoAuthIf->receiverContext);
  422. return p->state;
  423. }
  424. static void populateBeacon(struct InterfaceController* ifc, struct Headers_Beacon* beacon)
  425. {
  426. struct Context* ic = Identity_check((struct Context*) ifc);
  427. beacon->version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL);
  428. Bits_memcpyConst(beacon->password, ic->beaconPassword, Headers_Beacon_PASSWORD_LEN);
  429. Bits_memcpyConst(beacon->publicKey, ic->ca->publicKey, 32);
  430. }
  431. static int getPeerStats(struct InterfaceController* ifController,
  432. struct Allocator* alloc,
  433. struct InterfaceController_peerStats** statsOut)
  434. {
  435. struct Context* ic = Identity_check((struct Context*) ifController);
  436. int count = ic->peerMap.count;
  437. struct InterfaceController_peerStats* stats =
  438. Allocator_malloc(alloc, sizeof(struct InterfaceController_peerStats)*count);
  439. for (int i = 0; i < count; i++) {
  440. struct IFCPeer* peer = ic->peerMap.values[i];
  441. struct InterfaceController_peerStats* s = &stats[i];
  442. s->pubKey = CryptoAuth_getHerPublicKey(peer->cryptoAuthIf);
  443. s->bytesOut = peer->bytesOut;
  444. s->bytesIn = peer->bytesIn;
  445. s->timeOfLastMessage = peer->timeOfLastMessage;
  446. s->state = peer->state;
  447. s->switchLabel = peer->switchLabel;
  448. s->isIncomingConnection = peer->isIncomingConnection;
  449. s->user = NULL;
  450. if (s->isIncomingConnection) {
  451. s->user = CryptoAuth_getUser(peer->cryptoAuthIf);
  452. }
  453. struct ReplayProtector* rp = CryptoAuth_getReplayProtector(peer->cryptoAuthIf);
  454. s->duplicates = rp->duplicates;
  455. s->lostPackets = rp->lostPackets;
  456. s->receivedOutOfRange = rp->receivedOutOfRange;
  457. }
  458. *statsOut = stats;
  459. return count;
  460. }
  461. static int disconnectPeer(struct InterfaceController* ifController, uint8_t herPublicKey[32])
  462. {
  463. struct Context* ic = Identity_check((struct Context*) ifController);
  464. for (uint32_t i = 0; i < ic->peerMap.count; i++) {
  465. struct IFCPeer* peer = ic->peerMap.values[i];
  466. if (!Bits_memcmp(herPublicKey, CryptoAuth_getHerPublicKey(peer->cryptoAuthIf), 32)) {
  467. Allocator_free(peer->external->allocator);
  468. return 0;
  469. }
  470. }
  471. return InterfaceController_disconnectPeer_NOTFOUND;
  472. }
  473. struct InterfaceController* DefaultInterfaceController_new(struct CryptoAuth* ca,
  474. struct SwitchCore* switchCore,
  475. struct RouterModule* routerModule,
  476. struct RumorMill* rumorMill,
  477. struct Log* logger,
  478. struct EventBase* eventBase,
  479. struct SwitchPinger* switchPinger,
  480. struct Random* rand,
  481. struct Allocator* allocator)
  482. {
  483. struct Context* out = Allocator_malloc(allocator, sizeof(struct Context));
  484. Bits_memcpyConst(out, (&(struct Context) {
  485. .pub = {
  486. .registerPeer = registerPeer,
  487. .disconnectPeer = disconnectPeer,
  488. .getPeerState = getPeerState,
  489. .populateBeacon = populateBeacon,
  490. .getPeerStats = getPeerStats,
  491. },
  492. .peerMap = {
  493. .allocator = allocator
  494. },
  495. .allocator = allocator,
  496. .ca = ca,
  497. .switchCore = switchCore,
  498. .routerModule = routerModule,
  499. .rumorMill = rumorMill,
  500. .logger = logger,
  501. .eventBase = eventBase,
  502. .switchPinger = switchPinger,
  503. .unresponsiveAfterMilliseconds = UNRESPONSIVE_AFTER_MILLISECONDS,
  504. .pingAfterMilliseconds = PING_AFTER_MILLISECONDS,
  505. .timeoutMilliseconds = TIMEOUT_MILLISECONDS,
  506. .forgetAfterMilliseconds = FORGET_AFTER_MILLISECONDS,
  507. .pingInterval = (switchPinger)
  508. ? Timeout_setInterval(pingCallback,
  509. out,
  510. PING_INTERVAL_MILLISECONDS,
  511. eventBase,
  512. allocator)
  513. : NULL
  514. }), sizeof(struct Context));
  515. Identity_set(out);
  516. // Add the beaconing password.
  517. Random_bytes(rand, out->beaconPassword, Headers_Beacon_PASSWORD_LEN);
  518. String strPass = { .bytes=(char*)out->beaconPassword, .len=Headers_Beacon_PASSWORD_LEN };
  519. int ret = CryptoAuth_addUser(&strPass, 1, String_CONST("Local Peers"), ca);
  520. if (ret) {
  521. Log_warn(logger, "CryptoAuth_addUser() returned [%d]", ret);
  522. }
  523. return &out->pub;
  524. }