2 // This file is part of aMule Project
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
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()
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__
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
)
108 DebugSend(Kad2BootstrapReq
, ip
, port
);
110 if (kadVersion
>= 6) {
111 SendPacket(bio
, KADEMLIA2_BOOTSTRAP_REQ
, ip
, port
, 0, cryptTargetID
);
113 SendPacket(bio
, KADEMLIA2_BOOTSTRAP_REQ
, ip
, port
, 0, NULL
);
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
)
125 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
127 if (kadVersion
> 0) {
128 packetdata
.WriteUInt16(thePrefs::GetPort());
129 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
131 uint8_t tagCount
= 0;
132 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
135 if (kadVersion
>= 8 && (requestAckPacket
|| CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true))) {
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)
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)
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
);
161 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, cryptTargetID
);
164 SendPacket(packetdata
, opcode
, ip
, port
, 0, NULL
);
165 wxASSERT(targetKey
.IsEmpty());
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
);
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
)
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());
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
);
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
));
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
)) {
254 case KADEMLIA_BOOTSTRAP_REQ
:
255 DebugRecv(KadBootstrapReq
, ip
, port
);
256 ProcessBootstrapRequest(packetData
, lenPacket
, ip
, port
);
258 case KADEMLIA2_BOOTSTRAP_REQ
:
259 DebugRecv(Kad2BootstrapReq
, ip
, port
);
260 Process2BootstrapRequest(ip
, port
, senderKey
);
262 case KADEMLIA_BOOTSTRAP_RES
:
263 DebugRecv(KadBootstrapRes
, ip
, port
);
264 ProcessBootstrapResponse(packetData
, lenPacket
, ip
);
266 case KADEMLIA2_BOOTSTRAP_RES
:
267 DebugRecv(Kad2BootstrapRes
, ip
, port
);
268 Process2BootstrapResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
270 case KADEMLIA_HELLO_REQ
:
271 DebugRecv(KadHelloReq
, ip
, port
);
272 ProcessHelloRequest(packetData
, lenPacket
, ip
, port
);
274 case KADEMLIA2_HELLO_REQ
:
275 DebugRecv(Kad2HelloReq
, ip
, port
);
276 Process2HelloRequest(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
278 case KADEMLIA_HELLO_RES
:
279 DebugRecv(KadHelloRes
, ip
, port
);
280 ProcessHelloResponse(packetData
, lenPacket
, ip
, port
);
282 case KADEMLIA2_HELLO_RES
:
283 DebugRecv(Kad2HelloRes
, ip
, port
);
284 Process2HelloResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
286 case KADEMLIA2_HELLO_RES_ACK
:
287 DebugRecv(Kad2HelloResAck
, ip
, port
);
288 Process2HelloResponseAck(packetData
, lenPacket
, ip
, validReceiverKey
);
291 DebugRecv(KadReq
, ip
, port
);
292 ProcessKademliaRequest(packetData
, lenPacket
, ip
, port
);
295 DebugRecv(Kad2Req
, ip
, port
);
296 ProcessKademlia2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
299 DebugRecv(KadRes
, ip
, port
);
300 ProcessKademliaResponse(packetData
, lenPacket
, ip
, port
);
303 DebugRecv(Kad2Res
, ip
, port
);
304 ProcessKademlia2Response(packetData
, lenPacket
, ip
, port
, senderKey
);
306 case KADEMLIA_SEARCH_REQ
:
307 DebugRecv(KadSearchReq
, ip
, port
);
308 ProcessSearchRequest(packetData
, lenPacket
, ip
, port
);
310 case KADEMLIA_SEARCH_NOTES_REQ
:
311 DebugRecv(KadSearchNotesReq
, ip
, port
);
312 ProcessSearchNotesRequest(packetData
, lenPacket
, ip
, port
);
314 case KADEMLIA2_SEARCH_NOTES_REQ
:
315 DebugRecv(Kad2SearchNotesReq
, ip
, port
);
316 Process2SearchNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
318 case KADEMLIA2_SEARCH_KEY_REQ
:
319 DebugRecv(Kad2SearchKeyReq
, ip
, port
);
320 Process2SearchKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
322 case KADEMLIA2_SEARCH_SOURCE_REQ
:
323 DebugRecv(Kad2SearchSourceReq
, ip
, port
);
324 Process2SearchSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
326 case KADEMLIA_SEARCH_RES
:
327 DebugRecv(KadSearchRes
, ip
, port
);
328 ProcessSearchResponse(packetData
, lenPacket
);
330 case KADEMLIA_SEARCH_NOTES_RES
:
331 DebugRecv(KadSearchNotesRes
, ip
, port
);
332 ProcessSearchNotesResponse(packetData
, lenPacket
, ip
);
334 case KADEMLIA2_SEARCH_RES
:
335 DebugRecv(Kad2SearchRes
, ip
, port
);
336 Process2SearchResponse(packetData
, lenPacket
, senderKey
);
338 case KADEMLIA_PUBLISH_REQ
:
339 DebugRecv(KadPublishReq
, ip
, port
);
340 ProcessPublishRequest(packetData
, lenPacket
, ip
, port
);
342 case KADEMLIA_PUBLISH_NOTES_REQ
:
343 DebugRecv(KadPublishNotesReq
, ip
, port
);
344 ProcessPublishNotesRequest(packetData
, lenPacket
, ip
, port
);
346 case KADEMLIA2_PUBLISH_NOTES_REQ
:
347 DebugRecv(Kad2PublishNotesReq
, ip
, port
);
348 Process2PublishNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
350 case KADEMLIA2_PUBLISH_KEY_REQ
:
351 DebugRecv(Kad2PublishKeyReq
, ip
, port
);
352 Process2PublishKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
354 case KADEMLIA2_PUBLISH_SOURCE_REQ
:
355 DebugRecv(Kad2PublishSourceReq
, ip
, port
);
356 Process2PublishSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
358 case KADEMLIA_PUBLISH_RES
:
359 DebugRecv(KadPublishRes
, ip
, port
);
360 ProcessPublishResponse(packetData
, lenPacket
, ip
);
362 case KADEMLIA_PUBLISH_NOTES_RES
:
363 DebugRecv(KadPublishNotesRes
, ip
, port
);
364 ProcessPublishNotesResponse(packetData
, lenPacket
, ip
);
366 case KADEMLIA2_PUBLISH_RES
:
367 DebugRecv(Kad2PublishRes
, ip
, port
);
368 Process2PublishResponse(packetData
, lenPacket
, ip
, port
, senderKey
);
370 case KADEMLIA_FIREWALLED_REQ
:
371 DebugRecv(KadFirewalledReq
, ip
, port
);
372 ProcessFirewalledRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
374 case KADEMLIA_FIREWALLED2_REQ
:
375 DebugRecv(KadFirewalled2Req
, ip
, port
);
376 ProcessFirewalled2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
378 case KADEMLIA_FIREWALLED_RES
:
379 DebugRecv(KadFirewalledRes
, ip
, port
);
380 ProcessFirewalledResponse(packetData
, lenPacket
, ip
, senderKey
);
382 case KADEMLIA_FIREWALLED_ACK_RES
:
383 DebugRecv(KadFirewalledAck
, ip
, port
);
384 ProcessFirewalledAckResponse(lenPacket
);
386 case KADEMLIA_FINDBUDDY_REQ
:
387 DebugRecv(KadFindBuddyReq
, ip
, port
);
388 ProcessFindBuddyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
390 case KADEMLIA_FINDBUDDY_RES
:
391 DebugRecv(KadFindBuddyRes
, ip
, port
);
392 ProcessFindBuddyResponse(packetData
, lenPacket
, ip
, port
, senderKey
);
394 case KADEMLIA_CALLBACK_REQ
:
395 DebugRecv(KadCallbackReq
, ip
, port
);
396 ProcessCallbackRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
399 DebugRecv(Kad2Ping
, ip
, port
);
400 Process2Ping(ip
, port
, senderKey
);
403 DebugRecv(Kad2Pong
, ip
, port
);
404 Process2Pong(packetData
, lenPacket
, ip
);
406 case KADEMLIA2_FIREWALLUDP
:
407 DebugRecv(Kad2FirewallUDP
, ip
, port
);
408 Process2FirewallUDP(packetData
, lenPacket
, ip
);
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
) {
429 tport
= bio
.ReadUInt16();
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
) {
449 uint16_t tport
= bio
.ReadUInt16();
450 uint8_t version
= bio
.ReadUInt8();
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();
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
) {
473 *outRequestsACK
= true;
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());
490 id
.ToByteArray(uchID
);
491 it
->requester
->KadSearchNodeIDByIPResult(KCSR_SUCCEEDED
, uchID
);
492 m_fetchNodeIDRequests
.erase(it
);
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);
509 AddDebugLogLineN(logKadRouting
, wxT("Not adding firewalled client to routing table (") + KadIPToString(ip
) + wxT(")"));
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();
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.
550 CMemFile
packetdata(527);
553 packetdata
.WriteUInt16(numContacts
);
555 for (ContactList::const_iterator it
= contacts
.begin(); it
!= contacts
.end(); ++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);
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.
586 CMemFile
packetdata(521);
588 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
589 packetdata
.WriteUInt16(thePrefs::GetPort());
590 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
593 packetdata
.WriteUInt16(numContacts
);
595 for (ContactList::const_iterator it
= contacts
.begin(); it
!= contacts
.end(); ++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());
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
)) {
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);
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;
677 bool addedOrUpdated
= AddContact(packetData
, lenPacket
, ip
, port
, 0, 0, validReceiverKey
, true, &contactID
);
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;
701 bool addedOrUpdated
= AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true, true, NULL
, &contactID
); // might change (udp)port, validReceiverKey
702 wxASSERT(contactVersion
>= 1);
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
));
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
);
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
));
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;
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(")"));
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(")"));
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
;
797 bool sendACK
= false;
798 bool addedOrUpdated
= AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true, false, &sendACK
, &contactID
);
801 // the client requested us to send an ACK packet, which proves that we're not a spoofed fake contact
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(")"));
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
);
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
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
)) {
870 // Get required number closest to target
872 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, type
, &results
);
873 uint16_t count
= (uint16_t)results
.size();
876 // Max count is 32. size 817..
878 CMemFile
packetdata(817);
879 packetdata
.WriteUInt128(target
);
880 packetdata
.WriteUInt8((uint8_t)count
);
882 for (ContactMap::const_iterator it
= results
.begin(); it
!= results
.end(); ++it
) {
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
);
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();
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
918 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, type
, &results
);
919 uint8_t count
= (uint8_t)results
.size();
922 // Max count is 32. size 817..
924 CMemFile
packetdata(817);
925 packetdata
.WriteUInt128(target
);
926 packetdata
.WriteUInt8(count
);
928 for (ContactMap::const_iterator it
= results
.begin(); it
!= results
.end(); ++it
) {
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
);
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
);
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?
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(")"));
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();
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
);
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());
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
);
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);
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?
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(")"));
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);
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
);
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
)
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')
1110 AddDebugLogLineN(logKadSearch
, wxT("***NOTE: Search expression tree exceeds depth limit!"));
1115 uint8_t op
= bio
.ReadUInt8();
1117 uint8_t boolop
= bio
.ReadUInt8();
1118 if (boolop
== 0x00) { // AND
1119 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1120 pSearchTerm
->type
= SSearchTerm::AND
;
1122 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1127 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1129 Free(pSearchTerm
->left
);
1134 } else if (boolop
== 0x01) { // OR
1135 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1136 pSearchTerm
->type
= SSearchTerm::OR
;
1138 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1143 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1145 Free(pSearchTerm
->left
);
1150 } else if (boolop
== 0x02) { // NOT
1151 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1152 pSearchTerm
->type
= SSearchTerm::NOT
;
1154 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1159 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
1161 Free(pSearchTerm
->left
);
1167 AddDebugLogLineN(logKadSearch
, wxString::Format(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop
));
1170 } else if (op
== 0x01) { // String
1171 wxString
str(bio
.ReadString(true));
1173 // Make lowercase, the search code expects lower case strings!
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
);
1191 } else if (op
== 0x02) { // Meta tag
1193 wxString
strValue(bio
.ReadString(true));
1194 // Make lowercase, the search code expects lower case strings!
1195 strValue
.MakeLower();
1198 wxString strTagName
= bio
.ReadString(false);
1200 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1201 pSearchTerm
->type
= SSearchTerm::MetaTag
;
1202 pSearchTerm
->tag
= new CTagString(strTagName
, strValue
);
1205 else if (op
== 0x03 || op
== 0x08) { // Numeric relation (0x03=32-bit or 0x08=64-bit)
1206 static const struct {
1207 SSearchTerm::ESearchTermType eSearchTermOp
;
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
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
));
1230 wxString strTagName
= bio
.ReadString(false);
1232 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1233 pSearchTerm
->type
= _aOps
[mmop
].eSearchTermOp
;
1234 pSearchTerm
->tag
= new CTagVarInt(strTagName
, ullValue
);
1238 AddDebugLogLineN(logKadSearch
, wxString::Format(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), op
));
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) {
1257 CKademlia::GetIndexed()->SendValidSourceResult(target
, ip
, port
, false, 0, 0, 0);
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;
1266 pSearchTerms
= CreateSearchExpressionTree(bio
, 0);
1267 if (pSearchTerms
== NULL
) {
1268 throw wxString(wxT("Invalid search expression"));
1270 if (restrictive
> 1) {
1277 // Keyword request with added options.
1278 CKademlia::GetIndexed()->SendValidKeywordResult(target
, pSearchTerms
, ip
, port
, oldClient
, false, 0, 0);
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
;
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
);
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();
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
;
1335 bio
.ReadTagPtrList(tags
, true/*bOptACP*/);
1337 deleteTagPtrListEntries(tags
);
1342 CSearchManager::ProcessResult(target
, answer
, tags
);
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);
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.
1390 CMemFile
bio(packetData
, lenPacket
);
1391 CUInt128 file
= bio
.ReadUInt128();
1393 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1396 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1400 DEBUG_ONLY( wxString strInfo
; )
1401 uint16_t count
= bio
.ReadUInt16();
1405 DEBUG_ONLY( strInfo
.Clear(); )
1407 CUInt128 target
= bio
.ReadUInt128();
1409 Kademlia::CKeyEntry
* entry
= new Kademlia::CKeyEntry();
1412 entry
->m_uUDPport
= port
;
1413 entry
->m_uKeyID
.SetValue(file
);
1414 entry
->m_uSourceID
.SetValue(target
);
1415 uint32_t tags
= bio
.ReadUInt8();
1417 CTag
* tag
= bio
.ReadTag();
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
));
1424 entry
->m_bSource
= true;
1426 //More than one sourcetype tag found.
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(); )
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());
1441 wxASSERT(tag
->IsInt());
1442 entry
->m_uSize
= tag
->GetInt();
1444 DEBUG_ONLY( strInfo
+= wxString::Format(wxT(" Size=%") WXLONGLONGFMTSPEC
wxT("u"), entry
->m_uSize
); )
1447 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
1448 if (entry
->m_uTCPport
== 0) {
1449 entry
->m_uTCPport
= tag
->GetInt();
1452 //More than one port tag found
1463 if (!strInfo
.IsEmpty()) {
1464 AddDebugLogLineN(logClientKadUDP
, strInfo
);
1468 //printf("Error on count %i tag %i\n",totalcount-count, totaltags-tags);
1469 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishRequest"),ip,port,packetData,lenPacket);
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
1479 if (indexed
->AddSources(file
, target
, sourceEntry
, load
)) {
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.
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..
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
)
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.
1529 CMemFile
bio(packetData
, lenPacket
);
1530 CUInt128 file
= bio
.ReadUInt128();
1532 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1535 // Shouldn't LAN IPs already be filtered?
1536 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1540 DEBUG_ONLY( wxString strInfo
; )
1541 uint16_t count
= bio
.ReadUInt16();
1544 DEBUG_ONLY( strInfo
.Clear(); )
1546 CUInt128 target
= bio
.ReadUInt128();
1548 Kademlia::CKeyEntry
* entry
= new Kademlia::CKeyEntry();
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();
1559 CTag
* tag
= bio
.ReadTag();
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());
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
1585 if (!strInfo
.IsEmpty()) {
1586 AddDebugLogLineN(logClientKadUDP
, strInfo
);
1590 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishKeyRequest"),ip,port,packetData,lenPacket);
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..
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
)
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.
1628 CMemFile
bio(packetData
, lenPacket
);
1629 CUInt128 file
= bio
.ReadUInt128();
1631 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1634 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1638 DEBUG_ONLY( wxString strInfo
; )
1641 CUInt128 target
= bio
.ReadUInt128();
1642 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
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();
1653 CTag
* tag
= bio
.ReadTag();
1655 if (!tag
->GetName().Cmp(TAG_SOURCETYPE
)) {
1656 if (entry
->m_bSource
== false) {
1657 entry
->AddTag(new CTagVarInt(TAG_SOURCEIP
, entry
->m_uIP
));
1659 entry
->m_bSource
= true;
1661 //More than one sourcetype tag found.
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());
1669 entry
->m_uSize
= tag
->GetInt();
1671 DEBUG_ONLY( strInfo
+= wxString::Format(wxT(" Size=%") WXLONGLONGFMTSPEC
wxT("u"), entry
->m_uSize
); )
1674 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
1675 if (entry
->m_uTCPport
== 0) {
1676 entry
->m_uTCPport
= (uint16_t)tag
->GetInt();
1679 //More than one port tag found
1682 } else if (!tag
->GetName().Cmp(TAG_SOURCEUPORT
)) {
1683 if (addUDPPortTag
&& tag
->IsInt() && tag
->GetInt() != 0) {
1684 entry
->m_uUDPport
= (uint16_t)tag
->GetInt();
1686 addUDPPortTag
= false;
1688 //More than one udp port tag found
1698 if (addUDPPortTag
) {
1699 entry
->AddTag(new CTagVarInt(TAG_SOURCEUPORT
, entry
->m_uUDPport
));
1702 if (!strInfo
.IsEmpty()) {
1703 AddDebugLogLineN(logClientKadUDP
, strInfo
);
1707 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishSourceRequest"),ip,port,packetData,lenPacket);
1712 if (entry
->m_bSource
== true) {
1713 if (indexed
->AddSources(file
, target
, entry
, load
)) {
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;
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()) {
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.
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
) {
1836 CUInt128 source
= bio
.ReadUInt128();
1838 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
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();
1848 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1849 if (entry
->GetCommonFileName().IsEmpty()) {
1850 entry
->SetFileName(tag
->GetStr());
1853 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1854 if (entry
->m_uSize
== 0) {
1855 entry
->m_uSize
= tag
->GetInt();
1865 entry
->m_bSource
= false;
1867 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishNotesRequest"),ip,port,packetData,lenPacket);
1873 if (entry
== NULL
) {
1874 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry == NULL"));
1875 } else if (entry
->GetTagCount() == 0 || entry
->GetTagCount() > 5) {
1877 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry->GetTagCount() == 0 || entry->GetTagCount() > 5"));
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
);
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.
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
) {
1913 CUInt128 source
= bio
.ReadUInt128();
1915 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
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();
1924 CTag
* tag
= bio
.ReadTag();
1926 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1927 if (entry
->GetCommonFileName().IsEmpty()) {
1928 entry
->SetFileName(tag
->GetStr());
1931 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1932 if (entry
->m_uSize
== 0) {
1933 entry
->m_uSize
= tag
->GetInt();
1944 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishNotesRequest"),ip,port,packetData,lenPacket);
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
);
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;
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();
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
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();
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
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..
2076 } else if (theApp
->clientlist
->GetBuddyStatus() == Connected
) {
2077 // we already have a buddy
2081 CMemFile
bio(packetData
, lenPacket
);
2082 CUInt128 BuddyID
= bio
.ReadUInt128();
2083 CUInt128 userID
= bio
.ReadUInt128();
2084 uint16_t tcpport
= bio
.ReadUInt16();
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();
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());
2157 throw wxString::FromAscii(__FUNCTION__
) + wxT(": Buddy has no valid socket");
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
);
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?
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(")"));
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
);
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];
2233 if (cryptTargetID
!= NULL
) {
2234 cryptKey
= (uint8_t *)&cryptData
;
2235 cryptTargetID
->StoreCryptValue(cryptKey
);
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
);
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
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
));
2289 if (HasActiveLegacyChallenge(ip
)) {
2290 // don't send more than one challenge at a time
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 ;)
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
);
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
);
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
)));
2323 printf("Packet dump:\n");
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()));
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);
2339 // No need for warnings for the rest of us.
2347 // File_checked_for_headers