2 // This file is part of aMule Project
4 // Copyright (c) 2004-2008 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2004-2008 aMule Project ( http://www.amule-project.net )
6 // Copyright (C)2003 Barry Dunne (http://www.emule-project.net)
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 Please do not change anything here and release it..
25 There is going to be a new forum created just for the Kademlia side of the client..
26 If you feel there is an error or a way to improve something, please
27 post it in the forum first and let us look at it.. If it is a real improvement,
28 it will be added to the offical client.. Changing something without knowing
29 what all it does can cause great harm to the network if released in mass form..
30 Any mod that changes anything within the Kademlia side will not be allowed to advertise
31 there client on the eMule forum..
36 #include "KademliaUDPListener.h"
38 #include <protocol/Protocols.h>
39 #include <protocol/kad/Constants.h>
40 #include <protocol/kad/Client2Client/UDP.h>
41 #include <protocol/kad2/Constants.h>
42 #include <protocol/kad2/Client2Client/UDP.h>
43 #include <protocol/ed2k/Client2Client/TCP.h> // OP_CALLBACK is sent in some cases.
44 #include <common/Macros.h>
45 #include <common/Format.h>
46 #include <tags/FileTags.h>
48 #include "../routing/Contact.h"
49 #include "../routing/RoutingZone.h"
50 #include "../kademlia/Indexed.h"
51 #include "../kademlia/Defines.h"
52 #include "../kademlia/UDPFirewallTester.h"
53 #include "../utils/KadUDPKey.h"
54 #include "../utils/KadClientSearcher.h"
55 #include "../../amule.h"
56 #include "../../ClientUDPSocket.h"
57 #include "../../Packet.h"
58 #include "../../ClientList.h"
59 #include "../../Statistics.h"
60 #include "../../MemFile.h"
61 #include "../../updownclient.h"
62 #include "../../ClientTCPSocket.h"
63 #include "../../Logger.h"
64 #include "../../Preferences.h"
65 #include "../../ScopedPtr.h"
66 #include "../../IPFilter.h"
68 #include <wx/tokenzr.h>
70 #define THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX 0
73 #define CHECK_PACKET_SIZE(OP, SIZE) \
74 if (lenPacket OP (uint32_t)(SIZE)) \
75 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__)
77 #define CHECK_PACKET_MIN_SIZE(SIZE) CHECK_PACKET_SIZE(<, SIZE)
78 #define CHECK_PACKET_EXACT_SIZE(SIZE) CHECK_PACKET_SIZE(!=, SIZE)
80 #define CHECK_TRACKED_PACKET(OPCODE) \
81 if (!IsOnOutTrackList(ip, OPCODE)) \
82 throw wxString::Format(wxT("***NOTE: Received unrequested response packet, size (%u) in "), lenPacket) + wxString::FromAscii(__FUNCTION__)
85 ////////////////////////////////////////
86 using namespace Kademlia
;
87 ////////////////////////////////////////
89 CKademliaUDPListener::~CKademliaUDPListener()
91 // report timeout to all pending FetchNodeIDRequests
92 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end(); ++it
) {
93 it
->requester
->KadSearchNodeIDByIPResult(KCSR_TIMEOUT
, NULL
);
97 // Used by Kad1.0 and Kad2.0
98 void CKademliaUDPListener::Bootstrap(uint32_t ip
, uint16_t port
, bool kad2
)
103 DebugSend(Kad2BootstrapReq
, ip
, port
);
105 // TODO: add possibility to encrypt bootstrap packets
106 SendPacket(bio
, KADEMLIA2_BOOTSTRAP_REQ
, ip
, port
, 0, NULL
);
108 DebugSend(KadBootstrapReq
, ip
, port
);
109 SendMyDetails(KADEMLIA_BOOTSTRAP_REQ
, ip
, port
, kad2
, 0, NULL
);
113 // Used by Kad1.0 and Kad2.0
114 void CKademliaUDPListener::SendMyDetails(uint8_t opcode
, uint32_t ip
, uint16_t port
, bool kad2
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
)
117 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
120 packetdata
.WriteUInt16(thePrefs::GetPort());
121 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
123 uint8_t tagCount
= 0;
124 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
127 packetdata
.WriteUInt8(tagCount
);
128 if (!CKademlia::GetPrefs()->GetUseExternKadPort()) {
129 packetdata
.WriteTag(CTagVarInt(TAG_SOURCEUPORT
, CKademlia::GetPrefs()->GetInternKadPort()));
131 // packetdata.WriteTag(CKadTagUInt(TAG_USER_COUNT, CKademlia::GetPrefs()->GetKademliaUsers()));
132 // packetdata.WriteTag(CKadTagUInt(TAG_FILE_COUNT, CKademlia::GetPrefs()->GetKademliaFiles()));
133 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, cryptTargetID
);
135 packetdata
.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
136 packetdata
.WriteUInt16(thePrefs::GetEffectiveUDPPort());
137 packetdata
.WriteUInt16(thePrefs::GetPort());
138 packetdata
.WriteUInt8(0);
139 SendPacket(packetdata
, opcode
, ip
, port
, 0, NULL
);
143 // Kad1.0 and Kad2.0 currently.
144 void CKademliaUDPListener::FirewalledCheck(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, uint8_t kadVersion
)
146 if (kadVersion
> 6) {
147 // new opcode since 0.49a with extended informations to support obfuscated connections properly
148 CMemFile
packetdata(19);
149 packetdata
.WriteUInt16(thePrefs::GetPort());
150 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
151 packetdata
.WriteUInt8(CPrefs::GetMyConnectOptions(true, false));
152 DebugSend(KadFirewalled2Req
, ip
, port
);
153 SendPacket(packetdata
, KADEMLIA_FIREWALLED2_REQ
, ip
, port
, senderKey
, NULL
);
155 CMemFile
packetdata(2);
156 packetdata
.WriteUInt16(thePrefs::GetPort());
157 DebugSend(KadFirewalledReq
, ip
, port
);
158 SendPacket(packetdata
, KADEMLIA_FIREWALLED_REQ
, ip
, port
, senderKey
, NULL
);
160 theApp
->clientlist
->AddKadFirewallRequest(wxUINT32_SWAP_ALWAYS(ip
));
163 void CKademliaUDPListener::SendNullPacket(uint8_t opcode
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
)
165 CMemFile
packetdata(0);
166 SendPacket(packetdata
, opcode
, ip
, port
, targetKey
, cryptTargetID
);
169 void CKademliaUDPListener::SendPublishSourcePacket(const CContact
& contact
, const CUInt128
&targetID
, const CUInt128
&contactID
, const TagPtrList
& tags
)
173 packetdata
.WriteUInt128(targetID
);
174 if (contact
.GetVersion() >= 4/*47c*/) {
175 opcode
= KADEMLIA2_PUBLISH_SOURCE_REQ
;
176 packetdata
.WriteUInt128(contactID
);
177 packetdata
.WriteTagPtrList(tags
);
178 DebugSend(Kad2PublishSrcReq
, contact
.GetIPAddress(), contact
.GetUDPPort());
180 opcode
= KADEMLIA_PUBLISH_REQ
;
181 //We only use this for publishing sources now.. So we always send one here..
182 packetdata
.WriteUInt16(1);
183 packetdata
.WriteUInt128(contactID
);
184 packetdata
.WriteTagPtrList(tags
);
185 DebugSend(KadPublishReq
, contact
.GetIPAddress(), contact
.GetUDPPort());
187 if (contact
.GetVersion() >= 6) { // obfuscated ?
188 CUInt128 clientID
= contact
.GetClientID();
189 SendPacket(packetdata
, opcode
, contact
.GetIPAddress(), contact
.GetUDPPort(), contact
.GetUDPKey(), &clientID
);
191 SendPacket(packetdata
, opcode
, contact
.GetIPAddress(), contact
.GetUDPPort(), 0, NULL
);
195 void CKademliaUDPListener::ProcessPacket(const uint8_t* data
, uint32_t lenData
, uint32_t ip
, uint16_t port
, bool validReceiverKey
, const CKadUDPKey
& senderKey
)
197 // we do not accept (<= 0.48a) unencrypted incoming packets from port 53 (DNS) to avoid attacks based on DNS protocol confusion
198 if (port
== 53 && senderKey
.IsEmpty()) {
200 AddDebugLogLineM(false, logKadPacketTracking
, wxT("Dropping incoming unencrypted packet on port 53 (DNS), IP: ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)));
205 //Update connection state only when it changes.
206 bool curCon
= CKademlia::GetPrefs()->HasHadContact();
207 CKademlia::GetPrefs()->SetLastContact();
208 CUDPFirewallTester::Connected();
209 if( curCon
!= CKademlia::GetPrefs()->HasHadContact()) {
210 theApp
->ShowConnectionState();
213 uint8_t opcode
= data
[1];
214 const uint8_t *packetData
= data
+ 2;
215 uint32_t lenPacket
= lenData
- 2;
217 if (!InTrackListIsAllowedPacket(ip
, opcode
, validReceiverKey
)) {
222 case KADEMLIA_BOOTSTRAP_REQ
:
223 DebugRecv(KadBootstrapReq
, ip
, port
);
224 ProcessBootstrapRequest(packetData
, lenPacket
, ip
, port
);
226 case KADEMLIA2_BOOTSTRAP_REQ
:
227 DebugRecv(Kad2BootstrapReq
, ip
, port
);
228 Process2BootstrapRequest(ip
, port
, senderKey
);
230 case KADEMLIA_BOOTSTRAP_RES
:
231 DebugRecv(KadBootstrapRes
, ip
, port
);
232 ProcessBootstrapResponse(packetData
, lenPacket
, ip
);
234 case KADEMLIA2_BOOTSTRAP_RES
:
235 DebugRecv(Kad2BootstrapRes
, ip
, port
);
236 Process2BootstrapResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
238 case KADEMLIA_HELLO_REQ
:
239 DebugRecv(KadHelloReq
, ip
, port
);
240 ProcessHelloRequest(packetData
, lenPacket
, ip
, port
);
242 case KADEMLIA2_HELLO_REQ
:
243 DebugRecv(Kad2HelloReq
, ip
, port
);
244 Process2HelloRequest(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
246 case KADEMLIA_HELLO_RES
:
247 DebugRecv(KadHelloRes
, ip
, port
);
248 ProcessHelloResponse(packetData
, lenPacket
, ip
, port
);
250 case KADEMLIA2_HELLO_RES
:
251 DebugRecv(Kad2HelloRes
, ip
, port
);
252 Process2HelloResponse(packetData
, lenPacket
, ip
, port
, senderKey
, validReceiverKey
);
255 DebugRecv(KadReq
, ip
, port
);
256 ProcessKademliaRequest(packetData
, lenPacket
, ip
, port
);
259 DebugRecv(Kad2Req
, ip
, port
);
260 ProcessKademlia2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
263 DebugRecv(KadRes
, ip
, port
);
264 ProcessKademliaResponse(packetData
, lenPacket
, ip
, port
);
267 DebugRecv(Kad2Res
, ip
, port
);
268 ProcessKademlia2Response(packetData
, lenPacket
, ip
, port
, senderKey
);
270 case KADEMLIA_SEARCH_REQ
:
271 DebugRecv(KadSearchReq
, ip
, port
);
272 ProcessSearchRequest(packetData
, lenPacket
, ip
, port
);
274 case KADEMLIA_SEARCH_NOTES_REQ
:
275 DebugRecv(KadSearchNotesReq
, ip
, port
);
276 ProcessSearchNotesRequest(packetData
, lenPacket
, ip
, port
);
278 case KADEMLIA2_SEARCH_NOTES_REQ
:
279 DebugRecv(Kad2SearchNotesReq
, ip
, port
);
280 Process2SearchNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
282 case KADEMLIA2_SEARCH_KEY_REQ
:
283 DebugRecv(Kad2SearchKeyReq
, ip
, port
);
284 Process2SearchKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
286 case KADEMLIA2_SEARCH_SOURCE_REQ
:
287 DebugRecv(Kad2SearchSourceReq
, ip
, port
);
288 Process2SearchSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
290 case KADEMLIA_SEARCH_RES
:
291 DebugRecv(KadSearchRes
, ip
, port
);
292 ProcessSearchResponse(packetData
, lenPacket
);
294 case KADEMLIA_SEARCH_NOTES_RES
:
295 DebugRecv(KadSearchNotesRes
, ip
, port
);
296 ProcessSearchNotesResponse(packetData
, lenPacket
, ip
);
298 case KADEMLIA2_SEARCH_RES
:
299 DebugRecv(Kad2SearchRes
, ip
, port
);
300 Process2SearchResponse(packetData
, lenPacket
, senderKey
);
302 case KADEMLIA_PUBLISH_REQ
:
303 DebugRecv(KadPublishReq
, ip
, port
);
304 ProcessPublishRequest(packetData
, lenPacket
, ip
, port
);
306 case KADEMLIA_PUBLISH_NOTES_REQ
:
307 DebugRecv(KadPublishNotesReq
, ip
, port
);
308 ProcessPublishNotesRequest(packetData
, lenPacket
, ip
, port
);
310 case KADEMLIA2_PUBLISH_NOTES_REQ
:
311 DebugRecv(Kad2PublishNotesReq
, ip
, port
);
312 Process2PublishNotesRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
314 case KADEMLIA2_PUBLISH_KEY_REQ
:
315 DebugRecv(Kad2PublishKeyReq
, ip
, port
);
316 Process2PublishKeyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
318 case KADEMLIA2_PUBLISH_SOURCE_REQ
:
319 DebugRecv(Kad2PublishSourceReq
, ip
, port
);
320 Process2PublishSourceRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
322 case KADEMLIA_PUBLISH_RES
:
323 DebugRecv(KadPublishRes
, ip
, port
);
324 ProcessPublishResponse(packetData
, lenPacket
, ip
);
326 case KADEMLIA_PUBLISH_NOTES_RES
:
327 DebugRecv(KadPublishNotesRes
, ip
, port
);
328 ProcessPublishNotesResponse(packetData
, lenPacket
, ip
);
330 case KADEMLIA2_PUBLISH_RES
:
331 DebugRecv(Kad2PublishRes
, ip
, port
);
332 Process2PublishResponse(packetData
, lenPacket
, ip
, senderKey
);
334 case KADEMLIA_FIREWALLED_REQ
:
335 DebugRecv(KadFirewalledReq
, ip
, port
);
336 ProcessFirewalledRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
338 case KADEMLIA_FIREWALLED2_REQ
:
339 DebugRecv(KadFirewalled2Req
, ip
, port
);
340 ProcessFirewalled2Request(packetData
, lenPacket
, ip
, port
, senderKey
);
342 case KADEMLIA_FIREWALLED_RES
:
343 DebugRecv(KadFirewalledRes
, ip
, port
);
344 ProcessFirewalledResponse(packetData
, lenPacket
, ip
, senderKey
);
346 case KADEMLIA_FIREWALLED_ACK_RES
:
347 DebugRecv(KadFirewalledAck
, ip
, port
);
348 ProcessFirewalledAckResponse(lenPacket
);
350 case KADEMLIA_FINDBUDDY_REQ
:
351 DebugRecv(KadFindBuddyReq
, ip
, port
);
352 ProcessFindBuddyRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
354 case KADEMLIA_FINDBUDDY_RES
:
355 DebugRecv(KadFindBuddyRes
, ip
, port
);
356 ProcessFindBuddyResponse(packetData
, lenPacket
, ip
, port
, senderKey
);
358 case KADEMLIA_CALLBACK_REQ
:
359 DebugRecv(KadCallbackReq
, ip
, port
);
360 ProcessCallbackRequest(packetData
, lenPacket
, ip
, port
, senderKey
);
363 DebugRecv(Kad2Ping
, ip
, port
);
364 Process2Ping(ip
, port
, senderKey
);
367 DebugRecv(Kad2Pong
, ip
, port
);
368 Process2Pong(packetData
, lenPacket
, ip
);
370 case KADEMLIA2_FIREWALLUDP
:
371 DebugRecv(Kad2FirewallUDP
, ip
, port
);
372 Process2FirewallUDP(packetData
, lenPacket
, ip
);
375 throw wxString::Format(wxT("Unknown opcode %02x on CKademliaUDPListener::ProcessPacket()"), opcode
);
380 // Used only for Kad1.0
381 void 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
)
383 CMemFile
bio(data
, lenData
);
384 CUInt128 id
= bio
.ReadUInt128();
390 tport
= bio
.ReadUInt16();
393 //AddDebugLogLineM(false, logKadMain, wxT("Adding a contact with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port));
394 if(IsGoodIPPort(wxUINT32_SWAP_ALWAYS(ip
), port
)) {
395 // Ignore stated ip and port, use the address the packet came from
396 CKademlia::GetRoutingZone()->Add(id
, ip
, port
, tport
, 0, udpKey
, ipVerified
, update
);
400 // Used only for Kad2.0
401 void 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
)
403 CMemFile
bio(data
, lenData
);
404 CUInt128 id
= bio
.ReadUInt128();
405 uint16_t tport
= bio
.ReadUInt16();
406 uint8_t version
= bio
.ReadUInt8();
407 if (outVersion
!= NULL
) {
408 *outVersion
= version
;
410 uint8_t tags
= bio
.ReadUInt8();
412 CTag
*tag
= bio
.ReadTag();
413 if (!tag
->GetName().Cmp(TAG_SOURCEUPORT
)) {
414 if (tag
->IsInt() && (uint16_t)tag
->GetInt() > 0) {
415 port
= tag
->GetInt();
424 // check if we are waiting for informations (nodeid) about this client and if so inform the requester
425 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end(); ++it
) {
426 if (it
->ip
== ip
&& it
->tcpPort
== tport
) {
427 //AddDebugLogLineM(false, logKadMain, wxT("Result Addcontact: ") + id.ToHexString());
429 id
.ToByteArray(uchID
);
430 it
->requester
->KadSearchNodeIDByIPResult(KCSR_SUCCEEDED
, uchID
);
431 m_fetchNodeIDRequests
.erase(it
);
436 CKademlia::GetRoutingZone()->Add(id
, ip
, port
, tport
, version
, udpKey
, ipVerified
, update
);
439 // Used only for Kad1.0
440 void CKademliaUDPListener::AddContacts(const uint8_t *data
, uint32_t lenData
, uint16_t numContacts
, bool update
)
442 CMemFile
bio(data
, lenData
);
443 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
444 for (uint16_t i
= 0; i
< numContacts
; i
++) {
445 CUInt128 id
= bio
.ReadUInt128();
446 uint32_t ip
= bio
.ReadUInt32();
447 ip
= wxUINT32_SWAP_ALWAYS(ip
);
448 uint16_t port
= bio
.ReadUInt16();
449 uint16_t tport
= bio
.ReadUInt16();
451 //AddDebugLogLineM(false, logKadMain, wxT("Adding contact(s) with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port));
452 if (IsGoodIPPort(wxUINT32_SWAP_ALWAYS(ip
), port
)) {
453 routingZone
->Add(id
, ip
, port
, tport
, 0, 0, false, update
);
458 // KADEMLIA_BOOTSTRAP_REQ
459 // Used only for Kad1.0
460 void CKademliaUDPListener::ProcessBootstrapRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
462 // Verify packet is expected size
463 CHECK_PACKET_EXACT_SIZE(25);
465 // Add the sender to the list of contacts
466 AddContact(packetData
, lenPacket
, ip
, port
, 0, 0, false, true);
468 // Get some contacts to return
469 ContactList contacts
;
470 uint16_t numContacts
= 1 + (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts
, 20);
472 // Create response packet
473 //We only collect a max of 20 contacts here.. Max size is 527.
475 CMemFile
packetdata(527);
478 packetdata
.WriteUInt16(numContacts
);
480 for (ContactList::const_iterator it
= contacts
.begin(); it
!= contacts
.end(); ++it
) {
482 packetdata
.WriteUInt128(contact
->GetClientID());
483 packetdata
.WriteUInt32(contact
->GetIPAddress());
484 packetdata
.WriteUInt16(contact
->GetUDPPort());
485 packetdata
.WriteUInt16(contact
->GetTCPPort());
486 packetdata
.WriteUInt8(contact
->GetType());
489 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
490 packetdata
.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
491 packetdata
.WriteUInt16(thePrefs::GetEffectiveUDPPort());
492 packetdata
.WriteUInt16(thePrefs::GetPort());
493 packetdata
.WriteUInt8(0);
496 DebugSend(KadBootstrapRes
, ip
, port
);
497 SendPacket(packetdata
, KADEMLIA_BOOTSTRAP_RES
, ip
, port
, 0, NULL
);
500 // KADEMLIA2_BOOTSTRAP_REQ
501 // Used only for Kad2.0
502 void CKademliaUDPListener::Process2BootstrapRequest(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
504 // Get some contacts to return
505 ContactList contacts
;
506 uint16_t numContacts
= (uint16_t)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts
, 20);
508 // Create response packet
509 //We only collect a max of 20 contacts here.. Max size is 521.
511 CMemFile
packetdata(521);
513 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
514 packetdata
.WriteUInt16(thePrefs::GetPort());
515 packetdata
.WriteUInt8(KADEMLIA_VERSION
);
518 packetdata
.WriteUInt16(numContacts
);
520 for (ContactList::const_iterator it
= contacts
.begin(); it
!= contacts
.end(); ++it
) {
522 packetdata
.WriteUInt128(contact
->GetClientID());
523 packetdata
.WriteUInt32(contact
->GetIPAddress());
524 packetdata
.WriteUInt16(contact
->GetUDPPort());
525 packetdata
.WriteUInt16(contact
->GetTCPPort());
526 packetdata
.WriteUInt8(contact
->GetVersion());
530 DebugSend(Kad2BootstrapRes
, ip
, port
);
531 SendPacket(packetdata
, KADEMLIA2_BOOTSTRAP_RES
, ip
, port
, senderKey
, NULL
);
534 // KADEMLIA_BOOTSTRAP_RES
535 // Used only for Kad1.0
536 void CKademliaUDPListener::ProcessBootstrapResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
538 // Verify packet is expected size
539 CHECK_PACKET_MIN_SIZE(27);
540 CHECK_TRACKED_PACKET(KADEMLIA_BOOTSTRAP_REQ
);
542 // How many contacts were given
543 CMemFile
bio(packetData
, lenPacket
);
544 uint16_t numContacts
= bio
.ReadUInt16();
546 // Verify packet is expected size
547 if (lenPacket
!= (uint32_t)(2 + 25 * numContacts
)) {
551 // Add these contacts to the list.
552 AddContacts(packetData
+ 2, lenPacket
- 2, numContacts
, false);
555 // KADEMLIA2_BOOTSTRAP_RES
556 // Used only for Kad2.0
557 void CKademliaUDPListener::Process2BootstrapResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
559 CHECK_TRACKED_PACKET(KADEMLIA2_BOOTSTRAP_REQ
);
561 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
563 // How many contacts were given
564 CMemFile
bio(packetData
, lenPacket
);
565 CUInt128 contactID
= bio
.ReadUInt128();
566 uint16_t tport
= bio
.ReadUInt16();
567 uint8_t version
= bio
.ReadUInt8();
568 routingZone
->Add(contactID
, ip
, port
, tport
, version
, senderKey
, validReceiverKey
, true);
570 uint16_t numContacts
= bio
.ReadUInt16();
571 while (numContacts
) {
572 contactID
= bio
.ReadUInt128();
573 ip
= bio
.ReadUInt32();
574 port
= bio
.ReadUInt16();
575 tport
= bio
.ReadUInt16();
576 version
= bio
.ReadUInt8();
577 routingZone
->Add(contactID
, ip
, port
, tport
, version
, 0, false, false);
582 // KADEMLIA_HELLO_REQ
583 // Used in Kad1.0 only
584 void CKademliaUDPListener::ProcessHelloRequest (const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
586 // Verify packet is expected size
587 CHECK_PACKET_EXACT_SIZE(25);
589 // Add the sender to the list of contacts
590 AddContact(packetData
, lenPacket
, ip
, port
, 0, 0, false, true);
593 DebugSend(KadHelloRes
, ip
, port
);
594 SendMyDetails(KADEMLIA_HELLO_RES
, ip
, port
, false, 0, NULL
);
596 // Check if firewalled
597 if (CKademlia::GetPrefs()->GetRecheckIP()) {
598 FirewalledCheck(ip
, port
, 0, 0);
602 // KADEMLIA2_HELLO_REQ
603 // Used in Kad2.0 only
604 void CKademliaUDPListener::Process2HelloRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
606 uint16_t dbgOldUDPPort
= port
;
607 uint8_t contactVersion
;
608 AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true); // might change (udp)port
610 if (dbgOldUDPPort
!= port
) {
611 AddDebugLogLineM(false, logClientKadUDP
, wxT("KadContact ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)) + wxString::Format(wxT(" uses his internal (%u) instead external (%u) UDP Port"), port
, dbgOldUDPPort
));
615 DebugSend(Kad2HelloRes
, ip
, port
);
616 SendMyDetails(KADEMLIA2_HELLO_RES
, ip
, port
, true, senderKey
, NULL
);
618 // Check if firewalled
619 if (CKademlia::GetPrefs()->GetRecheckIP()) {
620 FirewalledCheck(ip
, port
, senderKey
, contactVersion
);
623 // do we need to find out our extern port?
624 if (CKademlia::GetPrefs()->GetExternalKadPort() == 0 && contactVersion
> 5) {
625 DebugSend(Kad2Ping
, ip
, port
);
626 SendNullPacket(KADEMLIA2_PING
, ip
, port
, senderKey
, NULL
);
630 // KADEMLIA_HELLO_RES
631 // Used in Kad1.0 only
632 void CKademliaUDPListener::ProcessHelloResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
634 CHECK_TRACKED_PACKET(KADEMLIA_HELLO_REQ
);
636 // Verify packet is expected size
637 CHECK_PACKET_EXACT_SIZE(25);
639 // Add or Update contact.
640 AddContact(packetData
, lenPacket
, ip
, port
, 0, 0, false, true);
643 // KADEMLIA2_HELLO_RES
644 // Used in Kad2.0 only
645 void CKademliaUDPListener::Process2HelloResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
, bool validReceiverKey
)
647 CHECK_TRACKED_PACKET(KADEMLIA2_HELLO_REQ
);
649 // Add or Update contact.
650 uint8_t contactVersion
;
651 AddContact2(packetData
, lenPacket
, ip
, port
, &contactVersion
, senderKey
, validReceiverKey
, true);
653 // do we need to find out our extern port?
654 if (CKademlia::GetPrefs()->GetExternalKadPort() == 0 && contactVersion
> 5) {
655 DebugSend(Kad2Ping
, ip
, port
);
656 SendNullPacket(KADEMLIA2_PING
, ip
, port
, senderKey
, NULL
);
659 // Check if firewalled
660 if (CKademlia::GetPrefs()->GetRecheckIP()) {
661 FirewalledCheck(ip
, port
, senderKey
, contactVersion
);
666 // Used in Kad1.0 only
667 void CKademliaUDPListener::ProcessKademliaRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
669 // Verify packet is expected size
670 CHECK_PACKET_EXACT_SIZE(33);
672 // RecheckIP and firewall status
673 if (CKademlia::GetPrefs()->GetRecheckIP()) {
674 FirewalledCheck(ip
, port
, 0, 0);
675 DebugSend(KadHelloReq
, ip
, port
);
676 SendMyDetails(KADEMLIA_HELLO_REQ
, ip
, port
, false, 0, NULL
);
679 // Get target and type
680 CMemFile
bio(packetData
, lenPacket
);
681 uint8_t type
= bio
.ReadUInt8();
682 // bool flag1 = (type >> 6); //Reserved
683 // bool flag2 = (type >> 7); //Reserved
684 // bool flag3 = (type >> 8); //Reserved
688 throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type
) + wxString::FromAscii(__FUNCTION__
);
691 // This is the target node trying to be found.
692 CUInt128 target
= bio
.ReadUInt128();
693 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
694 distance
.XOR(target
);
696 // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.
697 CUInt128 check
= bio
.ReadUInt128();
698 if (CKademlia::GetPrefs()->GetKadID().CompareTo(check
)) {
702 // Get required number closest to target
704 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, type
, &results
);
705 uint16_t count
= (uint16_t)results
.size();
708 // Max count is 32. size 817..
710 CMemFile
packetdata(817);
711 packetdata
.WriteUInt128(target
);
712 packetdata
.WriteUInt8((uint8_t)count
);
714 for (ContactMap::const_iterator it
= results
.begin(); it
!= results
.end(); ++it
) {
716 packetdata
.WriteUInt128(c
->GetClientID());
717 packetdata
.WriteUInt32(c
->GetIPAddress());
718 packetdata
.WriteUInt16(c
->GetUDPPort());
719 packetdata
.WriteUInt16(c
->GetTCPPort());
720 packetdata
.WriteUInt8(c
->GetType());
723 DebugSendF(wxString::Format(wxT("KadRes (count=%u)"), count
), ip
, port
);
724 SendPacket(packetdata
, KADEMLIA_RES
, ip
, port
, 0, NULL
);
728 // Used in Kad2.0 only
729 void CKademliaUDPListener::ProcessKademlia2Request(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
731 // Get target and type
732 CMemFile
bio(packetData
, lenPacket
);
733 uint8_t type
= bio
.ReadUInt8();
736 throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type
) + wxString::FromAscii(__FUNCTION__
);
739 // This is the target node trying to be found.
740 CUInt128 target
= bio
.ReadUInt128();
741 // Convert Target to Distance as this is how we store contacts.
742 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
743 distance
.XOR(target
);
745 // This makes sure we are not mistaken identify. Some client may have fresh installed and have a new KadID.
746 CUInt128 check
= bio
.ReadUInt128();
747 if (CKademlia::GetPrefs()->GetKadID() == check
) {
748 // Get required number closest to target
750 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, type
, &results
);
751 uint8_t count
= (uint8_t)results
.size();
754 // Max count is 32. size 817..
756 CMemFile
packetdata(817);
757 packetdata
.WriteUInt128(target
);
758 packetdata
.WriteUInt8(count
);
760 for (ContactMap::const_iterator it
= results
.begin(); it
!= results
.end(); ++it
) {
762 packetdata
.WriteUInt128(c
->GetClientID());
763 packetdata
.WriteUInt32(c
->GetIPAddress());
764 packetdata
.WriteUInt16(c
->GetUDPPort());
765 packetdata
.WriteUInt16(c
->GetTCPPort());
766 packetdata
.WriteUInt8(c
->GetVersion()); //<- Kad Version inserted to allow backward compatibility.
769 DebugSendF(wxString::Format(wxT("Kad2Res (count=%u)"), count
), ip
, port
);
770 SendPacket(packetdata
, KADEMLIA2_RES
, ip
, port
, senderKey
, NULL
);
775 // Used in Kad1.0 only
776 void CKademliaUDPListener::ProcessKademliaResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
778 // Verify packet is expected size
779 CHECK_PACKET_MIN_SIZE(17);
780 CHECK_TRACKED_PACKET(KADEMLIA_REQ
);
783 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
785 if (CKademlia::GetPrefs()->GetRecheckIP()) {
786 FirewalledCheck(ip
, port
, 0, 0);
787 DebugSend(KadHelloReq
, ip
, port
);
788 SendMyDetails(KADEMLIA_HELLO_REQ
, ip
, port
, false, 0, NULL
);
791 // What search does this relate to
792 CMemFile
bio(packetData
, lenPacket
);
793 CUInt128 target
= bio
.ReadUInt128();
794 uint16 numContacts
= bio
.ReadUInt8();
796 // Verify packet is expected size
797 CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts
);
799 CScopedPtr
<ContactList
> results(new ContactList
);
801 for (uint16_t i
= 0; i
< numContacts
; i
++) {
802 CUInt128 id
= bio
.ReadUInt128();
803 uint32_t contactIP
= bio
.ReadUInt32();
804 uint16_t contactPort
= bio
.ReadUInt16();
805 uint16_t tport
= bio
.ReadUInt16();
807 uint32_t hostIP
= wxUINT32_SWAP_ALWAYS(contactIP
);
808 if(::IsGoodIPPort(hostIP
, contactPort
) && contactPort
!= 53 /*No DNS Port without encryption*/) {
809 if (!theApp
->ipfilter
->IsFiltered(hostIP
)) {
810 routingZone
->AddUnfiltered(id
, contactIP
, contactPort
, tport
, 0, 0, false, false);
811 results
->push_back(new CContact(id
, contactIP
, contactPort
, tport
, 0, 0, false, target
));
816 CSearchManager::ProcessResponse(target
, ip
, port
, results
.release());
820 // Used in Kad2.0 only
821 void CKademliaUDPListener::ProcessKademlia2Response(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& WXUNUSED(senderKey
))
823 CHECK_TRACKED_PACKET(KADEMLIA2_REQ
);
826 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
828 // don't do firewallchecks on this opcode anymore, since we need the contacts kad version - hello opcodes are good enough
829 // if (CKademlia::GetPrefs()->GetRecheckIP()) {
830 // FirewalledCheck(ip, port, senderKey);
831 // DebugSend(Kad2HelloReq, ip, port);
832 // SendMyDetails(KADEMLIA2_HELLO_REQ, ip, port, true, senderKey, NULL);
835 // What search does this relate to
836 CMemFile
bio(packetData
, lenPacket
);
837 CUInt128 target
= bio
.ReadUInt128();
838 uint8_t numContacts
= bio
.ReadUInt8();
840 // Verify packet is expected size
841 CHECK_PACKET_EXACT_SIZE(16+1 + (16+4+2+2+1)*numContacts
);
843 // is this a search for firewallcheck ips?
844 bool isFirewallUDPCheckSearch
= false;
845 if (CUDPFirewallTester::IsFWCheckUDPRunning() && CSearchManager::IsFWCheckUDPSearch(target
)) {
846 isFirewallUDPCheckSearch
= true;
849 CScopedPtr
<ContactList
> results(new ContactList
);
850 for (uint8_t i
= 0; i
< numContacts
; i
++) {
851 CUInt128 id
= bio
.ReadUInt128();
852 uint32_t contactIP
= bio
.ReadUInt32();
853 uint16_t contactPort
= bio
.ReadUInt16();
854 uint16_t tport
= bio
.ReadUInt16();
855 uint8_t version
= bio
.ReadUInt8();
856 uint32_t hostIP
= wxUINT32_SWAP_ALWAYS(contactIP
);
857 if (::IsGoodIPPort(hostIP
, contactPort
)) {
858 if (!theApp
->ipfilter
->IsFiltered(hostIP
) && !(contactPort
== 53 && version
<= 5) /*No DNS Port without encryption*/) {
859 if (isFirewallUDPCheckSearch
) {
860 // UDP FirewallCheck searches are special. The point is we need an IP which we didn't sent an UDP message yet
861 // (or in the near future), so we do not try to add those contacts to our routingzone and we also don't
862 // deliver them back to the searchmanager (because he would UDP-ask them for further results), but only report
863 // them to FirewallChecker - this will of course cripple the search but thats not the point, since we only
864 // care for IPs and not the random set target
865 CUDPFirewallTester::AddPossibleTestContact(id
, contactIP
, contactPort
, tport
, target
, version
, 0, false);
867 routingZone
->AddUnfiltered(id
, contactIP
, contactPort
, tport
, version
, 0, false, false);
868 results
->push_back(new CContact(id
, contactIP
, contactPort
, tport
, version
, 0, false, target
));
874 CSearchManager::ProcessResponse(target
, ip
, port
, results
.release());
877 void CKademliaUDPListener::Free(SSearchTerm
* pSearchTerms
)
880 Free(pSearchTerms
->left
);
881 Free(pSearchTerms
->right
);
886 SSearchTerm
* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile
& bio
, int iLevel
)
888 // the max. depth has to match our own limit for creating the search expression
889 // (see also 'ParsedSearchExpression' and 'GetSearchPacket')
891 AddDebugLogLineM(false, logKadSearch
, wxT("***NOTE: Search expression tree exceeds depth limit!"));
896 uint8_t op
= bio
.ReadUInt8();
898 uint8_t boolop
= bio
.ReadUInt8();
899 if (boolop
== 0x00) { // AND
900 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
901 pSearchTerm
->type
= SSearchTerm::AND
;
903 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
908 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
910 Free(pSearchTerm
->left
);
915 } else if (boolop
== 0x01) { // OR
916 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
917 pSearchTerm
->type
= SSearchTerm::OR
;
919 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
924 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
926 Free(pSearchTerm
->left
);
931 } else if (boolop
== 0x02) { // NOT
932 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
933 pSearchTerm
->type
= SSearchTerm::NOT
;
935 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
940 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
942 Free(pSearchTerm
->left
);
948 AddDebugLogLineM(false, logKadSearch
, wxString::Format(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop
));
951 } else if (op
== 0x01) { // String
952 wxString
str(bio
.ReadString(true));
954 // Make lowercase, the search code expects lower case strings!
957 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
958 pSearchTerm
->type
= SSearchTerm::String
;
959 pSearchTerm
->astr
= new wxArrayString
;
961 // pre-tokenize the string term
962 //#warning TODO: TokenizeOptQuotedSearchTerm
963 wxStringTokenizer
token(str
, CSearchManager::GetInvalidKeywordChars(),wxTOKEN_DEFAULT
);
964 while (token
.HasMoreTokens()) {
965 wxString
strTok(token
.GetNextToken());
966 if (!strTok
.IsEmpty()) {
967 pSearchTerm
->astr
->Add(strTok
);
972 } else if (op
== 0x02) { // Meta tag
974 wxString
strValue(bio
.ReadString(true));
975 // Make lowercase, the search code expects lower case strings!
976 strValue
.MakeLower();
979 wxString strTagName
= bio
.ReadString(false);
981 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
982 pSearchTerm
->type
= SSearchTerm::MetaTag
;
983 pSearchTerm
->tag
= new CTagString(strTagName
, strValue
);
986 else if (op
== 0x03 || op
== 0x08) { // Numeric relation (0x03=32-bit or 0x08=64-bit)
987 static const struct {
988 SSearchTerm::ESearchTermType eSearchTermOp
;
992 { SSearchTerm::OpEqual
, wxT("=") }, // mmop=0x00
993 { SSearchTerm::OpGreater
, wxT(">") }, // mmop=0x01
994 { SSearchTerm::OpLess
, wxT("<") }, // mmop=0x02
995 { SSearchTerm::OpGreaterEqual
, wxT(">=") }, // mmop=0x03
996 { SSearchTerm::OpLessEqual
, wxT("<=") }, // mmop=0x04
997 { SSearchTerm::OpNotEqual
, wxT("<>") } // mmop=0x05
1001 uint64_t ullValue
= (op
== 0x03) ? bio
.ReadUInt32() : bio
.ReadUInt64();
1003 // read integer operator
1004 uint8_t mmop
= bio
.ReadUInt8();
1005 if (mmop
>= itemsof(_aOps
)){
1006 AddDebugLogLineM(false, logKadSearch
, wxString::Format(wxT("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop
));
1011 wxString strTagName
= bio
.ReadString(false);
1013 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
1014 pSearchTerm
->type
= _aOps
[mmop
].eSearchTermOp
;
1015 pSearchTerm
->tag
= new CTagVarInt(strTagName
, ullValue
);
1019 AddDebugLogLineM(false, logKadSearch
, wxString::Format(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), op
));
1024 // KADEMLIA_SEARCH_REQ
1025 // Used in Kad1.0 only
1026 void CKademliaUDPListener::ProcessSearchRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
1028 // Verify packet is expected size
1029 CHECK_PACKET_MIN_SIZE(17);
1031 CMemFile
bio(packetData
, lenPacket
);
1032 CUInt128 target
= bio
.ReadUInt128();
1033 uint8_t restrictive
= bio
.ReadUInt8();
1035 if (lenPacket
== 17) {
1038 CKademlia::GetIndexed()->SendValidSourceResult(target
, ip
, port
, false, 0, 0, 0);
1040 // Single keyword request
1041 CKademlia::GetIndexed()->SendValidKeywordResult(target
, NULL
, ip
, port
, true, false, 0, 0);
1043 } else if (lenPacket
> 17) {
1044 SSearchTerm
* pSearchTerms
= NULL
;
1045 bool oldClient
= true;
1047 pSearchTerms
= CreateSearchExpressionTree(bio
, 0);
1048 if (pSearchTerms
== NULL
) {
1049 throw wxString(wxT("Invalid search expression"));
1051 if (restrictive
> 1) {
1058 // Keyword request with added options.
1059 CKademlia::GetIndexed()->SendValidKeywordResult(target
, pSearchTerms
, ip
, port
, oldClient
, false, 0, 0);
1064 // KADEMLIA2_SEARCH_KEY_REQ
1065 // Used in Kad2.0 only
1066 void CKademliaUDPListener::Process2SearchKeyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1068 CMemFile
bio(packetData
, lenPacket
);
1069 CUInt128 target
= bio
.ReadUInt128();
1070 uint16_t startPosition
= bio
.ReadUInt16();
1071 bool restrictive
= ((startPosition
& 0x8000) == 0x8000);
1072 startPosition
&= 0x7FFF;
1073 SSearchTerm
* pSearchTerms
= NULL
;
1075 pSearchTerms
= CreateSearchExpressionTree(bio
, 0);
1076 if (pSearchTerms
== NULL
) {
1077 throw wxString(wxT("Invalid search expression"));
1080 CKademlia::GetIndexed()->SendValidKeywordResult(target
, pSearchTerms
, ip
, port
, false, true, startPosition
, senderKey
);
1086 // KADEMLIA2_SEARCH_SOURCE_REQ
1087 // Used in Kad2.0 only
1088 void CKademliaUDPListener::Process2SearchSourceRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1090 CMemFile
bio(packetData
, lenPacket
);
1091 CUInt128 target
= bio
.ReadUInt128();
1092 uint16_t startPosition
= (bio
.ReadUInt16() & 0x7FFF);
1093 uint64_t fileSize
= bio
.ReadUInt64();
1094 CKademlia::GetIndexed()->SendValidSourceResult(target
, ip
, port
, true, startPosition
, fileSize
, senderKey
);
1097 // KADEMLIA_SEARCH_RES
1098 // Used in Kad1.0 only
1099 void CKademliaUDPListener::ProcessSearchResponse(const uint8_t *packetData
, uint32_t lenPacket
)
1101 // Verify packet is expected size
1102 CHECK_PACKET_MIN_SIZE(37);
1104 // What search does this relate to
1105 CMemFile
bio(packetData
, lenPacket
);
1106 CUInt128 target
= bio
.ReadUInt128();
1108 // How many results.. Not supported yet..
1109 uint16_t count
= bio
.ReadUInt16();
1111 // What is the answer
1112 CUInt128 answer
= bio
.ReadUInt128();
1114 // Get info about answer
1115 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
1116 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
1117 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
1118 // If that tag list is once used for something else than for viewing, special care has to be taken for any
1119 // string conversion!
1120 TagPtrList
* tags
= new TagPtrList
;
1122 bio
.ReadTagPtrList(tags
, true/*bOptACP*/);
1124 //DebugClientOutput(wxT("CKademliaUDPListener::processSearchResponse"),ip,port,packetData,lenPacket);
1125 deleteTagPtrListEntries(tags
);
1130 CSearchManager::ProcessResult(target
, answer
, tags
);
1135 // KADEMLIA2_SEARCH_RES
1136 // Used in Kad2.0 only
1137 void CKademliaUDPListener::Process2SearchResponse(const uint8_t *packetData
, uint32_t lenPacket
, const CKadUDPKey
& WXUNUSED(senderKey
))
1139 CMemFile
bio(packetData
, lenPacket
);
1141 // Who sent this packet.
1142 CUInt128 source
= bio
.ReadUInt128();
1144 // What search does this relate to
1145 CUInt128 target
= bio
.ReadUInt128();
1148 uint16_t count
= bio
.ReadUInt16();
1150 // What is the answer
1151 CUInt128 answer
= bio
.ReadUInt128();
1153 // Get info about answer
1154 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
1155 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
1156 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
1157 // If that tag list is once used for something else than for viewing, special care has to be taken for any
1158 // string conversion!
1159 TagPtrList
* tags
= new TagPtrList
;
1161 bio
.ReadTagPtrList(tags
, true);
1163 deleteTagPtrListEntries(tags
);
1168 CSearchManager::ProcessResult(target
, answer
, tags
);
1173 // KADEMLIA_PUBLISH_REQ
1174 // Used in Kad1.0 only
1175 void CKademliaUDPListener::ProcessPublishRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
1177 //There are different types of publishing..
1178 //Keyword and File are Stored..
1179 // Verify packet is expected size
1180 CHECK_PACKET_MIN_SIZE(37);
1183 CIndexed
*indexed
= CKademlia::GetIndexed();
1185 // check if we are UDP firewalled
1186 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1187 //We are firewalled. We should not index this entry and give publisher a false report.
1191 CMemFile
bio(packetData
, lenPacket
);
1192 CUInt128 file
= bio
.ReadUInt128();
1194 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1197 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1202 uint16_t count
= bio
.ReadUInt16();
1208 CUInt128 target
= bio
.ReadUInt128();
1210 Kademlia::CKeyEntry
* entry
= new Kademlia::CKeyEntry();
1213 entry
->m_uUDPport
= port
;
1214 entry
->m_uKeyID
.SetValue(file
);
1215 entry
->m_uSourceID
.SetValue(target
);
1216 uint32_t tags
= bio
.ReadUInt8();
1218 CTag
* tag
= bio
.ReadTag();
1220 if (!tag
->GetName().Cmp(TAG_SOURCETYPE
)) {
1221 if (entry
->m_bSource
== false) {
1222 entry
->AddTag(new CTagVarInt(TAG_SOURCEIP
, entry
->m_uIP
));
1223 entry
->AddTag(new CTagVarInt(TAG_SOURCEUPORT
, entry
->m_uUDPport
));
1225 entry
->m_bSource
= true;
1227 //More than one sourcetype tag found.
1230 } else if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1231 if (entry
->GetCommonFileName().IsEmpty()) {
1232 entry
->SetFileName(tag
->GetStr());
1233 strInfo
+= CFormat(wxT(" Name=\"%s\"")) % tag
->GetStr();
1236 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1237 if (entry
->m_uSize
== 0) {
1238 if (tag
->IsBsob() && (tag
->GetBsobSize() == 8)) {
1239 // Kad1.0 uint64 type using a BSOB.
1240 entry
->m_uSize
= PeekUInt64(tag
->GetBsob());
1242 wxASSERT(tag
->IsInt());
1243 entry
->m_uSize
= tag
->GetInt();
1245 strInfo
+= wxString::Format(wxT(" Size=%") wxLongLongFmtSpec
wxT("u"), entry
->m_uSize
);
1248 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
1249 if (entry
->m_uTCPport
== 0) {
1250 entry
->m_uTCPport
= tag
->GetInt();
1253 //More than one port tag found
1263 if (!strInfo
.IsEmpty()) {
1264 AddDebugLogLineM(false, logClientKadUDP
, strInfo
);
1267 //printf("Error on count %i tag %i\n",totalcount-count, totaltags-tags);
1268 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishRequest"),ip,port,packetData,lenPacket);
1273 if (entry
->m_bSource
== true) {
1274 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMES
;
1275 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
1278 if (indexed
->AddSources(file
, target
, sourceEntry
, load
)) {
1285 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMEK
;
1286 if (indexed
->AddKeyword(file
, target
, entry
, load
)) {
1287 // This makes sure we send a publish response..
1288 // This also makes sure we index all the files for this keyword.
1291 //We already indexed the maximum number of keywords.
1292 //We do not index anymore but we still send a success..
1293 //Reason: Because if a VERY busy node tells the publisher it failed,
1294 //this busy node will spread to all the surrounding nodes causing popular
1295 //keywords to be stored on MANY nodes..
1296 //So, once we are full, we will periodically clean our list until we can
1297 //begin storing again..
1306 CMemFile
packetdata(17);
1307 packetdata
.WriteUInt128(file
);
1308 packetdata
.WriteUInt8(load
);
1310 DebugSend(KadPublishRes
, ip
, port
);
1311 SendPacket(packetdata
, KADEMLIA_PUBLISH_RES
, ip
, port
, 0, NULL
);
1315 // KADEMLIA2_PUBLISH_KEY_REQ
1316 // Used in Kad2.0 only
1317 void CKademliaUDPListener::Process2PublishKeyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1320 CIndexed
*indexed
= CKademlia::GetIndexed();
1322 // check if we are UDP firewalled
1323 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1324 //We are firewalled. We should not index this entry and give publisher a false report.
1328 CMemFile
bio(packetData
, lenPacket
);
1329 CUInt128 file
= bio
.ReadUInt128();
1331 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1334 // Shouldn't LAN IPs already be filtered?
1335 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1340 uint16_t count
= bio
.ReadUInt16();
1345 CUInt128 target
= bio
.ReadUInt128();
1347 Kademlia::CKeyEntry
* entry
= new Kademlia::CKeyEntry();
1351 entry
->m_uUDPport
= port
;
1352 entry
->m_uKeyID
.SetValue(file
);
1353 entry
->m_uSourceID
.SetValue(target
);
1354 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMEK
;
1355 entry
->m_bSource
= false;
1356 uint32_t tags
= bio
.ReadUInt8();
1358 CTag
* tag
= bio
.ReadTag();
1360 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1361 if (entry
->GetCommonFileName().IsEmpty()) {
1362 entry
->SetFileName(tag
->GetStr());
1363 strInfo
+= CFormat(wxT(" Name=\"%s\"")) % entry
->GetCommonFileName();
1365 delete tag
; // tag is no longer stored, but membervar is used
1366 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1367 if (entry
->m_uSize
== 0) {
1368 if (tag
->IsBsob() && tag
->GetBsobSize() == 8) {
1369 entry
->m_uSize
= PeekUInt64(tag
->GetBsob());
1371 entry
->m_uSize
= tag
->GetInt();
1373 strInfo
+= wxString::Format(wxT(" Size=%") wxLongLongFmtSpec
wxT("u"), entry
->m_uSize
);
1375 delete tag
; // tag is no longer stored, but membervar is used
1383 if (!strInfo
.IsEmpty()) {
1384 AddDebugLogLineM(false, logClientKadUDP
, strInfo
);
1387 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishKeyRequest"),ip,port,packetData,lenPacket);
1392 if (!indexed
->AddKeyword(file
, target
, entry
, load
)) {
1393 //We already indexed the maximum number of keywords.
1394 //We do not index anymore but we still send a success..
1395 //Reason: Because if a VERY busy node tells the publisher it failed,
1396 //this busy node will spread to all the surrounding nodes causing popular
1397 //keywords to be stored on MANY nodes..
1398 //So, once we are full, we will periodically clean our list until we can
1399 //begin storing again..
1405 CMemFile
packetdata(17);
1406 packetdata
.WriteUInt128(file
);
1407 packetdata
.WriteUInt8(load
);
1408 DebugSend(Kad2PublishRes
, ip
, port
);
1409 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1412 // KADEMLIA2_PUBLISH_SOURCE_REQ
1413 // Used in Kad2.0 only
1414 void CKademliaUDPListener::Process2PublishSourceRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1417 CIndexed
*indexed
= CKademlia::GetIndexed();
1419 // check if we are UDP firewalled
1420 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1421 //We are firewalled. We should not index this entry and give publisher a false report.
1425 CMemFile
bio(packetData
, lenPacket
);
1426 CUInt128 file
= bio
.ReadUInt128();
1428 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1431 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1438 CUInt128 target
= bio
.ReadUInt128();
1439 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
1442 entry
->m_uUDPport
= port
;
1443 entry
->m_uKeyID
.SetValue(file
);
1444 entry
->m_uSourceID
.SetValue(target
);
1445 entry
->m_bSource
= false;
1446 entry
->m_tLifeTime
= (uint32_t)time(NULL
) + KADEMLIAREPUBLISHTIMES
;
1447 bool addUDPPortTag
= true;
1448 uint32_t tags
= bio
.ReadUInt8();
1450 CTag
* tag
= bio
.ReadTag();
1452 if (!tag
->GetName().Cmp(TAG_SOURCETYPE
)) {
1453 if (entry
->m_bSource
== false) {
1454 entry
->AddTag(new CTagVarInt(TAG_SOURCEIP
, entry
->m_uIP
));
1456 entry
->m_bSource
= true;
1458 //More than one sourcetype tag found.
1461 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1462 if (entry
->m_uSize
== 0) {
1463 if (tag
->IsBsob() && tag
->GetBsobSize() == 8) {
1464 entry
->m_uSize
= PeekUInt64(tag
->GetBsob());
1466 entry
->m_uSize
= tag
->GetInt();
1468 strInfo
+= wxString::Format(wxT(" Size=%") wxLongLongFmtSpec
wxT("u"), entry
->m_uSize
);
1471 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
1472 if (entry
->m_uTCPport
== 0) {
1473 entry
->m_uTCPport
= (uint16_t)tag
->GetInt();
1476 //More than one port tag found
1479 } else if (!tag
->GetName().Cmp(TAG_SOURCEUPORT
)) {
1480 if (addUDPPortTag
&& tag
->IsInt() && tag
->GetInt() != 0) {
1481 entry
->m_uUDPport
= (uint16_t)tag
->GetInt();
1483 addUDPPortTag
= false;
1485 //More than one udp port tag found
1495 if (addUDPPortTag
) {
1496 entry
->AddTag(new CTagVarInt(TAG_SOURCEUPORT
, entry
->m_uUDPport
));
1498 if (!strInfo
.IsEmpty()) {
1499 AddDebugLogLineM(false, logClientKadUDP
, strInfo
);
1502 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishSourceRequest"),ip,port,packetData,lenPacket);
1507 if (entry
->m_bSource
== true) {
1508 if (indexed
->AddSources(file
, target
, entry
, load
)) {
1519 CMemFile
packetdata(17);
1520 packetdata
.WriteUInt128(file
);
1521 packetdata
.WriteUInt8(load
);
1522 DebugSend(Kad2PublishRes
, ip
, port
);
1523 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1527 // KADEMLIA_PUBLISH_RES
1528 // Used only by Kad1.0
1529 void CKademliaUDPListener::ProcessPublishResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1531 // Verify packet is expected size
1532 CHECK_PACKET_MIN_SIZE(16);
1533 CHECK_TRACKED_PACKET(KADEMLIA_PUBLISH_REQ
);
1535 CMemFile
bio(packetData
, lenPacket
);
1536 CUInt128 file
= bio
.ReadUInt128();
1538 bool loadResponse
= false;
1540 if (bio
.GetLength() > bio
.GetPosition()) {
1541 loadResponse
= true;
1542 load
= bio
.ReadUInt8();
1545 CSearchManager::ProcessPublishResult(file
, load
, loadResponse
);
1548 // KADEMLIA2_PUBLISH_RES
1549 // Used only by Kad2.0
1550 void CKademliaUDPListener::Process2PublishResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, const CKadUDPKey
& WXUNUSED(senderKey
))
1552 if (!IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_KEY_REQ
) && !IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_SOURCE_REQ
) && !IsOnOutTrackList(ip
, KADEMLIA2_PUBLISH_NOTES_REQ
)) {
1553 throw wxString::Format(wxT("***NOTE: Received unrequested response packet, size (%u) in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1555 CMemFile
bio(packetData
, lenPacket
);
1556 CUInt128 file
= bio
.ReadUInt128();
1557 uint8_t load
= bio
.ReadUInt8();
1558 CSearchManager::ProcessPublishResult(file
, load
, true);
1561 // KADEMLIA_SEARCH_NOTES_REQ
1562 // Used only by Kad1.0
1563 void CKademliaUDPListener::ProcessSearchNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
1565 // Verify packet is expected size
1566 CHECK_PACKET_MIN_SIZE(32);
1568 CMemFile
bio(packetData
, lenPacket
);
1569 CUInt128 target
= bio
.ReadUInt128();
1570 // This info is currently not used.
1571 // CUInt128 source = bio.ReadUInt128();
1573 CKademlia::GetIndexed()->SendValidNoteResult(target
, ip
, port
, false, 0, 0);
1576 // KADEMLIA2_SEARCH_NOTES_REQ
1577 // Used only by Kad2.0
1578 void CKademliaUDPListener::Process2SearchNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1580 CMemFile
bio(packetData
, lenPacket
);
1581 CUInt128 target
= bio
.ReadUInt128();
1582 uint64_t fileSize
= bio
.ReadUInt64();
1583 CKademlia::GetIndexed()->SendValidNoteResult(target
, ip
, port
, true, fileSize
, senderKey
);
1586 // KADEMLIA_SEARCH_NOTES_RES
1587 // Used only by Kad1.0
1588 void CKademliaUDPListener::ProcessSearchNotesResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1590 // Verify packet is expected size
1591 CHECK_PACKET_MIN_SIZE(37);
1592 CHECK_TRACKED_PACKET(KADEMLIA_SEARCH_NOTES_REQ
);
1594 // What search does this relate to
1595 CMemFile
bio(packetData
, lenPacket
);
1596 CUInt128 target
= bio
.ReadUInt128();
1598 uint16_t count
= bio
.ReadUInt16();
1600 // What is the answer
1601 CUInt128 answer
= bio
.ReadUInt128();
1603 // Get info about answer
1604 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
1605 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
1606 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
1607 // If that tag list is once used for something else than for viewing, special care has to be taken for any
1608 // string conversion!
1609 TagPtrList
* tags
= new TagPtrList
;
1611 bio
.ReadTagPtrList(tags
, true/*bOptACP*/);
1613 //DebugClientOutput(wxT("CKademliaUDPListener::processSearchNotesResponse"),ip,port,packetData,lenPacket);
1614 deleteTagPtrListEntries(tags
);
1619 CSearchManager::ProcessResult(target
, answer
, tags
);
1624 // KADEMLIA_PUBLISH_NOTES_REQ
1625 // Used only by Kad1.0
1626 void CKademliaUDPListener::ProcessPublishNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
)
1628 // Verify packet is expected size
1629 CHECK_PACKET_MIN_SIZE(37);
1631 // check if we are UDP firewalled
1632 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1633 //We are firewalled. We should not index this entry and give publisher a false report.
1637 CMemFile
bio(packetData
, lenPacket
);
1638 CUInt128 target
= bio
.ReadUInt128();
1640 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1641 distance
.XOR(target
);
1643 if( thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1647 CUInt128 source
= bio
.ReadUInt128();
1649 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
1652 entry
->m_uUDPport
= port
;
1653 entry
->m_uKeyID
.SetValue(target
);
1654 entry
->m_uSourceID
.SetValue(source
);
1655 uint32_t tagCount
= bio
.ReadUInt8();
1656 while (tagCount
> 0) {
1657 CTag
*tag
= bio
.ReadTag();
1659 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1660 if (entry
->GetCommonFileName().IsEmpty()) {
1661 entry
->SetFileName(tag
->GetStr());
1664 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1665 if (entry
->m_uSize
== 0) {
1666 entry
->m_uSize
= tag
->GetInt();
1676 entry
->m_bSource
= false;
1678 //DebugClientOutput(wxT("CKademliaUDPListener::processPublishNotesRequest"),ip,port,packetData,lenPacket);
1684 if (entry
== NULL
) {
1685 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry == NULL"));
1686 } else if (entry
->GetTagCount() == 0 || entry
->GetTagCount() > 5) {
1688 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry->GetTagCount() == 0 || entry->GetTagCount() > 5"));
1692 if (CKademlia::GetIndexed()->AddNotes(target
, source
, entry
, load
)) {
1693 CMemFile
packetdata(17);
1694 packetdata
.WriteUInt128(target
);
1695 packetdata
.WriteUInt8(load
);
1696 DebugSend(KadPublishNotesRes
, ip
, port
);
1697 SendPacket(packetdata
, KADEMLIA_PUBLISH_NOTES_RES
, ip
, port
, 0, NULL
);
1703 // KADEMLIA2_PUBLISH_NOTES_REQ
1704 // Used only by Kad2.0
1705 void CKademliaUDPListener::Process2PublishNotesRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1707 // check if we are UDP firewalled
1708 if (CUDPFirewallTester::IsFirewalledUDP(true)) {
1709 //We are firewalled. We should not index this entry and give publisher a false report.
1713 CMemFile
bio(packetData
, lenPacket
);
1714 CUInt128 target
= bio
.ReadUInt128();
1716 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
1717 distance
.XOR(target
);
1719 // Shouldn't LAN IPs already be filtered?
1720 if (thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
1724 CUInt128 source
= bio
.ReadUInt128();
1726 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
1729 entry
->m_uUDPport
= port
;
1730 entry
->m_uKeyID
.SetValue(target
);
1731 entry
->m_uSourceID
.SetValue(source
);
1732 entry
->m_bSource
= false;
1733 uint32_t tags
= bio
.ReadUInt8();
1735 CTag
* tag
= bio
.ReadTag();
1737 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
1738 if (entry
->GetCommonFileName().IsEmpty()) {
1739 entry
->SetFileName(tag
->GetStr());
1742 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
1743 if (entry
->m_uSize
== 0) {
1744 entry
->m_uSize
= tag
->GetInt();
1755 //DebugClientOutput(wxT("CKademliaUDPListener::Process2PublishNotesRequest"),ip,port,packetData,lenPacket);
1762 if (CKademlia::GetIndexed()->AddNotes(target
, source
, entry
, load
)) {
1763 CMemFile
packetdata(17);
1764 packetdata
.WriteUInt128(target
);
1765 packetdata
.WriteUInt8(load
);
1766 DebugSend(Kad2PublishRes
, ip
, port
);
1767 SendPacket(packetdata
, KADEMLIA2_PUBLISH_RES
, ip
, port
, senderKey
, NULL
);
1773 // KADEMLIA_PUBLISH_NOTES_RES
1774 // Used only by Kad1.0
1775 void CKademliaUDPListener::ProcessPublishNotesResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1777 // Verify packet is expected size
1778 CHECK_PACKET_MIN_SIZE(16);
1779 CHECK_TRACKED_PACKET(KADEMLIA_PUBLISH_NOTES_REQ
);
1781 CMemFile
bio(packetData
, lenPacket
);
1782 CUInt128 file
= bio
.ReadUInt128();
1784 bool loadResponse
= false;
1786 if( bio
.GetLength() > bio
.GetPosition() ) {
1787 loadResponse
= true;
1788 load
= bio
.ReadUInt8();
1791 CSearchManager::ProcessPublishResult(file
, load
, loadResponse
);
1794 // KADEMLIA_FIREWALLED_REQ
1795 // Used by Kad1.0 and Kad2.0
1796 void CKademliaUDPListener::ProcessFirewalledRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1798 // Verify packet is expected size
1799 CHECK_PACKET_EXACT_SIZE(2);
1801 CMemFile
bio(packetData
, lenPacket
);
1802 uint16_t tcpport
= bio
.ReadUInt16();
1805 CContact
contact(zero
, ip
, port
, tcpport
, 0, 0, false, zero
);
1806 if (!theApp
->clientlist
->RequestTCP(&contact
, 0)) {
1807 return; // cancelled for some reason, don't send a response
1811 CMemFile
packetdata(4);
1812 packetdata
.WriteUInt32(ip
);
1813 DebugSend(KadFirewalledRes
, ip
, port
);
1814 SendPacket(packetdata
, KADEMLIA_FIREWALLED_RES
, ip
, port
, senderKey
, NULL
);
1817 // KADEMLIA_FIREWALLED2_REQ
1818 // Used by Kad2.0 Prot.Version 7+
1819 void CKademliaUDPListener::ProcessFirewalled2Request(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1821 // Verify packet is expected size
1822 CHECK_PACKET_MIN_SIZE(19);
1824 CMemFile
bio(packetData
, lenPacket
);
1825 uint16_t tcpPort
= bio
.ReadUInt16();
1826 CUInt128 userID
= bio
.ReadUInt128();
1827 uint8_t connectOptions
= bio
.ReadUInt8();
1830 CContact
contact(userID
, ip
, port
, tcpPort
, 0, 0, false, zero
);
1831 if (!theApp
->clientlist
->RequestTCP(&contact
, connectOptions
)) {
1832 return; // cancelled for some reason, don't send a response
1836 CMemFile
packetdata(4);
1837 packetdata
.WriteUInt32(ip
);
1838 DebugSend(KadFirewalledRes
, ip
, port
);
1839 SendPacket(packetdata
, KADEMLIA_FIREWALLED_RES
, ip
, port
, senderKey
, NULL
);
1842 // KADEMLIA_FIREWALLED_RES
1843 // Used by Kad1.0 and Kad2.0
1844 void CKademliaUDPListener::ProcessFirewalledResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, const CKadUDPKey
& WXUNUSED(senderKey
))
1846 // Verify packet is expected size
1847 CHECK_PACKET_EXACT_SIZE(4);
1849 if (!theApp
->clientlist
->IsKadFirewallCheckIP(wxUINT32_SWAP_ALWAYS(ip
))) { /* KADEMLIA_FIREWALLED2_REQ + KADEMLIA_FIREWALLED_REQ */
1850 throw wxString(wxT("Received unrequested firewall response packet in ")) + wxString::FromAscii(__FUNCTION__
);
1853 CMemFile
bio(packetData
, lenPacket
);
1854 uint32_t firewalledIP
= bio
.ReadUInt32();
1856 // Update con state only if something changes.
1857 if (CKademlia::GetPrefs()->GetIPAddress() != firewalledIP
) {
1858 CKademlia::GetPrefs()->SetIPAddress(firewalledIP
);
1859 theApp
->ShowConnectionState();
1861 CKademlia::GetPrefs()->IncRecheckIP();
1864 // KADEMLIA_FIREWALLED_ACK_RES
1865 // Used by Kad1.0 and Kad2.0
1866 void CKademliaUDPListener::ProcessFirewalledAckResponse(uint32_t lenPacket
)
1868 // 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.
1869 // But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest.
1871 // Verify packet is expected size
1872 CHECK_PACKET_EXACT_SIZE(0);
1874 CKademlia::GetPrefs()->IncFirewalled();
1877 // KADEMLIA_FINDBUDDY_REQ
1878 // Used by Kad1.0 and Kad2.0
1879 void CKademliaUDPListener::ProcessFindBuddyRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1881 // Verify packet is expected size
1882 CHECK_PACKET_MIN_SIZE(34);
1884 if (CKademlia::GetPrefs()->GetFirewalled() || CUDPFirewallTester::IsFirewalledUDP(true) || !CUDPFirewallTester::IsVerified()) {
1885 // We are firewalled but somehow we still got this packet.. Don't send a response..
1887 } else if (theApp
->clientlist
->GetBuddyStatus() == Connected
) {
1888 // we already have a buddy
1892 CMemFile
bio(packetData
, lenPacket
);
1893 CUInt128 BuddyID
= bio
.ReadUInt128();
1894 CUInt128 userID
= bio
.ReadUInt128();
1895 uint16_t tcpport
= bio
.ReadUInt16();
1898 CContact
contact(userID
, ip
, port
, tcpport
, 0, 0, false, zero
);
1899 if (!theApp
->clientlist
->IncomingBuddy(&contact
, &BuddyID
)) {
1900 return; // cancelled for some reason, don't send a response
1903 CMemFile
packetdata(34);
1904 packetdata
.WriteUInt128(BuddyID
);
1905 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
1906 packetdata
.WriteUInt16(thePrefs::GetPort());
1907 if (!senderKey
.IsEmpty()) { // remove check for later versions
1908 packetdata
.WriteUInt8(CPrefs::GetMyConnectOptions(true, false)); // new since 0.49a, old mules will ignore it (hopefully ;) )
1911 DebugSend(KadFindBuddyRes
, ip
, port
);
1912 SendPacket(packetdata
, KADEMLIA_FINDBUDDY_RES
, ip
, port
, senderKey
, NULL
);
1915 // KADEMLIA_FINDBUDDY_RES
1916 // Used by Kad1.0 and Kad2.0
1917 void CKademliaUDPListener::ProcessFindBuddyResponse(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& WXUNUSED(senderKey
))
1919 // Verify packet is expected size
1920 CHECK_PACKET_MIN_SIZE(34);
1921 CHECK_TRACKED_PACKET(KADEMLIA_FINDBUDDY_REQ
);
1923 CMemFile
bio(packetData
, lenPacket
);
1924 CUInt128 check
= bio
.ReadUInt128();
1925 check
.XOR(CUInt128(true));
1926 if (CKademlia::GetPrefs()->GetKadID() == check
) {
1927 CUInt128 userID
= bio
.ReadUInt128();
1928 uint16_t tcpport
= bio
.ReadUInt16();
1929 uint8_t connectOptions
= 0;
1930 if (lenPacket
> 34) {
1931 // 0.49+ (kad version 7) sends additionally its connect options so we know whether to use an obfuscated connection
1932 connectOptions
= bio
.ReadUInt8();
1936 CContact
contact(userID
, ip
, port
, tcpport
, 0, 0, false, zero
);
1937 theApp
->clientlist
->RequestBuddy(&contact
, connectOptions
);
1941 // KADEMLIA_CALLBACK_REQ
1942 // Used by Kad1.0 and Kad2.0
1943 void CKademliaUDPListener::ProcessCallbackRequest(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
, uint16_t port
, const CKadUDPKey
& WXUNUSED(senderKey
))
1945 // Verify packet is expected size
1946 CHECK_PACKET_MIN_SIZE(34);
1948 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1949 if (buddy
!= NULL
) {
1950 CMemFile
bio(packetData
, lenPacket
);
1951 CUInt128 check
= bio
.ReadUInt128();
1952 // JOHNTODO: Begin filtering bad buddy ID's..
1953 // CUInt128 bud(buddy->GetBuddyID());
1954 CUInt128 file
= bio
.ReadUInt128();
1955 uint16_t tcp
= bio
.ReadUInt16();
1957 if (buddy
->GetSocket()) {
1958 CMemFile
packetdata(lenPacket
+ 6);
1959 packetdata
.WriteUInt128(check
);
1960 packetdata
.WriteUInt128(file
);
1961 packetdata
.WriteUInt32(ip
);
1962 packetdata
.WriteUInt16(tcp
);
1963 CPacket
* packet
= new CPacket(packetdata
, OP_EMULEPROT
, OP_CALLBACK
);
1964 DebugSend(KadCallbackReq
, ip
, port
);
1965 buddy
->GetSocket()->SendPacket(packet
);
1966 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1968 throw wxString::FromAscii(__FUNCTION__
) + wxT(": Buddy has no valid socket");
1974 void CKademliaUDPListener::Process2Ping(uint32_t ip
, uint16_t port
, const CKadUDPKey
& senderKey
)
1976 // can be used just as PING, currently it is however only used to determine one's external port
1977 CMemFile
packetdata(2);
1978 packetdata
.WriteUInt16(port
);
1979 DebugSend(Kad2Pong
, ip
, port
);
1980 SendPacket(packetdata
, KADEMLIA2_PONG
, ip
, port
, senderKey
, NULL
);
1984 void CKademliaUDPListener::Process2Pong(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
1986 CHECK_PACKET_MIN_SIZE(2);
1987 CHECK_TRACKED_PACKET(KADEMLIA2_PING
);
1989 if (CKademlia::GetPrefs()->GetExternalKadPort() == 0) {
1990 // the reported port doesn't always have to be our true external port, esp. if we used our intern port
1991 // and communicated recently with the client some routers might remember this and assign the intern port as source
1992 // but this shouldn't be a problem because we prefer intern ports anyway.
1993 // might have to be reviewed in later versions when more data is available
1994 CKademlia::GetPrefs()->SetExternKadPort(PeekUInt16(packetData
));
1995 AddDebugLogLineM(false, logKadMain
, wxString::Format(wxT("Set external Kad Port to %u"), CKademlia::GetPrefs()->GetExternalKadPort()));
1997 if (CUDPFirewallTester::IsFWCheckUDPRunning()) {
1998 CUDPFirewallTester::QueryNextClient();
2001 theApp
->ShowConnectionState();
2004 // KADEMLIA2_FIREWALLUDP
2005 void CKademliaUDPListener::Process2FirewallUDP(const uint8_t *packetData
, uint32_t lenPacket
, uint32_t ip
)
2007 // Verify packet is expected size
2008 CHECK_PACKET_MIN_SIZE(3);
2010 uint8_t errorCode
= PeekUInt8(packetData
);
2011 uint16_t incomingPort
= PeekUInt16(packetData
+ 1);
2012 if (incomingPort
!= CKademlia::GetPrefs()->GetExternalKadPort() && incomingPort
!= CKademlia::GetPrefs()->GetInternKadPort()) {
2013 AddDebugLogLineM(false, logClientKadUDP
, wxString::Format(wxT("Received UDP FirewallCheck on unexpected incoming port %u (") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)) + wxT(")"), incomingPort
));
2014 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip
, 0);
2015 } else if (errorCode
== 0) {
2016 AddDebugLogLineM(false, logClientKadUDP
, wxString::Format(wxT("Received UDP FirewallCheck packet from ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)) + wxT(" with incoming port %u"), incomingPort
));
2017 CUDPFirewallTester::SetUDPFWCheckResult(true, false, ip
, incomingPort
);
2019 AddDebugLogLineM(false, logClientKadUDP
, wxString::Format(wxT("Received UDP FirewallCheck packet from ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)) + wxT(" with incoming port %u with remote errorcode %u - ignoring result"), incomingPort
, errorCode
));
2020 CUDPFirewallTester::SetUDPFWCheckResult(false, true, ip
, 0);
2024 void CKademliaUDPListener::SendPacket(const CMemFile
&data
, uint8_t opcode
, uint32_t destinationHost
, uint16_t destinationPort
, const CKadUDPKey
& targetKey
, const CUInt128
* cryptTargetID
)
2026 AddTrackedOutPacket(destinationHost
, opcode
);
2027 CPacket
* packet
= new CPacket(data
, OP_KADEMLIAHEADER
, opcode
);
2028 if (packet
->GetPacketSize() > 200) {
2029 packet
->PackPacket();
2031 uint8_t cryptData
[16];
2033 if (cryptTargetID
!= NULL
) {
2034 cryptKey
= (uint8_t *)&cryptData
;
2035 cryptTargetID
->StoreCryptValue(cryptKey
);
2039 theStats::AddUpOverheadKad(packet
->GetPacketSize());
2040 theApp
->clientudp
->SendPacket(packet
, wxUINT32_SWAP_ALWAYS(destinationHost
), destinationPort
, true, cryptKey
, true, targetKey
.GetKeyValue(theApp
->GetPublicIP(false)));
2043 bool CKademliaUDPListener::FindNodeIDByIP(CKadClientSearcher
* requester
, uint32_t ip
, uint16_t tcpPort
, uint16_t udpPort
)
2045 // send a hello packet to the given IP in order to get a HELLO_RES with the NodeID
2047 // we will drop support for Kad1 soon, so dont bother sending two packets in case we don't know if kad2 is supported
2048 // (if we know that its not, this function isn't called in the first place)
2049 AddDebugLogLineM(false, logClientKadUDP
, wxT("FindNodeIDByIP: Requesting NodeID from ") + Uint32toStringIP(wxUINT32_SWAP_ALWAYS(ip
)) + wxT(" by sending Kad2HelloReq"));
2050 DebugSend(Kad2HelloReq
, ip
, udpPort
);
2051 SendMyDetails(KADEMLIA2_HELLO_REQ
, ip
, udpPort
, true, 0, NULL
); // todo: we send this unobfuscated, which is not perfect, see this can be avoided in the future
2052 FetchNodeID_Struct sRequest
= { ip
, tcpPort
, ::GetTickCount() + SEC2MS(60), requester
};
2053 m_fetchNodeIDRequests
.push_back(sRequest
);
2057 void CKademliaUDPListener::ExpireClientSearch(CKadClientSearcher
* expireImmediately
)
2059 uint32_t now
= ::GetTickCount();
2060 for (FetchNodeIDList::iterator it
= m_fetchNodeIDRequests
.begin(); it
!= m_fetchNodeIDRequests
.end();) {
2061 FetchNodeIDList::iterator it2
= it
++;
2062 if (it2
->requester
== expireImmediately
) {
2063 m_fetchNodeIDRequests
.erase(it2
);
2065 else if (it2
->expire
< now
) {
2066 it2
->requester
->KadSearchNodeIDByIPResult(KCSR_TIMEOUT
, NULL
);
2067 m_fetchNodeIDRequests
.erase(it2
);
2072 void CKademliaUDPListener::DebugClientOutput(const wxString
& place
, uint32 kad_ip
, uint32 port
, const byte
* data
, int len
)
2074 #if THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX
2075 uint32 ip
= wxUINT32_SWAP_ALWAYS(kad_ip
);
2076 printf("Error on %s received from: %s\n",(const char*)unicode2char(place
),(const char*)unicode2char(Uint32_16toStringIP_Port(ip
,port
)));
2078 printf("Packet dump:\n");
2081 CClientList::SourceList clientslist
= theApp
->clientlist
->GetClientsByIP(ip
);
2082 if (!clientslist
.empty()) {
2083 for (CClientList::SourceList::iterator it
= clientslist
.begin(); it
!= clientslist
.end(); ++it
) {
2084 printf("Ip Matches: %s\n",(const char*)unicode2char((*it
)->GetClientFullInfo()));
2087 printf("No ip match, trying to create a client connection:\n");
2088 printf("Trying port %d\n", port
- 10);
2089 CUpDownClient
* client
= new CUpDownClient(port
-10,kad_ip
,0,0,NULL
,false,false);
2090 client
->SetConnectionReason(wxT("Error on ") + place
);
2091 client
->TryToConnect(true);
2094 // No need for warnings for the rest of us.
2102 // File_checked_for_headers