2 // This file is part of aMule Project
4 // Copyright (c) 2004-2008 Angel Vidal (Kry) ( 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/ed2k/Client2Client/TCP.h> // OP_CALLBACK is sent in some cases.
42 #include <common/Macros.h>
43 #include <common/Format.h>
44 #include <tags/FileTags.h>
46 #include "../routing/Contact.h"
47 #include "../routing/RoutingZone.h"
48 #include "../kademlia/Indexed.h"
49 #include "../kademlia/Defines.h"
50 #include "../../amule.h"
51 #include "../../ClientUDPSocket.h"
52 #include "../../Packet.h"
53 #include "../../ClientList.h"
54 #include "../../Statistics.h"
55 #include "../../MemFile.h"
56 #include "../../updownclient.h"
57 #include "../../ClientTCPSocket.h"
58 #include "../../Logger.h"
59 #include "../../Preferences.h"
60 #include "../../ScopedPtr.h"
62 #include <wx/tokenzr.h>
64 #define THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX 0
66 extern wxChar
* InvKadKeywordChars
;
68 ////////////////////////////////////////
69 using namespace Kademlia
;
70 ////////////////////////////////////////
72 void CKademliaUDPListener::Bootstrap(uint32 ip
, uint16 port
)
75 SendMyDetails(KADEMLIA_BOOTSTRAP_REQ
, ip
, port
);
78 void CKademliaUDPListener::SendMyDetails(byte opcode
, uint32 ip
, uint16 port
)
80 CMemFile
packetdata(25);
81 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
82 packetdata
.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
83 packetdata
.WriteUInt16(thePrefs::GetEffectiveUDPPort());
84 packetdata
.WriteUInt16(thePrefs::GetPort());
85 packetdata
.WriteUInt8(0);
86 SendPacket(packetdata
, opcode
, ip
, port
);
89 void CKademliaUDPListener::FirewalledCheck(uint32 ip
, uint16 port
)
91 CMemFile
packetdata(2);
92 packetdata
.WriteUInt16(thePrefs::GetPort());
93 SendPacket(packetdata
, KADEMLIA_FIREWALLED_REQ
, ip
, port
);
96 void CKademliaUDPListener::SendNullPacket(byte opcode
,uint32 ip
, uint16 port
)
98 CMemFile
packetdata(0);
99 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadNullPacket %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
100 SendPacket(packetdata
, opcode
, ip
, port
);
103 void CKademliaUDPListener::PublishPacket(uint32 ip
, uint16 port
, const CUInt128
&targetID
, const CUInt128
&contactID
, const TagPtrList
& tags
)
106 packetdata
.WriteUInt128(targetID
);
107 //We only use this for publishing sources now.. So we always send one here..
108 packetdata
.WriteUInt16(1);
109 packetdata
.WriteUInt128(contactID
);
110 packetdata
.WriteTagPtrList(tags
);
111 SendPacket(packetdata
, KADEMLIA_PUBLISH_REQ
, ip
, port
);
114 void CKademliaUDPListener::ProcessPacket(const byte
* data
, uint32 lenData
, uint32 ip
, uint16 port
)
116 //Update connection state only when it changes.
117 bool curCon
= CKademlia::GetPrefs()->HasHadContact();
118 CKademlia::GetPrefs()->SetLastContact();
119 if( curCon
!= CKademlia::GetPrefs()->HasHadContact()) {
120 theApp
->ShowConnectionState();
123 byte opcode
= data
[1];
124 const byte
*packetData
= data
+ 2;
125 uint32 lenPacket
= lenData
- 2;
128 case KADEMLIA_BOOTSTRAP_REQ
:
129 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadBootstrapReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
130 ProcessBootstrapRequest(packetData
, lenPacket
, ip
, port
);
132 case KADEMLIA_BOOTSTRAP_RES
:
133 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadBootstrapRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
134 ProcessBootstrapResponse(packetData
, lenPacket
, ip
, port
);
136 case KADEMLIA_HELLO_REQ
:
137 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadHelloReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
138 ProcessHelloRequest(packetData
, lenPacket
, ip
, port
);
140 case KADEMLIA_HELLO_RES
:
141 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadHelloRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
142 ProcessHelloResponse(packetData
, lenPacket
, ip
, port
);
145 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
146 ProcessKademliaRequest(packetData
, lenPacket
, ip
, port
);
149 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
150 ProcessKademliaResponse(packetData
, lenPacket
, ip
, port
);
152 case KADEMLIA_SEARCH_REQ
:
153 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadSearchReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
154 ProcessSearchRequest(packetData
, lenPacket
, ip
, port
);
156 case KADEMLIA_SEARCH_RES
:
157 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadSearchRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
158 ProcessSearchResponse(packetData
, lenPacket
, ip
, port
);
160 case KADEMLIA_PUBLISH_REQ
:
161 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
162 ProcessPublishRequest(packetData
, lenPacket
, ip
, port
);
164 case KADEMLIA_PUBLISH_RES
:
165 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
166 ProcessPublishResponse(packetData
, lenPacket
, ip
, port
);
168 case KADEMLIA_SRC_NOTES_REQ
:
169 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadSearchNotesReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
170 ProcessSearchNotesRequest(packetData
, lenPacket
, ip
, port
);
172 case KADEMLIA_SRC_NOTES_RES
:
173 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadSearchNotesRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
174 ProcessSearchNotesResponse(packetData
, lenPacket
, ip
, port
);
176 case KADEMLIA_PUB_NOTES_REQ
:
177 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishNotesReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
178 ProcessPublishNotesRequest(packetData
, lenPacket
, ip
, port
);
180 case KADEMLIA_PUB_NOTES_RES
:
181 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishNotesRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
182 ProcessPublishNotesResponse(packetData
, lenPacket
, ip
, port
);
184 case KADEMLIA_FIREWALLED_REQ
:
185 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFirewalledReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
186 ProcessFirewalledRequest(packetData
, lenPacket
, ip
, port
);
188 case KADEMLIA_FIREWALLED_RES
:
189 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFirewalledRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
190 ProcessFirewalledResponse(packetData
, lenPacket
, ip
, port
);
192 case KADEMLIA_FIREWALLED_ACK
:
193 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFirewalledAck from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
194 ProcessFirewalledResponse2(packetData
, lenPacket
, ip
, port
);
196 case KADEMLIA_FINDBUDDY_REQ
:
197 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFindBuddyReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
198 ProcessFindBuddyRequest(packetData
, lenPacket
, ip
, port
);
200 case KADEMLIA_FINDBUDDY_RES
:
201 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFindBuddyRes from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
202 ProcessFindBuddyResponse(packetData
, lenPacket
, ip
, port
);
204 case KADEMLIA_CALLBACK_REQ
:
205 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadCallbackReq from %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
206 ProcessCallbackRequest(packetData
, lenPacket
, ip
, port
);
209 throw wxString::Format(wxT("Unknown opcode %02x on CKademliaUDPListener::processPacket"), opcode
);
214 void CKademliaUDPListener::AddContact( const byte
*data
, uint32 lenData
, uint32 ip
, uint16 port
, uint16 tport
)
216 CMemFile
bio((byte
*)data
, lenData
);
217 CUInt128 id
= bio
.ReadUInt128();
223 tport
= bio
.ReadUInt16();
225 byte type
= bio
.ReadUInt8();
226 //AddDebugLogLineM(false, logKadMain, wxT("Adding a contact with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port));
227 // Look for existing client
228 CContact
*contact
= CKademlia::GetRoutingZone()->GetContact(id
);
229 if (contact
!= NULL
) {
230 contact
->SetIPAddress(ip
);
231 contact
->SetUDPPort(port
);
232 contact
->SetTCPPort(tport
);
234 if(IsGoodIPPort(wxUINT32_SWAP_ALWAYS(ip
),port
)) {
235 // Ignore stated ip and port, use the address the packet came from
236 CKademlia::GetRoutingZone()->Add(id
, ip
, port
, tport
, type
);
241 void CKademliaUDPListener::AddContacts( const byte
*data
, uint32 lenData
, uint16 numContacts
)
243 CMemFile
bio((byte
*)data
, lenData
);
244 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
245 for (uint16 i
=0; i
<numContacts
; i
++) {
246 CUInt128 id
= bio
.ReadUInt128();
247 uint32 ip
= bio
.ReadUInt32();
248 ip
= wxUINT32_SWAP_ALWAYS(ip
);
249 uint16 port
= bio
.ReadUInt16();
250 uint16 tport
= bio
.ReadUInt16();
251 byte type
= bio
.ReadUInt8();
252 //AddDebugLogLineM(false, logKadMain, wxT("Adding contact(s) with ip ") + Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip),port));
253 if (IsGoodIPPort(wxUINT32_SWAP_ALWAYS(ip
),port
)) {
254 routingZone
->Add(id
, ip
, port
, tport
, type
);
259 //KADEMLIA_BOOTSTRAP_REQ
260 void CKademliaUDPListener::ProcessBootstrapRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
262 // Verify packet is expected size
263 if (lenPacket
!= 25){
264 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
267 // Add the sender to the list of contacts
268 AddContact(packetData
, lenPacket
, ip
, port
);
270 // Get some contacts to return
271 ContactList contacts
;
272 uint16 numContacts
= 1 + (uint16
)CKademlia::GetRoutingZone()->GetBootstrapContacts(&contacts
, 20);
274 // Create response packet
275 //We only collect a max of 20 contacts here.. Max size is 527.
277 CMemFile
packetdata(527);
280 packetdata
.WriteUInt16(numContacts
);
282 ContactList::const_iterator it
;
283 for (it
= contacts
.begin(); it
!= contacts
.end(); it
++) {
285 packetdata
.WriteUInt128(contact
->GetClientID());
286 packetdata
.WriteUInt32(contact
->GetIPAddress());
287 packetdata
.WriteUInt16(contact
->GetUDPPort());
288 packetdata
.WriteUInt16(contact
->GetTCPPort());
289 packetdata
.WriteUInt8(contact
->GetType());
292 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetKadID());
293 packetdata
.WriteUInt32(CKademlia::GetPrefs()->GetIPAddress());
294 packetdata
.WriteUInt16(thePrefs::GetEffectiveUDPPort());
295 packetdata
.WriteUInt16(thePrefs::GetPort());
296 packetdata
.WriteUInt8(0);
299 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadBootstrapRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
301 SendPacket(packetdata
, KADEMLIA_BOOTSTRAP_RES
, ip
, port
);
304 //KADEMLIA_BOOTSTRAP_RES
305 void CKademliaUDPListener::ProcessBootstrapResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
307 // Verify packet is expected size
309 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
312 // How many contacts were given
313 CMemFile
bio(packetData
, lenPacket
);
314 uint16 numContacts
= bio
.ReadUInt16();
316 // Verify packet is expected size
317 if (lenPacket
!= (uint32
)(2 + 25*numContacts
)) {
321 // Add these contacts to the list.
322 AddContacts(packetData
+2, lenPacket
-2, numContacts
);
323 // Send sender to alive.
324 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
328 void CKademliaUDPListener::ProcessHelloRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
330 // Verify packet is expected size
331 if (lenPacket
!= 25){
332 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
335 // Add the sender to the list of contacts
336 AddContact(packetData
, lenPacket
, ip
, port
);
339 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadHelloRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
340 SendMyDetails(KADEMLIA_HELLO_RES
, ip
, port
);
342 // Check if firewalled
343 if(CKademlia::GetPrefs()->GetRecheckIP()) {
344 FirewalledCheck(ip
, port
);
349 void CKademliaUDPListener::ProcessHelloResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
351 // Verify packet is expected size
352 if (lenPacket
!= 25){
353 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
356 // Add or Update contact.
357 AddContact(packetData
, lenPacket
, ip
, port
);
359 // Set contact to alive.
360 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
364 void CKademliaUDPListener::ProcessKademliaRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
366 // Verify packet is expected size
367 if (lenPacket
!= 33){
368 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
371 //RecheckIP and firewall status
372 if(CKademlia::GetPrefs()->GetRecheckIP())
374 FirewalledCheck(ip
, port
);
375 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadHelloReq %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
376 SendMyDetails(KADEMLIA_HELLO_REQ
, ip
, port
);
379 // Get target and type
380 CMemFile
bio(packetData
, lenPacket
);
381 byte type
= bio
.ReadUInt8();
382 // bool flag1 = (type >> 6); //Reserved
383 // bool flag2 = (type >> 7); //Reserved
384 // bool flag3 = (type >> 8); //Reserved
388 throw wxString::Format(wxT("***NOTE: Received wrong type (0x%02x) in "), type
) + wxString::FromAscii(__FUNCTION__
);
391 //This is the target node trying to be found.
392 CUInt128 target
= bio
.ReadUInt128();
393 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
394 distance
.XOR(target
);
396 //This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.
397 CUInt128 check
= bio
.ReadUInt128();
398 if( CKademlia::GetPrefs()->GetKadID().CompareTo(check
)) {
402 // Get required number closest to target
404 CKademlia::GetRoutingZone()->GetClosestTo(2, target
, distance
, (int)type
, &results
);
405 uint16 count
= (uint16
)results
.size();
408 // Max count is 32. size 817..
410 CMemFile
packetdata( 817 );
411 packetdata
.WriteUInt128(target
);
412 packetdata
.WriteUInt8((byte
)count
);
414 ContactMap::const_iterator it
;
415 for (it
= results
.begin(); it
!= results
.end(); it
++) {
417 packetdata
.WriteUInt128(c
->GetClientID());
418 packetdata
.WriteUInt32(c
->GetIPAddress());
419 packetdata
.WriteUInt16(c
->GetUDPPort());
420 packetdata
.WriteUInt16(c
->GetTCPPort());
421 packetdata
.WriteUInt8(c
->GetType());
424 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadRes %s Count=%u")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
) % count
);
426 SendPacket(packetdata
, KADEMLIA_RES
, ip
, port
);
430 void CKademliaUDPListener::ProcessKademliaResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
432 // Verify packet is expected size
434 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
438 CRoutingZone
*routingZone
= CKademlia::GetRoutingZone();
440 if(CKademlia::GetPrefs()->GetRecheckIP()) {
441 FirewalledCheck(ip
, port
);
442 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadHelloReq %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
443 SendMyDetails(KADEMLIA_HELLO_REQ
, ip
, port
);
446 // What search does this relate to
447 CMemFile
bio(packetData
, lenPacket
);
448 CUInt128 target
= bio
.ReadUInt128();
449 uint16 numContacts
= bio
.ReadUInt8();
451 // Verify packet is expected size
452 if (lenPacket
!= (uint32
)(16+1 + (16+4+2+2+1)*numContacts
)) {
453 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
456 // Set contact to alive.
457 routingZone
->SetAlive(ip
, port
);
460 CScopedPtr
<ContactList
> results(new ContactList
);
462 for (uint16 i
=0; i
<numContacts
; i
++) {
463 CUInt128 id
= bio
.ReadUInt128();
464 uint32 contactIP
= bio
.ReadUInt32();
465 uint16 contactPort
= bio
.ReadUInt16();
466 uint16 tport
= bio
.ReadUInt16();
467 byte type
= bio
.ReadUInt8();
468 if(::IsGoodIPPort(wxUINT32_SWAP_ALWAYS(contactIP
),contactPort
)) {
469 routingZone
->Add(id
, contactIP
, contactPort
, tport
, type
);
470 results
->push_back(new CContact(id
, contactIP
, contactPort
, tport
, target
));
474 CSearchManager::ProcessResponse(target
, ip
, port
, results
.release());
477 void CKademliaUDPListener::Free(SSearchTerm
* pSearchTerms
)
483 Free(pSearchTerms
->left
);
484 Free(pSearchTerms
->right
);
488 SSearchTerm
* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile
& bio
, int iLevel
)
490 // the max. depth has to match our own limit for creating the search expression
491 // (see also 'ParsedSearchExpression' and 'GetSearchPacket')
493 AddDebugLogLineM(false, logClientKadUDP
, wxT("***NOTE: Search expression tree exceeds depth limit!"));
498 uint8 op
= bio
.ReadUInt8();
500 uint8 boolop
= bio
.ReadUInt8();
501 if (boolop
== 0x00) { // AND
502 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
503 pSearchTerm
->type
= SSearchTerm::AND
;
505 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
510 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
512 Free(pSearchTerm
->left
);
517 } else if (boolop
== 0x01) { // OR
518 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
519 pSearchTerm
->type
= SSearchTerm::OR
;
521 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
526 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
528 Free(pSearchTerm
->left
);
533 } else if (boolop
== 0x02) { // NAND
534 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
535 pSearchTerm
->type
= SSearchTerm::NAND
;
537 if ((pSearchTerm
->left
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
542 if ((pSearchTerm
->right
= CreateSearchExpressionTree(bio
, iLevel
)) == NULL
){
544 Free(pSearchTerm
->left
);
550 AddDebugLogLineM(false, logKadSearch
, wxString::Format(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop
));
553 } else if (op
== 0x01) { // String
554 wxString
str(bio
.ReadString(true));
556 // Make lowercase, the search code expects lower case strings!
559 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
560 pSearchTerm
->type
= SSearchTerm::String
;
561 pSearchTerm
->astr
= new wxArrayString
;
563 // pre-tokenize the string term
564 wxStringTokenizer
token(str
,InvKadKeywordChars
,wxTOKEN_DEFAULT
);
565 while (token
.HasMoreTokens()) {
566 wxString
strTok(token
.GetNextToken());
567 if (!strTok
.IsEmpty()) {
568 pSearchTerm
->astr
->Add(strTok
);
573 } else if (op
== 0x02) { // Meta tag
575 wxString
strValue(bio
.ReadString(true));
576 // Make lowercase, the search code expects lower case strings!
577 strValue
.MakeLower();
580 wxString strTagName
= bio
.ReadString(true);
582 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
583 pSearchTerm
->type
= SSearchTerm::MetaTag
;
584 pSearchTerm
->tag
= new CTagString(strTagName
, strValue
);
587 else if (op
== 0x03) { // Min/Max
588 static const struct {
589 SSearchTerm::ESearchTermType eSearchTermOp
;
593 { SSearchTerm::OpEqual
, wxT("=") }, // mmop=0x00
594 { SSearchTerm::OpGreaterEqual
, wxT(">=") }, // mmop=0x01
595 { SSearchTerm::OpLessEqual
, wxT("<=") }, // mmop=0x02
596 { SSearchTerm::OpGreater
, wxT(">") }, // mmop=0x03
597 { SSearchTerm::OpLess
, wxT("<") }, // mmop=0x04
598 { SSearchTerm::OpNotEqual
, wxT("!=") } // mmop=0x05
602 uint32 uValue
= bio
.ReadUInt32();
604 // read integer operator
605 uint8 mmop
= bio
.ReadUInt8();
606 if (mmop
>= itemsof(_aOps
)){
607 AddDebugLogLineM(false, logClientKadUDP
, wxString::Format(wxT("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop
));
612 wxString strTagName
= bio
.ReadString(false);
614 SSearchTerm
* pSearchTerm
= new SSearchTerm
;
615 pSearchTerm
->type
= _aOps
[mmop
].eSearchTermOp
;
616 pSearchTerm
->tag
= new CTagVarInt(strTagName
, uValue
);
620 AddDebugLogLineM(false, logClientKadUDP
, wxString::Format(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), op
));
625 //KADEMLIA_SEARCH_REQ
626 void CKademliaUDPListener::ProcessSearchRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
628 // Verify packet is expected size
630 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
633 CMemFile
bio(packetData
, lenPacket
);
634 CUInt128 target
= bio
.ReadUInt128();
635 uint8 restrictive
= bio
.ReadUInt8();
638 //DWORD dwNow = GetTickCount();
640 if(lenPacket
== 17 ) {
643 CKademlia::GetIndexed()->SendValidSourceResult(target
, ip
, port
);
644 //DEBUG_ONLY( Debug("SendValidSourceResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
646 //Single keyword request
647 CKademlia::GetIndexed()->SendValidKeywordResult(target
, NULL
, ip
, port
);
648 //DEBUG_ONLY( Debug("SendValidKeywordResult (Single): Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
650 } else if(lenPacket
> 17) {
651 SSearchTerm
* pSearchTerms
= NULL
;
653 pSearchTerms
= CreateSearchExpressionTree(bio
, 0);
655 //Keyword request with added options.
656 CKademlia::GetIndexed()->SendValidKeywordResult(target
, pSearchTerms
, ip
, port
);
658 //DEBUG_ONLY( Debug("SendValidKeywordResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
662 //KADEMLIA_SEARCH_RES
663 void CKademliaUDPListener::ProcessSearchResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
665 // Verify packet is expected size
666 if (lenPacket
< 37) {
667 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
670 // Set contact to alive.
671 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
673 // What search does this relate to
674 CMemFile
bio(packetData
, lenPacket
);
675 CUInt128 target
= bio
.ReadUInt128();
677 // How many results.. Not supported yet..
678 uint16 count
= bio
.ReadUInt16();
680 // What is the answer
681 CUInt128 answer
= bio
.ReadUInt128();
683 // Get info about answer
684 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
685 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
686 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
687 // If that tag list is once used for something else than for viewing, special care has to be taken for any
688 // string conversion!
689 TagPtrList
* tags
= new TagPtrList
;
691 bio
.ReadTagPtrList(tags
, true/*bOptACP*/);
693 DebugClientOutput(wxT("CKademliaUDPListener::processSearchResponse"),ip
,port
,packetData
,lenPacket
);
694 deleteTagPtrListEntries(tags
);
699 CSearchManager::ProcessResult(target
, ip
, port
, answer
, tags
);
704 //KADEMLIA_PUBLISH_REQ
705 void CKademliaUDPListener::ProcessPublishRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
707 //There are different types of publishing..
708 //Keyword and File are Stored..
709 // Verify packet is expected size
710 if (lenPacket
< 37) {
711 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
715 CIndexed
*indexed
= CKademlia::GetIndexed();
717 if( CKademlia::GetPrefs()->GetFirewalled() ) {
718 //We are firewalled. We should not index this entry and give publisher a false report.
722 CMemFile
bio(packetData
, lenPacket
);
723 CUInt128 file
= bio
.ReadUInt128();
725 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
728 if( thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
733 uint16 count
= bio
.ReadUInt16();
734 uint16 totalcount
= count
;
740 CUInt128 target
= bio
.ReadUInt128();
742 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
743 uint32 tags
= 0, totaltags
= 0;
746 entry
->m_iUDPport
= port
;
747 entry
->m_iKeyID
.SetValue(file
);
748 entry
->m_iSourceID
.SetValue(target
);
749 tags
= bio
.ReadUInt8();
752 CTag
* tag
= bio
.ReadTag();
755 if (!tag
->GetName().Cmp(TAG_SOURCETYPE
) && tag
->GetType() == 9) {
756 if( entry
->m_bSource
== false ) {
757 entry
->m_lTagList
.push_back(new CTagVarInt(TAG_SOURCEIP
, entry
->m_iIP
));
758 entry
->m_lTagList
.push_back(new CTagVarInt(TAG_SOURCEUPORT
, entry
->m_iUDPport
));
760 //More than one sourcetype tag found.
763 entry
->m_bSource
= true;
766 if (!tag
->GetName().Cmp(TAG_FILENAME
)) {
767 if ( entry
->m_sFileName
.IsEmpty() ) {
768 entry
->m_sFileName
= tag
->GetStr();
769 // Make lowercase, the search code expects lower case strings!
770 entry
->m_sFileName
.MakeLower();
771 strInfo
+= CFormat(wxT(" Name=\"%s\"")) % entry
->m_sFileName
;
772 // NOTE: always add the 'name' tag, even if it's stored separately in 'fileName'. the tag is still needed for answering search request
773 entry
->m_lTagList
.push_back(tag
);
775 //More then one Name tag found.
778 } else if (!tag
->GetName().Cmp(TAG_FILESIZE
)) {
779 if( entry
->m_iSize
== 0 ) {
780 if (tag
->IsBsob() && (tag
->GetBsobSize() == 8)) {
781 // Kad1.0 uint64 type using a BSOB.
782 entry
->m_iSize
= PeekUInt64(tag
->GetBsob());
784 // Don't save as a BSOB tag ...
786 tag
= new CTagVarInt(TAG_FILESIZE
, entry
->m_iSize
);
788 wxASSERT(tag
->IsInt());
789 entry
->m_iSize
= tag
->GetInt();
791 strInfo
+= wxString::Format(wxT(" Size=%") wxLongLongFmtSpec
wxT("u"), entry
->m_iSize
);
792 // NOTE: always add the 'size' tag, even if it's stored separately in 'size'. the tag is still needed for answering search request
793 entry
->m_lTagList
.push_back(tag
);
795 //More then one size tag found
798 } else if (!tag
->GetName().Cmp(TAG_SOURCEPORT
)) {
799 if( entry
->m_iTCPport
== 0 ) {
800 entry
->m_iTCPport
= tag
->GetInt();
801 entry
->m_lTagList
.push_back(tag
);
803 //More then one port tag found
808 entry
->m_lTagList
.push_back(tag
);
813 if (!strInfo
.IsEmpty()) {
814 AddDebugLogLineM(false, logClientKadUDP
, strInfo
);
817 printf("Error on count %i tag %i\n",totalcount
-count
, totaltags
-tags
);
818 DebugClientOutput(wxT("CKademliaUDPListener::processPublishRequest"),ip
,port
,packetData
,lenPacket
);
823 if( entry
->m_bSource
== true ) {
824 entry
->m_tLifeTime
= (uint32
)time(NULL
)+KADEMLIAREPUBLISHTIMES
;
825 if( indexed
->AddSources(file
, target
, entry
, load
) ) {
832 entry
->m_tLifeTime
= (uint32
)time(NULL
)+KADEMLIAREPUBLISHTIMEK
;
833 if( indexed
->AddKeyword(file
, target
, entry
, load
) ) {
834 // This makes sure we send a publish response..
835 // This also makes sure we index all the files for this keyword.
838 //We already indexed the maximum number of keywords.
839 //We do not index anymore but we still send a success..
840 //Reason: Because if a VERY busy node tells the publisher it failed,
841 //this busy node will spread to all the surrounding nodes causing popular
842 //keywords to be stored on MANY nodes..
843 //So, once we are full, we will periodically clean our list until we can
844 //begin storing again..
853 CMemFile
packetdata(17);
854 packetdata
.WriteUInt128(file
);
855 packetdata
.WriteUInt8(load
);
856 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
858 SendPacket( packetdata
, KADEMLIA_PUBLISH_RES
, ip
, port
);
862 //KADEMLIA_PUBLISH_ACK
863 void CKademliaUDPListener::ProcessPublishResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
865 // Verify packet is expected size
866 if (lenPacket
< 16) {
867 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
870 // Set contact to alive.
871 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
873 CMemFile
bio(packetData
, lenPacket
);
874 CUInt128 file
= bio
.ReadUInt128();
876 bool loadResponse
= false;
878 if( bio
.GetLength() > bio
.GetPosition() ) {
880 load
= bio
.ReadUInt8();
883 CSearchManager::ProcessPublishResult(file
, load
, loadResponse
);
886 //KADEMLIA_SRC_NOTES_REQ
887 void CKademliaUDPListener::ProcessSearchNotesRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
889 // Verify packet is expected size
890 if (lenPacket
< 32) {
891 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
894 CMemFile
bio(packetData
, lenPacket
);
895 CUInt128 target
= bio
.ReadUInt128();
896 CUInt128 source
= bio
.ReadUInt128();
898 CKademlia::GetIndexed()->SendValidNoteResult(target
, source
, ip
, port
);
901 //KADEMLIA_SRC_NOTES_RES
902 void CKademliaUDPListener::ProcessSearchNotesResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
904 // Verify packet is expected size
905 if (lenPacket
< 37) {
906 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
909 // Set contact to alive.
910 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
912 // What search does this relate to
913 CMemFile
bio(packetData
, lenPacket
);
914 CUInt128 target
= bio
.ReadUInt128();
916 uint16 count
= bio
.ReadUInt16();
918 // What is the answer
919 CUInt128 answer
= bio
.ReadUInt128();
921 // Get info about answer
922 // NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
923 // case we did not receive an UTF8 string. this is for backward compatibility for search results which are
924 // supposed to be 'viewed' by user only and not feed into the Kad engine again!
925 // If that tag list is once used for something else than for viewing, special care has to be taken for any
926 // string conversion!
927 TagPtrList
* tags
= new TagPtrList
;
929 bio
.ReadTagPtrList(tags
, true/*bOptACP*/);
931 DebugClientOutput(wxT("CKademliaUDPListener::processSearchNotesResponse"),ip
,port
,packetData
,lenPacket
);
932 deleteTagPtrListEntries(tags
);
937 CSearchManager::ProcessResult(target
, ip
, port
, answer
, tags
);
942 //KADEMLIA_PUB_NOTES_REQ
943 void CKademliaUDPListener::ProcessPublishNotesRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
945 // Verify packet is expected size
946 if (lenPacket
< 37) {
947 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
950 if( CKademlia::GetPrefs()->GetFirewalled() ) {
951 //We are firewalled. We should not index this entry and give publisher a false report.
955 CMemFile
bio(packetData
, lenPacket
);
956 CUInt128 target
= bio
.ReadUInt128();
958 CUInt128
distance(CKademlia::GetPrefs()->GetKadID());
959 distance
.XOR(target
);
961 if( thePrefs::FilterLanIPs() && distance
.Get32BitChunk(0) > SEARCHTOLERANCE
) {
965 CUInt128 source
= bio
.ReadUInt128();
967 Kademlia::CEntry
* entry
= new Kademlia::CEntry();
970 entry
->m_iUDPport
= port
;
971 entry
->m_iKeyID
.SetValue(target
);
972 entry
->m_iSourceID
.SetValue(source
);
973 bio
.ReadTagPtrList(&entry
->m_lTagList
);
974 entry
->m_bSource
= false;
976 DebugClientOutput(wxT("CKademliaUDPListener::processPublishNotesRequest"),ip
,port
,packetData
,lenPacket
);
981 if( entry
== NULL
) {
982 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry == NULL"));
983 } else if( entry
->m_lTagList
.size() == 0 || entry
->m_lTagList
.size() > 5) {
985 throw wxString(wxT("CKademliaUDPListener::processPublishNotesRequest: entry->m_lTagList.size() == 0 || entry->m_lTagList.size() > 5"));
989 if( CKademlia::GetIndexed()->AddNotes(target
, source
, entry
, load
) ) {
990 CMemFile
packetdata(17);
991 packetdata
.WriteUInt128(target
);
992 packetdata
.WriteUInt8(load
);
993 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadPublishNotesRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
994 SendPacket( packetdata
, KADEMLIA_PUB_NOTES_RES
, ip
, port
);
1000 //KADEMLIA_PUB_NOTES_RES
1001 void CKademliaUDPListener::ProcessPublishNotesResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1003 // Verify packet is expected size
1004 if (lenPacket
< 16){
1005 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1008 // Set contact to alive.
1009 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
1011 CMemFile
bio(packetData
, lenPacket
);
1012 CUInt128 file
= bio
.ReadUInt128();
1014 bool loadResponse
= false;
1016 if( bio
.GetLength() > bio
.GetPosition() ) {
1017 loadResponse
= true;
1018 load
= bio
.ReadUInt8();
1021 CSearchManager::ProcessPublishResult(file
, load
, loadResponse
);
1024 //KADEMLIA_FIREWALLED_REQ
1025 void CKademliaUDPListener::ProcessFirewalledRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1027 // Verify packet is expected size
1028 if (lenPacket
!= 2){
1029 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1032 CMemFile
bio(packetData
, lenPacket
);
1033 uint16 tcpport
= bio
.ReadUInt16();
1035 CUInt128
zero((uint32
)0);
1036 CContact
contact(zero
, ip
, port
, tcpport
, zero
);
1037 theApp
->clientlist
->RequestTCP(&contact
);
1040 CMemFile
packetdata(4);
1041 packetdata
.WriteUInt32(ip
);
1042 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFirewalledRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
1044 SendPacket(packetdata
, KADEMLIA_FIREWALLED_RES
, ip
, port
);
1047 //KADEMLIA_FIREWALLED_RES
1048 void CKademliaUDPListener::ProcessFirewalledResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1050 // Verify packet is expected size
1051 if (lenPacket
!= 4){
1052 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1055 // Set contact to alive.
1056 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
1058 CMemFile
bio(packetData
, lenPacket
);
1059 uint32 firewalledIP
= bio
.ReadUInt32();
1061 //Update con state only if something changes.
1062 if( CKademlia::GetPrefs()->GetIPAddress() != firewalledIP
) {
1063 CKademlia::GetPrefs()->SetIPAddress(firewalledIP
);
1064 theApp
->ShowConnectionState();
1066 CKademlia::GetPrefs()->IncRecheckIP();
1069 //KADEMLIA_FIREWALLED_ACK
1070 void CKademliaUDPListener::ProcessFirewalledResponse2 (const byte
*WXUNUSED(packetData
), uint32 lenPacket
, uint32 ip
, uint16 port
)
1072 // Verify packet is expected size
1073 if (lenPacket
!= 0) {
1074 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1077 // Set contact to alive.
1078 CKademlia::GetRoutingZone()->SetAlive(ip
, port
);
1079 CKademlia::GetPrefs()->IncFirewalled();
1082 //KADEMLIA_FINDBUDDY_REQ
1083 void CKademliaUDPListener::ProcessFindBuddyRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1085 // Verify packet is expected size
1086 if (lenPacket
< 34) {
1087 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1090 if( CKademlia::GetPrefs()->GetFirewalled() ) {
1091 //We are firewalled but somehow we still got this packet.. Don't send a response..
1095 CMemFile
bio(packetData
, lenPacket
);
1096 CUInt128 BuddyID
= bio
.ReadUInt128();
1097 CUInt128 userID
= bio
.ReadUInt128();
1098 uint16 tcpport
= bio
.ReadUInt16();
1100 CUInt128
zero((uint32
)0);
1101 CContact
contact(userID
, ip
, port
, tcpport
, zero
);
1102 theApp
->clientlist
->IncomingBuddy(&contact
, &BuddyID
);
1104 CMemFile
packetdata(34);
1105 packetdata
.WriteUInt128(BuddyID
);
1106 packetdata
.WriteUInt128(CKademlia::GetPrefs()->GetClientHash());
1107 packetdata
.WriteUInt16(thePrefs::GetPort());
1108 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadFindBuddyRes %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
1110 SendPacket(packetdata
, KADEMLIA_FINDBUDDY_RES
, ip
, port
);
1113 //KADEMLIA_FINDBUDDY_RES
1114 void CKademliaUDPListener::ProcessFindBuddyResponse (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1116 // Verify packet is expected size
1117 if (lenPacket
< 34) {
1118 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1122 CMemFile
bio(packetData
, lenPacket
);
1123 CUInt128 check
= bio
.ReadUInt128();
1124 check
.XOR(CUInt128(true));
1125 if( CKademlia::GetPrefs()->GetKadID().CompareTo(check
)) {
1128 CUInt128 userID
= bio
.ReadUInt128();
1129 uint16 tcpport
= bio
.ReadUInt16();
1131 CUInt128
zero((uint32
)0);
1132 CContact
contact(userID
, ip
, port
, tcpport
, zero
);
1133 theApp
->clientlist
->RequestBuddy(&contact
);
1136 //KADEMLIA_CALLBACK_REQ
1137 void CKademliaUDPListener::ProcessCallbackRequest (const byte
*packetData
, uint32 lenPacket
, uint32 ip
, uint16 port
)
1139 // Verify packet is expected size
1140 if (lenPacket
< 34) {
1141 throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket
) + wxString::FromAscii(__FUNCTION__
);
1144 CUpDownClient
* buddy
= theApp
->clientlist
->GetBuddy();
1145 if( buddy
!= NULL
) {
1146 CMemFile
bio(packetData
, lenPacket
);
1147 CUInt128 check
= bio
.ReadUInt128();
1148 // JOHNTODO: Filter bad buddies
1149 //CUInt128 bud(buddy->GetBuddyID());
1150 CUInt128 file
= bio
.ReadUInt128();
1151 uint16 tcp
= bio
.ReadUInt16();
1152 CMemFile
packetdata(16+16+4+2);
1153 packetdata
.WriteUInt128(check
);
1154 packetdata
.WriteUInt128(file
);
1155 packetdata
.WriteUInt32(ip
);
1156 packetdata
.WriteUInt16(tcp
);
1157 CPacket
* packet
= new CPacket(packetdata
, OP_EMULEPROT
, OP_CALLBACK
);
1158 if( buddy
->GetSocket() ) {
1159 AddDebugLogLineM(false, logClientKadUDP
, CFormat(wxT("KadCallback %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip
), port
));
1160 theStats::AddUpOverheadFileRequest(packet
->GetPacketSize());
1161 buddy
->GetSocket()->SendPacket(packet
);
1168 void CKademliaUDPListener::SendPacket(const CMemFile
&data
, byte opcode
, uint32 destinationHost
, uint16 destinationPort
)
1170 CPacket
* packet
= new CPacket(data
, OP_KADEMLIAHEADER
, opcode
);
1171 if( packet
->GetPacketSize() > 200 ) {
1172 packet
->PackPacket();
1174 theStats::AddUpOverheadKad(packet
->GetPacketSize());
1175 theApp
->clientudp
->SendPacket(packet
,wxUINT32_SWAP_ALWAYS(destinationHost
), destinationPort
, false, NULL
, true, 0);
1178 void CKademliaUDPListener::DebugClientOutput(const wxString
& place
, uint32 kad_ip
, uint32 port
, const byte
* data
, int len
)
1180 #if THIS_DEBUG_IS_JUST_FOR_KRY_DONT_TOUCH_IT_KTHX
1181 uint32 ip
= wxUINT32_SWAP_ALWAYS(kad_ip
);
1182 printf("Error on %s received from: %s\n",(const char*)unicode2char(place
),(const char*)unicode2char(Uint32_16toStringIP_Port(ip
,port
)));
1184 printf("Packet dump:\n");
1187 CClientList::SourceList clientslist
= theApp
->clientlist
->GetClientsByIP(ip
);
1188 if (!clientslist
.empty()) {
1189 for (CClientList::SourceList::iterator it
= clientslist
.begin(); it
!= clientslist
.end(); ++it
) {
1190 printf("Ip Matches: %s\n",(const char*)unicode2char((*it
)->GetClientFullInfo()));
1193 printf("No ip match, trying to create a client connection:\n");
1194 printf("Trying port %d\n", port
- 10);
1195 CUpDownClient
* client
= new CUpDownClient(port
-10,kad_ip
,0,0,NULL
,false,false);
1196 client
->SetConnectionReason(wxT("Error on ") + place
);
1197 client
->TryToConnect(true);
1200 // No need for warnings for the rest of us.
1208 // File_checked_for_headers