InterfaceController.c 25 KB

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