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));
static int registerPeer(struct InterfaceController* ifController, uint8_t herPublicKey[32], String* password, bool requireAuth, bool transient, struct Interface* externalInterface) { struct Context* ic = Identity_cast((struct Context*) ifController); Log_debug(ic->logger, "registerPeer [%p] total [%u]", (void*)externalInterface, ic->peerMap.count); if (Map_OfIFCPeerByExernalIf_indexForKey(&externalInterface, &ic->peerMap) > -1) { Log_debug(ic->logger, "Skipping registerPeer [%p] because peer is already registered", (void*)externalInterface); return 0; } uint8_t ip6[16]; if (herPublicKey) { AddressCalc_addressForPublicKey(ip6, herPublicKey); if (!AddressCalc_validAddress(ip6)) { return InterfaceController_registerPeer_BAD_KEY; } } struct Allocator* epAllocator = externalInterface->allocator; struct IFCPeer* ep = Allocator_calloc(epAllocator, sizeof(struct IFCPeer), 1); 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 not supply a valid password to connect // we will set the connection state to HANDSHAKE because we don't // want the connection to be trashed after the first invalid packet. if (!requireAuth) { ep->state = InterfaceController_PeerState_HANDSHAKE; } ep->cryptoAuthIf = CryptoAuth_wrapInterface(externalInterface, herPublicKey, requireAuth, true, 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->transient = transient; 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));