2 // This file is part of aMule Project
4 // Copyright (c) 2004-2011 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Copyright (c) 2003-2011 Barry Dunne ( http://www.emule-project.net )
7 // Copyright (C)2007-2011 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
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..
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()
69 #include "../../CompilerSpecific.h" // Needed for __FUNCTION__
71 #include <wx/tokenzr.h>
73 #define THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX 0
75 #define CHECK_PACKET_SIZE(OP, SIZE) \
76 if (lenPacket OP (uint32_t)(SIZE)) \
77 throw wxString(CFormat(wxT("***NOTE: Received wrong size (%u) packet in %s")) % lenPacket % wxString::FromAscii(__FUNCTION__))
79 #define CHECK_PACKET_MIN_SIZE(SIZE) CHECK_PACKET_SIZE(<, SIZE)
80 #define CHECK_PACKET_EXACT_SIZE(SIZE) CHECK_PACKET_SIZE(!=, SIZE)
82 #define CHECK_TRACKED_PACKET(OPCODE) \
83 if (!IsOnOutTrackList(ip, OPCODE)) \
84 throw wxString(CFormat(wxT("***NOTE: Received unrequested response packet, size (%u) in %s")) % lenPacket % wxString::FromAscii(__FUNCTION__))
87 ////////////////////////////////////////
88 using namespace Kademlia
;
89 ////////////////////////////////////////
91 CKademliaUDPListener::~CKademliaUDPListener()
93 // report timeout to all pending FetchNodeIDRequests
94 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end(); ++it
) {
95 it
->requester
->KadSearchNodeIDByIPResult(KCSR_TIMEOUT
, NULL
);
99 // Used by Kad1.0 and Kad2.0
100 void CKademliaUDPListener::Bootstrap(uint32_t ip
, uint16_t port
, uint8_t kadVersion
, const CUInt128
* cryptTargetID
)
104 DebugSend(Kad2BootstrapReq
, ip
, port
);
106 if (kadVersion
>= 6) {
107 SendPacket(bio
, KADEMLIA2_BOOTSTRAP_REQ
, ip
, port
, 0, cryptTargetID
);
109 SendPacket(bio
, KADEMLIA2_BOOTSTRAP_REQ
, ip
, port
, 0, NULL
);
113 // Used by Kad1.0 and Kad2.0
114 void CKademliaUDPListener::SendMyDetails(uint8_t opcode
, uint32_t ip
, uint16_t port
, uint8_t kadVersion
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
, bool requestAckPacket
)
117 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
119 if (kadVersion
> 1) {
120 packetdata
.WriteUInt16(thePrefs::GetPort());
121 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
123 uint8_t tagCount
= 0;
124 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
127 if (kadVersion
>= 8 && (requestAckPacket
|| CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true))) {
130 packetdata
.WriteUInt8(tagCount
);
131 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
132 packetdata
.WriteTag(CTagVarInt(TAG_SOURCEUPORT
, CKademlia::GetPrefs()->GetInternKadPort()));
134 if (kadVersion
>= 8 && (requestAckPacket
|| CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true))) {
135 // 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)
137 // 1 - requesting HELLO_RES_ACK
138 // 1 - TCP firewalled
139 // 1 - UDP firewalled
140 packetdata
.WriteTag(CTagVarInt(TAG_KADMISCOPTIONS
, (uint8_t)(
141 (requestAckPacket
? 1 : 0) << 2 |
142 (CKademlia::GetPrefs()->GetFirewalled() ? 1 : 0) << 1 |
143 (CUDPFirewallTester::IsFirewalledUDP(true) ? 1 : 0)
146 if (kadVersion
>= 6) {
147 if (cryptTargetID
== NULL
|| *cryptTargetID
== 0) {
148 AddDebugLogLineN(logClientKadUDP
, CFormat(wxT("Sending hello response to crypt enabled Kad Node which provided an empty NodeID: %s (%u)")) % KadIPToString(ip
) % kadVersion
);
149 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, NULL
);
151 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, cryptTargetID
);
154 SendPacket(packetdata
, opcode
, ip
, port
, 0, NULL
);
155 wxASSERT(targetKey
.IsEmpty());
162 // Kad1.0 and Kad2.0 currently.
163 void CKademliaUDPListener::FirewalledCheck(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, uint8_t kadVersion
)
165 if (kadVersion
> 6) {
166 // new opcode since 0.49a with extended informations to support obfuscated connections properly
167 CMemFile
packetdata(19);
168 packetdata
.WriteUInt16(thePrefs::GetPort());
169 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
170 packetdata
.WriteUInt8(CPrefs::GetMyConnectOptions(true, false));
171 DebugSend(KadFirewalled2Req
, ip
, port
);
172 SendPacket(packetdata
, KADEMLIA_FIREWALLED2_REQ
, ip
, port
, senderKey
, NULL
);
174 CMemFile
packetdata(2);
175 packetdata
.WriteUInt16(thePrefs::GetPort());
176 DebugSend(KadFirewalledReq
, ip
, port
);
177 SendPacket(packetdata
, KADEMLIA_FIREWALLED_REQ
, ip
, port
, senderKey
, NULL
);
179 theApp
->clientlist
->AddKadFirewallRequest(wxUINT32_SWAP_ALWAYS(ip
));
182 void CKademliaUDPListener::SendNullPacket(uint8_t opcode
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
)
184 CMemFile
packetdata(0);
185 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, cryptTargetID
);
188 void CKademliaUDPListener::SendPublishSourcePacket(const CContact
& contact
, const CUInt128
&targetID
, const CUInt128
&contactID
, const TagPtrList
& tags
)
192 packetdata
.WriteUInt128(targetID
);
193 if (contact
.GetVersion() >= 4/*47c*/) {
194 opcode
= KADEMLIA2_PUBLISH_SOURCE_REQ
;
195 packetdata
.WriteUInt128(contactID
);
196 packetdata
.WriteTagPtrList(tags
);
197 DebugSend(Kad2PublishSrcReq
, contact
.GetIPAddress(), contact
.GetUDPPort());
199 opcode
= KADEMLIA_PUBLISH_REQ
;
200 //We only use this for publishing sources now.. So we always send one here..
201 packetdata
.WriteUInt16(1);
202 packetdata
.WriteUInt128(contactID
);
203 packetdata
.WriteTagPtrList(tags
);
204 DebugSend(KadPublishReq
, contact
.GetIPAddress(), contact
.GetUDPPort());
206 if (contact
.GetVersion() >= 6) { // obfuscated ?
207 CUInt128 clientID
= contact
.GetClientID();
208 SendPacket(packetdata
, opcode
, contact
.GetIPAddress(), contact
.GetUDPPort(), contact
.GetUDPKey(), &clientID
);
210 SendPacket(packetdata
, opcode
, contact
.GetIPAddress(), contact
.GetUDPPort(), 0, NULL
);
214 void CKademliaUDPListener::ProcessPacket(const uint8_t* data
, uint32_t lenData
, uint32_t ip
, uint16_t port
, bool validReceiverKey
, const CKadUDPKey
& senderKey
)
216 // we do not accept (<= 0.48a) unencrypted incoming packets from port 53 (DNS) to avoid attacks based on DNS protocol confusion
217 if (port
== 53 && senderKey
.IsEmpty()) {
218 AddDebugLogLineN(logKadPacketTracking
, wxT("Dropping incoming unencrypted packet on port 53 (DNS), IP: ") + KadIPToString(ip
));
222 //Update connection state only when it changes.
223 bool curCon
= CKademlia::GetPrefs()->HasHadContact();
224 CKademlia::GetPrefs()->SetLastContact();
225 CUDPFirewallTester::Connected();
226 if( curCon
!= CKademlia::GetPrefs()->HasHadContact()) {
227 theApp
->ShowConnectionState();
230 uint8_t opcode
= data
[1];
231 const uint8_t *packetData
= data
+ 2;
232 uint32_t lenPacket
= lenData
- 2;
234 if (!InTrackListIsAllowedPacket(ip
, opcode
, validReceiverKey
)) {
239 case KADEMLIA2_BOOTSTRAP_REQ
:
240 DebugRecv(Kad2BootstrapReq
, ip
, port
);
241 Process2BootstrapRequest(ip
, port
, senderKey
);
243 case KADEMLIA2_BOOTSTRAP_RES
:
244 DebugRecv(Kad2BootstrapRes
, ip
, port
);
245 Process2BootstrapResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
247 case KADEMLIA2_HELLO_REQ
:
248 DebugRecv(Kad2HelloReq
, ip
, port
);
249 Process2HelloRequest(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
251 case KADEMLIA2_HELLO_RES
:
252 DebugRecv(Kad2HelloRes
, ip
, port
);
253 Process2HelloResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
255 case KADEMLIA2_HELLO_RES_ACK
:
256 DebugRecv(Kad2HelloResAck
, ip
, port
);
257 Process2HelloResponseAck(packetData
, lenPacket
, ip
, validReceiverKey
);
260 DebugRecv(Kad2Req
, ip
, port
);
261 ProcessKademlia2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
264 DebugRecv(Kad2Res
, ip
, port
);
265 ProcessKademlia2Response(packetData
, lenPacket
, ip
, port
, senderKey
);
267 case KADEMLIA2_SEARCH_NOTES_REQ
:
268 DebugRecv(Kad2SearchNotesReq
, ip
, port
);
269 Process2SearchNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
271 case KADEMLIA2_SEARCH_KEY_REQ
:
272 DebugRecv(Kad2SearchKeyReq
, ip
, port
);
273 Process2SearchKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
275 case KADEMLIA2_SEARCH_SOURCE_REQ
:
276 DebugRecv(Kad2SearchSourceReq
, ip
, port
);
277 Process2SearchSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
279 case KADEMLIA_SEARCH_RES
:
280 DebugRecv(KadSearchRes
, ip
, port
);
281 ProcessSearchResponse(packetData
, lenPacket
);
283 case KADEMLIA_SEARCH_NOTES_RES
:
284 DebugRecv(KadSearchNotesRes
, ip
, port
);
285 ProcessSearchNotesResponse(packetData
, lenPacket
, ip
);
287 case KADEMLIA2_SEARCH_RES
:
288 DebugRecv(Kad2SearchRes
, ip
, port
);
289 Process2SearchResponse(packetData
, lenPacket
, senderKey
);
291 case KADEMLIA2_PUBLISH_NOTES_REQ
:
292 DebugRecv(Kad2PublishNotesReq
, ip
, port
);
293 Process2PublishNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
295 case KADEMLIA2_PUBLISH_KEY_REQ
:
296 DebugRecv(Kad2PublishKeyReq
, ip
, port
);
297 Process2PublishKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
299 case KADEMLIA2_PUBLISH_SOURCE_REQ
:
300 DebugRecv(Kad2PublishSourceReq
, ip
, port
);
301 Process2PublishSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
303 case KADEMLIA_PUBLISH_RES
:
304 DebugRecv(KadPublishRes
, ip
, port
);
305 ProcessPublishResponse(packetData
, lenPacket
, ip
);
307 case KADEMLIA2_PUBLISH_RES
:
308 DebugRecv(Kad2PublishRes
, ip
, port
);
309 Process2PublishResponse(packetData
, lenPacket
, ip
, port
, senderKey
);
311 case KADEMLIA_FIREWALLED_REQ
:
312 DebugRecv(KadFirewalledReq
, ip
, port
);
313 ProcessFirewalledRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
315 case KADEMLIA_FIREWALLED2_REQ
:
316 DebugRecv(KadFirewalled2Req
, ip
, port
);
317 ProcessFirewalled2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
319 case KADEMLIA_FIREWALLED_RES
:
320 DebugRecv(KadFirewalledRes
, ip
, port
);
321 ProcessFirewalledResponse(packetData
, lenPacket
, ip
, senderKey
);
323 case KADEMLIA_FIREWALLED_ACK_RES
:
324 DebugRecv(KadFirewalledAck
, ip
, port
);
325 ProcessFirewalledAckResponse(lenPacket
);
327 case KADEMLIA_FINDBUDDY_REQ
:
328 DebugRecv(KadFindBuddyReq
, ip
, port
);
329 ProcessFindBuddyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
331 case KADEMLIA_FINDBUDDY_RES
:
332 DebugRecv(KadFindBuddyRes
, ip
, port
);
333 ProcessFindBuddyResponse(packetData
, lenPacket
, ip
, port
, senderKey
);
335 case KADEMLIA_CALLBACK_REQ
:
336 DebugRecv(KadCallbackReq
, ip
, port
);
337 ProcessCallbackRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
340 DebugRecv(Kad2Ping
, ip
, port
);
341 Process2Ping(ip
, port
, senderKey
);
344 DebugRecv(Kad2Pong
, ip
, port
);
345 Process2Pong(packetData
, lenPacket
, ip
);
347 case KADEMLIA2_FIREWALLUDP
:
348 DebugRecv(Kad2FirewallUDP
, ip
, port
);
349 Process2FirewallUDP(packetData
, lenPacket
, ip
);
352 // old Kad1 opcodes which we don't handle anymore
353 case KADEMLIA_BOOTSTRAP_REQ_DEPRECATED
:
354 case KADEMLIA_BOOTSTRAP_RES_DEPRECATED
:
355 case KADEMLIA_HELLO_REQ_DEPRECATED
:
356 case KADEMLIA_HELLO_RES_DEPRECATED
:
357 case KADEMLIA_REQ_DEPRECATED
:
358 case KADEMLIA_RES_DEPRECATED
:
359 case KADEMLIA_PUBLISH_NOTES_REQ_DEPRECATED
:
360 case KADEMLIA_PUBLISH_NOTES_RES_DEPRECATED
:
361 case KADEMLIA_SEARCH_REQ
:
362 case KADEMLIA_PUBLISH_REQ
:
363 case KADEMLIA_SEARCH_NOTES_REQ
:
367 throw wxString(CFormat(wxT("Unknown opcode %02x on CKademliaUDPListener::ProcessPacket()")) % opcode
);
372 // Used only for Kad2.0
373 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
)
375 if (outRequestsACK
!= 0) {
376 *outRequestsACK
= false;
379 CMemFile
bio(data
, lenData
);
380 CUInt128 id
= bio
.ReadUInt128();
381 if (outContactID
!= NULL
) {
384 uint16_t tport
= bio
.ReadUInt16();
385 uint8_t version
= bio
.ReadUInt8();
387 throw wxString(CFormat(wxT("***NOTE: Received invalid Kademlia2 version (%u) in %s")) % version
% wxString::FromAscii(__FUNCTION__
));
389 if (outVersion
!= NULL
) {
390 *outVersion
= version
;
392 bool udpFirewalled
= false;
393 bool tcpFirewalled
= false;
394 uint8_t tags
= bio
.ReadUInt8();
396 CTag
*tag
= bio
.ReadTag();
397 if (!tag
->GetName().Cmp(TAG_SOURCEUPORT
)) {
398 if (tag
->IsInt() && (uint16_t)tag
->GetInt() > 0) {
399 port
= tag
->GetInt();
401 } else if (!tag
->GetName().Cmp(TAG_KADMISCOPTIONS
)) {
402 if (tag
->IsInt() && tag
->GetInt() > 0) {
403 udpFirewalled
= (tag
->GetInt() & 0x01) > 0;
404 tcpFirewalled
= (tag
->GetInt() & 0x02) > 0;
405 if ((tag
->GetInt() & 0x04) > 0) {
406 if (outRequestsACK
!= NULL
) {
408 *outRequestsACK
= true;
420 // check if we are waiting for informations (nodeid) about this client and if so inform the requester
421 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end(); ++it
) {
422 if (it
->ip
== ip
&& it
->tcpPort
== tport
) {
423 //AddDebugLogLineN(logKadMain, wxT("Result Addcontact: ") + id.ToHexString());
425 id
.ToByteArray(uchID
);
426 it
->requester
->KadSearchNodeIDByIPResult(KCSR_SUCCEEDED
, uchID
);
427 m_fetchNodeIDRequests
.erase(it
);
432 if (fromHelloReq
&& version
>= 8) {
433 // this is just for statistic calculations. We try to determine the ratio of (UDP) firewalled users,
434 // by counting how many of all nodes which have us in their routing table (our own routing table is supposed
435 // to have no UDP firewalled nodes at all) and support the firewalled tag are firewalled themself.
436 // Obviously this only works if we are not firewalled ourself
437 CKademlia::GetPrefs()->StatsIncUDPFirewalledNodes(udpFirewalled
);
438 CKademlia::GetPrefs()->StatsIncTCPFirewalledNodes(tcpFirewalled
);
441 if (!udpFirewalled
) { // do not add (or update) UDP firewalled sources to our routing table
442 return CKademlia::GetRoutingZone()->Add(id
, ip
, port
, tport
, version
, udpKey
, ipVerified
, update
, true);
444 AddDebugLogLineN(logKadRouting
, wxT("Not adding firewalled client to routing table (") + KadIPToString(ip
) + wxT(")"));
449 // KADEMLIA2_BOOTSTRAP_REQ
450 // Used only for Kad2.0
451 void CKademliaUDPListener::Process2BootstrapRequest(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
453 // Get some contacts to return
454 ContactList contacts
;
455 uint16_t numContacts
= (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts
, 20);
457 // Create response packet
458 //We only collect a max of 20 contacts here.. Max size is 521.
460 CMemFile
packetdata(521);
462 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
463 packetdata
.WriteUInt16(thePrefs::GetPort());
464 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
467 packetdata
.WriteUInt16(numContacts
);
469 for (ContactList::const_iterator it
= contacts
.begin(); it
!= contacts
.end(); ++it
) {
471 packetdata
.WriteUInt128(contact
->GetClientID());
472 packetdata
.WriteUInt32(contact
->GetIPAddress());
473 packetdata
.WriteUInt16(contact
->GetUDPPort());
474 packetdata
.WriteUInt16(contact
->GetTCPPort());
475 packetdata
.WriteUInt8(contact
->GetVersion());
479 DebugSend(Kad2BootstrapRes
, ip
, port
);
480 SendPacket(packetdata
, KADEMLIA2_BOOTSTRAP_RES
, ip
, port
, senderKey
, NULL
);
483 // KADEMLIA2_BOOTSTRAP_RES
484 // Used only for Kad2.0
485 void CKademliaUDPListener::Process2BootstrapResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
487 CHECK_TRACKED_PACKET(KADEMLIA2_BOOTSTRAP_REQ
);
489 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
491 // How many contacts were given
492 CMemFile
bio(packetData
, lenPacket
);
493 CUInt128 contactID
= bio
.ReadUInt128();
494 uint16_t tport
= bio
.ReadUInt16();
495 uint8_t version
= bio
.ReadUInt8();
496 // if we don't know any Contacts yet and try to Bootstrap, we assume that all contacts are verified,
497 // in order to speed up the connecting process. The attackvectors to exploit this are very small with no
498 // major effects, so that's a good trade
499 bool assumeVerified
= CKademlia::GetRoutingZone()->GetNumContacts() == 0;
501 if (CKademlia::s_bootstrapList
.empty()) {
502 routingZone
->Add(contactID
, ip
, port
, tport
, version
, senderKey
, validReceiverKey
, true, false);
504 //AddDebugLogLineN(logClientKadUDP, wxT("Inc Kad2 Bootstrap packet from ") + KadIPToString(ip));
506 uint16_t numContacts
= bio
.ReadUInt16();
507 while (numContacts
) {
508 contactID
= bio
.ReadUInt128();
509 ip
= bio
.ReadUInt32();
510 port
= bio
.ReadUInt16();
511 tport
= bio
.ReadUInt16();
512 version
= bio
.ReadUInt8();
513 bool verified
= assumeVerified
;
514 routingZone
->Add(contactID
, ip
, port
, tport
, version
, 0, verified
, false, false);
519 // KADEMLIA2_HELLO_REQ
520 // Used in Kad2.0 only
521 void CKademliaUDPListener::Process2HelloRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
523 DEBUG_ONLY( uint16_t dbgOldUDPPort
= port
; )
524 uint8_t contactVersion
= 0;
526 bool addedOrUpdated
= AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true, true, NULL
, &contactID
); // might change (udp)port, validReceiverKey
527 wxASSERT(contactVersion
>= 2);
529 if (dbgOldUDPPort
!= port
) {
530 AddDebugLogLineN(logClientKadUDP
, CFormat(wxT("KadContact %s uses his internal (%u) instead external (%u) UDP Port")) % KadIPToString(ip
) % port
% dbgOldUDPPort
);
534 DebugSend(Kad2HelloRes
, ip
, port
);
535 // 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
536 // receiver key or is already verified in the routing table, we request an additional ACK package to complete a three-way-handshake and
537 // verify the remote IP
538 SendMyDetails(KADEMLIA2_HELLO_RES
, ip
, port
, contactVersion
, senderKey
, &contactID
, addedOrUpdated
&& !validReceiverKey
);
540 if (addedOrUpdated
&& !validReceiverKey
&& contactVersion
== 7 && !HasActiveLegacyChallenge(ip
)) {
541 // Kad Version 7 doesn't support HELLO_RES_ACK but sender/receiver keys, so send a ping to validate
542 DebugSend(Kad2Ping
, ip
, port
);
543 SendNullPacket(KADEMLIA2_PING
, ip
, port
, senderKey
, NULL
);
545 CContact
* contact
= CKademlia::GetRoutingZone()->GetContact(contactID
);
546 if (contact
!= NULL
) {
547 if (contact
->GetType() < 2) {
548 AddDebugLogLineN(logKadRouting
, wxT("Sending (ping) challenge to a long known contact (should be verified already) - ") + KadIPToString(ip
));
554 } else if (CKademlia::GetPrefs()->FindExternKadPort(false) && contactVersion
> 5) { // do we need to find out our extern port?
555 DebugSend(Kad2Ping
, ip
, port
);
556 SendNullPacket(KADEMLIA2_PING
, ip
, port
, senderKey
, NULL
);
559 if (addedOrUpdated
&& !validReceiverKey
&& contactVersion
< 7 && !HasActiveLegacyChallenge(ip
)) {
560 // we need to verify this contact but it doesn't support HELLO_RES_ACK nor keys, do a little workaround
561 SendLegacyChallenge(ip
, port
, contactID
);
564 // Check if firewalled
565 if (CKademlia::GetPrefs()->GetRecheckIP()) {
566 FirewalledCheck(ip
, port
, senderKey
, contactVersion
);
570 // KADEMLIA2_HELLO_RES_ACK
571 // Used in Kad2.0 only
572 void CKademliaUDPListener::Process2HelloResponseAck(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, bool validReceiverKey
)
574 CHECK_PACKET_MIN_SIZE(17);
575 CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_RES
);
577 if (!validReceiverKey
) {
578 AddDebugLogLineN(logClientKadUDP
, wxT("Receiver key is invalid! (sender: ") + KadIPToString(ip
) + wxT(")"));
582 // Additional packet to complete a three-way-handshake, making sure the remote contact is not using a spoofed ip.
583 CMemFile
bio(packetData
, lenPacket
);
584 CUInt128 remoteID
= bio
.ReadUInt128();
585 // cppcheck-suppress duplicateBranch
586 if (!CKademlia::GetRoutingZone()->VerifyContact(remoteID
, ip
)) {
587 AddDebugLogLineN(logKadRouting
, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip
) + wxT(")"));
589 AddDebugLogLineN(logKadRouting
, wxT("Verified contact (") + KadIPToString(ip
) + wxT(") by HELLO_RES_ACK"));
593 // KADEMLIA2_HELLO_RES
594 // Used in Kad2.0 only
595 void CKademliaUDPListener::Process2HelloResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
597 CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_REQ
);
599 // Add or Update contact.
600 uint8_t contactVersion
;
602 bool sendACK
= false;
603 bool addedOrUpdated
= AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true, false, &sendACK
, &contactID
);
606 // the client requested us to send an ACK packet, which proves that we're not a spoofed fake contact
608 if (senderKey
.IsEmpty()) {
609 // but we don't have a valid sender key - there is no point to reply in this case
610 // most likely a bug in the remote client
611 AddDebugLogLineN(logClientKadUDP
, wxT("Remote client demands ACK, but didn't send any sender key! (sender: ") + KadIPToString(ip
) + wxT(")"));
614 packet
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
615 packet
.WriteUInt8(0); // no tags at this time
616 DebugSend(Kad2HelloResAck
, ip
, port
);
617 SendPacket(packet
, KADEMLIA2_HELLO_RES_ACK
, ip
, port
, senderKey
, NULL
);
619 } else if (addedOrUpdated
&& !validReceiverKey
&& contactVersion
< 7) {
620 // even though this is supposably an answer to a request from us, there are still possibilities to spoof
621 // it, as long as the attacker knows that we would send a HELLO_REQ (which in this case is quite often),
622 // so for old Kad Version which doesn't support keys, we need
623 SendLegacyChallenge(ip
, port
, contactID
);
626 // do we need to find out our extern port?
627 if (CKademlia::GetPrefs()->FindExternKadPort(false) && contactVersion
> 5) {
628 DebugSend(Kad2Ping
, ip
, port
);
629 SendNullPacket(KADEMLIA2_PING
, ip
, port
, senderKey
, NULL
);
632 // Check if firewalled
633 if (CKademlia::GetPrefs()->GetRecheckIP()) {
634 FirewalledCheck(ip
, port
, senderKey
, contactVersion
);
639 // Used in Kad2.0 only
640 void CKademliaUDPListener::ProcessKademlia2Request(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
642 // Get target and type
643 CMemFile
bio(packetData
, lenPacket
);
644 uint8_t type
= bio
.ReadUInt8();
647 throw wxString(CFormat(wxT("***NOTE: Received wrong type (0x%02x) in %s")) % type
% wxString::FromAscii(__FUNCTION__
));
650 // This is the target node trying to be found.
651 CUInt128 target
= bio
.ReadUInt128();
652 // Convert Target to Distance as this is how we store contacts.
653 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
656 // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new KadID.
657 CUInt128 check
= bio
.ReadUInt128();
658 if (CKademlia::GetPrefs()->GetKadID() == check
) {
659 // Get required number closest to target
661 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, type
, &results
);
662 uint8_t count
= (uint8_t)results
.size();
665 // Max count is 32. size 817..
667 CMemFile
packetdata(817);
668 packetdata
.WriteUInt128(target
);
669 packetdata
.WriteUInt8(count
);
671 for (ContactMap::const_iterator it
= results
.begin(); it
!= results
.end(); ++it
) {
673 packetdata
.WriteUInt128(c
->GetClientID());
674 packetdata
.WriteUInt32(c
->GetIPAddress());
675 packetdata
.WriteUInt16(c
->GetUDPPort());
676 packetdata
.WriteUInt16(c
->GetTCPPort());
677 packetdata
.WriteUInt8(c
->GetVersion()); //<- Kad Version inserted to allow backward compatibility.
680 DebugSendF(CFormat(wxT("Kad2Res (count=%u)")) % count
, ip
, port
);
681 SendPacket(packetdata
, KADEMLIA2_RES
, ip
, port
, senderKey
, NULL
);
686 // Used in Kad2.0 only
687 void CKademliaUDPListener::ProcessKademlia2Response(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& WXUNUSED(senderKey
))
689 CHECK_TRACKED_PACKET(KADEMLIA2_REQ
);
692 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
694 // What search does this relate to
695 CMemFile
bio(packetData
, lenPacket
);
696 CUInt128 target
= bio
.ReadUInt128();
697 uint8_t numContacts
= bio
.ReadUInt8();
699 // Is this one of our legacy challenge packets?
701 if (IsLegacyChallenge(target
, ip
, KADEMLIA2_REQ
, contactID
)) {
702 // yup it is, set the contact as verified
703 // cppcheck-suppress duplicateBranch
704 if (!routingZone
->VerifyContact(contactID
, ip
)) {
705 AddDebugLogLineN(logKadRouting
, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip
) + wxT(")"));
707 AddDebugLogLineN(logKadRouting
, wxT("Verified contact with legacy challenge (Kad2Req) - ") + KadIPToString(ip
));
709 return; // we do not actually care for its other content
711 // Verify packet is expected size
712 CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts
);
714 // is this a search for firewallcheck ips?
715 bool isFirewallUDPCheckSearch
= false;
716 if (CUDPFirewallTester::IsFWCheckUDPRunning() && CSearchManager::IsFWCheckUDPSearch(target
)) {
717 isFirewallUDPCheckSearch
= true;
720 DEBUG_ONLY( uint32_t ignoredCount
= 0; )
721 DEBUG_ONLY( uint32_t kad1Count
= 0; )
722 CScopedPtr
<ContactList
> results
;
723 for (uint8_t i
= 0; i
< numContacts
; i
++) {
724 CUInt128 id
= bio
.ReadUInt128();
725 uint32_t contactIP
= bio
.ReadUInt32();
726 uint16_t contactPort
= bio
.ReadUInt16();
727 uint16_t tport
= bio
.ReadUInt16();
728 uint8_t version
= bio
.ReadUInt8();
729 uint32_t hostIP
= wxUINT32_SWAP_ALWAYS(contactIP
);
730 if (version
> 1) { // Kad1 nodes are no longer accepted and ignored
731 if (::IsGoodIPPort(hostIP
, contactPort
)) {
732 if (!theApp
->ipfilter
->IsFiltered(hostIP
) && !(contactPort
== 53 && version
<= 5) /*No DNS Port without encryption*/) {
733 if (isFirewallUDPCheckSearch
) {
734 // UDP FirewallCheck searches are special. The point is we need an IP which we didn't sent a UDP message yet
735 // (or in the near future), so we do not try to add those contacts to our routingzone and we also don't
736 // deliver them back to the searchmanager (because he would UDP-ask them for further results), but only report
737 // them to FirewallChecker - this will of course cripple the search but thats not the point, since we only
738 // care for IPs and not the random set target
739 CUDPFirewallTester::AddPossibleTestContact(id
, contactIP
, contactPort
, tport
, target
, version
, 0, false);
741 bool verified
= false;
742 bool wasAdded
= routingZone
->AddUnfiltered(id
, contactIP
, contactPort
, tport
, version
, 0, verified
, false, false);
743 CContact
*temp
= new CContact(id
, contactIP
, contactPort
, tport
, version
, 0, false, target
);
744 if (wasAdded
|| routingZone
->IsAcceptableContact(temp
)) {
745 results
->push_back(temp
);
747 DEBUG_ONLY( ignoredCount
++; )
754 DEBUG_ONLY( kad1Count
++; )
759 if (ignoredCount
> 0) {
760 AddDebugLogLineN(logKadRouting
, CFormat(wxT("Ignored %u bad %s in routing answer from %s")) % ignoredCount
% (ignoredCount
> 1 ? wxT("contacts") : wxT("contact")) % KadIPToString(ip
));
763 AddDebugLogLineN(logKadRouting
, CFormat(wxT("Ignored %u kad1 %s in routing answer from %s")) % kad1Count
% (kad1Count
> 1 ? wxT("contacts") : wxT("contact")) % KadIPToString(ip
));
767 CSearchManager::ProcessResponse(target
, ip
, port
, results
.release());
770 void CKademliaUDPListener::Free(SSearchTerm
* pSearchTerms
)
773 Free(pSearchTerms
->left
);
774 Free(pSearchTerms
->right
);
779 SSearchTerm
* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile
& bio
, int iLevel
)
781 // the max. depth has to match our own limit for creating the search expression
782 // (see also 'ParsedSearchExpression' and 'GetSearchPacket')
784 AddDebugLogLineN(logKadSearch
, wxT("***NOTE: Search expression tree exceeds depth limit!"));
789 uint8_t op
= bio
.ReadUInt8();
791 uint8_t boolop
= bio
.ReadUInt8();
792 if (boolop
== 0x00) { // AND
793 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
794 pSearchTerm
->type
= SSearchTerm::AND
;
795 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
799 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
800 Free(pSearchTerm
->left
);
805 } else if (boolop
== 0x01) { // OR
806 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
807 pSearchTerm
->type
= SSearchTerm::OR
;
808 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
812 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
813 Free(pSearchTerm
->left
);
818 } else if (boolop
== 0x02) { // NOT
819 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
820 pSearchTerm
->type
= SSearchTerm::NOT
;
821 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
825 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
) {
826 Free(pSearchTerm
->left
);
832 AddDebugLogLineN(logKadSearch
, CFormat(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)")) % boolop
);
835 } else if (op
== 0x01) { // String
836 wxString
str(bio
.ReadString(true));
838 // Make lowercase, the search code expects lower case strings!
841 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
842 pSearchTerm
->type
= SSearchTerm::String
;
843 pSearchTerm
->astr
= new wxArrayString
;
845 // pre-tokenize the string term
846 //#warning TODO: TokenizeOptQuotedSearchTerm
847 wxStringTokenizer
token(str
, CSearchManager::GetInvalidKeywordChars(), wxTOKEN_DEFAULT
);
848 while (token
.HasMoreTokens()) {
849 wxString
strTok(token
.GetNextToken());
850 if (!strTok
.IsEmpty()) {
851 pSearchTerm
->astr
->Add(strTok
);
856 } else if (op
== 0x02) { // Meta tag
858 wxString
strValue(bio
.ReadString(true));
859 // Make lowercase, the search code expects lower case strings!
860 strValue
.MakeLower();
863 wxString strTagName
= bio
.ReadString(false);
865 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
866 pSearchTerm
->type
= SSearchTerm::MetaTag
;
867 pSearchTerm
->tag
= new CTagString(strTagName
, strValue
);
870 else if (op
== 0x03 || op
== 0x08) { // Numeric relation (0x03=32-bit or 0x08=64-bit)
871 static const struct {
872 SSearchTerm::ESearchTermType eSearchTermOp
;
876 { SSearchTerm::OpEqual
, wxT("=") }, // mmop=0x00
877 { SSearchTerm::OpGreater
, wxT(">") }, // mmop=0x01
878 { SSearchTerm::OpLess
, wxT("<") }, // mmop=0x02
879 { SSearchTerm::OpGreaterEqual
, wxT(">=") }, // mmop=0x03
880 { SSearchTerm::OpLessEqual
, wxT("<=") }, // mmop=0x04
881 { SSearchTerm::OpNotEqual
, wxT("<>") } // mmop=0x05
885 uint64_t ullValue
= (op
== 0x03) ? bio
.ReadUInt32() : bio
.ReadUInt64();
887 // read integer operator
888 uint8_t mmop
= bio
.ReadUInt8();
889 if (mmop
>= itemsof(_aOps
)){
890 AddDebugLogLineN(logKadSearch
, CFormat(wxT("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)")) % mmop
);
895 wxString strTagName
= bio
.ReadString(false);
897 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
898 pSearchTerm
->type
= _aOps
[mmop
].eSearchTermOp
;
899 pSearchTerm
->tag
= new CTagVarInt(strTagName
, ullValue
);
903 AddDebugLogLineN(logKadSearch
, CFormat(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)")) % op
);
908 // KADEMLIA2_SEARCH_KEY_REQ
909 // Used in Kad2.0 only
910 void CKademliaUDPListener::Process2SearchKeyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
912 CMemFile
bio(packetData
, lenPacket
);
913 CUInt128 target
= bio
.ReadUInt128();
914 uint16_t startPosition
= bio
.ReadUInt16();
915 bool restrictive
= ((startPosition
& 0x8000) == 0x8000);
916 startPosition
&= 0x7FFF;
917 SSearchTerm
* pSearchTerms
= NULL
;
919 pSearchTerms
= CreateSearchExpressionTree(bio
, 0);
920 if (pSearchTerms
== NULL
) {
921 throw wxString(wxT("Invalid search expression"));
924 CKademlia::GetIndexed()->SendValidKeywordResult(target
, pSearchTerms
, ip
, port
, false, startPosition
, senderKey
);
930 // KADEMLIA2_SEARCH_SOURCE_REQ
931 // Used in Kad2.0 only
932 void CKademliaUDPListener::Process2SearchSourceRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
934 CMemFile
bio(packetData
, lenPacket
);
935 CUInt128 target
= bio
.ReadUInt128();
936 uint16_t startPosition
= (bio
.ReadUInt16() & 0x7FFF);
937 uint64_t fileSize
= bio
.ReadUInt64();
938 CKademlia::GetIndexed()->SendValidSourceResult(target
, ip
, port
, startPosition
, fileSize
, senderKey
);
941 void CKademliaUDPListener::ProcessSearchResponse(CMemFile
& bio
)
943 // What search does this relate to
944 CUInt128 target
= bio
.ReadUInt128();
946 // How many results..
947 uint16_t count
= bio
.ReadUInt16();
949 // What is the answer
950 CUInt128 answer
= bio
.ReadUInt128();
952 // Get info about answer
953 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
954 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
955 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
956 // If that tag list is once used for something else than for viewing, special care has to be taken for any
957 // string conversion!
958 CScopedContainer
<TagPtrList
> tags
;
959 bio
.ReadTagPtrList(tags
.get(), true/*bOptACP*/);
960 CSearchManager::ProcessResult(target
, answer
, tags
.get());
966 // KADEMLIA_SEARCH_RES
967 // Used in Kad1.0 only
968 void CKademliaUDPListener::ProcessSearchResponse(const uint8_t *packetData
, uint32_t lenPacket
)
970 // Verify packet is expected size
971 CHECK_PACKET_MIN_SIZE(37);
973 CMemFile
bio(packetData
, lenPacket
);
974 ProcessSearchResponse(bio
);
977 // KADEMLIA2_SEARCH_RES
978 // Used in Kad2.0 only
979 void CKademliaUDPListener::Process2SearchResponse(const uint8_t *packetData
, uint32_t lenPacket
, const CKadUDPKey
& WXUNUSED(senderKey
))
981 CMemFile
bio(packetData
, lenPacket
);
983 // Who sent this packet.
986 ProcessSearchResponse(bio
);
989 // KADEMLIA2_PUBLISH_KEY_REQ
990 // Used in Kad2.0 only
991 void CKademliaUDPListener::Process2PublishKeyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
994 CIndexed
*indexed
= CKademlia::GetIndexed();
996 // check if we are UDP firewalled
997 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
998 //We are firewalled. We should not index this entry and give publisher a false report.
1002 CMemFile
bio(packetData
, lenPacket
);
1003 CUInt128 file
= bio
.ReadUInt128();
1005 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1008 if (distance
.Get32BitChunk(0) > SEARCHTOLERANCE
&& !::IsLanIP(wxUINT32_SWAP_ALWAYS(ip
))) {
1012 DEBUG_ONLY( wxString strInfo
; )
1013 uint16_t count
= bio
.ReadUInt16();
1016 DEBUG_ONLY( strInfo
.Clear(); )
1018 CUInt128 target
= bio
.ReadUInt128();
1020 Kademlia::CKeyEntry
* entry
= new Kademlia::CKeyEntry();
1024 entry
->m_uUDPport
= port
;
1025 entry
->m_uKeyID
= file
;
1026 entry
->m_uSourceID
= target
;
1027 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMEK
;
1028 entry
->m_bSource
= false;
1029 uint32_t tags
= bio
.ReadUInt8();
1031 CTag
* tag
= bio
.ReadTag();
1033 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1034 if (entry
->GetCommonFileName().IsEmpty()) {
1035 entry
->SetFileName(tag
->GetStr());
1036 DEBUG_ONLY( strInfo
+= CFormat(wxT(" Name=\"%s\"")) % entry
->GetCommonFileName(); )
1038 delete tag
; // tag is no longer stored, but membervar is used
1039 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1040 if (entry
->m_uSize
== 0) {
1041 if (tag
->IsBsob() && tag
->GetBsobSize() == 8) {
1042 entry
->m_uSize
= PeekUInt64(tag
->GetBsob());
1044 entry
->m_uSize
= tag
->GetInt();
1046 DEBUG_ONLY( strInfo
+= CFormat(wxT(" Size=%u")) % entry
->m_uSize
; )
1048 delete tag
; // tag is no longer stored, but membervar is used
1057 if (!strInfo
.IsEmpty()) {
1058 AddDebugLogLineN(logClientKadUDP
, strInfo
);
1062 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishKeyRequest"),ip,port,packetData,lenPacket);
1067 if (!indexed
->AddKeyword(file
, target
, entry
, load
)) {
1068 //We already indexed the maximum number of keywords.
1069 //We do not index anymore but we still send a success..
1070 //Reason: Because if a VERY busy node tells the publisher it failed,
1071 //this busy node will spread to all the surrounding nodes causing popular
1072 //keywords to be stored on MANY nodes..
1073 //So, once we are full, we will periodically clean our list until we can
1074 //begin storing again..
1080 CMemFile
packetdata(17);
1081 packetdata
.WriteUInt128(file
);
1082 packetdata
.WriteUInt8(load
);
1083 DebugSend(Kad2PublishRes
, ip
, port
);
1084 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1087 // KADEMLIA2_PUBLISH_SOURCE_REQ
1088 // Used in Kad2.0 only
1089 void CKademliaUDPListener::Process2PublishSourceRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1092 CIndexed
*indexed
= CKademlia::GetIndexed();
1094 // check if we are UDP firewalled
1095 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1096 //We are firewalled. We should not index this entry and give publisher a false report.
1100 CMemFile
bio(packetData
, lenPacket
);
1101 CUInt128 file
= bio
.ReadUInt128();
1103 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1106 if (distance
.Get32BitChunk(0) > SEARCHTOLERANCE
&& !::IsLanIP(wxUINT32_SWAP_ALWAYS(ip
))) {
1110 DEBUG_ONLY( wxString strInfo
; )
1113 CUInt128 target
= bio
.ReadUInt128();
1114 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
1117 entry
->m_uUDPport
= port
;
1118 entry
->m_uKeyID
= file
;
1119 entry
->m_uSourceID
= target
;
1120 entry
->m_bSource
= false;
1121 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMES
;
1122 bool addUDPPortTag
= true;
1123 uint32_t tags
= bio
.ReadUInt8();
1125 CTag
* tag
= bio
.ReadTag();
1127 if (!tag
->GetName().Cmp(TAG_SOURCETYPE
)) {
1128 if (entry
->m_bSource
== false) {
1129 entry
->AddTag(new CTagVarInt(TAG_SOURCEIP
, entry
->m_uIP
));
1131 entry
->m_bSource
= true;
1133 //More than one sourcetype tag found.
1136 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1137 if (entry
->m_uSize
== 0) {
1138 if (tag
->IsBsob() && tag
->GetBsobSize() == 8) {
1139 entry
->m_uSize
= PeekUInt64(tag
->GetBsob());
1141 entry
->m_uSize
= tag
->GetInt();
1143 DEBUG_ONLY( strInfo
+= CFormat(wxT(" Size=%u")) % entry
->m_uSize
; )
1146 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
1147 if (entry
->m_uTCPport
== 0) {
1148 entry
->m_uTCPport
= (uint16_t)tag
->GetInt();
1151 //More than one port tag found
1154 } else if (!tag
->GetName().Cmp(TAG_SOURCEUPORT
)) {
1155 if (addUDPPortTag
&& tag
->IsInt() && tag
->GetInt() != 0) {
1156 entry
->m_uUDPport
= (uint16_t)tag
->GetInt();
1158 addUDPPortTag
= false;
1160 //More than one udp port tag found
1170 if (addUDPPortTag
) {
1171 entry
->AddTag(new CTagVarInt(TAG_SOURCEUPORT
, entry
->m_uUDPport
));
1174 if (!strInfo
.IsEmpty()) {
1175 AddDebugLogLineN(logClientKadUDP
, strInfo
);
1179 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishSourceRequest"),ip,port,packetData,lenPacket);
1184 if (entry
->m_bSource
== true) {
1185 if (indexed
->AddSources(file
, target
, entry
, load
)) {
1196 CMemFile
packetdata(17);
1197 packetdata
.WriteUInt128(file
);
1198 packetdata
.WriteUInt8(load
);
1199 DebugSend(Kad2PublishRes
, ip
, port
);
1200 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1204 // KADEMLIA_PUBLISH_RES
1205 // Used only by Kad1.0
1206 void CKademliaUDPListener::ProcessPublishResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1208 // Verify packet is expected size
1209 CHECK_PACKET_MIN_SIZE(16);
1210 CHECK_TRACKED_PACKET(KADEMLIA_PUBLISH_REQ
);
1212 CMemFile
bio(packetData
, lenPacket
);
1213 CUInt128 file
= bio
.ReadUInt128();
1215 bool loadResponse
= false;
1217 if (bio
.GetLength() > bio
.GetPosition()) {
1218 loadResponse
= true;
1219 load
= bio
.ReadUInt8();
1222 CSearchManager::ProcessPublishResult(file
, load
, loadResponse
);
1225 // KADEMLIA2_PUBLISH_RES
1226 // Used only by Kad2.0
1227 void CKademliaUDPListener::Process2PublishResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1229 if (!IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_KEY_REQ
) && !IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_SOURCE_REQ
) && !IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_NOTES_REQ
)) {
1230 throw wxString(CFormat(wxT("***NOTE: Received unrequested response packet, size (%u) in %s")) % lenPacket
% wxString::FromAscii(__FUNCTION__
));
1232 CMemFile
bio(packetData
, lenPacket
);
1233 CUInt128 file
= bio
.ReadUInt128();
1234 uint8_t load
= bio
.ReadUInt8();
1235 CSearchManager::ProcessPublishResult(file
, load
, true);
1236 if (bio
.GetLength() > bio
.GetPosition()) {
1238 uint8_t options
= bio
.ReadUInt8();
1239 bool requestACK
= (options
& 0x01) > 0;
1240 if (requestACK
&& !senderKey
.IsEmpty()) {
1241 DebugSend(Kad2PublishResAck
, ip
, port
);
1242 SendNullPacket(KADEMLIA2_PUBLISH_RES_ACK
, ip
, port
, senderKey
, NULL
);
1247 // KADEMLIA2_SEARCH_NOTES_REQ
1248 // Used only by Kad2.0
1249 void CKademliaUDPListener::Process2SearchNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1251 CMemFile
bio(packetData
, lenPacket
);
1252 CUInt128 target
= bio
.ReadUInt128();
1253 uint64_t fileSize
= bio
.ReadUInt64();
1254 CKademlia::GetIndexed()->SendValidNoteResult(target
, ip
, port
, fileSize
, senderKey
);
1257 // KADEMLIA_SEARCH_NOTES_RES
1258 // Used only by Kad1.0
1259 void CKademliaUDPListener::ProcessSearchNotesResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1261 // Verify packet is expected size
1262 CHECK_PACKET_MIN_SIZE(37);
1263 CHECK_TRACKED_PACKET(KADEMLIA_SEARCH_NOTES_REQ
);
1265 // What search does this relate to
1266 CMemFile
bio(packetData
, lenPacket
);
1267 ProcessSearchResponse(bio
);
1270 // KADEMLIA2_PUBLISH_NOTES_REQ
1271 // Used only by Kad2.0
1272 void CKademliaUDPListener::Process2PublishNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1274 // check if we are UDP firewalled
1275 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1276 //We are firewalled. We should not index this entry and give publisher a false report.
1280 CMemFile
bio(packetData
, lenPacket
);
1281 CUInt128 target
= bio
.ReadUInt128();
1283 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1286 if (distance
.Get32BitChunk(0) > SEARCHTOLERANCE
&& !::IsLanIP(wxUINT32_SWAP_ALWAYS(ip
))) {
1290 CUInt128 source
= bio
.ReadUInt128();
1292 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
1295 entry
->m_uUDPport
= port
;
1296 entry
->m_uKeyID
= target
;
1297 entry
->m_uSourceID
= source
;
1298 entry
->m_bSource
= false;
1299 uint32_t tags
= bio
.ReadUInt8();
1301 CTag
* tag
= bio
.ReadTag();
1303 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1304 if (entry
->GetCommonFileName().IsEmpty()) {
1305 entry
->SetFileName(tag
->GetStr());
1308 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1309 if (entry
->m_uSize
== 0) {
1310 entry
->m_uSize
= tag
->GetInt();
1321 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishNotesRequest"),ip,port,packetData,lenPacket);
1328 if (CKademlia::GetIndexed()->AddNotes(target
, source
, entry
, load
)) {
1329 CMemFile
packetdata(17);
1330 packetdata
.WriteUInt128(target
);
1331 packetdata
.WriteUInt8(load
);
1332 DebugSend(Kad2PublishRes
, ip
, port
);
1333 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1339 // KADEMLIA_FIREWALLED_REQ
1340 // Used by Kad1.0 and Kad2.0
1341 void CKademliaUDPListener::ProcessFirewalledRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1343 // Verify packet is expected size
1344 CHECK_PACKET_EXACT_SIZE(2);
1346 CMemFile
bio(packetData
, lenPacket
);
1347 uint16_t tcpport
= bio
.ReadUInt16();
1350 CContact
contact(zero
, ip
, port
, tcpport
, 0, 0, false, zero
);
1351 if (!theApp
->clientlist
->RequestTCP(&contact
, 0)) {
1352 return; // cancelled for some reason, don't send a response
1356 CMemFile
packetdata(4);
1357 packetdata
.WriteUInt32(ip
);
1358 DebugSend(KadFirewalledRes
, ip
, port
);
1359 SendPacket(packetdata
, KADEMLIA_FIREWALLED_RES
, ip
, port
, senderKey
, NULL
);
1362 // KADEMLIA_FIREWALLED2_REQ
1363 // Used by Kad2.0 Prot.Version 7+
1364 void CKademliaUDPListener::ProcessFirewalled2Request(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1366 // Verify packet is expected size
1367 CHECK_PACKET_MIN_SIZE(19);
1369 CMemFile
bio(packetData
, lenPacket
);
1370 uint16_t tcpPort
= bio
.ReadUInt16();
1371 CUInt128 userID
= bio
.ReadUInt128();
1372 uint8_t connectOptions
= bio
.ReadUInt8();
1375 CContact
contact(userID
, ip
, port
, tcpPort
, 0, 0, false, zero
);
1376 if (!theApp
->clientlist
->RequestTCP(&contact
, connectOptions
)) {
1377 return; // cancelled for some reason, don't send a response
1381 CMemFile
packetdata(4);
1382 packetdata
.WriteUInt32(ip
);
1383 DebugSend(KadFirewalledRes
, ip
, port
);
1384 SendPacket(packetdata
, KADEMLIA_FIREWALLED_RES
, ip
, port
, senderKey
, NULL
);
1387 // KADEMLIA_FIREWALLED_RES
1388 // Used by Kad1.0 and Kad2.0
1389 void CKademliaUDPListener::ProcessFirewalledResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, const CKadUDPKey
& WXUNUSED(senderKey
))
1391 // Verify packet is expected size
1392 CHECK_PACKET_EXACT_SIZE(4);
1394 if (!theApp
->clientlist
->IsKadFirewallCheckIP(wxUINT32_SWAP_ALWAYS(ip
))) { /* KADEMLIA_FIREWALLED2_REQ + KADEMLIA_FIREWALLED_REQ */
1395 throw wxString(wxT("Received unrequested firewall response packet in ")) + wxString::FromAscii(__FUNCTION__
);
1398 CMemFile
bio(packetData
, lenPacket
);
1399 uint32_t firewalledIP
= bio
.ReadUInt32();
1401 // Update con state only if something changes.
1402 if (CKademlia::GetPrefs()->GetIPAddress() != firewalledIP
) {
1403 CKademlia::GetPrefs()->SetIPAddress(firewalledIP
);
1404 theApp
->ShowConnectionState();
1406 CKademlia::GetPrefs()->IncRecheckIP();
1409 // KADEMLIA_FIREWALLED_ACK_RES
1410 // Used by Kad1.0 and Kad2.0
1411 void CKademliaUDPListener::ProcessFirewalledAckResponse(uint32_t lenPacket
)
1413 // 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.
1414 // But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest.
1416 // Verify packet is expected size
1417 CHECK_PACKET_EXACT_SIZE(0);
1419 CKademlia::GetPrefs()->IncFirewalled();
1422 // KADEMLIA_FINDBUDDY_REQ
1423 // Used by Kad1.0 and Kad2.0
1424 void CKademliaUDPListener::ProcessFindBuddyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1426 // Verify packet is expected size
1427 CHECK_PACKET_MIN_SIZE(34);
1429 if (CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true) || !CUDPFirewallTester::IsVerified()) {
1430 // We are firewalled but somehow we still got this packet.. Don't send a response..
1432 } else if (theApp
->clientlist
->GetBuddyStatus() == Connected
) {
1433 // we already have a buddy
1437 CMemFile
bio(packetData
, lenPacket
);
1438 CUInt128 BuddyID
= bio
.ReadUInt128();
1439 CUInt128 userID
= bio
.ReadUInt128();
1440 uint16_t tcpport
= bio
.ReadUInt16();
1443 CContact
contact(userID
, ip
, port
, tcpport
, 0, 0, false, zero
);
1444 if (!theApp
->clientlist
->IncomingBuddy(&contact
, &BuddyID
)) {
1445 return; // cancelled for some reason, don't send a response
1448 CMemFile
packetdata(34);
1449 packetdata
.WriteUInt128(BuddyID
);
1450 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
1451 packetdata
.WriteUInt16(thePrefs::GetPort());
1452 if (!senderKey
.IsEmpty()) { // remove check for later versions
1453 packetdata
.WriteUInt8(CPrefs::GetMyConnectOptions(true, false)); // new since 0.49a, old mules will ignore it (hopefully ;) )
1456 DebugSend(KadFindBuddyRes
, ip
, port
);
1457 SendPacket(packetdata
, KADEMLIA_FINDBUDDY_RES
, ip
, port
, senderKey
, NULL
);
1460 // KADEMLIA_FINDBUDDY_RES
1461 // Used by Kad1.0 and Kad2.0
1462 void CKademliaUDPListener::ProcessFindBuddyResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& WXUNUSED(senderKey
))
1464 // Verify packet is expected size
1465 CHECK_PACKET_MIN_SIZE(34);
1466 CHECK_TRACKED_PACKET(KADEMLIA_FINDBUDDY_REQ
);
1468 CMemFile
bio(packetData
, lenPacket
);
1469 CUInt128 check
= bio
.ReadUInt128();
1470 check
^= CUInt128(true);
1471 if (CKademlia::GetPrefs()->GetKadID() == check
) {
1472 CUInt128 userID
= bio
.ReadUInt128();
1473 uint16_t tcpport
= bio
.ReadUInt16();
1474 uint8_t connectOptions
= 0;
1475 if (lenPacket
> 34) {
1476 // 0.49+ (kad version 7) sends additionally its connect options so we know whether to use an obfuscated connection
1477 connectOptions
= bio
.ReadUInt8();
1481 CContact
contact(userID
, ip
, port
, tcpport
, 0, 0, false, zero
);
1482 theApp
->clientlist
->RequestBuddy(&contact
, connectOptions
);
1486 // KADEMLIA_CALLBACK_REQ
1487 // Used by Kad1.0 and Kad2.0
1488 void CKademliaUDPListener::ProcessCallbackRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t WXUNUSED(port
), const CKadUDPKey
& WXUNUSED(senderKey
))
1490 // Verify packet is expected size
1491 CHECK_PACKET_MIN_SIZE(34);
1493 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1494 if (buddy
!= NULL
) {
1495 CMemFile
bio(packetData
, lenPacket
);
1496 CUInt128 check
= bio
.ReadUInt128();
1497 // JOHNTODO: Begin filtering bad buddy ID's..
1498 // CUInt128 bud(buddy->GetBuddyID());
1499 CUInt128 file
= bio
.ReadUInt128();
1500 uint16_t tcp
= bio
.ReadUInt16();
1502 if (buddy
->GetSocket()) {
1503 CMemFile
packetdata(lenPacket
+ 6);
1504 packetdata
.WriteUInt128(check
);
1505 packetdata
.WriteUInt128(file
);
1506 packetdata
.WriteUInt32(ip
);
1507 packetdata
.WriteUInt16(tcp
);
1508 CPacket
* packet
= new CPacket(packetdata
, OP_EMULEPROT
, OP_CALLBACK
);
1509 AddDebugLogLineN(logLocalClient
, wxT("Local Client: OP_CALLBACK to ") + KadIPToString(ip
));
1510 buddy
->GetSocket()->SendPacket(packet
);
1511 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1513 throw wxString::FromAscii(__FUNCTION__
) + wxT(": Buddy has no valid socket");
1519 void CKademliaUDPListener::Process2Ping(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1521 // can be used just as PING, currently it is however only used to determine one's external port
1522 CMemFile
packetdata(2);
1523 packetdata
.WriteUInt16(port
);
1524 DebugSend(Kad2Pong
, ip
, port
);
1525 SendPacket(packetdata
, KADEMLIA2_PONG
, ip
, port
, senderKey
, NULL
);
1529 void CKademliaUDPListener::Process2Pong(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1531 CHECK_PACKET_MIN_SIZE(2);
1532 CHECK_TRACKED_PACKET(KADEMLIA2_PING
);
1534 // Is this one of our legacy challenge packets?
1536 if (IsLegacyChallenge(CUInt128((uint32_t)0), ip
, KADEMLIA2_PING
, contactID
)) {
1537 // yup it is, set the contact as verified
1538 // cppcheck-suppress duplicateBranch
1539 if (!CKademlia::GetRoutingZone()->VerifyContact(contactID
, ip
)) {
1540 AddDebugLogLineN(logKadRouting
, wxT("Unable to find valid sender in routing table (sender: ") + KadIPToString(ip
) + wxT(")"));
1542 AddDebugLogLineN(logKadRouting
, wxT("Verified contact with legacy challenge (Kad2Ping) - ") + KadIPToString(ip
));
1544 return; // we do not actually care for its other content
1547 if (CKademlia::GetPrefs()->FindExternKadPort(false)) {
1548 // the reported port doesn't always have to be our true external port, esp. if we used our intern port
1549 // and communicated recently with the client some routers might remember this and assign the intern port as source
1550 // but this shouldn't be a problem because we prefer intern ports anyway.
1551 // might have to be reviewed in later versions when more data is available
1552 CKademlia::GetPrefs()->SetExternKadPort(PeekUInt16(packetData
), ip
);
1554 if (CUDPFirewallTester::IsFWCheckUDPRunning()) {
1555 CUDPFirewallTester::QueryNextClient();
1558 theApp
->ShowConnectionState();
1561 // KADEMLIA2_FIREWALLUDP
1562 void CKademliaUDPListener::Process2FirewallUDP(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1564 // Verify packet is expected size
1565 CHECK_PACKET_MIN_SIZE(3);
1567 uint8_t errorCode
= PeekUInt8(packetData
);
1568 uint16_t incomingPort
= PeekUInt16(packetData
+ 1);
1569 if ((incomingPort
!= CKademlia::GetPrefs()->GetExternalKadPort() && incomingPort
!= CKademlia::GetPrefs()->GetInternKadPort()) || incomingPort
== 0) {
1570 AddDebugLogLineN(logClientKadUDP
, CFormat(wxT("Received UDP FirewallCheck on unexpected incoming port %u from %s")) % incomingPort
% KadIPToString(ip
));
1571 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip
, 0);
1572 } else if (errorCode
== 0) {
1573 AddDebugLogLineN(logClientKadUDP
, CFormat(wxT("Received UDP FirewallCheck packet from %s with incoming port %u")) % KadIPToString(ip
) % incomingPort
);
1574 CUDPFirewallTester::SetUDPFWCheckResult(true, false, ip
, incomingPort
);
1576 AddDebugLogLineN(logClientKadUDP
, CFormat(wxT("Received UDP FirewallCheck packet from %s with incoming port %u with remote errorcode %u - ignoring result"))
1577 % KadIPToString(ip
) % incomingPort
% errorCode
);
1578 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip
, 0);
1582 void CKademliaUDPListener::SendPacket(const CMemFile
&data
, uint8_t opcode
, uint32_t destinationHost
, uint16_t destinationPort
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
)
1584 AddTrackedOutPacket(destinationHost
, opcode
);
1585 CPacket
* packet
= new CPacket(data
, OP_KADEMLIAHEADER
, opcode
);
1586 if (packet
->GetPacketSize() > 200) {
1587 packet
->PackPacket();
1589 uint8_t cryptData
[16];
1591 if (cryptTargetID
!= NULL
) {
1592 cryptKey
= (uint8_t *)&cryptData
;
1593 cryptTargetID
->StoreCryptValue(cryptKey
);
1597 theStats::AddUpOverheadKad(packet
->GetPacketSize());
1598 theApp
->clientudp
->SendPacket(packet
, wxUINT32_SWAP_ALWAYS(destinationHost
), destinationPort
, true, cryptKey
, true, targetKey
.GetKeyValue(theApp
->GetPublicIP(false)));
1601 bool CKademliaUDPListener::FindNodeIDByIP(CKadClientSearcher
* requester
, uint32_t ip
, uint16_t tcpPort
, uint16_t udpPort
)
1603 // send a hello packet to the given IP in order to get a HELLO_RES with the NodeID
1604 AddDebugLogLineN(logClientKadUDP
, wxT("FindNodeIDByIP: Requesting NodeID from ") + KadIPToString(ip
) + wxT(" by sending Kad2HelloReq"));
1605 DebugSend(Kad2HelloReq
, ip
, udpPort
);
1606 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
1607 FetchNodeID_Struct sRequest
= { ip
, tcpPort
, ::GetTickCount() + SEC2MS(60), requester
};
1608 m_fetchNodeIDRequests
.push_back(sRequest
);
1612 void CKademliaUDPListener::ExpireClientSearch(CKadClientSearcher
* expireImmediately
)
1614 uint32_t now
= ::GetTickCount();
1615 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end();) {
1616 FetchNodeIDList::iterator it2
= it
++;
1617 if (it2
->requester
== expireImmediately
) {
1618 m_fetchNodeIDRequests
.erase(it2
);
1620 else if (it2
->expire
< now
) {
1621 it2
->requester
->KadSearchNodeIDByIPResult(KCSR_TIMEOUT
, NULL
);
1622 m_fetchNodeIDRequests
.erase(it2
);
1627 void CKademliaUDPListener::SendLegacyChallenge(uint32_t ip
, uint16_t port
, const CUInt128
& contactID
)
1629 // We want to verify that a pre-0.49a contact is valid and not sent from a spoofed IP.
1630 // Because those versions don't support any direct validating, we send a KAD_REQ with a random ID,
1631 // which is our challenge. If we receive an answer packet for this request, we can be sure the
1632 // contact is not spoofed
1634 CContact
* contact
= CKademlia::GetRoutingZone()->GetContact(contactID
);
1635 if (contact
!= NULL
) {
1636 if (contact
->GetType() < 2) {
1637 AddDebugLogLineN(logKadRouting
, wxT("Sending challenge to a long known contact (should be verified already) - ") + KadIPToString(ip
));
1644 if (HasActiveLegacyChallenge(ip
)) {
1645 // don't send more than one challenge at a time
1648 CMemFile
packetdata(33);
1649 packetdata
.WriteUInt8(KADEMLIA_FIND_VALUE
);
1650 CUInt128
challenge(GetRandomUint128());
1651 if (challenge
== 0) {
1652 // hey there is a 2^128 chance that this happens ;)
1656 // Put the target we want into the packet. This is our challenge
1657 packetdata
.WriteUInt128(challenge
);
1658 // Add the ID of the contact we are contacting for sanity checks on the other end.
1659 packetdata
.WriteUInt128(contactID
);
1660 DebugSendF(wxT("Kad2Req(SendLegacyChallenge)"), ip
, port
);
1661 // those versions we send those requests to don't support encryption / obfuscation
1662 SendPacket(packetdata
, KADEMLIA2_REQ
, ip
, port
, 0, NULL
);
1663 AddLegacyChallenge(contactID
, challenge
, ip
, KADEMLIA2_REQ
);
1666 void CKademliaUDPListener::DebugClientOutput(const wxString
& place
, uint32 kad_ip
, uint32 port
, const byte
* data
, int len
)
1668 #if THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX
1669 uint32 ip
= wxUINT32_SWAP_ALWAYS(kad_ip
);
1670 printf("Error on %s received from: %s\n",(const char*)unicode2char(place
),(const char*)unicode2char(Uint32_16toStringIP_Port(ip
,port
)));
1672 printf("Packet dump:\n");
1675 CClientList::SourceList clientslist
= theApp
->clientlist
->GetClientsByIP(ip
);
1676 if (!clientslist
.empty()) {
1677 for (CClientList::SourceList::iterator it
= clientslist
.begin(); it
!= clientslist
.end(); ++it
) {
1678 printf("Ip Matches: %s\n",(const char*)unicode2char((*it
)->GetClientFullInfo()));
1681 printf("No ip match, trying to create a client connection:\n");
1682 printf("Trying port %d\n", port
- 10);
1683 CUpDownClient
* client
= new CUpDownClient(port
-10,kad_ip
,0,0,NULL
,false,false);
1684 client
->SetConnectionReason(wxT("Error on ") + place
);
1685 client
->TryToConnect(true);
1688 // No need for warnings for the rest of us.
1696 // File_checked_for_headers