Upstream tarball 10110
[amule.git] / src / kademlia / net / KademliaUDPListener.cpp
blob9accb8c6ed7ec8c3ac13c52a293430f5c6e7df18
1 //
2 // This file is part of aMule Project
3 //
4 // Copyright (c) 2004-2008 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Copyright (c) 2003-2008 Barry Dunne ( http://www.emule-project.net )
7 // Copyright (C)2007-2008 Merkur ( strEmail.Format("%s@%s", "devteam", "emule-project.net") / http://www.emule-project.net )
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 // Note To Mods //
25 Please do not change anything here and release it..
26 There is going to be a new forum created just for the Kademlia side of the client..
27 If you feel there is an error or a way to improve something, please
28 post it in the forum first and let us look at it.. If it is a real improvement,
29 it will be added to the offical client.. Changing something without knowing
30 what all it does can cause great harm to the network if released in mass form..
31 Any mod that changes anything within the Kademlia side will not be allowed to advertise
32 there client on the eMule forum..
35 #include <wx/wx.h>
37 #include "KademliaUDPListener.h"
39 #include <protocol/Protocols.h>
40 #include <protocol/kad/Constants.h>
41 #include <protocol/kad/Client2Client/UDP.h>
42 #include <protocol/kad2/Constants.h>
43 #include <protocol/kad2/Client2Client/UDP.h>
44 #include <protocol/ed2k/Client2Client/TCP.h> // OP_CALLBACK is sent in some cases.
45 #include <common/Macros.h>
46 #include <common/Format.h>
47 #include <tags/FileTags.h>
49 #include "../routing/Contact.h"
50 #include "../routing/RoutingZone.h"
51 #include "../kademlia/Indexed.h"
52 #include "../kademlia/Defines.h"
53 #include "../kademlia/UDPFirewallTester.h"
54 #include "../utils/KadUDPKey.h"
55 #include "../utils/KadClientSearcher.h"
56 #include "../../amule.h"
57 #include "../../ClientUDPSocket.h"
58 #include "../../Packet.h"
59 #include "../../ClientList.h"
60 #include "../../Statistics.h"
61 #include "../../MemFile.h"
62 #include "../../updownclient.h"
63 #include "../../ClientTCPSocket.h"
64 #include "../../Logger.h"
65 #include "../../Preferences.h"
66 #include "../../ScopedPtr.h"
67 #include "../../IPFilter.h"
68 #include "../../RandomFunctions.h" // Needed for GetRandomUint128()
70 #include <wx/tokenzr.h>
72 #define THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX 0
74 #if defined(__SUNPRO_CC)
75 #define __FUNCTION__ __FILE__+__LINE__
76 #endif
78 #define CHECK_PACKET_SIZE(OP, SIZE) \
79 if (lenPacket OP (uint32_t)(SIZE)) \
80 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__)
82 #define CHECK_PACKET_MIN_SIZE(SIZE) CHECK_PACKET_SIZE(<, SIZE)
83 #define CHECK_PACKET_EXACT_SIZE(SIZE) CHECK_PACKET_SIZE(!=, SIZE)
85 #define CHECK_TRACKED_PACKET(OPCODE) \
86 if (!IsOnOutTrackList(ip, OPCODE)) \
87 throw wxString::Format(wxT("***NOTE: Received unrequested response packet, size (%u) in "), lenPacket) + wxString::FromAscii(__FUNCTION__)
90 ////////////////////////////////////////
91 using namespace Kademlia;
92 ////////////////////////////////////////
94 CKademliaUDPListener::~CKademliaUDPListener()
96 // report timeout to all pending FetchNodeIDRequests
97 for (FetchNodeIDList::iterator it = m_fetchNodeIDRequests.begin(); it != m_fetchNodeIDRequests.end(); ++it) {
98 it->requester->KadSearchNodeIDByIPResult(KCSR_TIMEOUT, NULL);
102 // Used by Kad1.0 and Kad2.0
103 void CKademliaUDPListener::Bootstrap(uint32_t ip, uint16_t port, bool kad2, uint8_t kadVersion, const CUInt128* cryptTargetID)
105 wxASSERT(ip);
107 if (kad2) {
108 DebugSend(Kad2BootstrapReq, ip, port);
109 CMemFile bio(0);
110 if (kadVersion >= 6) {
111 SendPacket(bio, KADEMLIA2_BOOTSTRAP_REQ, ip, port, 0, cryptTargetID);
112 } else {
113 SendPacket(bio, KADEMLIA2_BOOTSTRAP_REQ, ip, port, 0, NULL);
115 } else {
116 DebugSend(KadBootstrapReq, ip, port);
117 SendMyDetails(KADEMLIA_BOOTSTRAP_REQ, ip, port, 0, 0, NULL, false);
121 // Used by Kad1.0 and Kad2.0
122 void CKademliaUDPListener::SendMyDetails(uint8_t opcode, uint32_t ip, uint16_t port, uint8_t kadVersion, const CKadUDPKey& targetKey, const CUInt128* cryptTargetID, bool requestAckPacket)
124 CMemFile packetdata;
125 packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
127 if (kadVersion > 0) {
128 packetdata.WriteUInt16(thePrefs::GetPort());
129 packetdata.WriteUInt8(KADEMLIA_VERSION);
130 // Tag Count.
131 uint8_t tagCount = 0;
132 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
133 tagCount++;
135 if (kadVersion >= 8 && (requestAckPacket || CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true))) {
136 tagCount++;
138 packetdata.WriteUInt8(tagCount);
139 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
140 packetdata.WriteTag(CTagVarInt(TAG_SOURCEUPORT, CKademlia::GetPrefs()->GetInternKadPort()));
142 if (kadVersion >= 8 && (requestAckPacket || CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true))) {
143 // if we're firewalled we send this tag, so the other client doesn't add us to his routing table (if UDP firewalled) and for statistics reasons (TCP firewalled)
144 // 5 - reserved (!)
145 // 1 - requesting HELLO_RES_ACK
146 // 1 - TCP firewalled
147 // 1 - UDP firewalled
148 packetdata.WriteTag(CTagVarInt(TAG_KADMISCOPTIONS, (uint8_t)(
149 (requestAckPacket ? 1 : 0) << 2 |
150 (CKademlia::GetPrefs()->GetFirewalled() ? 1 : 0) << 1 |
151 (CUDPFirewallTester::IsFirewalledUDP(true) ? 1 : 0)
152 )));
154 // packetdata.WriteTag(CKadTagUInt(TAG_USER_COUNT, CKademlia::GetPrefs()->GetKademliaUsers()));
155 // packetdata.WriteTag(CKadTagUInt(TAG_FILE_COUNT, CKademlia::GetPrefs()->GetKademliaFiles()));
156 if (kadVersion >= 6) {
157 if (cryptTargetID == NULL || *cryptTargetID == 0) {
158 AddDebugLogLineN(logClientKadUDP, wxT("Sending hello response to crypt enabled Kad Node which provided an empty NodeID: ") + KadIPToString(ip) + wxString::Format(wxT(" (%u)"), kadVersion));
159 SendPacket(packetdata, opcode, ip, port, targetKey, NULL);
160 } else {
161 SendPacket(packetdata, opcode, ip, port, targetKey, cryptTargetID);
163 } else {
164 SendPacket(packetdata, opcode, ip, port, 0, NULL);
165 wxASSERT(targetKey.IsEmpty());
167 } else {
168 wxASSERT(!requestAckPacket);
169 packetdata.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
170 packetdata.WriteUInt16(thePrefs::GetEffectiveUDPPort());
171 packetdata.WriteUInt16(thePrefs::GetPort());
172 packetdata.WriteUInt8(0);
173 SendPacket(packetdata, opcode, ip, port, 0, NULL);
177 // Kad1.0 and Kad2.0 currently.
178 void CKademliaUDPListener::FirewalledCheck(uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, uint8_t kadVersion)
180 if (kadVersion > 6) {
181 // new opcode since 0.49a with extended informations to support obfuscated connections properly
182 CMemFile packetdata(19);
183 packetdata.WriteUInt16(thePrefs::GetPort());
184 packetdata.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
185 packetdata.WriteUInt8(CPrefs::GetMyConnectOptions(true, false));
186 DebugSend(KadFirewalled2Req, ip, port);
187 SendPacket(packetdata, KADEMLIA_FIREWALLED2_REQ, ip, port, senderKey, NULL);
188 } else {
189 CMemFile packetdata(2);
190 packetdata.WriteUInt16(thePrefs::GetPort());
191 DebugSend(KadFirewalledReq, ip, port);
192 SendPacket(packetdata, KADEMLIA_FIREWALLED_REQ, ip, port, senderKey, NULL);
194 theApp->clientlist->AddKadFirewallRequest(wxUINT32_SWAP_ALWAYS(ip));
197 void CKademliaUDPListener::SendNullPacket(uint8_t opcode, uint32_t ip, uint16_t port, const CKadUDPKey& targetKey, const CUInt128* cryptTargetID)
199 CMemFile packetdata(0);
200 SendPacket(packetdata, opcode, ip, port, targetKey, cryptTargetID);
203 void CKademliaUDPListener::SendPublishSourcePacket(const CContact& contact, const CUInt128 &targetID, const CUInt128 &contactID, const TagPtrList& tags)
205 uint8_t opcode;
206 CMemFile packetdata;
207 packetdata.WriteUInt128(targetID);
208 if (contact.GetVersion() >= 4/*47c*/) {
209 opcode = KADEMLIA2_PUBLISH_SOURCE_REQ;
210 packetdata.WriteUInt128(contactID);
211 packetdata.WriteTagPtrList(tags);
212 DebugSend(Kad2PublishSrcReq, contact.GetIPAddress(), contact.GetUDPPort());
213 } else {
214 opcode = KADEMLIA_PUBLISH_REQ;
215 //We only use this for publishing sources now.. So we always send one here..
216 packetdata.WriteUInt16(1);
217 packetdata.WriteUInt128(contactID);
218 packetdata.WriteTagPtrList(tags);
219 DebugSend(KadPublishReq, contact.GetIPAddress(), contact.GetUDPPort());
221 if (contact.GetVersion() >= 6) { // obfuscated ?
222 CUInt128 clientID = contact.GetClientID();
223 SendPacket(packetdata, opcode, contact.GetIPAddress(), contact.GetUDPPort(), contact.GetUDPKey(), &clientID);
224 } else {
225 SendPacket(packetdata, opcode, contact.GetIPAddress(), contact.GetUDPPort(), 0, NULL);
229 void CKademliaUDPListener::ProcessPacket(const uint8_t* data, uint32_t lenData, uint32_t ip, uint16_t port, bool validReceiverKey, const CKadUDPKey& senderKey)
231 // we do not accept (<= 0.48a) unencrypted incoming packets from port 53 (DNS) to avoid attacks based on DNS protocol confusion
232 if (port == 53 && senderKey.IsEmpty()) {
233 AddDebugLogLineN(logKadPacketTracking, wxT("Dropping incoming unencrypted packet on port 53 (DNS), IP: ") + KadIPToString(ip));
234 return;
237 //Update connection state only when it changes.
238 bool curCon = CKademlia::GetPrefs()->HasHadContact();
239 CKademlia::GetPrefs()->SetLastContact();
240 CUDPFirewallTester::Connected();
241 if( curCon != CKademlia::GetPrefs()->HasHadContact()) {
242 theApp->ShowConnectionState();
245 uint8_t opcode = data[1];
246 const uint8_t *packetData = data + 2;
247 uint32_t lenPacket = lenData - 2;
249 if (!InTrackListIsAllowedPacket(ip, opcode, validReceiverKey)) {
250 return;
253 switch (opcode) {
254 case KADEMLIA_BOOTSTRAP_REQ:
255 DebugRecv(KadBootstrapReq, ip, port);
256 ProcessBootstrapRequest(packetData, lenPacket, ip, port);
257 break;
258 case KADEMLIA2_BOOTSTRAP_REQ:
259 DebugRecv(Kad2BootstrapReq, ip, port);
260 Process2BootstrapRequest(ip, port, senderKey);
261 break;
262 case KADEMLIA_BOOTSTRAP_RES:
263 DebugRecv(KadBootstrapRes, ip, port);
264 ProcessBootstrapResponse(packetData, lenPacket, ip);
265 break;
266 case KADEMLIA2_BOOTSTRAP_RES:
267 DebugRecv(Kad2BootstrapRes, ip, port);
268 Process2BootstrapResponse(packetData, lenPacket, ip, port, senderKey, validReceiverKey);
269 break;
270 case KADEMLIA_HELLO_REQ:
271 DebugRecv(KadHelloReq, ip, port);
272 ProcessHelloRequest(packetData, lenPacket, ip, port);
273 break;
274 case KADEMLIA2_HELLO_REQ:
275 DebugRecv(Kad2HelloReq, ip, port);
276 Process2HelloRequest(packetData, lenPacket, ip, port, senderKey, validReceiverKey);
277 break;
278 case KADEMLIA_HELLO_RES:
279 DebugRecv(KadHelloRes, ip, port);
280 ProcessHelloResponse(packetData, lenPacket, ip, port);
281 break;
282 case KADEMLIA2_HELLO_RES:
283 DebugRecv(Kad2HelloRes, ip, port);
284 Process2HelloResponse(packetData, lenPacket, ip, port, senderKey, validReceiverKey);
285 break;
286 case KADEMLIA2_HELLO_RES_ACK:
287 DebugRecv(Kad2HelloResAck, ip, port);
288 Process2HelloResponseAck(packetData, lenPacket, ip, validReceiverKey);
289 break;
290 case KADEMLIA_REQ:
291 DebugRecv(KadReq, ip, port);
292 ProcessKademliaRequest(packetData, lenPacket, ip, port);
293 break;
294 case KADEMLIA2_REQ:
295 DebugRecv(Kad2Req, ip, port);
296 ProcessKademlia2Request(packetData, lenPacket, ip, port, senderKey);
297 break;
298 case KADEMLIA_RES:
299 DebugRecv(KadRes, ip, port);
300 ProcessKademliaResponse(packetData, lenPacket, ip, port);
301 break;
302 case KADEMLIA2_RES:
303 DebugRecv(Kad2Res, ip, port);
304 ProcessKademlia2Response(packetData, lenPacket, ip, port, senderKey);
305 break;
306 case KADEMLIA_SEARCH_REQ:
307 DebugRecv(KadSearchReq, ip, port);
308 ProcessSearchRequest(packetData, lenPacket, ip, port);
309 break;
310 case KADEMLIA_SEARCH_NOTES_REQ:
311 DebugRecv(KadSearchNotesReq, ip, port);
312 ProcessSearchNotesRequest(packetData, lenPacket, ip, port);
313 break;
314 case KADEMLIA2_SEARCH_NOTES_REQ:
315 DebugRecv(Kad2SearchNotesReq, ip, port);
316 Process2SearchNotesRequest(packetData, lenPacket, ip, port, senderKey);
317 break;
318 case KADEMLIA2_SEARCH_KEY_REQ:
319 DebugRecv(Kad2SearchKeyReq, ip, port);
320 Process2SearchKeyRequest(packetData, lenPacket, ip, port, senderKey);
321 break;
322 case KADEMLIA2_SEARCH_SOURCE_REQ:
323 DebugRecv(Kad2SearchSourceReq, ip, port);
324 Process2SearchSourceRequest(packetData, lenPacket, ip, port, senderKey);
325 break;
326 case KADEMLIA_SEARCH_RES:
327 DebugRecv(KadSearchRes, ip, port);
328 ProcessSearchResponse(packetData, lenPacket);
329 break;
330 case KADEMLIA_SEARCH_NOTES_RES:
331 DebugRecv(KadSearchNotesRes, ip, port);
332 ProcessSearchNotesResponse(packetData, lenPacket, ip);
333 break;
334 case KADEMLIA2_SEARCH_RES:
335 DebugRecv(Kad2SearchRes, ip, port);
336 Process2SearchResponse(packetData, lenPacket, senderKey);
337 break;
338 case KADEMLIA_PUBLISH_REQ:
339 DebugRecv(KadPublishReq, ip, port);
340 ProcessPublishRequest(packetData, lenPacket, ip, port);
341 break;
342 case KADEMLIA_PUBLISH_NOTES_REQ:
343 DebugRecv(KadPublishNotesReq, ip, port);
344 ProcessPublishNotesRequest(packetData, lenPacket, ip, port);
345 break;
346 case KADEMLIA2_PUBLISH_NOTES_REQ:
347 DebugRecv(Kad2PublishNotesReq, ip, port);
348 Process2PublishNotesRequest(packetData, lenPacket, ip, port, senderKey);
349 break;
350 case KADEMLIA2_PUBLISH_KEY_REQ:
351 DebugRecv(Kad2PublishKeyReq, ip, port);
352 Process2PublishKeyRequest(packetData, lenPacket, ip, port, senderKey);
353 break;
354 case KADEMLIA2_PUBLISH_SOURCE_REQ:
355 DebugRecv(Kad2PublishSourceReq, ip, port);
356 Process2PublishSourceRequest(packetData, lenPacket, ip, port, senderKey);
357 break;
358 case KADEMLIA_PUBLISH_RES:
359 DebugRecv(KadPublishRes, ip, port);
360 ProcessPublishResponse(packetData, lenPacket, ip);
361 break;
362 case KADEMLIA_PUBLISH_NOTES_RES:
363 DebugRecv(KadPublishNotesRes, ip, port);
364 ProcessPublishNotesResponse(packetData, lenPacket, ip);
365 break;
366 case KADEMLIA2_PUBLISH_RES:
367 DebugRecv(Kad2PublishRes, ip, port);
368 Process2PublishResponse(packetData, lenPacket, ip, port, senderKey);
369 break;
370 case KADEMLIA_FIREWALLED_REQ:
371 DebugRecv(KadFirewalledReq, ip, port);
372 ProcessFirewalledRequest(packetData, lenPacket, ip, port, senderKey);
373 break;
374 case KADEMLIA_FIREWALLED2_REQ:
375 DebugRecv(KadFirewalled2Req, ip, port);
376 ProcessFirewalled2Request(packetData, lenPacket, ip, port, senderKey);
377 break;
378 case KADEMLIA_FIREWALLED_RES:
379 DebugRecv(KadFirewalledRes, ip, port);
380 ProcessFirewalledResponse(packetData, lenPacket, ip, senderKey);
381 break;
382 case KADEMLIA_FIREWALLED_ACK_RES:
383 DebugRecv(KadFirewalledAck, ip, port);
384 ProcessFirewalledAckResponse(lenPacket);
385 break;
386 case KADEMLIA_FINDBUDDY_REQ:
387 DebugRecv(KadFindBuddyReq, ip, port);
388 ProcessFindBuddyRequest(packetData, lenPacket, ip, port, senderKey);
389 break;
390 case KADEMLIA_FINDBUDDY_RES:
391 DebugRecv(KadFindBuddyRes, ip, port);
392 ProcessFindBuddyResponse(packetData, lenPacket, ip, port, senderKey);
393 break;
394 case KADEMLIA_CALLBACK_REQ:
395 DebugRecv(KadCallbackReq, ip, port);
396 ProcessCallbackRequest(packetData, lenPacket, ip, port, senderKey);
397 break;
398 case KADEMLIA2_PING:
399 DebugRecv(Kad2Ping, ip, port);
400 Process2Ping(ip, port, senderKey);
401 break;
402 case KADEMLIA2_PONG:
403 DebugRecv(Kad2Pong, ip, port);
404 Process2Pong(packetData, lenPacket, ip);
405 break;
406 case KADEMLIA2_FIREWALLUDP:
407 DebugRecv(Kad2FirewallUDP, ip, port);
408 Process2FirewallUDP(packetData, lenPacket, ip);
409 break;
410 default: {
411 throw wxString::Format(wxT("Unknown opcode %02x on CKademliaUDPListener::ProcessPacket()"), opcode);
416 // Used only for Kad1.0
417 bool 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)
419 CMemFile bio(data, lenData);
420 CUInt128 id = bio.ReadUInt128();
421 if (outContactID != NULL) {
422 *outContactID = id;
424 bio.ReadUInt32();
425 bio.ReadUInt16();
426 if (tport) {
427 bio.ReadUInt16();
428 } else {
429 tport = bio.ReadUInt16();
431 bio.ReadUInt8();
432 //AddDebugLogLineN(logKadMain, wxT("Adding a contact with ip ") + KadIPPortToString(ip, port));
433 // Ignore stated ip and port, use the address the packet came from
434 return CKademlia::GetRoutingZone()->Add(id, ip, port, tport, 0, udpKey, ipVerified, update, false, true);
437 // Used only for Kad2.0
438 bool 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)
440 if (outRequestsACK != 0) {
441 *outRequestsACK = false;
444 CMemFile bio(data, lenData);
445 CUInt128 id = bio.ReadUInt128();
446 if (outContactID != NULL) {
447 *outContactID = id;
449 uint16_t tport = bio.ReadUInt16();
450 uint8_t version = bio.ReadUInt8();
451 if (version == 0) {
452 throw wxString::Format(wxT("***NOTE: Received invalid Kademlia2 version (%u) in "), version) + wxString::FromAscii(__FUNCTION__);
454 if (outVersion != NULL) {
455 *outVersion = version;
457 bool udpFirewalled = false;
458 bool tcpFirewalled = false;
459 uint8_t tags = bio.ReadUInt8();
460 while (tags) {
461 CTag *tag = bio.ReadTag();
462 if (!tag->GetName().Cmp(TAG_SOURCEUPORT)) {
463 if (tag->IsInt() && (uint16_t)tag->GetInt() > 0) {
464 port = tag->GetInt();
466 } else if (!tag->GetName().Cmp(TAG_KADMISCOPTIONS)) {
467 if (tag->IsInt() && tag->GetInt() > 0) {
468 udpFirewalled = (tag->GetInt() & 0x01) > 0;
469 tcpFirewalled = (tag->GetInt() & 0x02) > 0;
470 if ((tag->GetInt() & 0x04) > 0) {
471 if (outRequestsACK != NULL) {
472 if (version >= 8) {
473 *outRequestsACK = true;
475 } else {
476 wxFAIL;
481 delete tag;
482 --tags;
485 // check if we are waiting for informations (nodeid) about this client and if so inform the requester
486 for (FetchNodeIDList::iterator it = m_fetchNodeIDRequests.begin(); it != m_fetchNodeIDRequests.end(); ++it) {
487 if (it->ip == ip && it->tcpPort == tport) {
488 //AddDebugLogLineN(logKadMain, wxT("Result Addcontact: ") + id.ToHexString());
489 uint8_t uchID[16];
490 id.ToByteArray(uchID);
491 it->requester->KadSearchNodeIDByIPResult(KCSR_SUCCEEDED, uchID);
492 m_fetchNodeIDRequests.erase(it);
493 break;
497 if (fromHelloReq && version >= 8) {
498 // this is just for statistic calculations. We try to determine the ratio of (UDP) firewalled users,
499 // by counting how many of all nodes which have us in their routing table (our own routing table is supposed
500 // to have no UDP firewalled nodes at all) and support the firewalled tag are firewalled themself.
501 // Obviously this only works if we are not firewalled ourself
502 CKademlia::GetPrefs()->StatsIncUDPFirewalledNodes(udpFirewalled);
503 CKademlia::GetPrefs()->StatsIncTCPFirewalledNodes(tcpFirewalled);
506 if (!udpFirewalled) { // do not add (or update) UDP firewalled sources to our routing table
507 return CKademlia::GetRoutingZone()->Add(id, ip, port, tport, version, udpKey, ipVerified, update, false, true);
508 } else {
509 AddDebugLogLineN(logKadRouting, wxT("Not adding firewalled client to routing table (") + KadIPToString(ip) + wxT(")"));
510 return false;
514 // Used only for Kad1.0
515 void CKademliaUDPListener::AddContacts(const uint8_t *data, uint32_t lenData, uint16_t numContacts, bool update)
517 CMemFile bio(data, lenData);
518 CRoutingZone *routingZone = CKademlia::GetRoutingZone();
519 for (uint16_t i = 0; i < numContacts; i++) {
520 CUInt128 id = bio.ReadUInt128();
521 uint32_t ip = bio.ReadUInt32();
522 ip = wxUINT32_SWAP_ALWAYS(ip);
523 uint16_t port = bio.ReadUInt16();
524 uint16_t tport = bio.ReadUInt16();
525 bio.ReadUInt8();
526 bool verified = false;
527 //AddDebugLogLineN(logKadMain, wxT("Adding contact(s) with ip ") + KadIPPortToString(ip, port));
528 routingZone->Add(id, ip, port, tport, 0, 0, verified, update, false, false);
532 // KADEMLIA_BOOTSTRAP_REQ
533 // Used only for Kad1.0
534 void CKademliaUDPListener::ProcessBootstrapRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
536 // Verify packet is expected size
537 CHECK_PACKET_EXACT_SIZE(25);
539 // Add the sender to the list of contacts
540 bool verified = false;
541 AddContact(packetData, lenPacket, ip, port, 0, 0, verified, true, NULL);
543 // Get some contacts to return
544 ContactList contacts;
545 uint16_t numContacts = 1 + (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts, 20);
547 // Create response packet
548 //We only collect a max of 20 contacts here.. Max size is 527.
549 //2 + 25(20) + 25
550 CMemFile packetdata(527);
552 // Write packet info
553 packetdata.WriteUInt16(numContacts);
554 CContact *contact;
555 for (ContactList::const_iterator it = contacts.begin(); it != contacts.end(); ++it) {
556 contact = *it;
557 packetdata.WriteUInt128(contact->GetClientID());
558 packetdata.WriteUInt32(contact->GetIPAddress());
559 packetdata.WriteUInt16(contact->GetUDPPort());
560 packetdata.WriteUInt16(contact->GetTCPPort());
561 packetdata.WriteUInt8(contact->GetType());
564 packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
565 packetdata.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
566 packetdata.WriteUInt16(thePrefs::GetEffectiveUDPPort());
567 packetdata.WriteUInt16(thePrefs::GetPort());
568 packetdata.WriteUInt8(0);
570 // Send response
571 DebugSend(KadBootstrapRes, ip, port);
572 SendPacket(packetdata, KADEMLIA_BOOTSTRAP_RES, ip, port, 0, NULL);
575 // KADEMLIA2_BOOTSTRAP_REQ
576 // Used only for Kad2.0
577 void CKademliaUDPListener::Process2BootstrapRequest(uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
579 // Get some contacts to return
580 ContactList contacts;
581 uint16_t numContacts = (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts, 20);
583 // Create response packet
584 //We only collect a max of 20 contacts here.. Max size is 521.
585 //2 + 25(20) + 19
586 CMemFile packetdata(521);
588 packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
589 packetdata.WriteUInt16(thePrefs::GetPort());
590 packetdata.WriteUInt8(KADEMLIA_VERSION);
592 // Write packet info
593 packetdata.WriteUInt16(numContacts);
594 CContact *contact;
595 for (ContactList::const_iterator it = contacts.begin(); it != contacts.end(); ++it) {
596 contact = *it;
597 packetdata.WriteUInt128(contact->GetClientID());
598 packetdata.WriteUInt32(contact->GetIPAddress());
599 packetdata.WriteUInt16(contact->GetUDPPort());
600 packetdata.WriteUInt16(contact->GetTCPPort());
601 packetdata.WriteUInt8(contact->GetVersion());
604 // Send response
605 DebugSend(Kad2BootstrapRes, ip, port);
606 SendPacket(packetdata, KADEMLIA2_BOOTSTRAP_RES, ip, port, senderKey, NULL);
609 // KADEMLIA_BOOTSTRAP_RES
610 // Used only for Kad1.0
611 void CKademliaUDPListener::ProcessBootstrapResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
613 // Verify packet is expected size
614 CHECK_PACKET_MIN_SIZE(27);
615 CHECK_TRACKED_PACKET(KADEMLIA_BOOTSTRAP_REQ);
617 //AddDebugLogLineN(logClientKadUDP, wxT("Inc Kad1 Bootstrap packet from ") + KadIPToString(ip));
618 // How many contacts were given
619 CMemFile bio(packetData, lenPacket);
620 uint16_t numContacts = bio.ReadUInt16();
622 // Verify packet is expected size
623 if (lenPacket != (uint32_t)(2 + 25 * numContacts)) {
624 return;
627 // Add these contacts to the list.
628 AddContacts(packetData + 2, lenPacket - 2, numContacts, false);
631 // KADEMLIA2_BOOTSTRAP_RES
632 // Used only for Kad2.0
633 void CKademliaUDPListener::Process2BootstrapResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey)
635 CHECK_TRACKED_PACKET(KADEMLIA2_BOOTSTRAP_REQ);
637 CRoutingZone *routingZone = CKademlia::GetRoutingZone();
639 // How many contacts were given
640 CMemFile bio(packetData, lenPacket);
641 CUInt128 contactID = bio.ReadUInt128();
642 uint16_t tport = bio.ReadUInt16();
643 uint8_t version = bio.ReadUInt8();
644 // if we don't know any Contacts yet and try to Bootstrap, we assume that all contacts are verified,
645 // in order to speed up the connecting process. The attackvectors to exploit this are very small with no
646 // major effects, so that's a good trade
647 bool assumeVerified = CKademlia::GetRoutingZone()->GetNumContacts() == 0;
649 if (CKademlia::s_bootstrapList.empty()) {
650 routingZone->Add(contactID, ip, port, tport, version, senderKey, validReceiverKey, true, false, false);
652 //AddDebugLogLineN(logClientKadUDP, wxT("Inc Kad2 Bootstrap packet from ") + KadIPToString(ip));
654 uint16_t numContacts = bio.ReadUInt16();
655 while (numContacts) {
656 contactID = bio.ReadUInt128();
657 ip = bio.ReadUInt32();
658 port = bio.ReadUInt16();
659 tport = bio.ReadUInt16();
660 version = bio.ReadUInt8();
661 bool verified = assumeVerified;
662 routingZone->Add(contactID, ip, port, tport, version, 0, verified, false, false, false);
663 numContacts--;
667 // KADEMLIA_HELLO_REQ
668 // Used in Kad1.0 only
669 void CKademliaUDPListener::ProcessHelloRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
671 // Verify packet is expected size
672 CHECK_PACKET_EXACT_SIZE(25);
674 // Add the sender to the list of contacts
675 bool validReceiverKey = false;
676 CUInt128 contactID;
677 bool addedOrUpdated = AddContact(packetData, lenPacket, ip, port, 0, 0, validReceiverKey, true, &contactID);
679 // Send response
680 DebugSend(KadHelloRes, ip, port);
681 SendMyDetails(KADEMLIA_HELLO_RES, ip, port, 0, 0, NULL, false);
683 if (addedOrUpdated && !validReceiverKey) {
684 // we need to verify this contact but it doesn't support HELLO_RES_ACK nor keys, do a little workaround
685 SendLegacyChallenge(ip, port, contactID, false);
688 // Check if firewalled
689 if (CKademlia::GetPrefs()->GetRecheckIP()) {
690 FirewalledCheck(ip, port, 0, 0);
694 // KADEMLIA2_HELLO_REQ
695 // Used in Kad2.0 only
696 void CKademliaUDPListener::Process2HelloRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey)
698 DEBUG_ONLY( uint16_t dbgOldUDPPort = port; )
699 uint8_t contactVersion = 0;
700 CUInt128 contactID;
701 bool addedOrUpdated = AddContact2(packetData, lenPacket, ip, port, &contactVersion, senderKey, validReceiverKey, true, true, NULL, &contactID); // might change (udp)port, validReceiverKey
702 wxASSERT(contactVersion >= 1);
703 #ifdef __DEBUG__
704 if (dbgOldUDPPort != port) {
705 AddDebugLogLineN(logClientKadUDP, wxT("KadContact ") + KadIPToString(ip) + wxString::Format(wxT(" uses his internal (%u) instead external (%u) UDP Port"), port, dbgOldUDPPort));
707 #endif
709 DebugSend(Kad2HelloRes, ip, port);
710 // 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
711 // receiver key or is already verified in the routing table, we request an additional ACK package to complete a three-way-handshake and
712 // verify the remote IP
713 SendMyDetails(KADEMLIA2_HELLO_RES, ip, port, contactVersion, senderKey, &contactID, addedOrUpdated && !validReceiverKey);
715 if (addedOrUpdated && !validReceiverKey && contactVersion == 7 && !HasActiveLegacyChallenge(ip)) {
716 // Kad Version 7 doesn't support HELLO_RES_ACK but sender/receiver keys, so send a ping to validate
717 DebugSend(Kad2Ping, ip, port);
718 SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL);
719 #ifdef __DEBUG__
720 CContact* contact = CKademlia::GetRoutingZone()->GetContact(contactID);
721 if (contact != NULL) {
722 if (contact->GetType() < 2) {
723 AddDebugLogLineN(logKadRouting, wxT("Sending (ping) challenge to a long known contact (should be verified already) - ") + KadIPToString(ip));
725 } else {
726 wxFAIL;
728 #endif
729 } else if (CKademlia::GetPrefs()->FindExternKadPort(false) && contactVersion > 5) { // do we need to find out our extern port?
730 DebugSend(Kad2Ping, ip, port);
731 SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL);
734 if (addedOrUpdated && !validReceiverKey && contactVersion < 7 && !HasActiveLegacyChallenge(ip)) {
735 // we need to verify this contact but it doesn't support HELLO_RES_ACK nor keys, do a little workaround
736 SendLegacyChallenge(ip, port, contactID, true);
739 // Check if firewalled
740 if (CKademlia::GetPrefs()->GetRecheckIP()) {
741 FirewalledCheck(ip, port, senderKey, contactVersion);
745 // KADEMLIA_HELLO_RES
746 // Used in Kad1.0 only
747 void CKademliaUDPListener::ProcessHelloResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
749 CHECK_TRACKED_PACKET(KADEMLIA_HELLO_REQ);
751 // Verify packet is expected size
752 CHECK_PACKET_EXACT_SIZE(25);
754 // Add or Update contact.
755 bool validReceiverKey = false;
756 CUInt128 contactID;
757 bool addedOrUpdated = AddContact(packetData, lenPacket, ip, port, 0, 0, validReceiverKey, true, &contactID);
758 if (addedOrUpdated && !validReceiverKey) {
759 // even though this is supposably an answer to a request from us, there are still possibilities to spoof
760 // it, as long as the attacker knows that we would send a HELLO_REQ (which in this case is quite often),
761 // so for old Kad Version which doesn't support keys, we need
762 SendLegacyChallenge(ip, port, contactID, false);
766 // KADEMLIA2_HELLO_RES_ACK
767 // Used in Kad2.0 only
768 void CKademliaUDPListener::Process2HelloResponseAck(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, bool validReceiverKey)
770 CHECK_PACKET_MIN_SIZE(17);
771 CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_RES);
773 if (!validReceiverKey) {
774 AddDebugLogLineN(logClientKadUDP, wxT("Receiver key is invalid! (sender: ") + KadIPToString(ip) + wxT(")"));
775 return;
778 // Additional packet to complete a three-way-handshake, making sure the remote contact is not using a spoofed ip.
779 CMemFile bio(packetData, lenPacket);
780 CUInt128 remoteID = bio.ReadUInt128();
781 if (!CKademlia::GetRoutingZone()->VerifyContact(remoteID, ip)) {
782 AddDebugLogLineN(logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip) + wxT(")"));
783 } else {
784 AddDebugLogLineN(logKadRouting, wxT("Verified contact (") + KadIPToString(ip) + wxT(") by HELLO_RES_ACK"));
788 // KADEMLIA2_HELLO_RES
789 // Used in Kad2.0 only
790 void CKademliaUDPListener::Process2HelloResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey, bool validReceiverKey)
792 CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_REQ);
794 // Add or Update contact.
795 uint8_t contactVersion;
796 CUInt128 contactID;
797 bool sendACK = false;
798 bool addedOrUpdated = AddContact2(packetData, lenPacket, ip, port, &contactVersion, senderKey, validReceiverKey, true, false, &sendACK, &contactID);
800 if (sendACK) {
801 // the client requested us to send an ACK packet, which proves that we're not a spoofed fake contact
802 // fulfill his wish
803 if (senderKey.IsEmpty()) {
804 // but we don't have a valid sender key - there is no point to reply in this case
805 // most likely a bug in the remote client
806 AddDebugLogLineN(logClientKadUDP, wxT("Remote client demands ACK, but didn't send any sender key! (sender: ") + KadIPToString(ip) + wxT(")"));
807 } else {
808 CMemFile packet(17);
809 packet.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
810 packet.WriteUInt8(0); // no tags at this time
811 DebugSend(Kad2HelloResAck, ip, port);
812 SendPacket(packet, KADEMLIA2_HELLO_RES_ACK, ip, port, senderKey, NULL);
814 } else if (addedOrUpdated && !validReceiverKey && contactVersion < 7) {
815 // even though this is supposably an answer to a request from us, there are still possibilities to spoof
816 // it, as long as the attacker knows that we would send a HELLO_REQ (which in this case is quite often),
817 // so for old Kad Version which doesn't support keys, we need
818 SendLegacyChallenge(ip, port, contactID, true);
821 // do we need to find out our extern port?
822 if (CKademlia::GetPrefs()->FindExternKadPort(false) && contactVersion > 5) {
823 DebugSend(Kad2Ping, ip, port);
824 SendNullPacket(KADEMLIA2_PING, ip, port, senderKey, NULL);
827 // Check if firewalled
828 if (CKademlia::GetPrefs()->GetRecheckIP()) {
829 FirewalledCheck(ip, port, senderKey, contactVersion);
833 // KADEMLIA_REQ
834 // Used in Kad1.0 only
835 void CKademliaUDPListener::ProcessKademliaRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
837 // Verify packet is expected size
838 CHECK_PACKET_EXACT_SIZE(33);
840 // RecheckIP and firewall status
841 if (CKademlia::GetPrefs()->GetRecheckIP()) {
842 FirewalledCheck(ip, port, 0, 0);
843 DebugSend(KadHelloReq, ip, port);
844 SendMyDetails(KADEMLIA_HELLO_REQ, ip, port, 0, 0, NULL, false);
847 // Get target and type
848 CMemFile bio(packetData, lenPacket);
849 uint8_t type = bio.ReadUInt8();
850 // bool flag1 = (type >> 6); //Reserved
851 // bool flag2 = (type >> 7); //Reserved
852 // bool flag3 = (type >> 8); //Reserved
854 type &= 0x1F;
855 if( type == 0 ) {
856 throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type) + wxString::FromAscii(__FUNCTION__);
859 // This is the target node trying to be found.
860 CUInt128 target = bio.ReadUInt128();
861 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
862 distance.XOR(target);
864 // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.
865 CUInt128 check = bio.ReadUInt128();
866 if (CKademlia::GetPrefs()->GetKadID().CompareTo(check)) {
867 return;
870 // Get required number closest to target
871 ContactMap results;
872 CKademlia::GetRoutingZone()->GetClosestTo(2, target, distance, type, &results);
873 uint16_t count = (uint16_t)results.size();
875 // Write response
876 // Max count is 32. size 817..
877 // 16 + 1 + 25(32)
878 CMemFile packetdata(817);
879 packetdata.WriteUInt128(target);
880 packetdata.WriteUInt8((uint8_t)count);
881 CContact *c;
882 for (ContactMap::const_iterator it = results.begin(); it != results.end(); ++it) {
883 c = it->second;
884 packetdata.WriteUInt128(c->GetClientID());
885 packetdata.WriteUInt32(c->GetIPAddress());
886 packetdata.WriteUInt16(c->GetUDPPort());
887 packetdata.WriteUInt16(c->GetTCPPort());
888 packetdata.WriteUInt8(c->GetType());
891 DebugSendF(wxString::Format(wxT("KadRes (count=%u)"), count), ip, port);
892 SendPacket(packetdata, KADEMLIA_RES, ip, port, 0, NULL);
895 // KADEMLIA2_REQ
896 // Used in Kad2.0 only
897 void CKademliaUDPListener::ProcessKademlia2Request(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
899 // Get target and type
900 CMemFile bio(packetData, lenPacket);
901 uint8_t type = bio.ReadUInt8();
902 type &= 0x1F;
903 if (type == 0) {
904 throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type) + wxString::FromAscii(__FUNCTION__);
907 // This is the target node trying to be found.
908 CUInt128 target = bio.ReadUInt128();
909 // Convert Target to Distance as this is how we store contacts.
910 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
911 distance.XOR(target);
913 // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new KadID.
914 CUInt128 check = bio.ReadUInt128();
915 if (CKademlia::GetPrefs()->GetKadID() == check) {
916 // Get required number closest to target
917 ContactMap results;
918 CKademlia::GetRoutingZone()->GetClosestTo(2, target, distance, type, &results);
919 uint8_t count = (uint8_t)results.size();
921 // Write response
922 // Max count is 32. size 817..
923 // 16 + 1 + 25(32)
924 CMemFile packetdata(817);
925 packetdata.WriteUInt128(target);
926 packetdata.WriteUInt8(count);
927 CContact *c;
928 for (ContactMap::const_iterator it = results.begin(); it != results.end(); ++it) {
929 c = it->second;
930 packetdata.WriteUInt128(c->GetClientID());
931 packetdata.WriteUInt32(c->GetIPAddress());
932 packetdata.WriteUInt16(c->GetUDPPort());
933 packetdata.WriteUInt16(c->GetTCPPort());
934 packetdata.WriteUInt8(c->GetVersion()); //<- Kad Version inserted to allow backward compatibility.
937 DebugSendF(wxString::Format(wxT("Kad2Res (count=%u)"), count), ip, port);
938 SendPacket(packetdata, KADEMLIA2_RES, ip, port, senderKey, NULL);
942 // KADEMLIA_RES
943 // Used in Kad1.0 only
944 void CKademliaUDPListener::ProcessKademliaResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
946 // Verify packet is expected size
947 CHECK_PACKET_MIN_SIZE(17);
948 CHECK_TRACKED_PACKET(KADEMLIA_REQ);
950 // Used Pointers
951 CRoutingZone *routingZone = CKademlia::GetRoutingZone();
953 if (CKademlia::GetPrefs()->GetRecheckIP()) {
954 FirewalledCheck(ip, port, 0, 0);
955 DebugSend(KadHelloReq, ip, port);
956 SendMyDetails(KADEMLIA_HELLO_REQ, ip, port, 0, 0, NULL, false);
959 // What search does this relate to
960 CMemFile bio(packetData, lenPacket);
961 CUInt128 target = bio.ReadUInt128();
962 uint8_t numContacts = bio.ReadUInt8();
964 // Is this one of our legacy challenge packets?
965 CUInt128 contactID;
966 if (IsLegacyChallenge(target, ip, KADEMLIA_REQ, contactID)) {
967 // yup it is, set the contact as verified
968 if (!routingZone->VerifyContact(contactID, ip)) {
969 AddDebugLogLineN(logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip) + wxT(")"));
970 } else {
971 AddDebugLogLineN(logKadRouting, wxT("Verified contact with legacy challenge (KadReq) - ") + KadIPToString(ip));
973 return; // we do not actually care for its other content
976 // Verify packet is expected size
977 CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts);
979 uint32_t ignoredCount = 0;
980 CScopedPtr<ContactList> results(new ContactList);
982 for (uint16_t i = 0; i < numContacts; i++) {
983 CUInt128 id = bio.ReadUInt128();
984 uint32_t contactIP = bio.ReadUInt32();
985 uint16_t contactPort = bio.ReadUInt16();
986 uint16_t tport = bio.ReadUInt16();
987 bio.ReadUInt8();
988 uint32_t hostIP = wxUINT32_SWAP_ALWAYS(contactIP);
989 if(::IsGoodIPPort(hostIP, contactPort) && contactPort != 53 /*No DNS Port without encryption*/) {
990 if (!theApp->ipfilter->IsFiltered(hostIP)) {
991 bool verified = false;
992 // we are now setting all version for received contact to "2" which means we assume full Kad2 when adding
993 // the contact to the routing table. If this should be an old Kad1 contact, we won't be able to keep it, but
994 // we avoid having to send double hello packets to the 90% Kad2 nodes
995 // This is the first step of dropping Kad1 support
996 bool wasAdded = routingZone->AddUnfiltered(id, contactIP, contactPort, tport, 2, 0, verified, false, false, false);
997 CContact *temp = new CContact(id, contactIP, contactPort, tport, 0, 0, false, target);
998 if (wasAdded || routingZone->IsAcceptableContact(temp)) {
999 results->push_back(temp);
1000 } else {
1001 ignoredCount++;
1002 delete temp;
1008 if (ignoredCount > 0) {
1009 AddDebugLogLineN(logClientKadUDP, wxString::Format(wxT("Ignored %u bad contacts in routing answer from "), ignoredCount) + KadIPToString(ip));
1012 CSearchManager::ProcessResponse(target, ip, port, results.release());
1015 // KADEMLIA2_RES
1016 // Used in Kad2.0 only
1017 void CKademliaUDPListener::ProcessKademlia2Response(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& WXUNUSED(senderKey))
1019 CHECK_TRACKED_PACKET(KADEMLIA2_REQ);
1021 // Used Pointers
1022 CRoutingZone *routingZone = CKademlia::GetRoutingZone();
1024 // don't do firewallchecks on this opcode anymore, since we need the contacts kad version - hello opcodes are good enough
1025 // if (CKademlia::GetPrefs()->GetRecheckIP()) {
1026 // FirewalledCheck(ip, port, senderKey);
1027 // DebugSend(Kad2HelloReq, ip, port);
1028 // SendMyDetails(KADEMLIA2_HELLO_REQ, ip, port, true, senderKey, NULL);
1029 // }
1031 // What search does this relate to
1032 CMemFile bio(packetData, lenPacket);
1033 CUInt128 target = bio.ReadUInt128();
1034 uint8_t numContacts = bio.ReadUInt8();
1036 // Is this one of our legacy challenge packets?
1037 CUInt128 contactID;
1038 if (IsLegacyChallenge(target, ip, KADEMLIA2_REQ, contactID)) {
1039 // yup it is, set the contact as verified
1040 if (!routingZone->VerifyContact(contactID, ip)) {
1041 AddDebugLogLineN(logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip) + wxT(")"));
1042 } else {
1043 AddDebugLogLineN(logKadRouting, wxT("Verified contact with legacy challenge (Kad2Req) - ") + KadIPToString(ip));
1045 return; // we do not actually care for its other content
1047 // Verify packet is expected size
1048 CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts);
1050 // is this a search for firewallcheck ips?
1051 bool isFirewallUDPCheckSearch = false;
1052 if (CUDPFirewallTester::IsFWCheckUDPRunning() && CSearchManager::IsFWCheckUDPSearch(target)) {
1053 isFirewallUDPCheckSearch = true;
1056 uint32_t ignoredCount = 0;
1057 CScopedPtr<ContactList> results(new ContactList);
1058 for (uint8_t i = 0; i < numContacts; i++) {
1059 CUInt128 id = bio.ReadUInt128();
1060 uint32_t contactIP = bio.ReadUInt32();
1061 uint16_t contactPort = bio.ReadUInt16();
1062 uint16_t tport = bio.ReadUInt16();
1063 uint8_t version = bio.ReadUInt8();
1064 uint32_t hostIP = wxUINT32_SWAP_ALWAYS(contactIP);
1065 if (::IsGoodIPPort(hostIP, contactPort)) {
1066 if (!theApp->ipfilter->IsFiltered(hostIP) && !(contactPort == 53 && version <= 5) /*No DNS Port without encryption*/) {
1067 if (isFirewallUDPCheckSearch) {
1068 // UDP FirewallCheck searches are special. The point is we need an IP which we didn't sent a UDP message yet
1069 // (or in the near future), so we do not try to add those contacts to our routingzone and we also don't
1070 // deliver them back to the searchmanager (because he would UDP-ask them for further results), but only report
1071 // them to FirewallChecker - this will of course cripple the search but thats not the point, since we only
1072 // care for IPs and not the random set target
1073 CUDPFirewallTester::AddPossibleTestContact(id, contactIP, contactPort, tport, target, version, 0, false);
1074 } else {
1075 bool verified = false;
1076 bool wasAdded = routingZone->AddUnfiltered(id, contactIP, contactPort, tport, version, 0, verified, false, false, false);
1077 CContact *temp = new CContact(id, contactIP, contactPort, tport, version, 0, false, target);
1078 if (wasAdded || routingZone->IsAcceptableContact(temp)) {
1079 results->push_back(temp);
1080 } else {
1081 ignoredCount++;
1082 delete temp;
1089 if (ignoredCount > 0) {
1090 AddDebugLogLineN(logClientKadUDP, wxString::Format(wxT("Ignored %u bad contacts in routing answer from "), ignoredCount) + KadIPToString(ip));
1093 CSearchManager::ProcessResponse(target, ip, port, results.release());
1096 void CKademliaUDPListener::Free(SSearchTerm* pSearchTerms)
1098 if (pSearchTerms) {
1099 Free(pSearchTerms->left);
1100 Free(pSearchTerms->right);
1101 delete pSearchTerms;
1105 SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile& bio, int iLevel)
1107 // the max. depth has to match our own limit for creating the search expression
1108 // (see also 'ParsedSearchExpression' and 'GetSearchPacket')
1109 if (iLevel >= 24){
1110 AddDebugLogLineN(logKadSearch, wxT("***NOTE: Search expression tree exceeds depth limit!"));
1111 return NULL;
1113 iLevel++;
1115 uint8_t op = bio.ReadUInt8();
1116 if (op == 0x00) {
1117 uint8_t boolop = bio.ReadUInt8();
1118 if (boolop == 0x00) { // AND
1119 SSearchTerm* pSearchTerm = new SSearchTerm;
1120 pSearchTerm->type = SSearchTerm::AND;
1121 //TRACE(" AND");
1122 if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1123 wxFAIL;
1124 delete pSearchTerm;
1125 return NULL;
1127 if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1128 wxFAIL;
1129 Free(pSearchTerm->left);
1130 delete pSearchTerm;
1131 return NULL;
1133 return pSearchTerm;
1134 } else if (boolop == 0x01) { // OR
1135 SSearchTerm* pSearchTerm = new SSearchTerm;
1136 pSearchTerm->type = SSearchTerm::OR;
1137 //TRACE(" OR");
1138 if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1139 wxFAIL;
1140 delete pSearchTerm;
1141 return NULL;
1143 if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1144 wxFAIL;
1145 Free(pSearchTerm->left);
1146 delete pSearchTerm;
1147 return NULL;
1149 return pSearchTerm;
1150 } else if (boolop == 0x02) { // NOT
1151 SSearchTerm* pSearchTerm = new SSearchTerm;
1152 pSearchTerm->type = SSearchTerm::NOT;
1153 //TRACE(" NOT");
1154 if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1155 wxFAIL;
1156 delete pSearchTerm;
1157 return NULL;
1159 if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
1160 wxFAIL;
1161 Free(pSearchTerm->left);
1162 delete pSearchTerm;
1163 return NULL;
1165 return pSearchTerm;
1166 } else {
1167 AddDebugLogLineN(logKadSearch, wxString::Format(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop));
1168 return NULL;
1170 } else if (op == 0x01) { // String
1171 wxString str(bio.ReadString(true));
1173 // Make lowercase, the search code expects lower case strings!
1174 str.MakeLower();
1176 SSearchTerm* pSearchTerm = new SSearchTerm;
1177 pSearchTerm->type = SSearchTerm::String;
1178 pSearchTerm->astr = new wxArrayString;
1180 // pre-tokenize the string term
1181 //#warning TODO: TokenizeOptQuotedSearchTerm
1182 wxStringTokenizer token(str, CSearchManager::GetInvalidKeywordChars(),wxTOKEN_DEFAULT );
1183 while (token.HasMoreTokens()) {
1184 wxString strTok(token.GetNextToken());
1185 if (!strTok.IsEmpty()) {
1186 pSearchTerm->astr->Add(strTok);
1190 return pSearchTerm;
1191 } else if (op == 0x02) { // Meta tag
1192 // read tag value
1193 wxString strValue(bio.ReadString(true));
1194 // Make lowercase, the search code expects lower case strings!
1195 strValue.MakeLower();
1197 // read tag name
1198 wxString strTagName = bio.ReadString(false);
1200 SSearchTerm* pSearchTerm = new SSearchTerm;
1201 pSearchTerm->type = SSearchTerm::MetaTag;
1202 pSearchTerm->tag = new CTagString(strTagName, strValue);
1203 return pSearchTerm;
1205 else if (op == 0x03 || op == 0x08) { // Numeric relation (0x03=32-bit or 0x08=64-bit)
1206 static const struct {
1207 SSearchTerm::ESearchTermType eSearchTermOp;
1208 wxString pszOp;
1209 } _aOps[] =
1211 { SSearchTerm::OpEqual, wxT("=") }, // mmop=0x00
1212 { SSearchTerm::OpGreater, wxT(">") }, // mmop=0x01
1213 { SSearchTerm::OpLess, wxT("<") }, // mmop=0x02
1214 { SSearchTerm::OpGreaterEqual, wxT(">=") }, // mmop=0x03
1215 { SSearchTerm::OpLessEqual, wxT("<=") }, // mmop=0x04
1216 { SSearchTerm::OpNotEqual, wxT("<>") } // mmop=0x05
1219 // read tag value
1220 uint64_t ullValue = (op == 0x03) ? bio.ReadUInt32() : bio.ReadUInt64();
1222 // read integer operator
1223 uint8_t mmop = bio.ReadUInt8();
1224 if (mmop >= itemsof(_aOps)){
1225 AddDebugLogLineN(logKadSearch, wxString::Format(wxT("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop));
1226 return NULL;
1229 // read tag name
1230 wxString strTagName = bio.ReadString(false);
1232 SSearchTerm* pSearchTerm = new SSearchTerm;
1233 pSearchTerm->type = _aOps[mmop].eSearchTermOp;
1234 pSearchTerm->tag = new CTagVarInt(strTagName, ullValue);
1236 return pSearchTerm;
1237 } else {
1238 AddDebugLogLineN(logKadSearch, wxString::Format(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), op));
1239 return NULL;
1243 // KADEMLIA_SEARCH_REQ
1244 // Used in Kad1.0 only
1245 void CKademliaUDPListener::ProcessSearchRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
1247 // Verify packet is expected size
1248 CHECK_PACKET_MIN_SIZE(17);
1250 CMemFile bio(packetData, lenPacket);
1251 CUInt128 target = bio.ReadUInt128();
1252 uint8_t restrictive = bio.ReadUInt8();
1254 if (lenPacket == 17) {
1255 if (restrictive) {
1256 // Source request
1257 CKademlia::GetIndexed()->SendValidSourceResult(target, ip, port, false, 0, 0, 0);
1258 } else {
1259 // Single keyword request
1260 CKademlia::GetIndexed()->SendValidKeywordResult(target, NULL, ip, port, true, false, 0, 0);
1262 } else if (lenPacket > 17) {
1263 SSearchTerm* pSearchTerms = NULL;
1264 bool oldClient = true;
1265 if (restrictive) {
1266 pSearchTerms = CreateSearchExpressionTree(bio, 0);
1267 if (pSearchTerms == NULL) {
1268 throw wxString(wxT("Invalid search expression"));
1270 if (restrictive > 1) {
1271 oldClient = false;
1273 } else {
1274 oldClient = false;
1277 // Keyword request with added options.
1278 CKademlia::GetIndexed()->SendValidKeywordResult(target, pSearchTerms, ip, port, oldClient, false, 0, 0);
1279 Free(pSearchTerms);
1283 // KADEMLIA2_SEARCH_KEY_REQ
1284 // Used in Kad2.0 only
1285 void CKademliaUDPListener::Process2SearchKeyRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1287 CMemFile bio(packetData, lenPacket);
1288 CUInt128 target = bio.ReadUInt128();
1289 uint16_t startPosition = bio.ReadUInt16();
1290 bool restrictive = ((startPosition & 0x8000) == 0x8000);
1291 startPosition &= 0x7FFF;
1292 SSearchTerm* pSearchTerms = NULL;
1293 if (restrictive) {
1294 pSearchTerms = CreateSearchExpressionTree(bio, 0);
1295 if (pSearchTerms == NULL) {
1296 throw wxString(wxT("Invalid search expression"));
1299 CKademlia::GetIndexed()->SendValidKeywordResult(target, pSearchTerms, ip, port, false, true, startPosition, senderKey);
1300 if (pSearchTerms) {
1301 Free(pSearchTerms);
1305 // KADEMLIA2_SEARCH_SOURCE_REQ
1306 // Used in Kad2.0 only
1307 void CKademliaUDPListener::Process2SearchSourceRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1309 CMemFile bio(packetData, lenPacket);
1310 CUInt128 target = bio.ReadUInt128();
1311 uint16_t startPosition = (bio.ReadUInt16() & 0x7FFF);
1312 uint64_t fileSize = bio.ReadUInt64();
1313 CKademlia::GetIndexed()->SendValidSourceResult(target, ip, port, true, startPosition, fileSize, senderKey);
1316 void CKademliaUDPListener::ProcessSearchResponse(CMemFile& bio)
1318 // What search does this relate to
1319 CUInt128 target = bio.ReadUInt128();
1321 // How many results..
1322 uint16_t count = bio.ReadUInt16();
1323 while (count > 0) {
1324 // What is the answer
1325 CUInt128 answer = bio.ReadUInt128();
1327 // Get info about answer
1328 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
1329 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
1330 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
1331 // If that tag list is once used for something else than for viewing, special care has to be taken for any
1332 // string conversion!
1333 TagPtrList* tags = new TagPtrList;
1334 try {
1335 bio.ReadTagPtrList(tags, true/*bOptACP*/);
1336 } catch(...) {
1337 deleteTagPtrListEntries(tags);
1338 delete tags;
1339 tags = NULL;
1340 throw;
1342 CSearchManager::ProcessResult(target, answer, tags);
1343 count--;
1348 // KADEMLIA_SEARCH_RES
1349 // Used in Kad1.0 only
1350 void CKademliaUDPListener::ProcessSearchResponse(const uint8_t *packetData, uint32_t lenPacket)
1352 // Verify packet is expected size
1353 CHECK_PACKET_MIN_SIZE(37);
1355 // What search does this relate to
1356 CMemFile bio(packetData, lenPacket);
1357 ProcessSearchResponse(bio);
1360 // KADEMLIA2_SEARCH_RES
1361 // Used in Kad2.0 only
1362 void CKademliaUDPListener::Process2SearchResponse(const uint8_t *packetData, uint32_t lenPacket, const CKadUDPKey& WXUNUSED(senderKey))
1364 CMemFile bio(packetData, lenPacket);
1366 // Who sent this packet.
1367 CUInt128 source = bio.ReadUInt128();
1369 ProcessSearchResponse(bio);
1372 // KADEMLIA_PUBLISH_REQ
1373 // Used in Kad1.0 only
1374 void CKademliaUDPListener::ProcessPublishRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
1376 //There are different types of publishing..
1377 //Keyword and File are Stored..
1378 // Verify packet is expected size
1379 CHECK_PACKET_MIN_SIZE(37);
1381 //Used Pointers
1382 CIndexed *indexed = CKademlia::GetIndexed();
1384 // check if we are UDP firewalled
1385 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1386 //We are firewalled. We should not index this entry and give publisher a false report.
1387 return;
1390 CMemFile bio(packetData, lenPacket);
1391 CUInt128 file = bio.ReadUInt128();
1393 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
1394 distance.XOR(file);
1396 if (thePrefs::FilterLanIPs() && distance.Get32BitChunk(0) > SEARCHTOLERANCE) {
1397 return;
1400 DEBUG_ONLY( wxString strInfo; )
1401 uint16_t count = bio.ReadUInt16();
1402 bool flag = false;
1403 uint8_t load = 0;
1404 while (count > 0) {
1405 DEBUG_ONLY( strInfo.Clear(); )
1407 CUInt128 target = bio.ReadUInt128();
1409 Kademlia::CKeyEntry* entry = new Kademlia::CKeyEntry();
1410 try {
1411 entry->m_uIP = ip;
1412 entry->m_uUDPport = port;
1413 entry->m_uKeyID.SetValue(file);
1414 entry->m_uSourceID.SetValue(target);
1415 uint32_t tags = bio.ReadUInt8();
1416 while (tags > 0) {
1417 CTag* tag = bio.ReadTag();
1418 if (tag) {
1419 if (!tag->GetName().Cmp(TAG_SOURCETYPE)) {
1420 if (entry->m_bSource == false) {
1421 entry->AddTag(new CTagVarInt(TAG_SOURCEIP, entry->m_uIP));
1422 entry->AddTag(new CTagVarInt(TAG_SOURCEUPORT, entry->m_uUDPport));
1423 entry->AddTag(tag);
1424 entry->m_bSource = true;
1425 } else {
1426 //More than one sourcetype tag found.
1427 delete tag;
1429 } else if (!tag->GetName().Cmp(TAG_FILENAME)) {
1430 if (entry->GetCommonFileName().IsEmpty()) {
1431 entry->SetFileName(tag->GetStr());
1432 DEBUG_ONLY( strInfo += CFormat(wxT(" Name=\"%s\"")) % tag->GetStr(); )
1434 delete tag;
1435 } else if (!tag->GetName().Cmp(TAG_FILESIZE)) {
1436 if (entry->m_uSize == 0) {
1437 if (tag->IsBsob() && (tag->GetBsobSize() == 8)) {
1438 // Kad1.0 uint64 type using a BSOB.
1439 entry->m_uSize = PeekUInt64(tag->GetBsob());
1440 } else {
1441 wxASSERT(tag->IsInt());
1442 entry->m_uSize = tag->GetInt();
1444 DEBUG_ONLY( strInfo += wxString::Format(wxT(" Size=%") WXLONGLONGFMTSPEC wxT("u"), entry->m_uSize); )
1446 delete tag;
1447 } else if (!tag->GetName().Cmp(TAG_SOURCEPORT)) {
1448 if (entry->m_uTCPport == 0) {
1449 entry->m_uTCPport = tag->GetInt();
1450 entry->AddTag(tag);
1451 } else {
1452 //More than one port tag found
1453 delete tag;
1455 } else {
1456 //TODO: Filter tags
1457 entry->AddTag(tag);
1460 tags--;
1462 #ifdef __DEBUG__
1463 if (!strInfo.IsEmpty()) {
1464 AddDebugLogLineN(logClientKadUDP, strInfo);
1466 #endif
1467 } catch(...) {
1468 //printf("Error on count %i tag %i\n",totalcount-count, totaltags-tags);
1469 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishRequest"),ip,port,packetData,lenPacket);
1470 delete entry;
1471 throw;
1474 if (entry->m_bSource == true) {
1475 entry->m_tLifeTime = (uint32_t)time(NULL) + KADEMLIAREPUBLISHTIMES;
1476 CEntry *sourceEntry = entry->Copy(); // "downcast" since we didnt knew before if this was a keyword, Kad1 support gets removed soon anyway no need for a beautiful solution here
1477 delete entry;
1478 entry = NULL;
1479 if (indexed->AddSources(file, target, sourceEntry, load)) {
1480 flag = true;
1481 } else {
1482 delete sourceEntry;
1483 sourceEntry = NULL;
1485 } else {
1486 entry->m_tLifeTime = (uint32_t)time(NULL) + KADEMLIAREPUBLISHTIMEK;
1487 if (indexed->AddKeyword(file, target, entry, load)) {
1488 // This makes sure we send a publish response..
1489 // This also makes sure we index all the files for this keyword.
1490 flag = true;
1491 } else {
1492 //We already indexed the maximum number of keywords.
1493 //We do not index anymore but we still send a success..
1494 //Reason: Because if a VERY busy node tells the publisher it failed,
1495 //this busy node will spread to all the surrounding nodes causing popular
1496 //keywords to be stored on MANY nodes..
1497 //So, once we are full, we will periodically clean our list until we can
1498 //begin storing again..
1499 flag = true;
1500 delete entry;
1501 entry = NULL;
1504 count--;
1506 if (flag) {
1507 CMemFile packetdata(17);
1508 packetdata.WriteUInt128(file);
1509 packetdata.WriteUInt8(load);
1511 DebugSend(KadPublishRes, ip, port);
1512 SendPacket(packetdata, KADEMLIA_PUBLISH_RES, ip, port, 0, NULL);
1516 // KADEMLIA2_PUBLISH_KEY_REQ
1517 // Used in Kad2.0 only
1518 void CKademliaUDPListener::Process2PublishKeyRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1520 //Used Pointers
1521 CIndexed *indexed = CKademlia::GetIndexed();
1523 // check if we are UDP firewalled
1524 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1525 //We are firewalled. We should not index this entry and give publisher a false report.
1526 return;
1529 CMemFile bio(packetData, lenPacket);
1530 CUInt128 file = bio.ReadUInt128();
1532 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
1533 distance.XOR(file);
1535 // Shouldn't LAN IPs already be filtered?
1536 if (thePrefs::FilterLanIPs() && distance.Get32BitChunk(0) > SEARCHTOLERANCE) {
1537 return;
1540 DEBUG_ONLY( wxString strInfo; )
1541 uint16_t count = bio.ReadUInt16();
1542 uint8_t load = 0;
1543 while (count > 0) {
1544 DEBUG_ONLY( strInfo.Clear(); )
1546 CUInt128 target = bio.ReadUInt128();
1548 Kademlia::CKeyEntry* entry = new Kademlia::CKeyEntry();
1551 entry->m_uIP = ip;
1552 entry->m_uUDPport = port;
1553 entry->m_uKeyID.SetValue(file);
1554 entry->m_uSourceID.SetValue(target);
1555 entry->m_tLifeTime = (uint32_t)time(NULL) + KADEMLIAREPUBLISHTIMEK;
1556 entry->m_bSource = false;
1557 uint32_t tags = bio.ReadUInt8();
1558 while (tags > 0) {
1559 CTag* tag = bio.ReadTag();
1560 if (tag) {
1561 if (!tag->GetName().Cmp(TAG_FILENAME)) {
1562 if (entry->GetCommonFileName().IsEmpty()) {
1563 entry->SetFileName(tag->GetStr());
1564 DEBUG_ONLY( strInfo += CFormat(wxT(" Name=\"%s\"")) % entry->GetCommonFileName(); )
1566 delete tag; // tag is no longer stored, but membervar is used
1567 } else if (!tag->GetName().Cmp(TAG_FILESIZE)) {
1568 if (entry->m_uSize == 0) {
1569 if (tag->IsBsob() && tag->GetBsobSize() == 8) {
1570 entry->m_uSize = PeekUInt64(tag->GetBsob());
1571 } else {
1572 entry->m_uSize = tag->GetInt();
1574 DEBUG_ONLY( strInfo += wxString::Format(wxT(" Size=%") WXLONGLONGFMTSPEC wxT("u"), entry->m_uSize); )
1576 delete tag; // tag is no longer stored, but membervar is used
1577 } else {
1578 //TODO: Filter tags
1579 entry->AddTag(tag);
1582 tags--;
1584 #ifdef __DEBUG__
1585 if (!strInfo.IsEmpty()) {
1586 AddDebugLogLineN(logClientKadUDP, strInfo);
1588 #endif
1589 } catch(...) {
1590 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishKeyRequest"),ip,port,packetData,lenPacket);
1591 delete entry;
1592 throw;
1595 if (!indexed->AddKeyword(file, target, entry, load)) {
1596 //We already indexed the maximum number of keywords.
1597 //We do not index anymore but we still send a success..
1598 //Reason: Because if a VERY busy node tells the publisher it failed,
1599 //this busy node will spread to all the surrounding nodes causing popular
1600 //keywords to be stored on MANY nodes..
1601 //So, once we are full, we will periodically clean our list until we can
1602 //begin storing again..
1603 delete entry;
1604 entry = NULL;
1606 count--;
1608 CMemFile packetdata(17);
1609 packetdata.WriteUInt128(file);
1610 packetdata.WriteUInt8(load);
1611 DebugSend(Kad2PublishRes, ip, port);
1612 SendPacket(packetdata, KADEMLIA2_PUBLISH_RES, ip, port, senderKey, NULL);
1615 // KADEMLIA2_PUBLISH_SOURCE_REQ
1616 // Used in Kad2.0 only
1617 void CKademliaUDPListener::Process2PublishSourceRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1619 //Used Pointers
1620 CIndexed *indexed = CKademlia::GetIndexed();
1622 // check if we are UDP firewalled
1623 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1624 //We are firewalled. We should not index this entry and give publisher a false report.
1625 return;
1628 CMemFile bio(packetData, lenPacket);
1629 CUInt128 file = bio.ReadUInt128();
1631 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
1632 distance.XOR(file);
1634 if (thePrefs::FilterLanIPs() && distance.Get32BitChunk(0) > SEARCHTOLERANCE) {
1635 return;
1638 DEBUG_ONLY( wxString strInfo; )
1639 uint8_t load = 0;
1640 bool flag = false;
1641 CUInt128 target = bio.ReadUInt128();
1642 Kademlia::CEntry* entry = new Kademlia::CEntry();
1643 try {
1644 entry->m_uIP = ip;
1645 entry->m_uUDPport = port;
1646 entry->m_uKeyID.SetValue(file);
1647 entry->m_uSourceID.SetValue(target);
1648 entry->m_bSource = false;
1649 entry->m_tLifeTime = (uint32_t)time(NULL) + KADEMLIAREPUBLISHTIMES;
1650 bool addUDPPortTag = true;
1651 uint32_t tags = bio.ReadUInt8();
1652 while (tags > 0) {
1653 CTag* tag = bio.ReadTag();
1654 if (tag) {
1655 if (!tag->GetName().Cmp(TAG_SOURCETYPE)) {
1656 if (entry->m_bSource == false) {
1657 entry->AddTag(new CTagVarInt(TAG_SOURCEIP, entry->m_uIP));
1658 entry->AddTag(tag);
1659 entry->m_bSource = true;
1660 } else {
1661 //More than one sourcetype tag found.
1662 delete tag;
1664 } else if (!tag->GetName().Cmp(TAG_FILESIZE)) {
1665 if (entry->m_uSize == 0) {
1666 if (tag->IsBsob() && tag->GetBsobSize() == 8) {
1667 entry->m_uSize = PeekUInt64(tag->GetBsob());
1668 } else {
1669 entry->m_uSize = tag->GetInt();
1671 DEBUG_ONLY( strInfo += wxString::Format(wxT(" Size=%") WXLONGLONGFMTSPEC wxT("u"), entry->m_uSize); )
1673 delete tag;
1674 } else if (!tag->GetName().Cmp(TAG_SOURCEPORT)) {
1675 if (entry->m_uTCPport == 0) {
1676 entry->m_uTCPport = (uint16_t)tag->GetInt();
1677 entry->AddTag(tag);
1678 } else {
1679 //More than one port tag found
1680 delete tag;
1682 } else if (!tag->GetName().Cmp(TAG_SOURCEUPORT)) {
1683 if (addUDPPortTag && tag->IsInt() && tag->GetInt() != 0) {
1684 entry->m_uUDPport = (uint16_t)tag->GetInt();
1685 entry->AddTag(tag);
1686 addUDPPortTag = false;
1687 } else {
1688 //More than one udp port tag found
1689 delete tag;
1691 } else {
1692 //TODO: Filter tags
1693 entry->AddTag(tag);
1696 tags--;
1698 if (addUDPPortTag) {
1699 entry->AddTag(new CTagVarInt(TAG_SOURCEUPORT, entry->m_uUDPport));
1701 #ifdef __DEBUG__
1702 if (!strInfo.IsEmpty()) {
1703 AddDebugLogLineN(logClientKadUDP, strInfo);
1705 #endif
1706 } catch(...) {
1707 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishSourceRequest"),ip,port,packetData,lenPacket);
1708 delete entry;
1709 throw;
1712 if (entry->m_bSource == true) {
1713 if (indexed->AddSources(file, target, entry, load)) {
1714 flag = true;
1715 } else {
1716 delete entry;
1717 entry = NULL;
1719 } else {
1720 delete entry;
1721 entry = NULL;
1723 if (flag) {
1724 CMemFile packetdata(17);
1725 packetdata.WriteUInt128(file);
1726 packetdata.WriteUInt8(load);
1727 DebugSend(Kad2PublishRes, ip, port);
1728 SendPacket(packetdata, KADEMLIA2_PUBLISH_RES, ip, port, senderKey, NULL);
1732 // KADEMLIA_PUBLISH_RES
1733 // Used only by Kad1.0
1734 void CKademliaUDPListener::ProcessPublishResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
1736 // Verify packet is expected size
1737 CHECK_PACKET_MIN_SIZE(16);
1738 CHECK_TRACKED_PACKET(KADEMLIA_PUBLISH_REQ);
1740 CMemFile bio(packetData, lenPacket);
1741 CUInt128 file = bio.ReadUInt128();
1743 bool loadResponse = false;
1744 uint8_t load = 0;
1745 if (bio.GetLength() > bio.GetPosition()) {
1746 loadResponse = true;
1747 load = bio.ReadUInt8();
1750 CSearchManager::ProcessPublishResult(file, load, loadResponse);
1753 // KADEMLIA2_PUBLISH_RES
1754 // Used only by Kad2.0
1755 void CKademliaUDPListener::Process2PublishResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1757 if (!IsOnOutTrackList(ip, KADEMLIA2_PUBLISH_KEY_REQ) && !IsOnOutTrackList(ip, KADEMLIA2_PUBLISH_SOURCE_REQ) && !IsOnOutTrackList(ip, KADEMLIA2_PUBLISH_NOTES_REQ)) {
1758 throw wxString::Format(wxT("***NOTE: Received unrequested response packet, size (%u) in "), lenPacket) + wxString::FromAscii(__FUNCTION__);
1760 CMemFile bio(packetData, lenPacket);
1761 CUInt128 file = bio.ReadUInt128();
1762 uint8_t load = bio.ReadUInt8();
1763 CSearchManager::ProcessPublishResult(file, load, true);
1764 if (bio.GetLength() > bio.GetPosition()) {
1765 // for future use
1766 uint8_t options = bio.ReadUInt8();
1767 bool requestACK = (options & 0x01) > 0;
1768 if (requestACK && !senderKey.IsEmpty()) {
1769 DebugSend(Kad2PublishResAck, ip, port);
1770 SendNullPacket(KADEMLIA2_PUBLISH_RES_ACK, ip, port, senderKey, NULL);
1775 // KADEMLIA_SEARCH_NOTES_REQ
1776 // Used only by Kad1.0
1777 void CKademliaUDPListener::ProcessSearchNotesRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
1779 // Verify packet is expected size
1780 CHECK_PACKET_MIN_SIZE(32);
1782 CMemFile bio(packetData, lenPacket);
1783 CUInt128 target = bio.ReadUInt128();
1784 // This info is currently not used.
1785 // CUInt128 source = bio.ReadUInt128();
1787 CKademlia::GetIndexed()->SendValidNoteResult(target, ip, port, false, 0, 0);
1790 // KADEMLIA2_SEARCH_NOTES_REQ
1791 // Used only by Kad2.0
1792 void CKademliaUDPListener::Process2SearchNotesRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1794 CMemFile bio(packetData, lenPacket);
1795 CUInt128 target = bio.ReadUInt128();
1796 uint64_t fileSize = bio.ReadUInt64();
1797 CKademlia::GetIndexed()->SendValidNoteResult(target, ip, port, true, fileSize, senderKey);
1800 // KADEMLIA_SEARCH_NOTES_RES
1801 // Used only by Kad1.0
1802 void CKademliaUDPListener::ProcessSearchNotesResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
1804 // Verify packet is expected size
1805 CHECK_PACKET_MIN_SIZE(37);
1806 CHECK_TRACKED_PACKET(KADEMLIA_SEARCH_NOTES_REQ);
1808 // What search does this relate to
1809 CMemFile bio(packetData, lenPacket);
1810 ProcessSearchResponse(bio);
1813 // KADEMLIA_PUBLISH_NOTES_REQ
1814 // Used only by Kad1.0
1815 void CKademliaUDPListener::ProcessPublishNotesRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port)
1817 // Verify packet is expected size
1818 CHECK_PACKET_MIN_SIZE(37);
1820 // check if we are UDP firewalled
1821 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1822 //We are firewalled. We should not index this entry and give publisher a false report.
1823 return;
1826 CMemFile bio(packetData, lenPacket);
1827 CUInt128 target = bio.ReadUInt128();
1829 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
1830 distance.XOR(target);
1832 if( thePrefs::FilterLanIPs() && distance.Get32BitChunk(0) > SEARCHTOLERANCE) {
1833 return;
1836 CUInt128 source = bio.ReadUInt128();
1838 Kademlia::CEntry* entry = new Kademlia::CEntry();
1839 try {
1840 entry->m_uIP = ip;
1841 entry->m_uUDPport = port;
1842 entry->m_uKeyID.SetValue(target);
1843 entry->m_uSourceID.SetValue(source);
1844 uint32_t tagCount = bio.ReadUInt8();
1845 while (tagCount > 0) {
1846 CTag *tag = bio.ReadTag();
1847 if (tag) {
1848 if (!tag->GetName().Cmp(TAG_FILENAME)) {
1849 if (entry->GetCommonFileName().IsEmpty()) {
1850 entry->SetFileName(tag->GetStr());
1852 delete tag;
1853 } else if (!tag->GetName().Cmp(TAG_FILESIZE)) {
1854 if (entry->m_uSize == 0) {
1855 entry->m_uSize = tag->GetInt();
1857 delete tag;
1858 } else {
1859 //TODO: Filter tags
1860 entry->AddTag(tag);
1863 tagCount--;
1865 entry->m_bSource = false;
1866 } catch(...) {
1867 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishNotesRequest"),ip,port,packetData,lenPacket);
1868 delete entry;
1869 entry = NULL;
1870 throw;
1873 if (entry == NULL) {
1874 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry == NULL"));
1875 } else if (entry->GetTagCount() == 0 || entry->GetTagCount() > 5) {
1876 delete entry;
1877 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry->GetTagCount() == 0 || entry->GetTagCount() > 5"));
1880 uint8_t load = 0;
1881 if (CKademlia::GetIndexed()->AddNotes(target, source, entry, load)) {
1882 CMemFile packetdata(17);
1883 packetdata.WriteUInt128(target);
1884 packetdata.WriteUInt8(load);
1885 DebugSend(KadPublishNotesRes, ip, port);
1886 SendPacket(packetdata, KADEMLIA_PUBLISH_NOTES_RES, ip, port, 0, NULL);
1887 } else {
1888 delete entry;
1892 // KADEMLIA2_PUBLISH_NOTES_REQ
1893 // Used only by Kad2.0
1894 void CKademliaUDPListener::Process2PublishNotesRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1896 // check if we are UDP firewalled
1897 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1898 //We are firewalled. We should not index this entry and give publisher a false report.
1899 return;
1902 CMemFile bio(packetData, lenPacket);
1903 CUInt128 target = bio.ReadUInt128();
1905 CUInt128 distance(CKademlia::GetPrefs()->GetKadID());
1906 distance.XOR(target);
1908 // Shouldn't LAN IPs already be filtered?
1909 if (thePrefs::FilterLanIPs() && distance.Get32BitChunk(0) > SEARCHTOLERANCE) {
1910 return;
1913 CUInt128 source = bio.ReadUInt128();
1915 Kademlia::CEntry* entry = new Kademlia::CEntry();
1916 try {
1917 entry->m_uIP = ip;
1918 entry->m_uUDPport = port;
1919 entry->m_uKeyID.SetValue(target);
1920 entry->m_uSourceID.SetValue(source);
1921 entry->m_bSource = false;
1922 uint32_t tags = bio.ReadUInt8();
1923 while (tags > 0) {
1924 CTag* tag = bio.ReadTag();
1925 if(tag) {
1926 if (!tag->GetName().Cmp(TAG_FILENAME)) {
1927 if (entry->GetCommonFileName().IsEmpty()) {
1928 entry->SetFileName(tag->GetStr());
1930 delete tag;
1931 } else if (!tag->GetName().Cmp(TAG_FILESIZE)) {
1932 if (entry->m_uSize == 0) {
1933 entry->m_uSize = tag->GetInt();
1935 delete tag;
1936 } else {
1937 //TODO: Filter tags
1938 entry->AddTag(tag);
1941 tags--;
1943 } catch(...) {
1944 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishNotesRequest"),ip,port,packetData,lenPacket);
1945 delete entry;
1946 entry = NULL;
1947 throw;
1950 uint8_t load = 0;
1951 if (CKademlia::GetIndexed()->AddNotes(target, source, entry, load)) {
1952 CMemFile packetdata(17);
1953 packetdata.WriteUInt128(target);
1954 packetdata.WriteUInt8(load);
1955 DebugSend(Kad2PublishRes, ip, port);
1956 SendPacket(packetdata, KADEMLIA2_PUBLISH_RES, ip, port, senderKey, NULL);
1957 } else {
1958 delete entry;
1962 // KADEMLIA_PUBLISH_NOTES_RES
1963 // Used only by Kad1.0
1964 void CKademliaUDPListener::ProcessPublishNotesResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
1966 // Verify packet is expected size
1967 CHECK_PACKET_MIN_SIZE(16);
1968 CHECK_TRACKED_PACKET(KADEMLIA_PUBLISH_NOTES_REQ);
1970 CMemFile bio(packetData, lenPacket);
1971 CUInt128 file = bio.ReadUInt128();
1973 bool loadResponse = false;
1974 uint8_t load = 0;
1975 if( bio.GetLength() > bio.GetPosition() ) {
1976 loadResponse = true;
1977 load = bio.ReadUInt8();
1980 CSearchManager::ProcessPublishResult(file, load, loadResponse);
1983 // KADEMLIA_FIREWALLED_REQ
1984 // Used by Kad1.0 and Kad2.0
1985 void CKademliaUDPListener::ProcessFirewalledRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
1987 // Verify packet is expected size
1988 CHECK_PACKET_EXACT_SIZE(2);
1990 CMemFile bio(packetData, lenPacket);
1991 uint16_t tcpport = bio.ReadUInt16();
1993 CUInt128 zero;
1994 CContact contact(zero, ip, port, tcpport, 0, 0, false, zero);
1995 if (!theApp->clientlist->RequestTCP(&contact, 0)) {
1996 return; // cancelled for some reason, don't send a response
1999 // Send response
2000 CMemFile packetdata(4);
2001 packetdata.WriteUInt32(ip);
2002 DebugSend(KadFirewalledRes, ip, port);
2003 SendPacket(packetdata, KADEMLIA_FIREWALLED_RES, ip, port, senderKey, NULL);
2006 // KADEMLIA_FIREWALLED2_REQ
2007 // Used by Kad2.0 Prot.Version 7+
2008 void CKademliaUDPListener::ProcessFirewalled2Request(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
2010 // Verify packet is expected size
2011 CHECK_PACKET_MIN_SIZE(19);
2013 CMemFile bio(packetData, lenPacket);
2014 uint16_t tcpPort = bio.ReadUInt16();
2015 CUInt128 userID = bio.ReadUInt128();
2016 uint8_t connectOptions = bio.ReadUInt8();
2018 CUInt128 zero;
2019 CContact contact(userID, ip, port, tcpPort, 0, 0, false, zero);
2020 if (!theApp->clientlist->RequestTCP(&contact, connectOptions)) {
2021 return; // cancelled for some reason, don't send a response
2024 // Send response
2025 CMemFile packetdata(4);
2026 packetdata.WriteUInt32(ip);
2027 DebugSend(KadFirewalledRes, ip, port);
2028 SendPacket(packetdata, KADEMLIA_FIREWALLED_RES, ip, port, senderKey, NULL);
2031 // KADEMLIA_FIREWALLED_RES
2032 // Used by Kad1.0 and Kad2.0
2033 void CKademliaUDPListener::ProcessFirewalledResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, const CKadUDPKey& WXUNUSED(senderKey))
2035 // Verify packet is expected size
2036 CHECK_PACKET_EXACT_SIZE(4);
2038 if (!theApp->clientlist->IsKadFirewallCheckIP(wxUINT32_SWAP_ALWAYS(ip))) { /* KADEMLIA_FIREWALLED2_REQ + KADEMLIA_FIREWALLED_REQ */
2039 throw wxString(wxT("Received unrequested firewall response packet in ")) + wxString::FromAscii(__FUNCTION__);
2042 CMemFile bio(packetData, lenPacket);
2043 uint32_t firewalledIP = bio.ReadUInt32();
2045 // Update con state only if something changes.
2046 if (CKademlia::GetPrefs()->GetIPAddress() != firewalledIP) {
2047 CKademlia::GetPrefs()->SetIPAddress(firewalledIP);
2048 theApp->ShowConnectionState();
2050 CKademlia::GetPrefs()->IncRecheckIP();
2053 // KADEMLIA_FIREWALLED_ACK_RES
2054 // Used by Kad1.0 and Kad2.0
2055 void CKademliaUDPListener::ProcessFirewalledAckResponse(uint32_t lenPacket)
2057 // Deprecated since KadVersion 7+, the result is now sent per TCP instead of UDP, because this will fail if our intern UDP port is unreachable.
2058 // But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest.
2060 // Verify packet is expected size
2061 CHECK_PACKET_EXACT_SIZE(0);
2063 CKademlia::GetPrefs()->IncFirewalled();
2066 // KADEMLIA_FINDBUDDY_REQ
2067 // Used by Kad1.0 and Kad2.0
2068 void CKademliaUDPListener::ProcessFindBuddyRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
2070 // Verify packet is expected size
2071 CHECK_PACKET_MIN_SIZE(34);
2073 if (CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true) || !CUDPFirewallTester::IsVerified()) {
2074 // We are firewalled but somehow we still got this packet.. Don't send a response..
2075 return;
2076 } else if (theApp->clientlist->GetBuddyStatus() == Connected) {
2077 // we already have a buddy
2078 return;
2081 CMemFile bio(packetData, lenPacket);
2082 CUInt128 BuddyID = bio.ReadUInt128();
2083 CUInt128 userID = bio.ReadUInt128();
2084 uint16_t tcpport = bio.ReadUInt16();
2086 CUInt128 zero;
2087 CContact contact(userID, ip, port, tcpport, 0, 0, false, zero);
2088 if (!theApp->clientlist->IncomingBuddy(&contact, &BuddyID)) {
2089 return; // cancelled for some reason, don't send a response
2092 CMemFile packetdata(34);
2093 packetdata.WriteUInt128(BuddyID);
2094 packetdata.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
2095 packetdata.WriteUInt16(thePrefs::GetPort());
2096 if (!senderKey.IsEmpty()) { // remove check for later versions
2097 packetdata.WriteUInt8(CPrefs::GetMyConnectOptions(true, false)); // new since 0.49a, old mules will ignore it (hopefully ;) )
2100 DebugSend(KadFindBuddyRes, ip, port);
2101 SendPacket(packetdata, KADEMLIA_FINDBUDDY_RES, ip, port, senderKey, NULL);
2104 // KADEMLIA_FINDBUDDY_RES
2105 // Used by Kad1.0 and Kad2.0
2106 void CKademliaUDPListener::ProcessFindBuddyResponse(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t port, const CKadUDPKey& WXUNUSED(senderKey))
2108 // Verify packet is expected size
2109 CHECK_PACKET_MIN_SIZE(34);
2110 CHECK_TRACKED_PACKET(KADEMLIA_FINDBUDDY_REQ);
2112 CMemFile bio(packetData, lenPacket);
2113 CUInt128 check = bio.ReadUInt128();
2114 check.XOR(CUInt128(true));
2115 if (CKademlia::GetPrefs()->GetKadID() == check) {
2116 CUInt128 userID = bio.ReadUInt128();
2117 uint16_t tcpport = bio.ReadUInt16();
2118 uint8_t connectOptions = 0;
2119 if (lenPacket > 34) {
2120 // 0.49+ (kad version 7) sends additionally its connect options so we know whether to use an obfuscated connection
2121 connectOptions = bio.ReadUInt8();
2124 CUInt128 zero;
2125 CContact contact(userID, ip, port, tcpport, 0, 0, false, zero);
2126 theApp->clientlist->RequestBuddy(&contact, connectOptions);
2130 // KADEMLIA_CALLBACK_REQ
2131 // Used by Kad1.0 and Kad2.0
2132 void CKademliaUDPListener::ProcessCallbackRequest(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip, uint16_t WXUNUSED(port), const CKadUDPKey& WXUNUSED(senderKey))
2134 // Verify packet is expected size
2135 CHECK_PACKET_MIN_SIZE(34);
2137 CUpDownClient* buddy = theApp->clientlist->GetBuddy();
2138 if (buddy != NULL) {
2139 CMemFile bio(packetData, lenPacket);
2140 CUInt128 check = bio.ReadUInt128();
2141 // JOHNTODO: Begin filtering bad buddy ID's..
2142 // CUInt128 bud(buddy->GetBuddyID());
2143 CUInt128 file = bio.ReadUInt128();
2144 uint16_t tcp = bio.ReadUInt16();
2146 if (buddy->GetSocket()) {
2147 CMemFile packetdata(lenPacket + 6);
2148 packetdata.WriteUInt128(check);
2149 packetdata.WriteUInt128(file);
2150 packetdata.WriteUInt32(ip);
2151 packetdata.WriteUInt16(tcp);
2152 CPacket* packet = new CPacket(packetdata, OP_EMULEPROT, OP_CALLBACK);
2153 AddDebugLogLineN(logLocalClient, wxT("Local Client: OP_CALLBACK to ") + KadIPToString(ip));
2154 buddy->GetSocket()->SendPacket(packet);
2155 theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
2156 } else {
2157 throw wxString::FromAscii(__FUNCTION__) + wxT(": Buddy has no valid socket");
2162 // KADEMLIA2_PING
2163 void CKademliaUDPListener::Process2Ping(uint32_t ip, uint16_t port, const CKadUDPKey& senderKey)
2165 // can be used just as PING, currently it is however only used to determine one's external port
2166 CMemFile packetdata(2);
2167 packetdata.WriteUInt16(port);
2168 DebugSend(Kad2Pong, ip, port);
2169 SendPacket(packetdata, KADEMLIA2_PONG, ip, port, senderKey, NULL);
2172 // KADEMLIA2_PONG
2173 void CKademliaUDPListener::Process2Pong(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
2175 CHECK_PACKET_MIN_SIZE(2);
2176 CHECK_TRACKED_PACKET(KADEMLIA2_PING);
2178 // Is this one of our legacy challenge packets?
2179 CUInt128 contactID;
2180 if (IsLegacyChallenge(CUInt128((uint32_t)0), ip, KADEMLIA2_PING, contactID)) {
2181 // yup it is, set the contact as verified
2182 if (!CKademlia::GetRoutingZone()->VerifyContact(contactID, ip)) {
2183 AddDebugLogLineN(logKadRouting, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip) + wxT(")"));
2184 } else {
2185 AddDebugLogLineN(logKadRouting, wxT("Verified contact with legacy challenge (Kad2Ping) - ") + KadIPToString(ip));
2187 return; // we do not actually care for its other content
2190 if (CKademlia::GetPrefs()->FindExternKadPort(false)) {
2191 // the reported port doesn't always have to be our true external port, esp. if we used our intern port
2192 // and communicated recently with the client some routers might remember this and assign the intern port as source
2193 // but this shouldn't be a problem because we prefer intern ports anyway.
2194 // might have to be reviewed in later versions when more data is available
2195 CKademlia::GetPrefs()->SetExternKadPort(PeekUInt16(packetData), ip);
2197 if (CUDPFirewallTester::IsFWCheckUDPRunning()) {
2198 CUDPFirewallTester::QueryNextClient();
2201 theApp->ShowConnectionState();
2204 // KADEMLIA2_FIREWALLUDP
2205 void CKademliaUDPListener::Process2FirewallUDP(const uint8_t *packetData, uint32_t lenPacket, uint32_t ip)
2207 // Verify packet is expected size
2208 CHECK_PACKET_MIN_SIZE(3);
2210 uint8_t errorCode = PeekUInt8(packetData);
2211 uint16_t incomingPort = PeekUInt16(packetData + 1);
2212 if ((incomingPort != CKademlia::GetPrefs()->GetExternalKadPort() && incomingPort != CKademlia::GetPrefs()->GetInternKadPort()) || incomingPort == 0) {
2213 AddDebugLogLineN(logClientKadUDP, wxString::Format(wxT("Received UDP FirewallCheck on unexpected incoming port %u (") + KadIPToString(ip) + wxT(")"), incomingPort));
2214 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip, 0);
2215 } else if (errorCode == 0) {
2216 AddDebugLogLineN(logClientKadUDP, wxString::Format(wxT("Received UDP FirewallCheck packet from ") + KadIPToString(ip) + wxT(" with incoming port %u"), incomingPort));
2217 CUDPFirewallTester::SetUDPFWCheckResult(true, false, ip, incomingPort);
2218 } else {
2219 AddDebugLogLineN(logClientKadUDP, wxString::Format(wxT("Received UDP FirewallCheck packet from ") + KadIPToString(ip) + wxT(" with incoming port %u with remote errorcode %u - ignoring result"), incomingPort, errorCode));
2220 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip, 0);
2224 void CKademliaUDPListener::SendPacket(const CMemFile &data, uint8_t opcode, uint32_t destinationHost, uint16_t destinationPort, const CKadUDPKey& targetKey, const CUInt128* cryptTargetID)
2226 AddTrackedOutPacket(destinationHost, opcode);
2227 CPacket* packet = new CPacket(data, OP_KADEMLIAHEADER, opcode);
2228 if (packet->GetPacketSize() > 200) {
2229 packet->PackPacket();
2231 uint8_t cryptData[16];
2232 uint8_t *cryptKey;
2233 if (cryptTargetID != NULL) {
2234 cryptKey = (uint8_t *)&cryptData;
2235 cryptTargetID->StoreCryptValue(cryptKey);
2236 } else {
2237 cryptKey = NULL;
2239 theStats::AddUpOverheadKad(packet->GetPacketSize());
2240 theApp->clientudp->SendPacket(packet, wxUINT32_SWAP_ALWAYS(destinationHost), destinationPort, true, cryptKey, true, targetKey.GetKeyValue(theApp->GetPublicIP(false)));
2243 bool CKademliaUDPListener::FindNodeIDByIP(CKadClientSearcher* requester, uint32_t ip, uint16_t tcpPort, uint16_t udpPort)
2245 // send a hello packet to the given IP in order to get a HELLO_RES with the NodeID
2247 // we will drop support for Kad1 soon, so don't bother sending two packets in case we don't know if kad2 is supported
2248 // (if we know that it's not, this function isn't called in the first place)
2249 AddDebugLogLineN(logClientKadUDP, wxT("FindNodeIDByIP: Requesting NodeID from ") + KadIPToString(ip) + wxT(" by sending Kad2HelloReq"));
2250 DebugSend(Kad2HelloReq, ip, udpPort);
2251 SendMyDetails(KADEMLIA2_HELLO_REQ, ip, udpPort, 1, 0, NULL, false); // todo: we send this unobfuscated, which is not perfect, see this can be avoided in the future
2252 FetchNodeID_Struct sRequest = { ip, tcpPort, ::GetTickCount() + SEC2MS(60), requester };
2253 m_fetchNodeIDRequests.push_back(sRequest);
2254 return true;
2257 void CKademliaUDPListener::ExpireClientSearch(CKadClientSearcher* expireImmediately)
2259 uint32_t now = ::GetTickCount();
2260 for (FetchNodeIDList::iterator it = m_fetchNodeIDRequests.begin(); it != m_fetchNodeIDRequests.end();) {
2261 FetchNodeIDList::iterator it2 = it++;
2262 if (it2->requester == expireImmediately) {
2263 m_fetchNodeIDRequests.erase(it2);
2265 else if (it2->expire < now) {
2266 it2->requester->KadSearchNodeIDByIPResult(KCSR_TIMEOUT, NULL);
2267 m_fetchNodeIDRequests.erase(it2);
2272 void CKademliaUDPListener::SendLegacyChallenge(uint32_t ip, uint16_t port, const CUInt128& contactID, bool kad2)
2274 // We want to verify that a pre-0.49a contact is valid and not sent from a spoofed IP.
2275 // Because those versions don't support any direct validating, we send a KAD_REQ with a random ID,
2276 // which is our challenge. If we receive an answer packet for this request, we can be sure the
2277 // contact is not spoofed
2278 #ifdef __DEBUG__
2279 CContact* contact = CKademlia::GetRoutingZone()->GetContact(contactID);
2280 if (contact != NULL) {
2281 if (contact->GetType() < 2) {
2282 AddDebugLogLineN(logKadRouting, wxT("Sending challenge to a long known contact (should be verified already) - ") + KadIPToString(ip));
2284 } else {
2285 wxFAIL;
2287 #endif
2289 if (HasActiveLegacyChallenge(ip)) {
2290 // don't send more than one challenge at a time
2291 return;
2293 CMemFile packetdata(33);
2294 packetdata.WriteUInt8(KADEMLIA_FIND_VALUE);
2295 CUInt128 challenge(GetRandomUint128());
2296 if (challenge == 0) {
2297 // hey there is a 2^128 chance that this happens ;)
2298 wxFAIL;
2299 challenge = 1;
2301 // Put the target we want into the packet. This is our challenge
2302 packetdata.WriteUInt128(challenge);
2303 // Add the ID of the contact we are contacting for sanity checks on the other end.
2304 packetdata.WriteUInt128(contactID);
2305 if (kad2) {
2306 DebugSendF(wxT("Kad2Req(SendLegacyChallenge)"), ip, port);
2307 // those versions we send those requests to don't support encryption / obfuscation
2308 SendPacket(packetdata, KADEMLIA2_REQ, ip, port, 0, NULL);
2309 AddLegacyChallenge(contactID, challenge, ip, KADEMLIA2_REQ);
2310 } else {
2311 DebugSendF(wxT("KadReq(SendLegacyChallenge)"), ip, port);
2312 SendPacket(packetdata, KADEMLIA_REQ, ip, port, 0, NULL);
2313 AddLegacyChallenge(contactID, challenge, ip, KADEMLIA_REQ);
2317 void CKademliaUDPListener::DebugClientOutput(const wxString& place, uint32 kad_ip, uint32 port, const byte* data, int len)
2319 #if THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX
2320 uint32 ip = wxUINT32_SWAP_ALWAYS(kad_ip);
2321 printf("Error on %s received from: %s\n",(const char*)unicode2char(place),(const char*)unicode2char(Uint32_16toStringIP_Port(ip,port)));
2322 if (data) {
2323 printf("Packet dump:\n");
2324 DumpMem(data, len);
2326 CClientList::SourceList clientslist = theApp->clientlist->GetClientsByIP(ip);
2327 if (!clientslist.empty()) {
2328 for (CClientList::SourceList::iterator it = clientslist.begin(); it != clientslist.end(); ++it) {
2329 printf("Ip Matches: %s\n",(const char*)unicode2char((*it)->GetClientFullInfo()));
2331 } else {
2332 printf("No ip match, trying to create a client connection:\n");
2333 printf("Trying port %d\n", port - 10);
2334 CUpDownClient* client = new CUpDownClient(port-10,kad_ip,0,0,NULL,false,false);
2335 client->SetConnectionReason(wxT("Error on ") + place);
2336 client->TryToConnect(true);
2338 #else
2339 // No need for warnings for the rest of us.
2340 (void)place;
2341 (void)kad_ip;
2342 (void)port;
2343 (void)data;
2344 (void)len;
2345 #endif
2347 // File_checked_for_headers