📄 kademliaudplistener.cpp
字号:
ProcessPublishNotesResponse(packetData, lenPacket, ip); break; case KADEMLIA2_PUBLISH_RES: DebugRecv(Kad2PublishRes, ip, port); Process2PublishResponse(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA_FIREWALLED_REQ: DebugRecv(KadFirewalledReq, ip, port); ProcessFirewalledRequest(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA_FIREWALLED2_REQ: DebugRecv(KadFirewalled2Req, ip, port); ProcessFirewalled2Request(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA_FIREWALLED_RES: DebugRecv(KadFirewalledRes, ip, port); ProcessFirewalledResponse(packetData, lenPacket, ip, senderKey); break; case KADEMLIA_FIREWALLED_ACK_RES: DebugRecv(KadFirewalledAck, ip, port); ProcessFirewalledAckResponse(lenPacket); break; case KADEMLIA_FINDBUDDY_REQ: DebugRecv(KadFindBuddyReq, ip, port); ProcessFindBuddyRequest(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA_FINDBUDDY_RES: DebugRecv(KadFindBuddyRes, ip, port); ProcessFindBuddyResponse(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA_CALLBACK_REQ: DebugRecv(KadCallbackReq, ip, port); ProcessCallbackRequest(packetData, lenPacket, ip, port, senderKey); break; case KADEMLIA2_PING: DebugRecv(Kad2Ping, ip, port); Process2Ping(ip, port, senderKey); break; case KADEMLIA2_PONG: DebugRecv(Kad2Pong, ip, port); Process2Pong(packetData, lenPacket, ip); break; case KADEMLIA2_FIREWALLUDP: DebugRecv(Kad2FirewallUDP, ip, port); Process2FirewallUDP(packetData, lenPacket, ip); break; default: { throw wxString::Format(wxT("Unknown opcode %02x on CKademliaUDPListener::ProcessPacket()"), opcode); } }}// Used only for Kad1.0bool CKademliaUDPListener::AddContact(const uint8_t *data, uint32_t lenData, uint32_t ip, uint16_t port, uint16_t tport, const CKadUDPKey& udpKey, bool& ipVerified, bool update, CUInt128* outContactID){ CMemFile bio(data, lenData); CUInt128 id = bio.ReadUInt128(); if (outContactID != NULL) { *outContactID = id; } bio.ReadUInt32(); bio.ReadUInt16(); if (tport) { bio.ReadUInt16(); } else { tport = bio.ReadUInt16(); } bio.ReadUInt8(); //AddDebugLogLineM(false, logKadMain, wxT("Adding a contact with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port)); // Ignore stated ip and port, use the address the packet came from return CKademlia::GetRoutingZone()->Add(id, ip, port, tport, 0, udpKey, ipVerified, update, false, true);}// Used only for Kad2.0bool CKademliaUDPListener::AddContact2(const uint8_t *data, uint32_t lenData, uint32_t ip, uint16_t& port, uint8_t *outVersion, const CKadUDPKey& udpKey, bool& ipVerified, bool update, bool fromHelloReq, bool* outRequestsACK, CUInt128* outContactID){ if (outRequestsACK != 0) { *outRequestsACK = false; } CMemFile bio(data, lenData); CUInt128 id = bio.ReadUInt128(); if (outContactID != NULL) { *outContactID = id; } uint16_t tport = bio.ReadUInt16(); uint8_t version = bio.ReadUInt8(); if (version == 0) { throw wxString::Format(wxT("***NOTE: Received invalid Kademlia2 version (%u) in "), version) + wxString::FromAscii(__FUNCTION__); } if (outVersion != NULL) { *outVersion = version; } bool udpFirewalled = false; bool tcpFirewalled = false; uint8_t tags = bio.ReadUInt8(); while (tags) { CTag *tag = bio.ReadTag(); if (!tag->GetName().Cmp(TAG_SOURCEUPORT)) { if (tag->IsInt() && (uint16_t)tag->GetInt() > 0) { port = tag->GetInt(); } } else if (!tag->GetName().Cmp(TAG_KADMISCOPTIONS)) { if (tag->IsInt() && tag->GetInt() > 0) { udpFirewalled = (tag->GetInt() & 0x01) > 0; tcpFirewalled = (tag->GetInt() & 0x02) > 0; if ((tag->GetInt() & 0x04) > 0) { if (outRequestsACK != NULL) { if (version >= 8) { *outRequestsACK = true; } } else { wxFAIL; } } } } delete tag; --tags; } // check if we are waiting for informations (nodeid) about this client and if so inform the requester for (FetchNodeIDList::iterator it = m_fetchNodeIDRequests.begin(); it != m_fetchNodeIDRequests.end(); ++it) { if (it->ip == ip && it->tcpPort == tport) { //AddDebugLogLineM(false, logKadMain, wxT("Result Addcontact: ") + id.ToHexString()); uint8_t uchID[16]; id.ToByteArray(uchID); it->requester->KadSearchNodeIDByIPResult(KCSR_SUCCEEDED, uchID); m_fetchNodeIDRequests.erase(it); break; } } if (fromHelloReq && version >= 8) { // this is just for statistic calculations. We try to determine the ratio of (UDP) firewalled users, // by counting how many of all nodes which have us in their routing table (our own routing table is supposed // to have no UDP firewalled nodes at all) and support the firewalled tag are firewalled themself. // Obviously this only works if we are not firewalled ourself CKademlia::GetPrefs()->StatsIncUDPFirewalledNodes(udpFirewalled); CKademlia::GetPrefs()->StatsIncTCPFirewalledNodes(tcpFirewalled); } if (!udpFirewalled) { // do not add (or update) UDP firewalled sources to our routing table return CKademlia::GetRoutingZone()->Add(id, ip, port, tport, version, udpKey, ipVerified, update, false, true); } else { AddDebugLogLineM(false, logKadRouting, wxT("Not adding firewalled client to routing table (") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxT(")")); return false; }}// Used only for Kad1.0void CKademliaUDPListener::AddContacts(const uint8_t *data, uint32_t lenData, uint16_t numContacts, bool update){ CMemFile bio(data, lenData); CRoutingZone *routingZone = CKademlia::GetRoutingZone(); for (uint16_t i = 0; i < numContacts; i++) { CUInt128 id = bio.ReadUInt128(); uint32_t ip = bio.ReadUInt32(); ip = wxUINT32_SWAP_ALWAYS(ip); uint16_t port = bio.ReadUInt16(); uint16_t tport = bio.ReadUInt16(); bio.ReadUInt8(); bool verified = false; //AddDebugLogLineM(false, logKadMain, wxT("Adding contact(s) with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port)); routingZone->Add(id, ip, port, tport, 0, 0, verified, update, false, false); }}// KADEMLIA_BOOTSTRAP_REQ// Used only for Kad1.0void CKademliaUDPListener::ProcessBootstrapRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port){ // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(25); // Add the sender to the list of contacts bool verified = false; AddContact(packetData, lenPacket, ip, port, 0, 0, verified, true, NULL); // Get some contacts to return ContactList contacts; uint16_t numContacts = 1 + (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts, 20); // Create response packet //We only collect a max of 20 contacts here.. Max size is 527. //2 + 25(20) + 25 CMemFile packetdata(527); // Write packet info packetdata.WriteUInt16(numContacts); CContact *contact; for (ContactList::const_iterator it = contacts.begin(); it != contacts.end(); ++it) { contact = *it; packetdata.WriteUInt128(contact->GetClientID()); packetdata.WriteUInt32(contact->GetIPAddress()); packetdata.WriteUInt16(contact->GetUDPPort()); packetdata.WriteUInt16(contact->GetTCPPort()); packetdata.WriteUInt8(contact->GetType()); } packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID()); packetdata.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress()); packetdata.WriteUInt16(thePrefs::GetEffectiveUDPPort()); packetdata.WriteUInt16(thePrefs::GetPort()); packetdata.WriteUInt8(0); // Send response DebugSend(KadBootstrapRes, ip, port); SendPacket(packetdata, KADEMLIA_BOOTSTRAP_RES, ip, port, 0, NULL);}// KADEMLIA2_BOOTSTRAP_REQ// Used only for Kad2.0void CKademliaUDPListener::Process2BootstrapRequest(uint32_t ip, uint16_t port, const CKadUDPKey& senderKey){ // Get some contacts to return ContactList contacts; uint16_t numContacts = (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts, 20); // Create response packet //We only collect a max of 20 contacts here.. Max size is 521. //2 + 25(20) + 19 CMemFile packetdata(521); packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID()); packetdata.WriteUInt16(thePrefs::GetPort()); packetdata.WriteUInt8(KADEMLIA_VERSION); // Write packet info packetdata.WriteUInt16(numContacts); CContact *contact; for (ContactList::const_iterator it = contacts.begin(); it != contacts.end(); ++it) { contact = *it; packetdata.WriteUInt128(contact->GetClientID()); packetdata.WriteUInt32(contact->GetIPAddress()); packetdata.WriteUInt16(contact->GetUDPPort()); packetdata.WriteUInt16(contact->GetTCPPort()); packetdata.WriteUInt8(contact->GetVersion()); } // Send response DebugSend(Kad2BootstrapRes, ip, port); SendPacket(packetdata, KADEMLIA2_BOOTSTRAP_RES, ip, port, senderKey, NULL);}// KADEMLIA_BOOTSTRAP_RES// Used only for Kad1.0void CKademliaUDPListener::ProcessBootstrapResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip){ // Verify packet is expected size CHECK_PACKET_MIN_SIZE(27); CHECK_TRACKED_PACKET(KADEMLIA_BOOTSTRAP_REQ); // How many contacts were given CMemFile bio(packetData, lenPacket); uint16_t numContacts = bio.ReadUInt16(); // Verify packet is expected size if (lenPacket != (uint32_t)(2 + 25 * numContacts)) { return; } // Add these contacts to the list. AddContacts(packetData + 2, lenPacket - 2, numContacts, false);}// KADEMLIA2_BOOTSTRAP_RES// Used only for Kad2.0void CKademliaUDPListener::Process2BootstrapResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey){ CHECK_TRACKED_PACKET(KADEMLIA2_BOOTSTRAP_REQ); CRoutingZone *routingZone = CKademlia::GetRoutingZone(); // How many contacts were given CMemFile bio(packetData, lenPacket); CUInt128 contactID = bio.ReadUInt128(); uint16_t tport = bio.ReadUInt16(); uint8_t version = bio.ReadUInt8(); // if we don't know any Contacts yet and try to Bootstrap, we assume that all contacts are verified, // in order to speed up the connecting process. The attackvectors to exploit this are very small with no // major effects, so that's a good trade bool assumeVerified = CKademlia::GetRoutingZone()->GetNumContacts() == 0; if (CKademlia::s_bootstrapList.empty()) { routingZone->Add(contactID, ip, port, tport, version, senderKey, validReceiverKey, true, false, false); } uint16_t numContacts = bio.ReadUInt16(); while (numContacts) { contactID = bio.ReadUInt128(); ip = bio.ReadUInt32(); port = bio.ReadUInt16(); tport = bio.ReadUInt16(); version = bio.ReadUInt8(); bool verified = assumeVerified; routingZone->Add(contactID, ip, port, tport, version, 0, verified, false, false, false); numContacts--; }}// KADEMLIA_HELLO_REQ// Used in Kad1.0 onlyvoid CKademliaUDPListener::ProcessHelloRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port){ // Verify packet is expected size CHECK_PACKET_EXACT_SIZE(25); // Add the sender to the list of contacts bool validReceiverKey = false; CUInt128 contactID; bool addedOrUpdated = AddContact(packetData, lenPacket, ip, port, 0, 0, validReceiverKey, true, &contactID); // Send response DebugSend(KadHelloRes, ip, port); SendMyDetails(KADEMLIA_HELLO_RES, ip, port, 0, 0, NULL, false); if (addedOrUpdated && !validReceiverKey) { // we need to verify this contact but it doesn't support HELLO_RES_ACK nor keys, do a little workaround SendLegacyChallenge(ip, port, contactID, false); } // Check if firewalled if (CKademlia::GetPrefs()->GetRecheckIP()) { FirewalledCheck(ip, port, 0, 0); }}// KADEMLIA2_HELLO_REQ// Used in Kad2.0 onlyvoid CKademliaUDPListener::Process2HelloRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey){ uint16_t dbgOldUDPPort = port; uint8_t contactVersion = 0; CUInt128 contactID; bool addedOrUpdated = AddContact2(packetData, lenPacket, ip, port, &contactVersion, senderKey, validReceiverKey, true, true, NULL, &contactID); // might change (udp)port, validReceiverKey wxASSERT(contactVersion >= 1);#ifdef __DEBUG__ if (dbgOldUDPPort != port) { AddDebugLogLineM(false, logClientKadUDP, wxT("KadContact ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip)) + wxString::Format(wxT(" uses his internal (%u) instead external (%u) UDP Port"), port, dbgOldUDPPort)); }#endif DebugSend(Kad2HelloRes, ip, port); // if this contact was added or updated (so with other words not filtered or invalid) to our routing table and did not already send a valid // receiver key or is already verified in the routing table, we request an additional ACK package to complete a three-way-handshake and // verify the remote IP SendMyDetails(KADEMLIA2_HELLO_RES, ip, port, contactVersion, senderKey, &contactID, addedOrUpdated && !validReceiverKey); if (addedOrUpdated && !validReceiverKey && contactVersion == 7 && !HasActiveLegacyChallenge(ip)) { // Kad Version 7 doesn't support HELLO_RES_ACK but sender/receiver keys, so send a ping to validate DebugSend(Kad2Ping, ip, port); SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL);#ifdef __DEBUG__ CContact* contact = CKademlia::GetRoutingZone()->GetContact(contactID); if (contact != NULL) { if (contact->GetType() < 2) { AddDebugLogLineM(false, logClientKadUDP, wxT("Sending (ping) challenge to a long known contact (should be verified already) - ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip))); } } else { wxFAIL; }#endif } else if (CKademlia::GetPrefs()->GetExternalKadPort() == 0 && contactVersion > 5) { // do we need to find out our extern port?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -