Bug Summary

File:rootdir/src/BaseClient.cpp
Warning:line 1715, column 5
Potential leak of memory pointed to by 'packet'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name BaseClient.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -D USE_WX_EXTENSIONS -I /usr/include/upnp -D ENABLE_UPNP=1 -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D ENABLE_IP2COUNTRY=1 -I ./libs -I libs -I ./include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-05-184004-17430-1 -x c++ BaseClient.cpp
1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24//
25
26#include <wx/wx.h>
27#include <wx/mstream.h>
28#include <wx/tokenzr.h>
29
30#include "updownclient.h" // Needed for CUpDownClient
31#include "SharedFileList.h" // Needed for CSharedFileList
32
33#include <protocol/Protocols.h>
34#include <protocol/ed2k/Client2Client/TCP.h>
35#include <protocol/ed2k/ClientSoftware.h>
36#include <protocol/kad/Client2Client/UDP.h>
37#include <protocol/kad2/Constants.h>
38#include <protocol/kad2/Client2Client/TCP.h>
39#include <protocol/kad2/Client2Client/UDP.h>
40
41#include <common/ClientVersion.h>
42
43#include <tags/ClientTags.h>
44
45#include <zlib.h> // Needed for inflateEnd
46
47#include <common/Format.h> // Needed for CFormat
48
49#include "SearchList.h" // Needed for CSearchList
50#include "DownloadQueue.h" // Needed for CDownloadQueue
51#include "UploadQueue.h" // Needed for CUploadQueue
52#include "IPFilter.h" // Needed for CIPFilter
53#include "ServerConnect.h" // Needed for CServerConnect
54#include "ClientCredits.h" // Needed for CClientCredits
55#include "ClientCreditsList.h" // Needed for CClientCreditsList
56#include "Server.h" // Needed for CServer
57#include "Preferences.h" // Needed for CPreferences
58#include "MemFile.h" // Needed for CMemFile
59#include "Packet.h" // Needed for CPacket
60#include "Friend.h" // Needed for CFriend
61#include "ClientList.h" // Needed for CClientList
62#ifndef AMULE_DAEMON
63#include "amuleDlg.h" // Needed for CamuleDlg
64#include "CaptchaDialog.h" // Needed for CCaptchaDialog
65#include "CaptchaGenerator.h"
66#include "ChatWnd.h" // Needed for CChatWnd
67#endif
68#include "amule.h" // Needed for theApp
69#include "PartFile.h" // Needed for CPartFile
70#include "ClientTCPSocket.h" // Needed for CClientTCPSocket
71#include "ListenSocket.h" // Needed for CListenSocket
72#include "FriendList.h" // Needed for CFriendList
73#include "Statistics.h" // Needed for theStats
74#include "ClientUDPSocket.h"
75#include "Logger.h"
76#include "DataToText.h" // Needed for GetSoftName()
77#include "GuiEvents.h" // Needed for Notify_
78#include "ServerList.h" // For CServerList
79
80#include "kademlia/kademlia/Kademlia.h"
81#include "kademlia/kademlia/Prefs.h"
82#include "kademlia/kademlia/Search.h"
83#include "kademlia/kademlia/UDPFirewallTester.h"
84#include "kademlia/routing/RoutingZone.h"
85
86
87//#define __PACKET_DEBUG__
88
89
90// some client testing variables
91static wxString crash_name = wxT("[Invalid User Name]")L"[Invalid User Name]";
92static wxString empty_name = wxT("[Empty User Name]")L"[Empty User Name]";
93
94// members of CUpDownClient
95// which are used by down and uploading functions
96
97
98CUpDownClient::CUpDownClient(CClientTCPSocket* sender)
99{
100#ifdef __DEBUG__
101 m_socket = NULL__null;
102 SetSocket(sender);
103#else
104 m_socket = sender;
105#endif
106 Init();
107}
108
109CUpDownClient::CUpDownClient(uint16 in_port, uint32 in_userid, uint32 in_serverip, uint16 in_serverport, CPartFile* in_reqfile, bool ed2kID, bool checkfriend)
110{
111 m_socket = NULL__null;
112 Init();
113 m_nUserPort = in_port;
114
115 if(ed2kID && !IsLowID(in_userid)) {
116 SetUserIDHybrid( wxUINT32_SWAP_ALWAYS(in_userid)((wxUint32) ( (((wxUint32) (in_userid) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (in_userid) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (in_userid) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (in_userid) & (wxUint32) 0xff000000U
) >> 24)))
);
117 } else {
118 SetUserIDHybrid( in_userid);
119 }
120
121 //If highID and ED2K source, incoming ID and IP are equal..
122 //If highID and Kad source, incoming IP needs swap for the IP
123
124 if (!HasLowID()) {
125 if (ed2kID) {
126 m_nConnectIP = in_userid;
127 } else {
128 m_nConnectIP = wxUINT32_SWAP_ALWAYS(in_userid)((wxUint32) ( (((wxUint32) (in_userid) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (in_userid) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (in_userid) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (in_userid) & (wxUint32) 0xff000000U
) >> 24)))
;
129 }
130 // Will be on right endianness now
131 m_FullUserIP = m_nConnectIP;
132 }
133
134 m_dwServerIP = in_serverip;
135 m_nServerPort = in_serverport;
136 SetRequestFile( in_reqfile );
137 ReGetClientSoft();
138
139 if (checkfriend) {
140 if ((m_Friend = theApp->friendlist->FindFriend(CMD4Hash(), m_dwUserIP, m_nUserPort)) != NULL__null){
141 m_Friend->LinkClient(CCLIENTREF(this, wxT("CUpDownClient::CUpDownClient m_Friend->LinkClient"))CClientRef(this));
142 } else{
143 // avoid that an unwanted client instance keeps a friend slot
144 m_bFriendSlot = false;
145 }
146 }
147
148}
149
150void CUpDownClient::Init()
151{
152 m_linked = 0;
153#ifdef DEBUG_ZOMBIE_CLIENTS
154 m_linkedDebug = false;
155#endif
156 m_bAddNextConnect = false;
157 credits = NULL__null;
158 m_byChatstate = MS_NONE;
159 m_nKadState = KS_NONE;
160 m_nChatCaptchaState = CA_NONE;
161 m_cShowDR = 0;
162 m_reqfile = NULL__null; // No file required yet
163 m_nTransferredUp = 0;
164 m_cSendblock = 0;
165 m_cAsked = 0;
166 msReceivedPrev = 0;
167 kBpsDown = 0.0;
168 bytesReceivedCycle = 0;
169 m_nServerPort = 0;
170 m_iFileListRequested = 0;
171 m_dwLastUpRequest = 0;
172 m_bEmuleProtocol = false;
173 m_bCompleteSource = false;
174 m_bFriendSlot = false;
175 m_bCommentDirty = false;
176 m_bReaskPending = false;
177 m_bUDPPending = false;
178 m_nUserPort = 0;
179 m_nPartCount = 0;
180 m_dwLastAskedTime = 0;
181 m_nDownloadState = DS_NONE;
182 m_dwUploadTime = 0;
183 m_nTransferredDown = 0;
184 m_nUploadState = US_NONE;
185 m_dwLastBlockReceived = 0;
186 m_bUnicodeSupport = false;
187
188 m_fSentOutOfPartReqs = 0;
189 m_nCurQueueSessionPayloadUp = 0;
190 m_addedPayloadQueueSession = 0;
191 m_nUpDatarate = 0;
192 m_nSumForAvgUpDataRate = 0;
193
194 m_nRemoteQueueRank = 0;
195 m_nOldRemoteQueueRank = 0;
196 m_dwLastSourceRequest = 0;
197 m_dwLastSourceAnswer = 0;
198 m_dwLastAskedForSources = 0;
199
200 m_SecureIdentState = IS_UNAVAILABLE;
201 m_dwLastSignatureIP = 0;
202
203 m_byInfopacketsReceived = IP_NONE;
204
205 m_bIsHybrid = false;
206 m_bIsML = false;
207 m_Friend = NULL__null;
208 m_iRating = 0;
209 m_nCurSessionUp = 0;
210 m_clientSoft=SO_UNKNOWN;
211
212 m_bRemoteQueueFull = false;
213 m_HasValidHash = false;
214 SetWaitStartTime();
215
216 m_fHashsetRequesting = 0;
217 m_fSharedDirectories = 0;
218 m_lastPartAsked = 0xffff;
219 m_nUpCompleteSourcesCount= 0;
220 m_waitingPosition = 0;
221 m_score = 0;
222 m_lastRefreshedDLDisplay = 0;
223 m_bHelloAnswerPending = false;
224 m_fSentCancelTransfer = 0;
225 m_Aggressiveness = 0;
226 m_LastFileRequest = 0;
227
228 m_clientState = CS_NEW;
229
230 ClearHelloProperties();
231
232 m_pReqFileAICHHash = NULL__null;
233 m_fSupportsAICH = 0;
234 m_fAICHRequested = 0;
235 m_fSupportsLargeFiles = 0;
236 m_fExtMultiPacket = 0;
237 m_fIsSpammer = 0;
238
239 m_dwUserIP = 0;
240 m_nConnectIP = 0;
241 m_dwServerIP = 0;
242
243 m_fNeedOurPublicIP = false;
244 m_bHashsetRequested = false;
245
246 m_lastDownloadingPart = 0;
247
248 m_uploadingfile = NULL__null;
249
250 m_OSInfo_sent = false;
251
252 /* Kad stuff */
253 SetBuddyID(NULL__null);
254 m_nBuddyIP = 0;
255 m_nBuddyPort = 0;
256 m_nUserIDHybrid = 0;
257
258 m_nSourceFrom = SF_NONE;
259
260 if (m_socket) {
261 SetIP(m_socket->GetPeerInt());
262 } else {
263 SetIP(0);
264 }
265
266 /* Statistics */
267 m_lastClientSoft = (uint32)(-1);
268 m_lastClientVersion = 0;
269
270 /* Creation time (for buddies timeout) */
271 m_nCreationTime = ::GetTickCount();
272
273 m_MaxBlockRequests = STANDARD_BLOCKS_REQUEST3; // Safe starting amount
274
275 m_last_block_start = 0;
276 m_lastaverage = 0;
277
278 SetLastBuddyPingPongTime();
279 m_fRequestsCryptLayer = 0;
280 m_fSupportsCryptLayer = 0;
281 m_fRequiresCryptLayer = 0;
282 m_fSupportsSourceEx2 = 0;
283 m_fSupportsCaptcha = 0;
284 m_fDirectUDPCallback = 0;
285 m_dwDirectCallbackTimeout = 0;
286
287 m_hasbeenobfuscatinglately = false;
288
289 m_cCaptchasSent = 0;
290 m_cMessagesReceived = 0;
291 m_cMessagesSent = 0;
292
293}
294
295
296CUpDownClient::~CUpDownClient()
297{
298 #ifdef __DEBUG__
299 if (!connection_reason.IsEmpty()) {
300 AddDebugLogLineN(logClient, wxT("Client to check for ") + connection_reason + wxT(" was deleted without connection."))do {} while (false);
301 }
302 #endif
303
304
305 if (m_lastClientSoft == SO_UNKNOWN) {
306 theStats::RemoveUnknownClient();
307 } else if (m_lastClientSoft != (uint32)(-1)) {
308 theStats::RemoveKnownClient(m_lastClientSoft, m_lastClientVersion, m_lastOSInfo);
309 }
310
311 // Indicate that we are not anymore on stats
312 m_lastClientSoft = (uint32)(-1);
313
314 // The socket should have been removed in Safe_Delete, but it
315 // doesn't hurt to have an extra check.
316 if (m_socket) {
317 m_socket->Safe_Delete();
318 // Paranoia
319 SetSocket(NULL__null);
320 }
321
322 ClearUploadBlockRequests();
323 ClearDownloadBlockRequests();
324
325 DeleteContents(m_WaitingPackets_list);
326
327 // Allow detection of deleted clients that didn't go through Safe_Delete
328 m_clientState = CS_DYING;
329}
330
331
332void CUpDownClient::ClearHelloProperties()
333{
334 m_nUDPPort = 0;
335 m_byUDPVer = 0;
336 m_byDataCompVer = 0;
337 m_byEmuleVersion = 0;
338 m_bySourceExchange1Ver = 0;
339 m_byAcceptCommentVer = 0;
340 m_byExtendedRequestsVer = 0;
341 m_byCompatibleClient = 0;
342 m_nKadPort = 0;
343 m_bySupportSecIdent = 0;
344 m_bSupportsPreview = 0;
345 m_nClientVersion = 0;
346 m_fSharedDirectories = 0;
347 m_bMultiPacket = 0;
348 m_fOsInfoSupport = 0;
349 m_fValueBasedTypeTags = 0;
350 SecIdentSupRec = 0;
351 m_byKadVersion = 0;
352 m_fRequestsCryptLayer = 0;
353 m_fSupportsCryptLayer = 0;
354 m_fRequiresCryptLayer = 0;
355 m_fSupportsSourceEx2 = 0;
356 m_fSupportsCaptcha = 0;
357 m_fDirectUDPCallback = 0;
358 m_bIsHybrid = false;
359 m_bIsML = false;
360 m_fNoViewSharedFiles = true; // that's a sensible default to assume until we get the real value
361 m_bUnicodeSupport = false;
362}
363
364bool CUpDownClient::ProcessHelloPacket(const uint8_t* pachPacket, uint32 nSize)
365{
366 const CMemFile data(pachPacket,nSize);
367 uint8 hashsize = data.ReadUInt8();
368 if ( 16 != hashsize ) {
369 /*
370 * Hint: We can not accept other sizes here because:
371 * - the magic number is spread all over the source
372 * - the answer packet lacks the size field
373 */
374 throw wxString(wxT("Invalid Hello packet: Other userhash sizes than 16 are not implemented")L"Invalid Hello packet: Other userhash sizes than 16 are not implemented");
375 }
376 // eMule 0.42: reset all client properties; a client may not send a particular emule tag any longer
377 ClearHelloProperties();
378
379 return ProcessHelloTypePacket(data);
380}
381
382void CUpDownClient::Safe_Delete()
383{
384 // Because we are delaying the deletion, we might end up trying to delete
385 // it twice, however, this is normal and shouldn't trigger any failures
386 if ( m_clientState == CS_DYING ) {
387 return;
388 }
389
390 // If called from background, post an event to process it in main thread
391 if (!wxThread::IsMain()) {
392 CoreNotify_Client_Delete(CCLIENTREF(this, wxT("CUpDownClient::Safe_Delete CoreNotify_Client_Delete")))MuleNotify::DoNotify(&MuleNotify::Client_Delete, CClientRef
(this))
;
393 return;
394 }
395
396 m_clientState = CS_DYING;
397
398 // Make sure client doesn't get deleted until this method is finished
399 CClientRef ref(CCLIENTREF(this, wxT("CUpDownClient::Safe_Delete reflocker"))CClientRef(this));
400
401 // Close the socket to avoid any more connections and related events
402 if ( m_socket ) {
403 m_socket->Safe_Delete();
404 // Paranoia
405 SetSocket(NULL__null);
406 }
407
408 // Remove the client from the clientlist if we still have it
409 if ( theApp->clientlist ) {
410 theApp->clientlist->RemoveClient( this );
411 }
412
413 // Doing what RemoveClient used to do. Just to be sure...
414 if (theApp->uploadqueue) {
415 theApp->uploadqueue->RemoveFromUploadQueue(this);
416 theApp->uploadqueue->RemoveFromWaitingQueue(this);
417 }
418 if (theApp->downloadqueue) {
419 theApp->downloadqueue->RemoveSource(this);
420 }
421
422 // For security, remove it from the lists unconditionally.
423 Notify_SharedCtrlRemoveClient(ECID(), (CKnownFile*)NULL)MuleNotify::DoNotify(&MuleNotify::SharedCtrlRemoveClient,
ECID(), (CKnownFile*)__null)
;
424 Notify_SourceCtrlRemoveSource(ECID(), (CPartFile*)NULL)MuleNotify::DoNotify(&MuleNotify::SourceCtrlRemoveSource,
ECID(), (CPartFile*)__null)
;
425
426 if (IsAICHReqPending()){
427 m_fAICHRequested = FALSE0;
428 CAICHHashSet::ClientAICHRequestFailed(this);
429 }
430
431 if (m_Friend) {
432 m_Friend->UnLinkClient(); // this notifies
433 m_Friend = NULL__null;
434 }
435
436 if (m_iRating>0 || !m_strComment.IsEmpty()) {
437 m_iRating = 0;
438 m_strComment.Clear();
439 if (m_reqfile) {
440 m_reqfile->UpdateFileRatingCommentAvail();
441 }
442 }
443
444 // Ensure that source-counts gets updated in case
445 // of a source not on the download-queue
446 SetRequestFile( NULL__null );
447
448 SetUploadFileID(NULL__null);
449
450 delete m_pReqFileAICHHash;
451 m_pReqFileAICHHash = NULL__null;
452
453#ifdef DEBUG_ZOMBIE_CLIENTS
454 if (m_linked > 1) {
455 AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % ECID() % (m_linked - 1) % GetLinkedFrom())theLogger.AddLogLine(L"BaseClient.cpp", 455, true, logStandard
, CFormat(L"Client %d still linked in %d places: %s") % ECID(
) % (m_linked - 1) % GetLinkedFrom())
;
456 m_linkedDebug = true;
457 }
458#endif
459}
460
461
462bool CUpDownClient::ProcessHelloAnswer(const uint8_t* pachPacket, uint32 nSize)
463{
464 const CMemFile data(pachPacket,nSize);
465 bool bIsMule = ProcessHelloTypePacket(data);
466 m_bHelloAnswerPending = false;
467 return bIsMule;
468}
469
470bool CUpDownClient::ProcessHelloTypePacket(const CMemFile& data)
471{
472 uint32 dwEmuleTags = 0;
473
474 CMD4Hash hash = data.ReadHash();
475 SetUserHash( hash );
476 SetUserIDHybrid( data.ReadUInt32() );
477 uint16 nUserPort = data.ReadUInt16(); // hmm clientport is sent twice - why?
478 uint32 tagcount = data.ReadUInt32();
479 for (uint32 i = 0;i < tagcount; i++){
480 CTag temptag(data, true);
481 switch(temptag.GetNameID()){
482 case CT_NAME:
483 m_Username = temptag.GetStr();
484 break;
485
486 case CT_VERSION:
487 m_nClientVersion = temptag.GetInt();
488 break;
489
490 case ET_MOD_VERSION:
491 if (temptag.IsStr()) {
492 m_strModVersion = temptag.GetStr();
493 } else if (temptag.IsInt()) {
494 m_strModVersion = CFormat(wxT("ModID=%u")L"ModID=%u") % temptag.GetInt();
495 } else {
496 m_strModVersion = wxT("ModID=<Unknown>")L"ModID=<Unknown>";
497 }
498
499 break;
500
501 case CT_PORT:
502 nUserPort = temptag.GetInt();
503 break;
504
505 case CT_EMULE_UDPPORTS:
506 // 16 KAD Port
507 // 16 UDP Port
508 SetKadPort((temptag.GetInt() >> 16) & 0xFFFF);
509 m_nUDPPort = temptag.GetInt() & 0xFFFF;
510 dwEmuleTags |= 1;
511 #ifdef __PACKET_DEBUG__
512 AddLogLineNS(CFormat(wxT("Hello type packet processing with eMule ports UDP=%i KAD=%i")) % m_nUDPPort % m_nKadPort)theLogger.AddLogLine(L"BaseClient.cpp", 512, false, logStandard
, CFormat(L"Hello type packet processing with eMule ports UDP=%i KAD=%i"
) % m_nUDPPort % m_nKadPort, true)
;
513 #endif
514 break;
515
516 case CT_EMULE_BUDDYIP:
517 // 32 BUDDY IP
518 m_nBuddyIP = temptag.GetInt();
519 #ifdef __PACKET_DEBUG__
520 AddLogLineNS(CFormat(wxT("Hello type packet processing with eMule BuddyIP=%u (%s)")) % m_nBuddyIP % Uint32toStringIP(m_nBuddyIP))theLogger.AddLogLine(L"BaseClient.cpp", 520, false, logStandard
, CFormat(L"Hello type packet processing with eMule BuddyIP=%u (%s)"
) % m_nBuddyIP % Uint32toStringIP(m_nBuddyIP), true)
;
521 #endif
522 break;
523
524 case CT_EMULE_BUDDYUDP:
525 // 16 --Reserved for future use--
526 // 16 BUDDY Port
527 m_nBuddyPort = (uint16)temptag.GetInt();
528 #ifdef __PACKET_DEBUG__
529 AddLogLineNS(CFormat(wxT("Hello type packet processing with eMule BuddyPort=%u")) % m_nBuddyPort)theLogger.AddLogLine(L"BaseClient.cpp", 529, false, logStandard
, CFormat(L"Hello type packet processing with eMule BuddyPort=%u"
) % m_nBuddyPort, true)
;
530 #endif
531 break;
532
533 case CT_EMULE_MISCOPTIONS1: {
534 // 3 AICH Version (0 = not supported)
535 // 1 Unicode
536 // 4 UDP version
537 // 4 Data compression version
538 // 4 Secure Ident
539 // 4 Source Exchange
540 // 4 Ext. Requests
541 // 4 Comments
542 // 1 PeerCache supported
543 // 1 No 'View Shared Files' supported
544 // 1 MultiPacket
545 // 1 Preview
546 uint32 flags = temptag.GetInt();
547 m_fSupportsAICH = (flags >> (4*7+1)) & 0x07;
548 m_bUnicodeSupport = (flags >> 4*7) & 0x01;
549 m_byUDPVer = (flags >> 4*6) & 0x0f;
550 m_byDataCompVer = (flags >> 4*5) & 0x0f;
551 m_bySupportSecIdent = (flags >> 4*4) & 0x0f;
552 m_bySourceExchange1Ver = (flags >> 4*3) & 0x0f;
553 m_byExtendedRequestsVer = (flags >> 4*2) & 0x0f;
554 m_byAcceptCommentVer = (flags >> 4*1) & 0x0f;
555 m_fNoViewSharedFiles = (flags >> 1*2) & 0x01;
556 m_bMultiPacket = (flags >> 1*1) & 0x01;
557 m_fSupportsPreview = (flags >> 1*0) & 0x01;
558 dwEmuleTags |= 2;
559 #ifdef __PACKET_DEBUG__
560 AddLogLineNS(wxT("Hello type packet processing with eMule Misc Options:"))theLogger.AddLogLine(L"BaseClient.cpp", 560, false, logStandard
, L"Hello type packet processing with eMule Misc Options:", true
)
;
561 AddLogLineNS(CFormat(wxT("m_byUDPVer = %i")) % m_byUDPVer)theLogger.AddLogLine(L"BaseClient.cpp", 561, false, logStandard
, CFormat(L"m_byUDPVer = %i") % m_byUDPVer, true)
;
562 AddLogLineNS(CFormat(wxT("m_byDataCompVer = %i")) % m_byDataCompVer)theLogger.AddLogLine(L"BaseClient.cpp", 562, false, logStandard
, CFormat(L"m_byDataCompVer = %i") % m_byDataCompVer, true)
;
563 AddLogLineNS(CFormat(wxT("m_bySupportSecIdent = %i")) % m_bySupportSecIdent)theLogger.AddLogLine(L"BaseClient.cpp", 563, false, logStandard
, CFormat(L"m_bySupportSecIdent = %i") % m_bySupportSecIdent,
true)
;
564 AddLogLineNS(CFormat(wxT("m_bySourceExchangeVer = %i")) % m_bySourceExchange1Ver)theLogger.AddLogLine(L"BaseClient.cpp", 564, false, logStandard
, CFormat(L"m_bySourceExchangeVer = %i") % m_bySourceExchange1Ver
, true)
;
565 AddLogLineNS(CFormat(wxT("m_byExtendedRequestsVer = %i")) % m_byExtendedRequestsVer)theLogger.AddLogLine(L"BaseClient.cpp", 565, false, logStandard
, CFormat(L"m_byExtendedRequestsVer = %i") % m_byExtendedRequestsVer
, true)
;
566 AddLogLineNS(CFormat(wxT("m_byAcceptCommentVer = %i")) % m_byAcceptCommentVer)theLogger.AddLogLine(L"BaseClient.cpp", 566, false, logStandard
, CFormat(L"m_byAcceptCommentVer = %i") % m_byAcceptCommentVer
, true)
;
567 AddLogLineNS(CFormat(wxT("m_fNoViewSharedFiles = %i")) % m_fNoViewSharedFiles)theLogger.AddLogLine(L"BaseClient.cpp", 567, false, logStandard
, CFormat(L"m_fNoViewSharedFiles = %i") % m_fNoViewSharedFiles
, true)
;
568 AddLogLineNS(CFormat(wxT("m_bMultiPacket = %i")) % m_bMultiPacket)theLogger.AddLogLine(L"BaseClient.cpp", 568, false, logStandard
, CFormat(L"m_bMultiPacket = %i") % m_bMultiPacket, true)
;
569 AddLogLineNS(CFormat(wxT("m_fSupportsPreview = %i")) % m_fSharedDirectories)theLogger.AddLogLine(L"BaseClient.cpp", 569, false, logStandard
, CFormat(L"m_fSupportsPreview = %i") % m_fSharedDirectories,
true)
;
570 AddLogLineNS(wxT("That's all."))theLogger.AddLogLine(L"BaseClient.cpp", 570, false, logStandard
, L"That's all.", true)
;
571 #endif
572 SecIdentSupRec += 1;
573 break;
574 }
575
576 case CT_EMULE_MISCOPTIONS2:
577 // 19 Reserved
578 // 1 Direct UDP Callback supported and available
579 // 1 Supports ChatCaptchas
580 // 1 Supports SourceExachnge2 Packets, ignores SX1 Packet Version
581 // 1 Requires CryptLayer
582 // 1 Requests CryptLayer
583 // 1 Supports CryptLayer
584 // 1 Reserved (ModBit)
585 // 1 Ext Multipacket (Hash+Size instead of Hash)
586 // 1 Large Files (includes support for 64bit tags)
587 // 4 Kad Version - will go up to version 15 only (may need to add another field at some point in the future)
588 m_fDirectUDPCallback = (temptag.GetInt() >> 12) & 0x01;
589 m_fSupportsCaptcha = (temptag.GetInt() >> 11) & 0x01;
590 m_fSupportsSourceEx2 = (temptag.GetInt() >> 10) & 0x01;
591 m_fRequiresCryptLayer = (temptag.GetInt() >> 9) & 0x01;
592 m_fRequestsCryptLayer = (temptag.GetInt() >> 8) & 0x01;
593 m_fSupportsCryptLayer = (temptag.GetInt() >> 7) & 0x01;
594 // reserved 1
595 m_fExtMultiPacket = (temptag.GetInt() >> 5) & 0x01;
596 m_fSupportsLargeFiles = (temptag.GetInt() >> 4) & 0x01;
597 m_byKadVersion = (temptag.GetInt() >> 0) & 0x0f;
598 dwEmuleTags |= 8;
599
600 m_fRequestsCryptLayer &= m_fSupportsCryptLayer;
601 m_fRequiresCryptLayer &= m_fRequestsCryptLayer;
602
603 #ifdef __PACKET_DEBUG__
604 AddLogLineNS(wxT("Hello type packet processing with eMule Misc Options 2:"))theLogger.AddLogLine(L"BaseClient.cpp", 604, false, logStandard
, L"Hello type packet processing with eMule Misc Options 2:",
true)
;
605 AddLogLineNS(CFormat(wxT(" m_fDirectUDPCallback = %i")) % m_fDirectUDPCallback)theLogger.AddLogLine(L"BaseClient.cpp", 605, false, logStandard
, CFormat(L" m_fDirectUDPCallback = %i") % m_fDirectUDPCallback
, true)
;
606 AddLogLineNS(CFormat(wxT(" m_fSupportsCaptcha = %i")) % m_fSupportsCaptcha)theLogger.AddLogLine(L"BaseClient.cpp", 606, false, logStandard
, CFormat(L" m_fSupportsCaptcha = %i") % m_fSupportsCaptcha,
true)
;
607 AddLogLineNS(CFormat(wxT(" m_fSupportsSourceEx2 = %i")) % m_fSupportsSourceEx2)theLogger.AddLogLine(L"BaseClient.cpp", 607, false, logStandard
, CFormat(L" m_fSupportsSourceEx2 = %i") % m_fSupportsSourceEx2
, true)
;
608 AddLogLineNS(CFormat(wxT(" m_fRequiresCryptLayer = %i")) % m_fRequiresCryptLayer)theLogger.AddLogLine(L"BaseClient.cpp", 608, false, logStandard
, CFormat(L" m_fRequiresCryptLayer = %i") % m_fRequiresCryptLayer
, true)
;
609 AddLogLineNS(CFormat(wxT(" m_fRequestsCryptLayer = %i")) % m_fRequestsCryptLayer)theLogger.AddLogLine(L"BaseClient.cpp", 609, false, logStandard
, CFormat(L" m_fRequestsCryptLayer = %i") % m_fRequestsCryptLayer
, true)
;
610 AddLogLineNS(CFormat(wxT(" m_fSupportsCryptLayer = %i")) % m_fSupportsCryptLayer)theLogger.AddLogLine(L"BaseClient.cpp", 610, false, logStandard
, CFormat(L" m_fSupportsCryptLayer = %i") % m_fSupportsCryptLayer
, true)
;
611 AddLogLineNS(CFormat(wxT(" m_fExtMultiPacket = %i")) % m_fExtMultiPacket)theLogger.AddLogLine(L"BaseClient.cpp", 611, false, logStandard
, CFormat(L" m_fExtMultiPacket = %i") % m_fExtMultiPacket, true
)
;
612 AddLogLineNS(CFormat(wxT(" m_fSupportsLargeFiles = %i")) % m_fSupportsLargeFiles)theLogger.AddLogLine(L"BaseClient.cpp", 612, false, logStandard
, CFormat(L" m_fSupportsLargeFiles = %i") % m_fSupportsLargeFiles
, true)
;
613 AddLogLineNS(CFormat(wxT(" KadVersion = %u")) % m_byKadVersion)theLogger.AddLogLine(L"BaseClient.cpp", 613, false, logStandard
, CFormat(L" KadVersion = %u") % m_byKadVersion, true)
;
614 AddLogLineNS(wxT("That's all."))theLogger.AddLogLine(L"BaseClient.cpp", 614, false, logStandard
, L"That's all.", true)
;
615 #endif
616 break;
617
618 // Special tag for Compat. Clients Misc options.
619 case CT_EMULECOMPAT_OPTIONS:
620 // 1 Operative System Info
621 // 1 Value-based-type int tags (experimental!)
622 m_fValueBasedTypeTags = (temptag.GetInt() >> 1*1) & 0x01;
623 m_fOsInfoSupport = (temptag.GetInt() >> 1*0) & 0x01;
624 break;
625
626 case CT_EMULE_VERSION:
627 // 8 Compatible Client ID
628 // 7 Mjr Version (Doesn't really matter..)
629 // 7 Min Version (Only need 0-99)
630 // 3 Upd Version (Only need 0-5)
631 // 7 Bld Version (Only need 0-99)
632 m_byCompatibleClient = (temptag.GetInt() >> 24);
633 m_nClientVersion = temptag.GetInt() & 0x00ffffff;
634 m_byEmuleVersion = 0x99;
635 m_fSharedDirectories = 1;
636 dwEmuleTags |= 4;
637 break;
638 }
639 }
640
641 m_nUserPort = nUserPort;
642 m_dwServerIP = data.ReadUInt32();
643 m_nServerPort = data.ReadUInt16();
644 // Hybrid now has an extra uint32.. What is it for?
645 // Also, many clients seem to send an extra 6? These are not eDonkeys or Hybrids..
646 if ( data.GetLength() - data.GetPosition() == sizeof(uint32) ) {
647 uint32 test = data.ReadUInt32();
648 /*if (test == 'KDLM') below kdlm is converted to ascii values.
649 This fixes a warning with gcc 3.4.
650 K=4b D=44 L=4c M=4d
651 */
652 if (test == 0x4b444c4d) { //if it's == "KDLM"
653 m_bIsML=true;
654 } else{
655 m_bIsHybrid = true;
656 m_fSharedDirectories = 1;
657 }
658 }
659
660 if (m_socket) {
661 SetIP(m_socket->GetPeerInt());
662 } else {
663 throw wxString(wxT("Huh, socket failure. Avoided crash this time.")L"Huh, socket failure. Avoided crash this time.");
664 }
665
666 if (thePrefs::AddServersFromClient()) {
667 CServer* addsrv = new CServer(m_nServerPort, Uint32toStringIP(m_dwServerIP));
668 addsrv->SetListName(addsrv->GetAddress());
669 if (!theApp->AddServer(addsrv)) {
670 delete addsrv;
671 }
672 }
673
674 //(a)If this is a highID user, store the ID in the Hybrid format.
675 //(b)Some older clients will not send a ID, these client are HighID users that are not connected to a server.
676 //(c)Kad users with a *.*.*.0 IPs will look like a lowID user they are actually a highID user.. They can be detected easily
677 //because they will send a ID that is the same as their IP..
678 if(!HasLowID() || m_nUserIDHybrid == 0 || m_nUserIDHybrid == m_dwUserIP ) {
679 SetUserIDHybrid(wxUINT32_SWAP_ALWAYS(m_dwUserIP)((wxUint32) ( (((wxUint32) (m_dwUserIP) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (m_dwUserIP) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (m_dwUserIP) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (m_dwUserIP) & (wxUint32) 0xff000000U
) >> 24)))
);
680 }
681
682 // get client credits
683 CClientCredits* pFoundCredits = theApp->clientcredits->GetCredit(m_UserHash);
684 if (credits == NULL__null){
685 credits = pFoundCredits;
686 if (!theApp->clientlist->ComparePriorUserhash(m_dwUserIP, m_nUserPort, pFoundCredits)){
687 AddDebugLogLineN( logClient, CFormat( wxT("Client: %s (%s) Banreason: Userhash changed (Found in TrackedClientsList)") ) % GetUserName() % GetFullIP() )do {} while (false);
688 Ban();
689 }
690 } else if (credits != pFoundCredits){
691 // userhash change ok, however two hours "waittime" before it can be used
692 credits = pFoundCredits;
693 AddDebugLogLineN( logClient, CFormat( wxT("Client: %s (%s) Banreason: Userhash changed") ) % GetUserName() % GetFullIP() )do {} while (false);
694 Ban();
695 }
696
697 if ((m_Friend = theApp->friendlist->FindFriend(m_UserHash, m_dwUserIP, m_nUserPort)) != NULL__null){
698 m_Friend->LinkClient(CCLIENTREF(this, wxT("CUpDownClient::ProcessHelloTypePacket m_Friend->LinkClient"))CClientRef(this));
699 } else{
700 // avoid that an unwanted client instance keeps a friend slot
701 SetFriendSlot(false);
702 }
703
704
705 ReGetClientSoft();
706
707 m_byInfopacketsReceived |= IP_EDONKEYPROTPACK;
708
709 // check if at least CT_EMULEVERSION was received, all other tags are optional
710 bool bIsMule = (dwEmuleTags & 0x04) == 0x04;
711 if (bIsMule) {
712 m_bEmuleProtocol = true;
713 m_byInfopacketsReceived |= IP_EMULEPROTPACK;
714 }
715
716 if (GetKadPort() && GetKadVersion() > 1) {
717 Kademlia::CKademlia::Bootstrap(wxUINT32_SWAP_ALWAYS(GetIP())((wxUint32) ( (((wxUint32) (GetIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetIP()) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (GetIP()) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (GetIP()) & (wxUint32) 0xff000000U
) >> 24)))
, GetKadPort());
718 }
719
720 return bIsMule;
721}
722
723
724bool CUpDownClient::SendHelloPacket()
725{
726 wxCHECK(m_socket != NULL, true)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 726, __FUNCTION__, "\"m_socket != __null\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); return true
; } struct wxDummyCheckStruct726
;
727
728 // if IP is filtered, don't greet him but disconnect...
729 if (theApp->ipfilter->IsFiltered(m_socket->GetPeerInt())) {
730 if (Disconnected(wxT("IPFilter")L"IPFilter")) {
731 Safe_Delete();
732 return false;
733 }
734 return true;
735 }
736
737 CMemFile data(128);
738 data.WriteUInt8(16); // size of userhash
739 SendHelloTypePacket(&data);
740
741 CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_HELLO);
742 theStats::AddUpOverheadOther(packet->GetPacketSize());
743 SendPacket(packet,true);
744 m_bHelloAnswerPending = true;
745 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_HELLO to ") + GetFullIP() )do {} while (false);
746 return true;
747}
748
749void CUpDownClient::SendMuleInfoPacket(bool bAnswer, bool OSInfo)
750{
751 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 751, __FUNCTION__, "\"m_socket != __null\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); return; }
struct wxDummyCheckStruct751
;
752
753 CPacket* packet = NULL__null;
754 CMemFile data;
755
756 data.WriteUInt8(CURRENT_VERSION_SHORT0x47);
757
758 if (OSInfo) {
759
760 // Special MuleInfo packet for clients supporting it.
761 // This means aMule >= 2.0.0 and Hydranode
762
763 // Violently mark it as special Mule Info packet
764 // Sending this makes non-supporting-osinfo clients to refuse to read this
765 // packet. Anyway, this packet should NEVER get to non-supporting clients.
766
767 data.WriteUInt8(/*EMULE_PROTOCOL*/ 0xFF);
768
769 data.WriteUInt32(1); // One Tag (OS_INFO)
770
771 CTagString tag1(ET_OS_INFO,theApp->GetOSType());
772 tag1.WriteTagToFile(&data);
773
774 m_OSInfo_sent = true; // So we don't send it again
775
776 } else {
777
778 // Normal MuleInfo packet
779
780 // Kry - There's no point on upgrading to VBT tags here
781 // as no client supporting it uses mule info packet.
782
783 data.WriteUInt8(EMULE_PROTOCOL0x01);
784
785 // Tag number
786 data.WriteUInt32(9);
787
788 CTagInt32 tag1(ET_COMPRESSION,1);
789 tag1.WriteTagToFile(&data);
790 CTagInt32 tag2(ET_UDPVER,4);
791 tag2.WriteTagToFile(&data);
792 CTagInt32 tag3(ET_UDPPORT, thePrefs::GetEffectiveUDPPort());
793 tag3.WriteTagToFile(&data);
794 CTagInt32 tag4(ET_SOURCEEXCHANGE,3);
795 tag4.WriteTagToFile(&data);
796 CTagInt32 tag5(ET_COMMENTS,1);
797 tag5.WriteTagToFile(&data);
798 CTagInt32 tag6(ET_EXTENDEDREQUEST,2);
799 tag6.WriteTagToFile(&data);
800
801 uint32 dwTagValue = (theApp->CryptoAvailable() ? 3 : 0);
802 // Kry - Needs the preview code from eMule
803 /*
804 // set 'Preview supported' only if 'View Shared Files' allowed
805 if (thePrefs::CanSeeShares() != vsfaNobody) {
806 dwTagValue |= 128;
807 }
808 */
809 CTagInt32 tag7(ET_FEATURES, dwTagValue);
810 tag7.WriteTagToFile(&data);
811
812 CTagInt32 tag8(ET_COMPATIBLECLIENT,SO_AMULE);
813 tag8.WriteTagToFile(&data);
814
815 // Support for tag ET_MOD_VERSION
816 wxString mod_name(MOD_VERSION_LONGL"aMule SVN");
817 CTagString tag9(ET_MOD_VERSION, mod_name);
818 tag9.WriteTagToFile(&data);
819 // Maella end
820
821 }
822
823 packet = new CPacket(data, OP_EMULEPROT, (bAnswer ? OP_EMULEINFOANSWER : OP_EMULEINFO));
824
825 if (m_socket) {
826 theStats::AddUpOverheadOther(packet->GetPacketSize());
827 SendPacket(packet,true,true);
828
829#ifdef __DEBUG__
830 if (!bAnswer) {
831 if (!OSInfo) {
832 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_EMULEINFO to ") + GetFullIP() )do {} while (false);
833 } else {
834 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_EMULEINFO/OS_INFO to ") + GetFullIP() )do {} while (false);
835 }
836 } else {
837 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_EMULEINFOANSWER to ") + GetFullIP() )do {} while (false);
838 }
839#endif
840 }
841}
842
843bool CUpDownClient::ProcessMuleInfoPacket(const uint8_t* pachPacket, uint32 nSize)
844{
845 uint8 protocol_version;
846
847 const CMemFile data(pachPacket,nSize);
848
849 // The version number part of this packet will soon be useless since
850 // it is only able to go to v.99. Why the version is a uint8 and why
851 // it was not done as a tag like the eDonkey hello packet is not known.
852 // Therefore, sooner or later, we are going to have to switch over to
853 // using the eDonkey hello packet to set the version. No sense making
854 // a third value sent for versions.
855 uint8 mule_version = data.ReadUInt8();
856 protocol_version = data.ReadUInt8();
857 uint32 tagcount = data.ReadUInt32();
858 if (protocol_version == 0xFF) {
859 // OS Info supporting clients sending a recycled Mule info packet
860 for (uint32 i = 0;i < tagcount; i++){
861 CTag temptag(data, true);
862 switch(temptag.GetNameID()){
863 case ET_OS_INFO:
864 // Special tag, only supporting clients (aMule/Hydranode)
865 // It was recycled from a mod's tag, so if the other side
866 // is not supporting OS Info, we're seriously fucked up :)
867 m_sClientOSInfo = temptag.GetStr();
868
869 // If we didn't send our OSInfo to this client, just send it
870 if (!m_OSInfo_sent) {
871 SendMuleInfoPacket(false,true);
872 }
873
874 UpdateStats();
875
876 break;
877
878 // Your ad... er... I mean TAG, here
879
880 default:
881 break;
882 }
883 }
884 } else {
885 // Old eMule sending tags
886 m_byCompatibleClient = 0;
887 m_byEmuleVersion = mule_version;
888
889 if( m_byEmuleVersion == 0x2B ) {
890 m_byEmuleVersion = 0x22;
891 }
892
893 if (!(m_bEmuleProtocol = (protocol_version == EMULE_PROTOCOL0x01))) {
894 return false;
895 }
896
897 for (uint32 i = 0;i < tagcount; i++){
898 CTag temptag(data, false);
899 switch(temptag.GetNameID()){
900 case ET_COMPRESSION:
901 // Bits 31- 8: 0 - reserved
902 // Bits 7- 0: data compression version
903 m_byDataCompVer = temptag.GetInt();
904 break;
905
906 case ET_UDPPORT:
907 // Bits 31-16: 0 - reserved
908 // Bits 15- 0: UDP port
909 m_nUDPPort = temptag.GetInt();
910 break;
911
912 case ET_UDPVER:
913 // Bits 31- 8: 0 - reserved
914 // Bits 7- 0: UDP protocol version
915 m_byUDPVer = temptag.GetInt();
916 break;
917
918 case ET_SOURCEEXCHANGE:
919 // Bits 31- 8: 0 - reserved
920 // Bits 7- 0: source exchange protocol version
921 m_bySourceExchange1Ver = temptag.GetInt();
922 break;
923
924 case ET_COMMENTS:
925 // Bits 31- 8: 0 - reserved
926 // Bits 7- 0: comments version
927 m_byAcceptCommentVer = temptag.GetInt();
928 break;
929
930 case ET_EXTENDEDREQUEST:
931 // Bits 31- 8: 0 - reserved
932 // Bits 7- 0: extended requests version
933 m_byExtendedRequestsVer = temptag.GetInt();
934 break;
935
936 case ET_COMPATIBLECLIENT:
937 // Bits 31- 8: 0 - reserved
938 // Bits 7- 0: compatible client ID
939 m_byCompatibleClient = temptag.GetInt();
940 break;
941
942 case ET_FEATURES:
943 // Bits 31- 8: 0 - reserved
944 // Bit 7: Preview
945 // Bit 6- 0: secure identification
946 m_bySupportSecIdent = temptag.GetInt() & 3;
947 m_bSupportsPreview = (temptag.GetInt() & 128) > 0;
948 SecIdentSupRec += 2;
949 break;
950
951 case ET_MOD_VERSION:
952 if (temptag.IsStr()) {
953 m_strModVersion = temptag.GetStr();
954 } else if (temptag.IsInt()) {
955 m_strModVersion = CFormat(wxT("ModID=%u")L"ModID=%u") % temptag.GetInt();
956 } else {
957 m_strModVersion = wxT("ModID=<Unknown>")L"ModID=<Unknown>";
958 }
959
960 break;
961
962 default:
963 AddDebugLogLineN( logPacketErrors,do {} while (false)
964 CFormat( wxT("Unknown Mule tag (%s) from client: %s") )do {} while (false)
965 % temptag.GetFullInfo()do {} while (false)
966 % GetClientFullInfo()do {} while (false)
967 )do {} while (false);
968
969 break;
970 }
971 }
972
973 if( m_byDataCompVer == 0 ){
974 m_bySourceExchange1Ver = 0;
975 m_byExtendedRequestsVer = 0;
976 m_byAcceptCommentVer = 0;
977 m_nUDPPort = 0;
978 }
979
980 //implicitly supported options by older clients
981 //in the future do not use version to guess about new features
982 if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x22) {
983 m_byUDPVer = 1;
984 }
985
986 if(m_byEmuleVersion < 0x25 && m_byEmuleVersion > 0x21) {
987 m_bySourceExchange1Ver = 1;
988 }
989
990 if(m_byEmuleVersion == 0x24) {
991 m_byAcceptCommentVer = 1;
992 }
993
994 // Shared directories are requested from eMule 0.28+ because eMule 0.27 has a bug in
995 // the OP_ASKSHAREDFILESDIR handler, which does not return the shared files for a
996 // directory which has a trailing backslash.
997 if(m_byEmuleVersion >= 0x28 && !m_bIsML) {// MLdonkey currently does not support shared directories
998 m_fSharedDirectories = 1;
999 }
1000
1001 ReGetClientSoft();
1002
1003 m_byInfopacketsReceived |= IP_EMULEPROTPACK;
1004 }
1005
1006 return (protocol_version == 0xFF); // This was a OS_Info?
1007}
1008
1009
1010void CUpDownClient::SendHelloAnswer()
1011{
1012 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 1012, __FUNCTION__,
"\"m_socket != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct1012
;
1013
1014 CMemFile data(128);
1015 SendHelloTypePacket(&data);
1016 CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_HELLOANSWER);
1017 theStats::AddUpOverheadOther(packet->GetPacketSize());
1018 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_HELLOANSWER to ") + GetFullIP() )do {} while (false);
1019 SendPacket(packet,true);
1020}
1021
1022
1023void CUpDownClient::SendHelloTypePacket(CMemFile* data)
1024{
1025 data->WriteHash(thePrefs::GetUserHash());
1026 data->WriteUInt32(theApp->GetID());
1027 data->WriteUInt16(thePrefs::GetPort());
1028
1029 uint32 tagcount = 6;
1030
1031 if( theApp->clientlist->GetBuddy() && theApp->IsFirewalled() ) {
1032 tagcount += 2;
1033 }
1034 tagcount ++; // eMule misc flags 2 (kad version)
1035
1036 #ifdef __SVN__
1037 // Kry - This is the tagcount!!! Be sure to update it!!
1038 // Last update: CT_EMULECOMPAT_OPTIONS included
1039 data->WriteUInt32(tagcount + 1);
1040 #else
1041 data->WriteUInt32(tagcount); // NO MOD_VERSION
1042 #endif
1043
1044
1045 CTagString tagname(CT_NAME,thePrefs::GetUserNick());
1046 tagname.WriteTagToFile(data, utf8strRaw);
1047
1048 CTagVarInt tagversion(CT_VERSION, EDONKEYVERSION0x3c, GetVBTTags() ? 0 : 32);
1049 tagversion.WriteTagToFile(data);
1050 // eMule UDP Ports
1051
1052 uint32 kadUDPPort = 0;
1053
1054 if(Kademlia::CKademlia::IsConnected()) {
1055 if (Kademlia::CKademlia::GetPrefs()->GetExternalKadPort() != 0 && Kademlia::CKademlia::GetPrefs()->GetUseExternKadPort() && Kademlia::CUDPFirewallTester::IsVerified()) {
1056 kadUDPPort = Kademlia::CKademlia::GetPrefs()->GetExternalKadPort();
1057 } else {
1058 kadUDPPort = Kademlia::CKademlia::GetPrefs()->GetInternKadPort();
1059 }
1060 }
1061
1062 CTagVarInt tagUdpPorts(CT_EMULE_UDPPORTS, (kadUDPPort << 16) | ((uint32)thePrefs::GetEffectiveUDPPort()), GetVBTTags() ? 0 : 32);
1063 tagUdpPorts.WriteTagToFile(data);
1064
1065 if( theApp->clientlist->GetBuddy() && theApp->IsFirewalled() ) {
1066 CTagVarInt tagBuddyIP(CT_EMULE_BUDDYIP, theApp->clientlist->GetBuddy()->GetIP(), GetVBTTags() ? 0 : 32);
1067 tagBuddyIP.WriteTagToFile(data);
1068
1069 CTagVarInt tagBuddyPort(CT_EMULE_BUDDYUDP,
1070// ( RESERVED )
1071 ((uint32)theApp->clientlist->GetBuddy()->GetUDPPort() )
1072 , GetVBTTags() ? 0 : 32);
1073 tagBuddyPort.WriteTagToFile(data);
1074 }
1075
1076 // aMule Version
1077 CTagVarInt tagMuleVersion(CT_EMULE_VERSION,
1078 (SO_AMULE << 24) |
1079 make_full_ed2k_version(VERSION_MJR2, VERSION_MIN4, VERSION_UPDATE0)
1080 // | (RESERVED )
1081 , GetVBTTags() ? 0 : 32);
1082 tagMuleVersion.WriteTagToFile(data);
1083
1084
1085 // eMule Misc. Options #1
1086 const uint32 uUdpVer = 4;
1087 const uint32 uDataCompVer = 1;
1088 const uint32 uSupportSecIdent = theApp->CryptoAvailable() ? 3 : 0;
1089 const uint32 uSourceExchangeVer = 3;
1090 const uint32 uExtendedRequestsVer = 2;
1091 const uint32 uAcceptCommentVer = 1;
1092 const uint32 uNoViewSharedFiles = (thePrefs::CanSeeShares() == vsfaNobody) ? 1 : 0; // for backward compatibility this has to be a 'negative' flag
1093 const uint32 uMultiPacket = 1;
1094 const uint32 uSupportPreview = 0; // No network preview at all.
1095 const uint32 uPeerCache = 0; // No peercache for aMule, baby
1096 const uint32 uUnicodeSupport = 1;
1097 const uint32 nAICHVer = 1; // AICH is ENABLED right now.
1098
1099 CTagVarInt tagMisOptions(CT_EMULE_MISCOPTIONS1,
1100 (nAICHVer << ((4*7)+1)) |
1101 (uUnicodeSupport << 4*7) |
1102 (uUdpVer << 4*6) |
1103 (uDataCompVer << 4*5) |
1104 (uSupportSecIdent << 4*4) |
1105 (uSourceExchangeVer << 4*3) |
1106 (uExtendedRequestsVer << 4*2) |
1107 (uAcceptCommentVer << 4*1) |
1108 (uPeerCache << 1*3) |
1109 (uNoViewSharedFiles << 1*2) |
1110 (uMultiPacket << 1*1) |
1111 (uSupportPreview << 1*0)
1112 , GetVBTTags() ? 0 : 32);
1113 tagMisOptions.WriteTagToFile(data);
1114
1115 // eMule Misc. Options #2
1116 const uint32 uKadVersion = KADEMLIA_VERSION0x08;
1117 const uint32 uSupportLargeFiles = 1;
1118 const uint32 uExtMultiPacket = 1;
1119 const uint32 uReserved = 0; // mod bit
1120 const uint32 uSupportsCryptLayer = thePrefs::IsClientCryptLayerSupported() ? 1 : 0;
1121 const uint32 uRequestsCryptLayer = thePrefs::IsClientCryptLayerRequested() ? 1 : 0;
1122 const uint32 uRequiresCryptLayer = thePrefs::IsClientCryptLayerRequired() ? 1 : 0;
1123 const uint32 uSupportsSourceEx2 = 1;
1124#ifdef AMULE_DAEMON
1125// captcha for daemon/remotegui not supported for now
1126 const uint32 uSupportsCaptcha = 0;
1127#else
1128 const uint32 uSupportsCaptcha = 1;
1129#endif
1130 // direct callback is only possible if connected to kad, tcp firewalled and verified UDP open (for example on a full cone NAT)
1131 const uint32 uDirectUDPCallback = (Kademlia::CKademlia::IsRunning() && Kademlia::CKademlia::IsFirewalled()
1132 && !Kademlia::CUDPFirewallTester::IsFirewalledUDP(true) && Kademlia::CUDPFirewallTester::IsVerified()) ? 1 : 0;
1133
1134 CTagVarInt tagMisOptions2(CT_EMULE_MISCOPTIONS2,
1135// (RESERVED )
1136 (uDirectUDPCallback << 12) |
1137 (uSupportsCaptcha << 11) |
1138 (uSupportsSourceEx2 << 10) |
1139 (uRequiresCryptLayer << 9) |
1140 (uRequestsCryptLayer << 8) |
1141 (uSupportsCryptLayer << 7) |
1142 (uReserved << 6) |
1143 (uExtMultiPacket << 5) |
1144 (uSupportLargeFiles << 4) |
1145 (uKadVersion << 0)
1146 , GetVBTTags() ? 0 : 32 );
1147 tagMisOptions2.WriteTagToFile(data);
1148
1149 const uint32 nOSInfoSupport = 1; // We support OS_INFO
1150 const uint32 nValueBasedTypeTags = 0; // Experimental, disabled
1151
1152 CTagVarInt tagMisCompatOptions(CT_EMULECOMPAT_OPTIONS,
1153 (nValueBasedTypeTags << 1*1) |
1154 (nOSInfoSupport << 1*0)
1155 , GetVBTTags() ? 0 : 32);
1156
1157 tagMisCompatOptions.WriteTagToFile(data);
1158
1159#ifdef __SVN__
1160 wxString mod_name(MOD_VERSION_LONGL"aMule SVN");
1161 CTagString tagModName(ET_MOD_VERSION, mod_name);
1162 tagModName.WriteTagToFile(data);
1163#endif
1164
1165 uint32 dwIP = 0;
1166 uint16 nPort = 0;
1167 if (theApp->IsConnectedED2K()) {
1168 dwIP = theApp->serverconnect->GetCurrentServer()->GetIP();
1169 nPort = theApp->serverconnect->GetCurrentServer()->GetPort();
1170 }
1171 data->WriteUInt32(dwIP);
1172 data->WriteUInt16(nPort);
1173}
1174
1175
1176void CUpDownClient::ProcessMuleCommentPacket(const uint8_t* pachPacket, uint32 nSize)
1177{
1178 if (!m_reqfile) {
1179 throw CInvalidPacket(wxT("Comment packet for unknown file")L"Comment packet for unknown file");
1180 }
1181
1182 if (!m_reqfile->IsPartFile()) {
1183 throw CInvalidPacket(wxT("Comment packet for completed file")L"Comment packet for completed file");
1184 }
1185
1186 const CMemFile data(pachPacket, nSize);
1187
1188 uint8 rating = data.ReadUInt8();
1189 if (rating > 5) {
1190 AddDebugLogLineN( logClient, wxString(wxT("Invalid Rating for file '")) << m_clientFilename << wxT("' received: ") << rating)do {} while (false);
1191 m_iRating = 0;
1192 } else {
1193 m_iRating = rating;
1194 AddDebugLogLineN( logClient, wxString(wxT("Rating for file '")) << m_clientFilename << wxT("' received: ") << m_iRating)do {} while (false);
1195 }
1196
1197 // The comment is unicoded, with a uin32 len and safe read
1198 // (won't break if string size is < than advertised len)
1199 // Truncated to MAXFILECOMMENTLEN size
1200 m_strComment = data.ReadString((GetUnicodeSupport() != utf8strNone), 4 /* bytes (it's a uint32)*/, true).Left(MAXFILECOMMENTLEN50);
1201
1202 AddDebugLogLineN( logClient, wxString(wxT("Description for file '")) << m_clientFilename << wxT("' received: ") << m_strComment)do {} while (false);
1203
1204 // Update file rating
1205 m_reqfile->UpdateFileRatingCommentAvail();
1206}
1207
1208
1209void CUpDownClient::ClearDownloadBlockRequests()
1210{
1211 {
1212 std::list<Requested_Block_Struct*>::iterator it = m_DownloadBlocks_list.begin();
1213 for (; it != m_DownloadBlocks_list.end(); ++it) {
1214 Requested_Block_Struct* cur_block = *it;
1215
1216 if (m_reqfile){
1217 m_reqfile->RemoveBlockFromList(cur_block->StartOffset, cur_block->EndOffset);
1218 }
1219
1220 delete cur_block;
1221 }
1222
1223 m_DownloadBlocks_list.clear();
1224 }
1225
1226 {
1227 std::list<Pending_Block_Struct*>::iterator it = m_PendingBlocks_list.begin();
1228 for (; it != m_PendingBlocks_list.end(); ++it) {
1229 Pending_Block_Struct* pending = *it;
1230
1231 if (m_reqfile) {
1232 m_reqfile->RemoveBlockFromList(pending->block->StartOffset, pending->block->EndOffset);
1233 }
1234
1235 delete pending->block;
1236 // Not always allocated
1237 if (pending->zStream){
1238 inflateEnd(pending->zStream);
1239 delete pending->zStream;
1240 }
1241
1242 delete pending;
1243 }
1244
1245 m_PendingBlocks_list.clear();
1246 }
1247}
1248
1249
1250bool CUpDownClient::Disconnected(const wxString& DEBUG_ONLY(strReason), bool bFromSocket)
1251{
1252 //wxASSERT(theApp->clientlist->IsValidClient(this));
1253
1254 if (HasBeenDeleted()) {
1255 AddDebugLogLineN(logClient, wxT("Disconnected() called for already deleted client on ip ") + Uint32toStringIP(GetConnectIP()))do {} while (false);
1256 return false;
1257 }
1258
1259 // was this a direct callback?
1260 if (m_dwDirectCallbackTimeout != 0) {
1261 theApp->clientlist->RemoveDirectCallback(this);
1262 m_dwDirectCallbackTimeout = 0;
1263 theApp->clientlist->AddDeadSource(this);
1264 AddDebugLogLineN(logClient, wxT("Direct callback failed to client on ip ") + Uint32toStringIP(GetConnectIP()))do {} while (false);
1265 }
1266
1267 if (GetKadState() == KS_QUEUED_FWCHECK_UDP || GetKadState() == KS_CONNECTING_FWCHECK_UDP) {
1268 Kademlia::CUDPFirewallTester::SetUDPFWCheckResult(false, true, wxUINT32_SWAP_ALWAYS(GetConnectIP())((wxUint32) ( (((wxUint32) (GetConnectIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetConnectIP()) & (wxUint32
) 0x0000ff00U) << 8) | (((wxUint32) (GetConnectIP()) &
(wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (GetConnectIP
()) & (wxUint32) 0xff000000U) >> 24)))
, 0); // inform the tester that this test was cancelled
1269 } else if (GetKadState() == KS_FWCHECK_UDP) {
1270 Kademlia::CUDPFirewallTester::SetUDPFWCheckResult(false, false, wxUINT32_SWAP_ALWAYS(GetConnectIP())((wxUint32) ( (((wxUint32) (GetConnectIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetConnectIP()) & (wxUint32
) 0x0000ff00U) << 8) | (((wxUint32) (GetConnectIP()) &
(wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (GetConnectIP
()) & (wxUint32) 0xff000000U) >> 24)))
, 0); // inform the tester that this test has failed
1271 } else if (GetKadState() == KS_CONNECTED_BUDDY) {
1272 AddDebugLogLineN(logClient, wxT("Buddy client disconnected - ") + strReason)do {} while (false);
1273 }
1274
1275 //If this is a KAD client object, just delete it!
1276 SetKadState(KS_NONE);
1277
1278 if (GetUploadState() == US_UPLOADING) {
1279 // sets US_NONE
1280 theApp->uploadqueue->RemoveFromUploadQueue(this);
1281 }
1282
1283 if (GetDownloadState() == DS_DOWNLOADING) {
1284 SetDownloadState(DS_ONQUEUE);
1285 } else {
1286 // ensure that all possible block requests are removed from the partfile
1287 ClearDownloadBlockRequests();
1288
1289 if (GetDownloadState() == DS_CONNECTED) {
1290 // successfully connected, but probably didn't respond to our filerequest
1291 theApp->clientlist->AddDeadSource(this);
1292 theApp->downloadqueue->RemoveSource(this);
1293 }
1294 }
1295
1296 // we had still an AICH request pending, handle it
1297 if (IsAICHReqPending()) {
1298 m_fAICHRequested = FALSE0;
1299 CAICHHashSet::ClientAICHRequestFailed(this);
1300 }
1301
1302 // The remote client does not have to answer with OP_HASHSETANSWER *immediately*
1303 // after we've sent OP_HASHSETREQUEST. It may occur that a (buggy) remote client
1304 // is sending use another OP_FILESTATUS which would let us change to DL-state to DS_ONQUEUE.
1305 if (((GetDownloadState() == DS_REQHASHSET) || m_fHashsetRequesting) && (m_reqfile)) {
1306 m_reqfile->SetHashSetNeeded(true);
1307 }
1308
1309 SourceItemType source_type = UNAVAILABLE_SOURCE;
1310 SourceItemType peer_type = UNAVAILABLE_SOURCE;
1311
1312 //check if this client is needed in any way, if not delete it
1313 bool bDelete = true;
1314 switch (m_nUploadState) {
1315 case US_ONUPLOADQUEUE:
1316 bDelete = false;
1317 peer_type = AVAILABLE_SOURCE;
1318 break;
1319 };
1320
1321 switch (m_nDownloadState) {
1322 case DS_ONQUEUE:
1323 source_type = A4AF_SOURCE; // Will be checked.
1324 /* fall through */
1325 case DS_TOOMANYCONNS:
1326 case DS_NONEEDEDPARTS:
1327 case DS_LOWTOLOWIP:
1328 bDelete = false;
1329 break;
1330 };
1331
1332 switch (m_nUploadState) {
1333 case US_CONNECTING:
1334 case US_WAITCALLBACK:
1335 case US_ERROR:
1336 theApp->clientlist->AddDeadSource(this);
1337 bDelete = true;
1338 };
1339
1340 switch (m_nDownloadState) {
1341 case DS_CONNECTING:
1342 case DS_WAITCALLBACK:
1343 case DS_ERROR:
1344 case DS_BANNED:
1345 theApp->clientlist->AddDeadSource(this);
1346 bDelete = true;
1347 };
1348
1349
1350 // We keep chat partners in any case
1351 if (GetChatState() != MS_NONE) {
1352 bDelete = false;
1353 m_pendingMessage.Clear();
1354 Notify_ChatConnResult(false,GUI_ID(GetIP(),GetUserPort()),wxEmptyString)MuleNotify::DoNotify(&MuleNotify::ChatConnResult, false, (
uint64)((((uint64)GetIP())<<16) + (uint64)GetUserPort()
), wxEmptyString)
;
1355 }
1356
1357 // Delete socket
1358 if (!bFromSocket && m_socket) {
1359 wxASSERT (theApp->listensocket->IsValidSocket(m_socket))do { if ( theApp->listensocket->IsValidSocket(m_socket)
) { } else if ( wxTheAssertHandler && (wxOnAssert("BaseClient.cpp"
, 1359, __FUNCTION__, "theApp->listensocket->IsValidSocket(m_socket)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1360 m_socket->Safe_Delete();
1361 }
1362
1363 SetSocket(NULL__null);
1364
1365 if (m_iFileListRequested) {
1366 AddLogLineC(CFormat(_("Failed to retrieve shared files from user '%s'")) % GetUserName() )theLogger.AddLogLine(L"BaseClient.cpp", 1366, true, logStandard
, CFormat(wxGetTranslation(("Failed to retrieve shared files from user '%s'"
))) % GetUserName())
;
1367 m_iFileListRequested = 0;
1368 }
1369
1370
1371 if (bDelete) {
1372 if (m_Friend) {
1373 // Remove the friend linkage
1374 m_Friend->UnLinkClient(); // this notifies
1375 }
1376 } else {
1377 Notify_SharedCtrlRefreshClient(ECID(), peer_type)MuleNotify::DoNotify(&MuleNotify::SharedCtrlRefreshClient
, ECID(), peer_type)
;
1378 Notify_SourceCtrlUpdateSource(ECID(), source_type)MuleNotify::DoNotify(&MuleNotify::SourceCtrlUpdateSource,
ECID(), source_type)
;
1379
1380 m_fHashsetRequesting = 0;
1381 SetSentCancelTransfer(0);
1382 m_bHelloAnswerPending = false;
1383 m_fSentOutOfPartReqs = 0;
1384 }
1385 AddDebugLogLineN(logClient, CFormat(wxT("--- %s client D:%d U:%d \"%s\"; Reason was %s"))do {} while (false)
1386 % (bDelete ? wxT("Deleted") : wxT("Disconnected"))do {} while (false)
1387 % m_nDownloadState % m_nUploadState % GetClientFullInfo() % strReason )do {} while (false);
1388
1389 return bDelete;
1390}
1391
1392//Returned bool is not if the TryToConnect is successful or not..
1393//false means the client was deleted!
1394//true means the client was not deleted!
1395bool CUpDownClient::TryToConnect(bool bIgnoreMaxCon)
1396{
1397 // Kad reviewed
1398 if (theApp->listensocket->TooManySockets() && !bIgnoreMaxCon ) {
1
Assuming the condition is false
1399 if (!(m_socket && m_socket->IsConnected())) {
1400 if(Disconnected(wxT("Too many connections")L"Too many connections")) {
1401 Safe_Delete();
1402 return false;
1403 }
1404 return true;
1405 }
1406 }
1407
1408 // Do not try to connect to source which are incompatible with our encryption setting (one requires it, and the other one doesn't supports it)
1409 if ( (RequiresCryptLayer() && !thePrefs::IsClientCryptLayerSupported()) || (thePrefs::IsClientCryptLayerRequired() && !SupportsCryptLayer()) ){
1410 if(Disconnected(wxT("CryptLayer-Settings (Obfuscation) incompatible")L"CryptLayer-Settings (Obfuscation) incompatible")){
1411 Safe_Delete();
1412 return false;
1413 } else {
1414 return true;
1415 }
1416 }
1417
1418 // Ipfilter check
1419 uint32 uClientIP = GetIP();
1420 if (uClientIP == 0 && !HasLowID()) {
2
Assuming 'uClientIP' is not equal to 0
1421 uClientIP = wxUINT32_SWAP_ALWAYS(m_nUserIDHybrid)((wxUint32) ( (((wxUint32) (m_nUserIDHybrid) & (wxUint32)
0x000000ffU) << 24) | (((wxUint32) (m_nUserIDHybrid) &
(wxUint32) 0x0000ff00U) << 8) | (((wxUint32) (m_nUserIDHybrid
) & (wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (m_nUserIDHybrid
) & (wxUint32) 0xff000000U) >> 24)))
;
1422 }
1423
1424 if (uClientIP
2.1
'uClientIP' is not equal to 0
) {
3
Taking true branch
1425 // Although we filter all received IPs (server sources, source exchange) and all incoming connection attempts,
1426 // we do have to filter outgoing connection attempts here too, because we may have updated the ip filter list
1427 if (theApp->ipfilter->IsFiltered(uClientIP)) {
4
Assuming the condition is false
5
Taking false branch
1428 AddDebugLogLineN(logIPFilter, CFormat(wxT("Filtered ip %u (%s) on TryToConnect\n")) % uClientIP % Uint32toStringIP(uClientIP))do {} while (false);
1429 if (Disconnected(wxT("IPFilter")L"IPFilter")) {
1430 Safe_Delete();
1431 return false;
1432 }
1433 return true;
1434 }
1435
1436 // for safety: check again whether that IP is banned
1437 if (theApp->clientlist->IsBannedClient(uClientIP)) {
6
Assuming the condition is false
7
Taking false branch
1438 AddDebugLogLineN(logClient, wxT("Refused to connect to banned client ") + Uint32toStringIP(uClientIP))do {} while (false);
1439 if (Disconnected(wxT("Banned IP")L"Banned IP")) {
1440 Safe_Delete();
1441 return false;
1442 }
1443 return true;
1444 }
1445 }
1446
1447 if (GetKadState() == KS_QUEUED_FWCHECK) {
8
Assuming the condition is false
9
Taking false branch
1448 SetKadState(KS_CONNECTING_FWCHECK);
1449 } else if (GetKadState() == KS_QUEUED_FWCHECK_UDP) {
10
Assuming the condition is false
11
Taking false branch
1450 SetKadState(KS_CONNECTING_FWCHECK_UDP);
1451 }
1452
1453 if (HasLowID()) {
1454 if (!theApp->CanDoCallback(GetServerIP(), GetServerPort())) {
1455 //We cannot do a callback!
1456 if (GetDownloadState() == DS_CONNECTING) {
1457 SetDownloadState(DS_LOWTOLOWIP);
1458 } else if (GetDownloadState() == DS_REQHASHSET) {
1459 SetDownloadState(DS_ONQUEUE);
1460 m_reqfile->SetHashSetNeeded(true);
1461 }
1462 if (GetUploadState() == US_CONNECTING) {
1463 if(Disconnected(wxT("LowID->LowID and US_CONNECTING")L"LowID->LowID and US_CONNECTING")) {
1464 Safe_Delete();
1465 return false;
1466 }
1467 }
1468 return true;
1469 }
1470
1471 //We already know we are not firewalled here as the above condition already detected LowID->LowID and returned.
1472 //If ANYTHING changes with the "if(!theApp->CanDoCallback(this))" above that will let you fall through
1473 //with the condition that the source is firewalled and we are firewalled, we must
1474 //recheck it before the this check..
1475 if (HasValidBuddyID() && !GetBuddyIP() && !GetBuddyPort() && !theApp->serverconnect->IsLocalServer(GetServerIP(), GetServerPort())
1476 && !(SupportsDirectUDPCallback() && thePrefs::GetEffectiveUDPPort() != 0)) {
1477 //This is a Kad firewalled source that we want to do a special callback because it has no buddyIP or buddyPort.
1478 if( Kademlia::CKademlia::IsConnected() ) {
1479 //We are connect to Kad
1480 if( Kademlia::CKademlia::GetPrefs()->GetTotalSource() > 0 || Kademlia::CSearchManager::AlreadySearchingFor(Kademlia::CUInt128(GetBuddyID()))) {
1481 //There are too many source lookups already or we are already searching this key.
1482 SetDownloadState(DS_TOOMANYCONNSKAD);
1483 return true;
1484 }
1485 }
1486 }
1487 }
1488
1489 if (!m_socket || !m_socket->IsConnected()) {
12
Assuming field 'm_socket' is non-null
13
Taking false branch
1490 if (m_socket) {
1491 m_socket->Safe_Delete();
1492 }
1493 m_socket = new CClientTCPSocket(this, thePrefs::GetProxyData());
1494 } else {
1495 ConnectionEstablished();
14
Calling 'CUpDownClient::ConnectionEstablished'
1496 return true;
1497 }
1498
1499
1500 if (HasLowID() && SupportsDirectUDPCallback() && thePrefs::GetEffectiveUDPPort() != 0 && GetConnectIP() != 0) { // LOWID with DirectCallback
1501 if (m_dwDirectCallbackTimeout != 0) {
1502 AddDebugLogLineN(logClient, wxT("ERROR: Trying Direct UDP Callback while already trying to connect to client on ip ") + Uint32toStringIP(GetConnectIP()))do {} while (false);
1503 return true; // We're already trying a direct connection to this client
1504 }
1505 // a direct callback is possible - since no other parties are involved and only one additional packet overhead
1506 // is used we basically handle it like a normal connection try, no restrictions apply
1507 // we already check above with !theApp->CanDoCallback(this) if any callback is possible at all
1508 m_dwDirectCallbackTimeout = ::GetTickCount() + SEC2MS(45)((45)*1000);
1509 theApp->clientlist->AddDirectCallbackClient(this);
1510 AddDebugLogLineN(logClient, CFormat(wxT("Direct Callback on port %u to client on ip %s")) % GetKadPort() % Uint32toStringIP(GetConnectIP()))do {} while (false);
1511
1512 CMemFile data;
1513 data.WriteUInt16(thePrefs::GetPort()); // needs to know our port
1514 data.WriteHash(thePrefs::GetUserHash()); // and userhash
1515 // our connection settings
1516 data.WriteUInt8(Kademlia::CPrefs::GetMyConnectOptions(true, false));
1517 AddDebugLogLineN(logClientUDP, wxT("Sending OP_DIRECTCALLBACKREQ to ") + Uint32_16toStringIP_Port(GetConnectIP(), GetKadPort()))do {} while (false);
1518 CPacket* packet = new CPacket(data, OP_EMULEPROT, OP_DIRECTCALLBACKREQ);
1519 theStats::AddUpOverheadOther(packet->GetPacketSize());
1520 theApp->clientudp->SendPacket(packet, GetConnectIP(), GetKadPort(), ShouldReceiveCryptUDPPackets(), GetUserHash().GetHash(), false, 0);
1521 } else if (HasLowID()) { // LOWID
1522 if (GetDownloadState() == DS_CONNECTING) {
1523 SetDownloadState(DS_WAITCALLBACK);
1524 }
1525 if (GetUploadState() == US_CONNECTING) {
1526 if(Disconnected(wxT("LowID and US_CONNECTING")L"LowID and US_CONNECTING")) {
1527 Safe_Delete();
1528 return false;
1529 }
1530 return true;
1531 }
1532
1533 if (theApp->serverconnect->IsLocalServer(m_dwServerIP,m_nServerPort)) {
1534 CMemFile data;
1535 // AFAICS, this id must be reversed to be sent to clients
1536 // But if I reverse it, we do a serve violation ;)
1537 data.WriteUInt32(m_nUserIDHybrid);
1538 CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_CALLBACKREQUEST);
1539 theStats::AddUpOverheadServer(packet->GetPacketSize());
1540 AddDebugLogLineN(logLocalClient, wxT("Local Client: OP_CALLBACKREQUEST to ") + GetFullIP())do {} while (false);
1541 theApp->serverconnect->SendPacket(packet);
1542 SetDownloadState(DS_WAITCALLBACK);
1543 } else {
1544 if (GetUploadState() == US_NONE && (!GetRemoteQueueRank() || m_bReaskPending)) {
1545
1546 if( !HasValidBuddyID() ) {
1547 theApp->downloadqueue->RemoveSource(this);
1548 if (Disconnected(wxT("LowID and US_NONE and QR=0")L"LowID and US_NONE and QR=0")) {
1549 Safe_Delete();
1550 return false;
1551 }
1552 return true;
1553 }
1554
1555 if( !Kademlia::CKademlia::IsConnected() ) {
1556 //We are not connected to Kad and this is a Kad Firewalled source..
1557 theApp->downloadqueue->RemoveSource(this);
1558 if(Disconnected(wxT("Kad Firewalled source but not connected to Kad.")L"Kad Firewalled source but not connected to Kad.")) {
1559 Safe_Delete();
1560 return false;
1561 }
1562 return true;
1563 }
1564
1565 if( GetDownloadState() == DS_WAITCALLBACK ) {
1566 if( GetBuddyIP() && GetBuddyPort()) {
1567 CMemFile bio(34);
1568 bio.WriteUInt128(Kademlia::CUInt128(GetBuddyID()));
1569 bio.WriteUInt128(Kademlia::CUInt128(m_reqfile->GetFileHash().GetHash()));
1570 bio.WriteUInt16(thePrefs::GetPort());
1571 CPacket* packet = new CPacket(bio, OP_KADEMLIAHEADER, KADEMLIA_CALLBACK_REQ);
1572 // eMule FIXME: We don't know which kadversion the buddy has, so we need to send unencrypted
1573 theApp->clientudp->SendPacket(packet, GetBuddyIP(), GetBuddyPort(), false, NULL__null, true, 0);
1574 AddDebugLogLineN(logClientKadUDP, CFormat(wxT("KadCallbackReq (size=%i) to %s")) % packet->GetPacketSize() % Uint32_16toStringIP_Port(GetBuddyIP(), GetBuddyPort()))do {} while (false);
1575 theStats::AddUpOverheadKad(packet->GetRealPacketSize());
1576 SetDownloadState(DS_WAITCALLBACKKAD);
1577 } else {
1578 AddLogLineN(_("Searching buddy for lowid connection"))theLogger.AddLogLine(L"BaseClient.cpp", 1578, false, logStandard
, wxGetTranslation(("Searching buddy for lowid connection")))
;
1579 //Create search to find buddy.
1580 Kademlia::CSearch *findSource = new Kademlia::CSearch;
1581 findSource->SetSearchTypes(Kademlia::CSearch::FINDSOURCE);
1582 findSource->SetTargetID(Kademlia::CUInt128(GetBuddyID()));
1583 findSource->AddFileID(Kademlia::CUInt128(m_reqfile->GetFileHash().GetHash()));
1584 if(Kademlia::CSearchManager::StartSearch(findSource)) {
1585 //Started lookup..
1586 SetDownloadState(DS_WAITCALLBACKKAD);
1587 } else {
1588 //This should never happen..
1589 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("BaseClient.cpp"
, 1589, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
1590 }
1591 }
1592 }
1593 } else {
1594 if (GetDownloadState() == DS_WAITCALLBACK) {
1595 m_bReaskPending = true;
1596 SetDownloadState(DS_ONQUEUE);
1597 }
1598 }
1599 }
1600 } else { // HIGHID
1601 if (!Connect()) {
1602 return false;
1603 }
1604 }
1605 return true;
1606}
1607
1608bool CUpDownClient::Connect()
1609{
1610 m_hasbeenobfuscatinglately = false;
1611
1612 if (!m_socket->IsOk()) {
1613 // Enable or disable crypting based on our and the remote clients preference
1614 if (HasValidHash() && SupportsCryptLayer() && thePrefs::IsClientCryptLayerSupported() && (RequestsCryptLayer() || thePrefs::IsClientCryptLayerRequested())){
1615 m_socket->SetConnectionEncryption(true, GetUserHash().GetHash(), false);
1616 } else {
1617 m_socket->SetConnectionEncryption(false, NULL__null, false);
1618 }
1619 amuleIPV4Address tmp;
1620 tmp.Hostname(GetConnectIP());
1621 tmp.Service(GetUserPort());
1622 AddDebugLogLineN(logClient, wxT("Trying to connect to ") + Uint32_16toStringIP_Port(GetConnectIP(),GetUserPort()))do {} while (false);
1623 m_socket->Connect(tmp, false);
1624 // We should send hello packets AFTER connecting!
1625 // so I moved it to OnConnect
1626 return true;
1627 } else {
1628 return false;
1629 }
1630}
1631
1632void CUpDownClient::ConnectionEstablished()
1633{
1634 /* Kry - First thing, check if this client was just used to retrieve
1635 info. That's some debug thing for myself... check connection_reason
1636 definition */
1637
1638 m_hasbeenobfuscatinglately = (m_socket
14.1
Field 'm_socket' is non-null
&& m_socket->IsConnected() && m_socket->IsObfusicating());
1639
1640 #ifdef __DEBUG__
1641 if (!connection_reason.IsEmpty()) {
1642 AddLogLineN(CFormat(wxT("Got client info checking for %s: %s\nDisconnecting and deleting.")) % connection_reason % GetClientFullInfo())theLogger.AddLogLine(L"BaseClient.cpp", 1642, false, logStandard
, CFormat(L"Got client info checking for %s: %s\nDisconnecting and deleting."
) % connection_reason % GetClientFullInfo())
;
1643 connection_reason.Clear(); // So we don't re-print on destructor.
1644 Safe_Delete();
1645 return;
1646 }
1647 #endif
1648
1649 // Check if we should use this client to retrieve our public IP
1650 // Ignore local ip on GetPublicIP (could be wrong)
1651 if (theApp->GetPublicIP(true) == 0 && theApp->IsConnectedED2K()) {
15
Assuming the condition is false
1652 SendPublicIPRequest();
1653 }
1654
1655 // was this a direct callback?
1656 if (m_dwDirectCallbackTimeout != 0){
16
Assuming field 'm_dwDirectCallbackTimeout' is equal to 0
17
Taking false branch
1657 theApp->clientlist->RemoveDirectCallback(this);
1658 m_dwDirectCallbackTimeout = 0;
1659 AddDebugLogLineN(logClient, wxT("Direct Callback succeeded, connection established to ") + Uint32toStringIP(GetConnectIP()))do {} while (false);
1660 }
1661
1662 switch (GetKadState()) {
18
Control jumps to the 'default' case at line 1674
1663 case KS_CONNECTING_FWCHECK:
1664 SetKadState(KS_CONNECTED_FWCHECK);
1665 break;
1666 case KS_CONNECTING_BUDDY:
1667 case KS_INCOMING_BUDDY:
1668 SetKadState(KS_CONNECTED_BUDDY);
1669 break;
1670 case KS_CONNECTING_FWCHECK_UDP:
1671 SetKadState(KS_FWCHECK_UDP);
1672 SendFirewallCheckUDPRequest();
1673 break;
1674 default:
1675 break;
1676 }
1677
1678 // ok we have a connection, lets see if we want anything from this client
1679 if (GetChatState() == MS_CONNECTING) {
19
Execution continues on line 1679
20
Assuming the condition is false
21
Taking false branch
1680 SetChatState( MS_CHATTING );
1681 }
1682
1683 if (GetChatState() == MS_CHATTING) {
22
Assuming the condition is false
23
Taking false branch
1684 bool result = true;
1685 if (!m_pendingMessage.IsEmpty()) {
1686 result = SendChatMessage(m_pendingMessage);
1687 }
1688 Notify_ChatConnResult(result,GUI_ID(GetIP(),GetUserPort()),m_pendingMessage)MuleNotify::DoNotify(&MuleNotify::ChatConnResult, result,
(uint64)((((uint64)GetIP())<<16) + (uint64)GetUserPort
()), m_pendingMessage)
;
1689 m_pendingMessage.Clear();
1690 }
1691
1692 switch(GetDownloadState()) {
1693 case DS_CONNECTING:
1694 case DS_WAITCALLBACK:
1695 case DS_WAITCALLBACKKAD:
1696 m_bReaskPending = false;
1697 SetDownloadState(DS_CONNECTED);
1698 SendFileRequest();
1699 }
1700 if (m_bReaskPending){
24
'Default' branch taken. Execution continues on line 1700
25
Assuming field 'm_bReaskPending' is false
26
Taking false branch
1701 m_bReaskPending = false;
1702 if (GetDownloadState() != DS_NONE && GetDownloadState() != DS_DOWNLOADING) {
1703 SetDownloadState(DS_CONNECTED);
1704 SendFileRequest();
1705 }
1706 }
1707 switch(GetUploadState()){
27
Control jumps to 'case US_WAITCALLBACK:' at line 1709
1708 case US_CONNECTING:
1709 case US_WAITCALLBACK:
1710 if (theApp->uploadqueue->IsDownloading(this)) {
28
Assuming the condition is true
29
Taking true branch
1711 SetUploadState(US_UPLOADING);
1712 CPacket* packet = new CPacket(OP_ACCEPTUPLOADREQ, 0, OP_EDONKEYPROT);
30
Memory is allocated
1713 theStats::AddUpOverheadFileRequest(packet->GetPacketSize());
1714 SendPacket(packet,true);
1715 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ACCEPTUPLOADREQ to ") + GetFullIP() )do {} while (false);
31
Potential leak of memory pointed to by 'packet'
1716 }
1717 }
1718 if (m_iFileListRequested == 1) {
1719 CPacket* packet = new CPacket(m_fSharedDirectories ? OP_ASKSHAREDDIRS : OP_ASKSHAREDFILES, 0, OP_EDONKEYPROT);
1720 theStats::AddUpOverheadOther(packet->GetPacketSize());
1721 SendPacket(packet,true,true);
1722#ifdef __DEBUG__
1723 if (m_fSharedDirectories) {
1724 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDDIRS to ") + GetFullIP() )do {} while (false);
1725 } else {
1726 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDFILES to ") + GetFullIP() )do {} while (false);
1727 }
1728#endif
1729 }
1730
1731 while (!m_WaitingPackets_list.empty()) {
1732 CPacket* packet = m_WaitingPackets_list.front();
1733 m_WaitingPackets_list.pop_front();
1734
1735 SendPacket(packet);
1736 }
1737}
1738
1739
1740int CUpDownClient::GetHashType() const
1741{
1742 if ( m_UserHash[5] == 13 && m_UserHash[14] == 110 ) {
1743 return SO_OLDEMULE;
1744 }
1745
1746 if ( m_UserHash[5] == 14 && m_UserHash[14] == 111 ) {
1747 return SO_EMULE;
1748 }
1749
1750 if ( m_UserHash[5] == 'M' && m_UserHash[14] == 'L' ) {
1751 return SO_MLDONKEY;
1752 }
1753
1754 return SO_UNKNOWN;
1755}
1756
1757
1758void CUpDownClient::SetSocket(CClientTCPSocket* socket)
1759{
1760#ifdef __DEBUG__
1761 if (m_socket == NULL__null && socket != NULL__null) {
1762 theStats::SocketAssignedToClient();
1763 } else if (m_socket != NULL__null && socket == NULL__null) {
1764 theStats::SocketUnassignedFromClient();
1765 }
1766#endif
1767 m_socket = socket;
1768}
1769
1770
1771void CUpDownClient::ReGetClientSoft()
1772{
1773 if (m_Username.IsEmpty()) {
1774 m_clientSoft=SO_UNKNOWN;
1775 m_clientVerString = m_clientSoftString = m_clientVersionString = m_fullClientVerString = _("Unknown")wxGetTranslation(("Unknown"));
1776 UpdateStats();
1777 return;
1778 }
1779
1780 int iHashType = GetHashType();
1781 wxString clientModString;
1782 if (iHashType == SO_EMULE) {
1783
1784 m_clientSoft = m_byCompatibleClient;
1785 m_clientSoftString = GetSoftName(m_clientSoft);
1786 // Special issues:
1787 if(!GetClientModString().IsEmpty() && (m_clientSoft != SO_EMULE)) {
1788 m_clientSoftString = GetClientModString();
1789 }
1790 // Isn't xMule annoying?
1791 if ((m_clientSoft == SO_LXMULE) && (GetMuleVersion() > 0x26) && (GetMuleVersion() != 0x99)) {
1792 m_clientSoftString += CFormat(_(" (Fake eMule version %#x)")wxGetTranslation((" (Fake eMule version %#x)"))) % GetMuleVersion();
1793 }
1794 if ((m_clientSoft == SO_EMULE) &&
1795 (
1796 wxString(GetClientModString()).MakeLower().Find(wxT("xmule")L"xmule") != -1
1797 || GetUserName().Find(wxT("xmule.")L"xmule.") != -1
1798 )
1799 ) {
1800 // FAKE eMule -a newer xMule faking is ident.
1801 m_clientSoft = SO_LXMULE;
1802 if (GetClientModString().IsEmpty() == false) {
1803 m_clientSoftString = GetClientModString() + _(" (Fake eMule)")wxGetTranslation((" (Fake eMule)"));
1804 } else {
1805 m_clientSoftString = _("xMule (Fake eMule)")wxGetTranslation(("xMule (Fake eMule)")); // don't use GetSoftName, it's not lmule.
1806 }
1807 }
1808 // Now, what if we don't know this SO_ID?
1809 if (m_clientSoftString.IsEmpty()) {
1810 if(m_bIsML) {
1811 m_clientSoft = SO_MLDONKEY;
1812 m_clientSoftString = GetSoftName(m_clientSoft);
1813 } else if (m_bIsHybrid) {
1814 m_clientSoft = SO_EDONKEYHYBRID;
1815 m_clientSoftString = GetSoftName(m_clientSoft);
1816 } else if (m_byCompatibleClient != 0) {
1817 m_clientSoft = SO_COMPAT_UNK;
1818 #ifdef __DEBUG__
1819 if (
1820 // Exceptions:
1821 (m_byCompatibleClient != 0xf0) // Chinese leech mod
1822 && (1==1) // Your ad here
1823 ) {
1824 AddLogLineNS(CFormat(wxT("Compatible client found with ET_COMPATIBLECLIENT of %x")) % m_byCompatibleClient)theLogger.AddLogLine(L"BaseClient.cpp", 1824, false, logStandard
, CFormat(L"Compatible client found with ET_COMPATIBLECLIENT of %x"
) % m_byCompatibleClient, true)
;
1825 }
1826 #endif
1827 m_clientSoftString = CFormat(wxT("%s(%#x)")L"%s(%#x)") % GetSoftName(m_clientSoft) % m_byCompatibleClient;
1828 } else {
1829 // If we step here, it might mean 2 things:
1830 // a eMule
1831 // a Compat Client that has sent no MuleInfo packet yet.
1832 m_clientSoft = SO_EMULE;
1833 m_clientSoftString = wxT("eMule")L"eMule";
1834 }
1835 }
1836
1837 if (m_byEmuleVersion == 0) {
1838 m_nClientVersion = MAKE_CLIENT_VERSION(0,0,0)((uint32)(0)*100U*10U*100U + (uint32)(0)*100U*10U + (uint32)(
0)*100U)
;
1839 } else if (m_byEmuleVersion != 0x99) {
1840 uint32 nClientMinVersion = (m_byEmuleVersion >> 4)*10 + (m_byEmuleVersion & 0x0f);
1841 m_nClientVersion = MAKE_CLIENT_VERSION(0,nClientMinVersion,0)((uint32)(0)*100U*10U*100U + (uint32)(nClientMinVersion)*100U
*10U + (uint32)(0)*100U)
;
1842 switch (m_clientSoft) {
1843 case SO_AMULE:
1844 m_clientVerString = CFormat(_("1.x (based on eMule v0.%u)")wxGetTranslation(("1.x (based on eMule v0.%u)"))) % nClientMinVersion;
1845 break;
1846 case SO_LPHANT:
1847 m_clientVerString = wxT("< v0.05")L"< v0.05";
1848 break;
1849 default:
1850 clientModString = GetClientModString();
1851 m_clientVerString = CFormat(wxT("v0.%u")L"v0.%u") % nClientMinVersion;
1852 break;
1853 }
1854 } else {
1855 uint32 nClientMajVersion = (m_nClientVersion >> 17) & 0x7f;
1856 uint32 nClientMinVersion = (m_nClientVersion >> 10) & 0x7f;
1857 uint32 nClientUpVersion = (m_nClientVersion >> 7) & 0x07;
1858
1859 m_nClientVersion = MAKE_CLIENT_VERSION(nClientMajVersion, nClientMinVersion, nClientUpVersion)((uint32)(nClientMajVersion)*100U*10U*100U + (uint32)(nClientMinVersion
)*100U*10U + (uint32)(nClientUpVersion)*100U)
;
1860
1861 switch (m_clientSoft) {
1862 case SO_AMULE:
1863 case SO_LXMULE:
1864 case SO_HYDRANODE:
1865 case SO_MLDONKEY:
1866 case SO_NEW_MLDONKEY:
1867 case SO_NEW2_MLDONKEY:
1868 // Kry - xMule started sending correct version tags on 1.9.1b.
1869 // It only took them 4 months, and being told by me and the
1870 // eMule+ developers, so I think they're slowly getting smarter.
1871 // They are based on our implementation, so we use the same format
1872 // for the version string.
1873 m_clientVerString = CFormat(wxT("v%u.%u.%u")L"v%u.%u.%u") % nClientMajVersion % nClientMinVersion % nClientUpVersion;
1874 break;
1875 case SO_LPHANT:
1876 m_clientVerString = CFormat(wxT(" v%u.%.2u%c")L" v%u.%.2u%c") % (nClientMajVersion-1) % nClientMinVersion % ('a' + nClientUpVersion);
1877 break;
1878 case SO_EMULEPLUS:
1879 m_clientVerString = CFormat(wxT("v%u")L"v%u") % nClientMajVersion;
1880 if(nClientMinVersion != 0) {
1881 m_clientVerString += CFormat(wxT(".%u")L".%u") % nClientMinVersion;
1882 }
1883 if(nClientUpVersion != 0) {
1884 m_clientVerString += CFormat(wxT("%c")L"%c") % ('a' + nClientUpVersion - 1);
1885 }
1886 break;
1887 default:
1888 clientModString = GetClientModString();
1889 m_clientVerString = CFormat(wxT("v%u.%u%c")L"v%u.%u%c") % nClientMajVersion % nClientMinVersion % ('a' + nClientUpVersion);
1890 break;
1891 }
1892 }
1893 } else if (m_bIsHybrid) {
1894 // seen:
1895 // 105010 50.10
1896 // 10501 50.1
1897 // 1051 51.0
1898 // 501 50.1
1899
1900 m_clientSoft = SO_EDONKEYHYBRID;
1901 m_clientSoftString = GetSoftName(m_clientSoft);
1902
1903 uint32 nClientMajVersion;
1904 uint32 nClientMinVersion;
1905 uint32 nClientUpVersion;
1906 if (m_nClientVersion > 100000) {
1907 uint32 uMaj = m_nClientVersion/100000;
1908 nClientMajVersion = uMaj - 1;
1909 nClientMinVersion = (m_nClientVersion - uMaj*100000) / 100;
1910 nClientUpVersion = m_nClientVersion % 100;
1911 }
1912 else if (m_nClientVersion > 10000) {
1913 uint32 uMaj = m_nClientVersion/10000;
1914 nClientMajVersion = uMaj - 1;
1915 nClientMinVersion = (m_nClientVersion - uMaj*10000) / 10;
1916 nClientUpVersion = m_nClientVersion % 10;
1917 }
1918 else if (m_nClientVersion > 1000) {
1919 uint32 uMaj = m_nClientVersion/1000;
1920 nClientMajVersion = uMaj - 1;
1921 nClientMinVersion = m_nClientVersion - uMaj*1000;
1922 nClientUpVersion = 0;
1923 }
1924 else if (m_nClientVersion > 100) {
1925 uint32 uMin = m_nClientVersion/10;
1926 nClientMajVersion = 0;
1927 nClientMinVersion = uMin;
1928 nClientUpVersion = m_nClientVersion - uMin*10;
1929 }
1930 else{
1931 nClientMajVersion = 0;
1932 nClientMinVersion = m_nClientVersion;
1933 nClientUpVersion = 0;
1934 }
1935 m_nClientVersion = MAKE_CLIENT_VERSION(nClientMajVersion, nClientMinVersion, nClientUpVersion)((uint32)(nClientMajVersion)*100U*10U*100U + (uint32)(nClientMinVersion
)*100U*10U + (uint32)(nClientUpVersion)*100U)
;
1936 if (nClientUpVersion) {
1937 m_clientVerString = CFormat(wxT("v%u.%u.%u")L"v%u.%u.%u") % nClientMajVersion % nClientMinVersion % nClientUpVersion;
1938 } else {
1939 m_clientVerString = CFormat(wxT("v%u.%u")L"v%u.%u") % nClientMajVersion % nClientMinVersion;
1940 }
1941 } else if (m_bIsML || (iHashType == SO_MLDONKEY)) {
1942 m_clientSoft = SO_MLDONKEY;
1943 m_clientSoftString = GetSoftName(m_clientSoft);
1944 uint32 nClientMinVersion = m_nClientVersion;
1945 m_nClientVersion = MAKE_CLIENT_VERSION(0, nClientMinVersion, 0)((uint32)(0)*100U*10U*100U + (uint32)(nClientMinVersion)*100U
*10U + (uint32)(0)*100U)
;
1946 m_clientVerString = CFormat(wxT("v0.%u")L"v0.%u") % nClientMinVersion;
1947 } else if (iHashType == SO_OLDEMULE) {
1948 m_clientSoft = SO_OLDEMULE;
1949 m_clientSoftString = GetSoftName(m_clientSoft);
1950 uint32 nClientMinVersion = m_nClientVersion;
1951 m_nClientVersion = MAKE_CLIENT_VERSION(0, nClientMinVersion, 0)((uint32)(0)*100U*10U*100U + (uint32)(nClientMinVersion)*100U
*10U + (uint32)(0)*100U)
;
1952 m_clientVerString = CFormat(wxT("v0.%u")L"v0.%u") % nClientMinVersion;
1953 } else {
1954 m_clientSoft = SO_EDONKEY;
1955 m_clientSoftString = GetSoftName(m_clientSoft);
1956 m_nClientVersion *= 10;
1957 m_clientVerString = CFormat(wxT("v%u.%u")L"v%u.%u") % (m_nClientVersion / 100000) % ((m_nClientVersion / 1000) % 100);
1958 }
1959
1960 m_clientVersionString = m_clientVerString;
1961 if (!clientModString.IsEmpty()) {
1962 m_clientVerString += wxT(" - ")L" - " + clientModString;
1963 }
1964 m_fullClientVerString = m_clientSoftString + wxT(" ")L" " + m_clientVerString;
1965
1966 UpdateStats();
1967}
1968
1969void CUpDownClient::RequestSharedFileList()
1970{
1971 if (m_iFileListRequested == 0) {
1972 AddDebugLogLineN( logClient, wxString( wxT("Requesting shared files from ") ) + GetUserName() )do {} while (false);
1973 m_iFileListRequested = 1;
1974 TryToConnect(true);
1975 } else {
1976 AddDebugLogLineN( logClient, CFormat( wxT("Requesting shared files from user %s (%u) is already in progress") ) % GetUserName() % GetUserIDHybrid() )do {} while (false);
1977 }
1978}
1979
1980
1981void CUpDownClient::ProcessSharedFileList(const uint8_t* pachPacket, uint32 nSize, wxString& pszDirectory)
1982{
1983 if (m_iFileListRequested > 0) {
1984 m_iFileListRequested--;
1985 theApp->searchlist->ProcessSharedFileList(pachPacket, nSize, this, NULL__null, pszDirectory);
1986 }
1987}
1988
1989
1990void CUpDownClient::ResetFileStatusInfo()
1991{
1992 m_nPartCount = 0;
1993
1994 if ( m_reqfile ) {
1995 m_reqfile->UpdatePartsFrequency( this, false );
1996 }
1997 m_downPartStatus.clear();
1998
1999 m_clientFilename.Clear();
2000
2001 m_bCompleteSource = false;
2002 m_dwLastAskedTime = 0;
2003 m_iRating = 0;
2004 m_strComment.Clear();
2005
2006 if (m_pReqFileAICHHash != NULL__null) {
2007 delete m_pReqFileAICHHash;
2008 m_pReqFileAICHHash = NULL__null;
2009 }
2010
2011}
2012
2013wxString CUpDownClient::GetUploadFileInfo()
2014{
2015 // build info text and display it
2016 wxString sRet;
2017 sRet = (CFormat(_("NickName: %s ID: %u")wxGetTranslation(("NickName: %s ID: %u"))) % GetUserName() % GetUserIDHybrid()) + wxT(" ")L" ";
2018 if (m_reqfile) {
2019 sRet += CFormat(_("Requested: %s\n")wxGetTranslation(("Requested: %s\n"))) % m_reqfile->GetFileName();
2020 sRet += CFormat(
2021 wxPLURAL("Filestats for this session: Accepted %d of %d request, %s transferred\n", "Filestats for this session: Accepted %d of %d requests, %s transferred\n", m_reqfile->statistic.GetRequests())wxGetTranslation(("Filestats for this session: Accepted %d of %d request, %s transferred\n"
), ("Filestats for this session: Accepted %d of %d requests, %s transferred\n"
), m_reqfile->statistic.GetRequests())
2022 ) % m_reqfile->statistic.GetAccepts() % m_reqfile->statistic.GetRequests() % CastItoXBytes(m_reqfile->statistic.GetTransferred());
2023 sRet += CFormat(
2024 wxPLURAL("Filestats for all sessions: Accepted %d of %d request, %s transferred\n", "Filestats for all sessions: Accepted %d of %d requests, %s transferred\n", m_reqfile->statistic.GetAllTimeRequests())wxGetTranslation(("Filestats for all sessions: Accepted %d of %d request, %s transferred\n"
), ("Filestats for all sessions: Accepted %d of %d requests, %s transferred\n"
), m_reqfile->statistic.GetAllTimeRequests())
2025 ) % m_reqfile->statistic.GetAllTimeAccepts() % m_reqfile->statistic.GetAllTimeRequests() % CastItoXBytes(m_reqfile->statistic.GetAllTimeTransferred());
2026 } else {
2027 sRet += _("Requested unknown file")wxGetTranslation(("Requested unknown file"));
2028 }
2029 return sRet;
2030}
2031
2032// sends a packet, if needed it will establish a connection before
2033// options used: ignore max connections, control packet, delete packet
2034// !if the functions returns false it is _possible_ that this clientobject was deleted, because the connectiontry fails
2035bool CUpDownClient::SafeSendPacket(CPacket* packet)
2036{
2037 if (IsConnected()) {
2038 SendPacket(packet, true);
2039 return true;
2040 } else {
2041 m_WaitingPackets_list.push_back(packet);
2042 return TryToConnect(true);
2043 }
2044}
2045
2046void CUpDownClient::SendPublicKeyPacket()
2047{
2048 // send our public key to the client who requested it
2049 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2049, __FUNCTION__,
"\"m_socket != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2049
;
2050 wxCHECK2(credits != NULL, return)if ( credits != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2050, __FUNCTION__,
"\"credits != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2050
;
2051 wxCHECK2(m_SecureIdentState == IS_KEYANDSIGNEEDED, return)if ( m_SecureIdentState == IS_KEYANDSIGNEEDED ) {} else { do {
if ( wxTheAssertHandler && (wxOnAssert("BaseClient.cpp"
, 2051, __FUNCTION__, "\"m_SecureIdentState == IS_KEYANDSIGNEEDED\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); return; }
struct wxDummyCheckStruct2051
;
2052
2053 if (!theApp->CryptoAvailable())
2054 return;
2055
2056 CMemFile data;
2057 data.WriteUInt8(theApp->clientcredits->GetPubKeyLen());
2058 data.Write(theApp->clientcredits->GetPublicKey(), theApp->clientcredits->GetPubKeyLen());
2059 CPacket* packet = new CPacket(data, OP_EMULEPROT, OP_PUBLICKEY);
2060
2061 theStats::AddUpOverheadOther(packet->GetPacketSize());
2062 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_PUBLICKEY to ") + GetFullIP() )do {} while (false);
2063 SendPacket(packet,true,true);
2064 m_SecureIdentState = IS_SIGNATURENEEDED;
2065}
2066
2067
2068void CUpDownClient::SendSignaturePacket()
2069{
2070 // signate the public key of this client and send it
2071 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2071, __FUNCTION__,
"\"m_socket != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2071
;
2072 wxCHECK2(credits != NULL, return)if ( credits != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2072, __FUNCTION__,
"\"credits != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2072
;
2073 wxCHECK2(m_SecureIdentState != 0, return)if ( m_SecureIdentState != 0 ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2073, __FUNCTION__,
"\"m_SecureIdentState != 0\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2073
;
2074
2075 if (!theApp->CryptoAvailable()) {
2076 return;
2077 }
2078 if (credits->GetSecIDKeyLen() == 0) {
2079 return; // We don't have his public key yet, will be back here later
2080 }
2081 // do we have a challenge value received (actually we should if we are in this function)
2082 if (credits->m_dwCryptRndChallengeFrom == 0){
2083 AddDebugLogLineN( logClient, wxString(wxT("Want to send signature but challenge value is invalid - User ")) + GetUserName())do {} while (false);
2084 return;
2085 }
2086 // v2
2087 // we will use v1 as default, except if only v2 is supported
2088 bool bUseV2;
2089 if ( (m_bySupportSecIdent&1) == 1 )
2090 bUseV2 = false;
2091 else
2092 bUseV2 = true;
2093
2094 uint8 byChaIPKind = 0;
2095 uint32 ChallengeIP = 0;
2096 if (bUseV2){
2097 if (::IsLowID(theApp->GetED2KID())) {
2098 // we cannot do not know for sure our public ip, so use the remote clients one
2099 ChallengeIP = GetIP();
2100 byChaIPKind = CRYPT_CIP_REMOTECLIENT10;
2101 } else {
2102 ChallengeIP = theApp->GetED2KID();
2103 byChaIPKind = CRYPT_CIP_LOCALCLIENT20;
2104 }
2105 }
2106 //end v2
2107 uint8_t achBuffer[250];
2108
2109 uint8 siglen = theApp->clientcredits->CreateSignature(credits, achBuffer, 250, ChallengeIP, byChaIPKind );
2110 wxCHECK2(siglen != 0, return)if ( siglen != 0 ) {} else { do { if ( wxTheAssertHandler &&
(wxOnAssert("BaseClient.cpp", 2110, __FUNCTION__, "\"siglen != 0\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); return; }
struct wxDummyCheckStruct2110
;
2111
2112 CMemFile data;
2113 data.WriteUInt8(siglen);
2114 data.Write(achBuffer, siglen);
2115 if (bUseV2) {
2116 data.WriteUInt8(byChaIPKind);
2117 }
2118
2119 CPacket* packet = new CPacket(data, OP_EMULEPROT, OP_SIGNATURE);
2120
2121 theStats::AddUpOverheadOther(packet->GetPacketSize());
2122 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_SIGNATURE to ") + GetFullIP() )do {} while (false);
2123 SendPacket(packet,true,true);
2124 m_SecureIdentState = IS_ALLREQUESTSSEND;
2125}
2126
2127
2128void CUpDownClient::ProcessPublicKeyPacket(const uint8_t* pachPacket, uint32 nSize)
2129{
2130 theApp->clientlist->AddTrackClient(this);
2131
2132 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2132, __FUNCTION__,
"\"m_socket != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2132
;
2133 wxCHECK2(credits != NULL, return)if ( credits != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2133, __FUNCTION__,
"\"credits != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2133
;
2134 if (pachPacket[0] != nSize - 1) {
2135 AddDebugLogLineN(logClient, CFormat(wxT("Inconsistent packet size (%d != %d)")) % pachPacket[0] % (nSize - 1))do {} while (false);
2136 return;
2137 }
2138 if (nSize == 0) {
2139 AddDebugLogLineN(logClient, wxT("Invalid packet size (0)"))do {} while (false);
2140 return;
2141 }
2142 if (nSize > 250) {
2143 AddDebugLogLineN(logClient, CFormat(wxT("Invalid packet size (%d > 250)")) % nSize)do {} while (false);
2144 return;
2145 }
2146 if (!theApp->CryptoAvailable())
2147 return;
2148 // the function will handle everything (multiple key etc)
2149 if (credits->SetSecureIdent(pachPacket+1, pachPacket[0])){
2150 // if this client wants a signature, now we can send him one
2151 if (m_SecureIdentState == IS_SIGNATURENEEDED){
2152 SendSignaturePacket();
2153 }
2154 else if (m_SecureIdentState == IS_KEYANDSIGNEEDED) {
2155 // something is wrong
2156 AddDebugLogLineN( logClient, wxT("Invalid State error: IS_KEYANDSIGNEEDED in ProcessPublicKeyPacket") )do {} while (false);
2157 }
2158 } else {
2159 AddDebugLogLineN( logClient, wxT("Failed to use new received public key") )do {} while (false);
2160 }
2161}
2162
2163
2164void CUpDownClient::ProcessSignaturePacket(const uint8_t* pachPacket, uint32 nSize)
2165{
2166 // here we spread the good guys from the bad ones ;)
2167
2168 wxCHECK2(m_socket != NULL, return)if ( m_socket != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2168, __FUNCTION__,
"\"m_socket != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2168
;
2169 wxCHECK2(credits != NULL, return)if ( credits != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2169, __FUNCTION__,
"\"credits != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2169
;
2170 if (nSize == 0) {
2171 AddDebugLogLineN(logClient, wxT("Invalid packet size (0)"))do {} while (false);
2172 return;
2173 }
2174 if (nSize > 250) {
2175 AddDebugLogLineN(logClient, CFormat(wxT("Invalid packet size (%d > 250)")) % nSize)do {} while (false);
2176 return;
2177 }
2178
2179 uint8 byChaIPKind;
2180 if (pachPacket[0] == nSize-1)
2181 byChaIPKind = 0;
2182 else if (pachPacket[0] == nSize-2 && (m_bySupportSecIdent & 2) > 0) //v2
2183 byChaIPKind = pachPacket[nSize-1];
2184 else {
2185 // Unknown or invalid format
2186 AddDebugLogLineN(logClient, wxT("Invalid or unknown challenge format - ignoring"))do {} while (false);
2187 return;
2188 }
2189
2190 if (!theApp->CryptoAvailable())
2191 return;
2192
2193 // we accept only one signature per IP, to avoid floods which need a lot cpu time for cryptfunctions
2194 if (m_dwLastSignatureIP == GetIP()){
2195 AddDebugLogLineN( logClient, wxT("received multiple signatures from one client") )do {} while (false);
2196 return;
2197 }
2198 // also make sure this client has a public key
2199 if (credits->GetSecIDKeyLen() == 0){
2200 AddDebugLogLineN( logClient, wxT("received signature for client without public key") )do {} while (false);
2201 return;
2202 }
2203 // and one more check: did we ask for a signature and sent a challenge packet?
2204 if (credits->m_dwCryptRndChallengeFor == 0){
2205 AddDebugLogLineN( logClient, wxT("received signature for client with invalid challenge value - User ") + GetUserName() )do {} while (false);
2206 return;
2207 }
2208
2209 // cppcheck-suppress duplicateBranch
2210 if (theApp->clientcredits->VerifyIdent(credits, pachPacket+1, pachPacket[0], GetIP(), byChaIPKind ) ) {
2211 // result is saved in function above
2212 AddDebugLogLineN( logClient, CFormat( wxT("'%s' has passed the secure identification, V2 State: %i") ) % GetUserName() % byChaIPKind )do {} while (false);
2213 } else {
2214 AddDebugLogLineN( logClient, CFormat( wxT("'%s' has failed the secure identification, V2 State: %i") ) % GetUserName() % byChaIPKind )do {} while (false);
2215 }
2216
2217 m_dwLastSignatureIP = GetIP();
2218}
2219
2220void CUpDownClient::SendSecIdentStatePacket()
2221{
2222 wxCHECK2(credits != NULL, return)if ( credits != __null ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2222, __FUNCTION__,
"\"credits != __null\"", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return; } struct wxDummyCheckStruct2222
;
2223
2224 // check if we need public key and signature
2225 uint8 nValue = 0;
2226 if (theApp->CryptoAvailable()){
2227 if (credits->GetSecIDKeyLen() == 0) {
2228 nValue = IS_KEYANDSIGNEEDED;
2229 } else if (m_dwLastSignatureIP != GetIP()) {
2230 nValue = IS_SIGNATURENEEDED;
2231 }
2232 }
2233 if (nValue == 0){
2234 AddDebugLogLineN( logClient, wxT("Not sending SecIdentState Packet, because State is Zero") )do {} while (false);
2235 return;
2236 }
2237 // crypt: send random data to sign
2238 uint32 dwRandom = rand()+1;
2239 credits->m_dwCryptRndChallengeFor = dwRandom;
2240
2241 CMemFile data;
2242 data.WriteUInt8(nValue);
2243 data.WriteUInt32(dwRandom);
2244 CPacket* packet = new CPacket(data, OP_EMULEPROT, OP_SECIDENTSTATE);
2245
2246 theStats::AddUpOverheadOther(packet->GetPacketSize());
2247 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_SECIDENTSTATE to ") + GetFullIP() )do {} while (false);
2248 SendPacket(packet,true,true);
2249}
2250
2251
2252void CUpDownClient::ProcessSecIdentStatePacket(const uint8_t* pachPacket, uint32 nSize)
2253{
2254 if ( nSize != 5 ) {
2255 return;
2256 }
2257
2258 wxCHECK2(credits, return)if ( credits ) {} else { do { if ( wxTheAssertHandler &&
(wxOnAssert("BaseClient.cpp", 2258, __FUNCTION__, "\"credits\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); return; }
struct wxDummyCheckStruct2258
;
2259
2260 CMemFile data(pachPacket,nSize);
2261
2262 switch ( data.ReadUInt8() ) {
2263 case 0:
2264 m_SecureIdentState = IS_UNAVAILABLE;
2265 break;
2266 case 1:
2267 m_SecureIdentState = IS_SIGNATURENEEDED;
2268 break;
2269 case 2:
2270 m_SecureIdentState = IS_KEYANDSIGNEEDED;
2271 break;
2272 default:
2273 return;
2274 }
2275
2276 credits->m_dwCryptRndChallengeFrom = data.ReadUInt32();
2277}
2278
2279
2280void CUpDownClient::InfoPacketsReceived()
2281{
2282 // indicates that both Information Packets has been received
2283 // needed for actions, which process data from both packets
2284 wxASSERT ( m_byInfopacketsReceived == IP_BOTH )do { if ( m_byInfopacketsReceived == IP_BOTH ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2284, __FUNCTION__,
"m_byInfopacketsReceived == IP_BOTH", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 )
;
2285 m_byInfopacketsReceived = IP_NONE;
2286
2287 if (m_bySupportSecIdent){
2288 SendSecIdentStatePacket();
2289 }
2290}
2291
2292
2293bool CUpDownClient::CheckHandshakeFinished() const
2294{
2295 if (m_bHelloAnswerPending) {
2296 // this triggers way too often.. need more time to look at this -> only create a warning
2297 // The reason for this is that 2 clients are connecting to each other at the same time..
2298 AddDebugLogLineN( logClient, wxT("Handshake not finished while processing packet.") )do {} while (false);
2299 return false;
2300 }
2301
2302 return true;
2303}
2304
2305
2306#ifdef __DEBUG__
2307wxString CUpDownClient::GetClientFullInfo()
2308{
2309 if (m_clientVerString.IsEmpty()) {
2310 ReGetClientSoft();
2311 }
2312
2313 return CFormat( wxT("Client %s on IP:Port %s:%d using %s %s %s")L"Client %s on IP:Port %s:%d using %s %s %s" )
2314 % ( m_Username.IsEmpty() ? wxString(_("Unknown")wxGetTranslation(("Unknown"))) : m_Username )
2315 % GetFullIP()
2316 % GetUserPort()
2317 % m_clientSoftString
2318 % m_clientVerString
2319 % m_strModVersion;
2320}
2321#endif
2322
2323wxString CUpDownClient::GetClientShortInfo()
2324{
2325 if (m_clientVerString.IsEmpty()) {
2326 ReGetClientSoft();
2327 }
2328
2329 return CFormat( wxT("'%s' (%s %s %s)")L"'%s' (%s %s %s)" )
2330 % ( m_Username.IsEmpty() ? wxString(_("Unknown")wxGetTranslation(("Unknown"))) : m_Username )
2331 % m_clientSoftString
2332 % m_clientVerString
2333 % m_strModVersion;
2334}
2335
2336
2337void CUpDownClient::SendPublicIPRequest()
2338{
2339 if (IsConnected()){
2340 CPacket* packet = new CPacket(OP_PUBLICIP_REQ,0,OP_EMULEPROT);
2341 theStats::AddUpOverheadOther(packet->GetPacketSize());
2342 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_PUBLICIP_REQ to ") + GetFullIP())do {} while (false);
2343 SendPacket(packet,true);
2344 m_fNeedOurPublicIP = true;
2345 }
2346}
2347
2348void CUpDownClient::ProcessPublicIPAnswer(const uint8_t* pbyData, uint32 uSize)
2349{
2350 if (uSize != 4) {
2351 throw wxString(wxT("Wrong Packet size on Public IP answer")L"Wrong Packet size on Public IP answer");
2352 }
2353 uint32 dwIP = PeekUInt32(pbyData);
2354 if (m_fNeedOurPublicIP == true){ // did we?
2355 m_fNeedOurPublicIP = false;
2356 // Ignore local ip on GetPublicIP (could be wrong)
2357 if (theApp->GetPublicIP(true) == 0 && !IsLowID(dwIP) ) {
2358 theApp->SetPublicIP(dwIP);
2359 }
2360 }
2361}
2362
2363
2364bool CUpDownClient::IsConnected() const
2365{
2366 return m_socket && m_socket->IsConnected();
2367}
2368
2369bool CUpDownClient::SendPacket(CPacket* packet, bool delpacket, bool controlpacket)
2370{
2371 if ( m_socket ) {
2372 m_socket->SendPacket(packet, delpacket, controlpacket );
2373 return true;
2374 } else {
2375 AddLogLineN(wxT("CAUGHT DEAD SOCKET IN SENDPACKET()"))theLogger.AddLogLine(L"BaseClient.cpp", 2375, false, logStandard
, L"CAUGHT DEAD SOCKET IN SENDPACKET()")
;
2376 return false;
2377 }
2378}
2379
2380float CUpDownClient::SetDownloadLimit(uint32 reducedownload)
2381{
2382 // lfroen: in daemon it actually can happen
2383 wxASSERT( m_socket )do { if ( m_socket ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("BaseClient.cpp", 2383, __FUNCTION__, "m_socket"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
2384
2385 float kBpsClient = CalculateKBpsDown();
2386
2387 if ( m_socket ) {
2388
2389 if (reducedownload) {
2390 // (% to reduce * current speed) / 100 and THEN, / (1000 / CORE_TIMER_PERIOD)
2391 // which is how often it is called per second.
2392 uint32 limit = (uint32)(reducedownload * kBpsClient * 1024.0 / 100000.0 * CORE_TIMER_PERIOD100);
2393
2394 if(limit<1024 && reducedownload >= 200) {
2395 // If we're going up and this download is < 1kB,
2396 // we want it to go up fast. Can be reduced later,
2397 // and it'll probably be in a more fair way with
2398 // other downloads that are faster.
2399 limit +=1024;
2400 } else if(limit == 0) {
2401 // This download is not transferring yet... make it
2402 // 1024 so we don't fill the TCP stack and lose the
2403 // connection.
2404 limit = 1024;
2405 }
2406
2407 m_socket->SetDownloadLimit(limit);
2408 } else {
2409 m_socket->DisableDownloadLimit();
2410 }
2411
2412 } else {
2413 AddLogLineNS(CFormat(wxT("CAUGHT DEAD SOCKET IN SETDOWNLOADLIMIT() WITH SPEED %f")) % kBpsClient)theLogger.AddLogLine(L"BaseClient.cpp", 2413, false, logStandard
, CFormat(L"CAUGHT DEAD SOCKET IN SETDOWNLOADLIMIT() WITH SPEED %f"
) % kBpsClient, true)
;
2414 }
2415
2416 return kBpsClient;
2417}
2418
2419void CUpDownClient::SetUserIDHybrid(uint32 nUserID)
2420{
2421 theApp->clientlist->UpdateClientID( this, nUserID );
2422
2423 m_nUserIDHybrid = nUserID;
2424}
2425
2426
2427void CUpDownClient::SetIP( uint32 val )
2428{
2429 theApp->clientlist->UpdateClientIP( this, val );
2430
2431 m_dwUserIP = val;
2432
2433 m_nConnectIP = val;
2434
2435 m_FullUserIP = val;
2436}
2437
2438
2439void CUpDownClient::SetUserHash(const CMD4Hash& userhash)
2440{
2441 theApp->clientlist->UpdateClientHash( this, userhash );
2442
2443 m_UserHash = userhash;
2444
2445 ValidateHash();
2446}
2447
2448EUtf8Str CUpDownClient::GetUnicodeSupport() const
2449{
2450 return m_bUnicodeSupport ? utf8strRaw : utf8strNone;
2451}
2452
2453void CUpDownClient::SetSpammer(bool bVal)
2454{
2455 if (bVal) {
2456 Ban();
2457 } else if (IsBanned() && m_fIsSpammer) {
2458 UnBan();
2459 }
2460 m_fIsSpammer = bVal;
2461}
2462
2463uint8 CUpDownClient::GetSecureIdentState()
2464{
2465 if (m_SecureIdentState != IS_UNAVAILABLE) {
2466 if (!SecIdentSupRec) {
2467 // This can be caused by a 0.30x based client which sends the old
2468 // style Hello packet, and the mule info packet, but between them they
2469 // send a secure ident state packet (after a hello but before we have
2470 // the SUI capabilities). This is a misbehaving client, and somehow I
2471 // feel like it should be dropped. But then again, it won't harm to use
2472 // this SUI state if they are reporting no SUI (won't be used) and if
2473 // they report using SUI on the mule info packet, it's ok to use it.
2474
2475 AddDebugLogLineN(logClient, wxT("A client sent secure ident state before telling us the SUI capabilities"))do {} while (false);
2476 AddDebugLogLineN(logClient, wxT("Client info: ") + GetClientFullInfo())do {} while (false);
2477 AddDebugLogLineN(logClient, wxT("This client won't be disconnected, but it should be. :P"))do {} while (false);
2478 }
2479 }
2480
2481 return m_SecureIdentState;
2482}
2483
2484
2485bool CUpDownClient::SendChatMessage(const wxString& message)
2486{
2487 if (GetChatCaptchaState() == CA_CAPTCHARECV) {
2488 m_nChatCaptchaState = CA_SOLUTIONSENT;
2489 } else if (GetChatCaptchaState() == CA_SOLUTIONSENT) {
2490 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("BaseClient.cpp"
, 2490, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
; // we responded to a captcha but didn't hear from the client afterwards - hopefully it's just lag and this message will get through
2491 } else {
2492 m_nChatCaptchaState = CA_ACCEPTING;
2493 }
2494
2495 SetSpammer(false);
2496 IncMessagesSent();
2497 // Already connecting?
2498 if (GetChatState() == MS_CONNECTING) {
2499 // Queue all messages till we're able to send them (or discard them)
2500 if (!m_pendingMessage.IsEmpty()) {
2501 m_pendingMessage += wxT("\n")L"\n";
2502 } else {
2503 // There must be a message to send
2504 // - except if we got disconnected. No need to assert therefore.
2505 }
2506 m_pendingMessage += message;
2507 return false;
2508 }
2509 if (IsConnected()) {
2510 // If we are already connected when we send the first message,
2511 // we have to update the chat status.
2512 SetChatState(MS_CHATTING);
2513 CMemFile data;
2514 data.WriteString(message, GetUnicodeSupport());
2515 CPacket* packet = new CPacket(data, OP_EDONKEYPROT, OP_MESSAGE);
2516 theStats::AddUpOverheadOther(packet->GetPacketSize());
2517 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_MESSAGE to ") + GetFullIP())do {} while (false);
2518 SendPacket(packet, true, true);
2519 return true;
2520 } else {
2521 m_pendingMessage = message;
2522 SetChatState(MS_CONNECTING);
2523 // True to ignore "Too Many Connections"
2524 TryToConnect(true);
2525 return false;
2526 }
2527}
2528
2529/* Kad stuff */
2530
2531void CUpDownClient::SetBuddyID(const uint8_t* pucBuddyID)
2532{
2533 if( pucBuddyID == NULL__null ){
2534 md4clr(m_achBuddyID);
2535 m_bBuddyIDValid = false;
2536 return;
2537 }
2538 m_bBuddyIDValid = true;
2539 md4cpy(m_achBuddyID, pucBuddyID);
2540}
2541
2542// Kad added by me
2543
2544bool CUpDownClient::SendBuddyPing() {
2545 SetLastBuddyPingPongTime();
2546 CPacket* buddyPing = new CPacket(OP_BUDDYPING, 0, OP_EMULEPROT);
2547 theStats::AddUpOverheadKad(buddyPing->GetPacketSize());
2548 AddDebugLogLineN(logLocalClient,wxT("Local Client: OP_BUDDYPING to ") + GetFullIP())do {} while (false);
2549 return SafeSendPacket(buddyPing);
2550}
2551
2552
2553/* Statistics */
2554
2555void CUpDownClient::UpdateStats()
2556{
2557 if (m_lastClientSoft != m_clientSoft || m_lastClientVersion != m_nClientVersion || m_lastOSInfo != m_sClientOSInfo) {
2558 if (m_lastClientSoft == SO_UNKNOWN) {
2559 theStats::RemoveUnknownClient();
2560 } else if (m_lastClientSoft != (uint32)(-1)) {
2561 theStats::RemoveKnownClient(m_lastClientSoft, m_lastClientVersion, m_lastOSInfo);
2562 }
2563
2564 m_lastClientSoft = m_clientSoft;
2565 m_lastClientVersion = m_nClientVersion;
2566 m_lastOSInfo = m_sClientOSInfo;
2567
2568 if (m_clientSoft == SO_UNKNOWN) {
2569 theStats::AddUnknownClient();
2570 } else {
2571 theStats::AddKnownClient(this);
2572 }
2573 }
2574}
2575
2576bool CUpDownClient::IsIdentified() const
2577{
2578 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDENTIFIED);
2579}
2580
2581bool CUpDownClient::IsBadGuy() const
2582{
2583 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDBADGUY);
2584}
2585
2586bool CUpDownClient::SUIFailed() const
2587{
2588 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDFAILED);
2589}
2590
2591bool CUpDownClient::SUINeeded() const
2592{
2593 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_IDNEEDED);
2594}
2595
2596bool CUpDownClient::SUINotSupported() const
2597{
2598 return (credits && credits->GetCurrentIdentState(GetIP()) == IS_NOTAVAILABLE);
2599}
2600
2601uint64 CUpDownClient::GetDownloadedTotal() const
2602{
2603 return credits ? credits->GetDownloadedTotal() : 0;
2604}
2605
2606uint64 CUpDownClient::GetUploadedTotal() const
2607{
2608 return credits ? credits->GetUploadedTotal() : 0;
2609}
2610
2611double CUpDownClient::GetScoreRatio() const
2612{
2613 return credits ? credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable()) : 0;
2614}
2615
2616const wxString CUpDownClient::GetServerName() const
2617{
2618 wxString ret;
2619 wxString srvaddr = Uint32toStringIP(GetServerIP());
2620 CServer* cserver = theApp->serverlist->GetServerByAddress(
2621 srvaddr, GetServerPort());
2622 if (cserver) {
2623 ret = cserver->GetListName();
2624 } else {
2625 ret = _("Unknown")wxGetTranslation(("Unknown"));
2626 }
2627
2628 return ret;
2629}
2630
2631bool CUpDownClient::ShouldReceiveCryptUDPPackets() const
2632{
2633 return (thePrefs::IsClientCryptLayerSupported() && SupportsCryptLayer() && theApp->GetPublicIP() != 0
2634 && HasValidHash() && (thePrefs::IsClientCryptLayerRequested() || RequestsCryptLayer()) );
2635}
2636
2637#ifdef AMULE_DAEMON
2638
2639void CUpDownClient::ProcessCaptchaRequest(CMemFile* WXUNUSED(data)) {}
2640void CUpDownClient::ProcessCaptchaReqRes(uint8 WXUNUSED(nStatus)) {}
2641void CUpDownClient::ProcessChatMessage(const wxString WXUNUSED(message)) {}
2642
2643#else
2644
2645void CUpDownClient::ProcessCaptchaRequest(CMemFile* data)
2646{
2647 uint64 id = GUI_ID(GetIP(),GetUserPort())(uint64)((((uint64)GetIP())<<16) + (uint64)GetUserPort(
))
;
2648 // received a captcha request, check if we actually accept it (only after sending a message ourself to this client)
2649 if (GetChatCaptchaState() == CA_ACCEPTING && GetChatState() != MS_NONE
2650 && theApp->amuledlg->m_chatwnd->IsIdValid(id)) {
2651 // read tags (for future use)
2652 uint8 nTagCount = data->ReadUInt8();
2653 if (nTagCount) {
2654 AddDebugLogLineN(logClient, CFormat(wxT("Received captcha request from client (%s) with (%u) tags")) % GetFullIP() % nTagCount)do {} while (false);
2655 // and ignore them for now
2656 for (uint32 i = 0; i < nTagCount; i++) {
2657 CTag tag(*data, true);
2658 }
2659 }
2660
2661 // sanitize checks - we want a small captcha not a wallpaper
2662 uint32 nSize = (uint32)(data->GetLength() - data->GetPosition());
2663
2664 if ( nSize > 128 && nSize < 4096 ) {
2665 uint64 pos = data->GetPosition();
2666 wxMemoryInputStream memstr(data->GetRawBuffer() + pos, nSize);
2667 wxImage imgCaptcha(memstr, wxBITMAP_TYPE_BMP);
2668
2669 if (imgCaptcha.IsOk() && imgCaptcha.GetHeight() > 10 && imgCaptcha.GetHeight() < 50
2670 && imgCaptcha.GetWidth() > 10 && imgCaptcha.GetWidth() < 150 ) {
2671 m_nChatCaptchaState = CA_CAPTCHARECV;
2672 CCaptchaDialog * dialog = new CCaptchaDialog(theApp->amuledlg, imgCaptcha, id);
2673 dialog->Show();
2674
2675 } else {
2676 AddDebugLogLineN(logClient, CFormat(wxT("Received captcha request from client, processing image failed or invalid pixel size (%s)")) % GetFullIP())do {} while (false);
2677 }
2678 } else {
2679 AddDebugLogLineN(logClient, CFormat(wxT("Received captcha request from client, size sanitize check failed (%u) (%s)")) % nSize % GetFullIP())do {} while (false);
2680 }
2681 } else {
2682 AddDebugLogLineN(logClient, CFormat(wxT("Received captcha request from client, but don't accepting it at this time (%s)")) % GetFullIP())do {} while (false);
2683 }
2684}
2685
2686void CUpDownClient::ProcessCaptchaReqRes(uint8 nStatus)
2687{
2688 uint64 id = GUI_ID(GetIP(),GetUserPort())(uint64)((((uint64)GetIP())<<16) + (uint64)GetUserPort(
))
;
2689 if (GetChatCaptchaState() == CA_SOLUTIONSENT && GetChatState() != MS_NONE
2690 && theApp->amuledlg->m_chatwnd->IsIdValid(id)) {
2691 wxASSERT( nStatus < 3 )do { if ( nStatus < 3 ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("BaseClient.cpp", 2691, __FUNCTION__, "nStatus < 3"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
2692 m_nChatCaptchaState = CA_NONE;
2693 theApp->amuledlg->m_chatwnd->ShowCaptchaResult(id, nStatus == 0);
2694 } else {
2695 m_nChatCaptchaState = CA_NONE;
2696 AddDebugLogLineN(logClient, CFormat(wxT("Received captcha result from client, but not accepting it at this time (%s)")) % GetFullIP())do {} while (false);
2697 }
2698}
2699
2700void CUpDownClient::ProcessChatMessage(wxString message)
2701{
2702 if (IsMessageFiltered(message)) {
2703 AddLogLineC(CFormat(_("Message filtered from '%s' (IP:%s)")) % GetUserName() % GetFullIP())theLogger.AddLogLine(L"BaseClient.cpp", 2703, true, logStandard
, CFormat(wxGetTranslation(("Message filtered from '%s' (IP:%s)"
))) % GetUserName() % GetFullIP())
;
2704 return;
2705 }
2706
2707 // advanced spamfilter check
2708 if (thePrefs::IsChatCaptchaEnabled() && !IsFriend()) {
2709 // captcha checks outrank any further checks - if the captcha has been solved, we assume it's not spam
2710 // first check if we need to send a captcha request to this client
2711 if (GetMessagesSent() == 0 && GetMessagesReceived() == 0 && GetChatCaptchaState() != CA_CAPTCHASOLVED) {
2712 // we have never sent a message to this client, and no message from him has ever passed our filters
2713 if (GetChatCaptchaState() != CA_CHALLENGESENT) {
2714 // we also aren't currently expecting a captcha response
2715 if (m_fSupportsCaptcha) {
2716 // and he supports captcha, so send him one and store the message (without showing for now)
2717 if (m_cCaptchasSent < 3) { // no more than 3 tries
2718 m_strCaptchaPendingMsg = message;
2719 wxMemoryOutputStream memstr;
2720 memstr.PutC(0); // no tags, for future use
2721 CCaptchaGenerator captcha(4);
2722 if (captcha.WriteCaptchaImage(memstr)){
2723 m_strCaptchaChallenge = captcha.GetCaptchaText();
2724 m_nChatCaptchaState = CA_CHALLENGESENT;
2725 m_cCaptchasSent++;
2726 CMemFile fileAnswer((uint8_t*) memstr.GetOutputStreamBuffer()->GetBufferStart(), memstr.GetLength());
2727 CPacket* packet = new CPacket(fileAnswer, OP_EMULEPROT, OP_CHATCAPTCHAREQ);
2728 theStats::AddUpOverheadOther(packet->GetPacketSize());
2729 AddLogLineN(CFormat(wxT("sent Captcha %s (%d)")) % m_strCaptchaChallenge % packet->GetPacketSize())theLogger.AddLogLine(L"BaseClient.cpp", 2729, false, logStandard
, CFormat(L"sent Captcha %s (%d)") % m_strCaptchaChallenge % packet
->GetPacketSize())
;
2730 SafeSendPacket(packet);
2731 } else {
2732 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("BaseClient.cpp"
, 2732, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
2733 }
2734 }
2735 } else {
2736 // client doesn't support captchas, but we require them, tell him that it's not going to work out
2737 // with an answer message (will not be shown and doesn't count as sent message)
2738 if (m_cCaptchasSent < 1) { // don't send this notifier more than once
2739 m_cCaptchasSent++;
2740 // always sent in english
2741 SendChatMessage(wxT("In order to avoid spam messages, this user requires you to solve a captcha before you can send a message to him. However your client does not supports captchas, so you will not be able to chat with this user.")L"In order to avoid spam messages, this user requires you to solve a captcha before you can send a message to him. However your client does not supports captchas, so you will not be able to chat with this user.");
2742 AddDebugLogLineN(logClient, CFormat(wxT("Received message from client not supporting captchas, filtered and sent notifier (%s)")) % GetClientFullInfo())do {} while (false);
2743 } else {
2744 AddDebugLogLineN(logClient, CFormat(wxT("Received message from client not supporting captchas, filtered, didn't send notifier (%s)")) % GetClientFullInfo())do {} while (false);
2745 }
2746 }
2747 return;
2748 } else { // (GetChatCaptchaState() == CA_CHALLENGESENT)
2749 // this message must be the answer to the captcha request we sent him, let's verify
2750 wxASSERT( !m_strCaptchaChallenge.IsEmpty() )do { if ( !m_strCaptchaChallenge.IsEmpty() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2750, __FUNCTION__,
"!m_strCaptchaChallenge.IsEmpty()", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 )
;
2751 if (m_strCaptchaChallenge.CmpNoCase(message.Trim().Right(std::min(message.Length(), m_strCaptchaChallenge.Length()))) == 0) {
2752 // allright
2753 AddDebugLogLineN(logClient, CFormat(wxT("Captcha solved, showing withheld message (%s)")) % GetClientFullInfo())do {} while (false);
2754 m_nChatCaptchaState = CA_CAPTCHASOLVED; // this state isn't persitent, but the messagecounter will be used to determine later if the captcha has been solved
2755 // replace captchaanswer with withheld message and show it
2756 message = m_strCaptchaPendingMsg;
2757 m_cCaptchasSent = 0;
2758 m_strCaptchaChallenge.Clear();
2759 CPacket* packet = new CPacket(OP_CHATCAPTCHARES, 1, OP_EMULEPROT, false);
2760 uint8_t statusResponse = 0; // status response
2761 packet->CopyToDataBuffer(0, &statusResponse, 1);
2762 theStats::AddUpOverheadOther(packet->GetPacketSize());
2763 SafeSendPacket(packet);
2764 } else { // wrong, cleanup and ignore
2765 AddDebugLogLineN(logClient, CFormat(wxT("Captcha answer failed (%s)")) % GetClientFullInfo())do {} while (false);
2766 m_nChatCaptchaState = CA_NONE;
2767 m_strCaptchaChallenge.Clear();
2768 m_strCaptchaPendingMsg.Clear();
2769 CPacket* packet = new CPacket(OP_CHATCAPTCHARES, 1, OP_EMULEPROT, false);
2770 uint8_t statusResponse = (m_cCaptchasSent < 3) ? 1 : 2; // status response
2771 packet->CopyToDataBuffer(0, &statusResponse, 1);
2772 theStats::AddUpOverheadOther(packet->GetPacketSize());
2773 SafeSendPacket(packet);
2774 return; // nothing more todo
2775 }
2776 }
2777 }
2778 }
2779
2780 if (thePrefs::IsAdvancedSpamfilterEnabled() && !IsFriend()) { // friends are never spammer... (but what if two spammers are friends :P )
2781 bool bIsSpam = false;
2782 if (m_fIsSpammer) {
2783 bIsSpam = true;
2784 } else {
2785 // first fixed criteria: If a client sends me an URL in his first message before I respond to him
2786 // there is a 99,9% chance that it is some poor guy advising his leech mod, or selling you .. well you know :P
2787 if (GetMessagesSent() == 0) {
2788 static wxArrayString urlindicators(wxStringTokenize(wxT("http:|www.|.de |.net |.com |.org |.to |.tk |.cc |.fr |ftp:|ed2k:|https:|ftp.|.info|.biz|.uk|.eu|.es|.tv|.cn|.tw|.ws|.nu|.jp")L"http:|www.|.de |.net |.com |.org |.to |.tk |.cc |.fr |ftp:|ed2k:|https:|ftp.|.info|.biz|.uk|.eu|.es|.tv|.cn|.tw|.ws|.nu|.jp", wxT("|")L"|"));
2789 for (size_t pos = urlindicators.GetCount(); pos--;) {
2790 if (message.Find(urlindicators[pos]) != wxNOT_FOUND(-1)) {
2791 bIsSpam = true;
2792 break;
2793 }
2794 }
2795 // second fixed criteria: he sent me 4 or more messages and I didn't answer him once
2796 if (GetMessagesReceived() > 3) {
2797 bIsSpam = true;
2798 }
2799 }
2800 }
2801 if (bIsSpam) {
2802 AddDebugLogLineN(logClient, CFormat(wxT("'%s' has been marked as spammer")) % GetUserName())do {} while (false);
2803 SetSpammer(true);
2804 theApp->amuledlg->m_chatwnd->EndSession(GUI_ID(GetIP(),GetUserPort())(uint64)((((uint64)GetIP())<<16) + (uint64)GetUserPort(
))
);
2805 return;
2806 }
2807 }
2808
2809
2810 wxString logMsg = CFormat(_("New message from '%s' (IP:%s)")wxGetTranslation(("New message from '%s' (IP:%s)"))) % GetUserName() % GetFullIP();
2811 if(thePrefs::ShowMessagesInLog()) {
2812 logMsg += wxT(": ")L": " + message;
2813 }
2814 AddLogLineC(logMsg)theLogger.AddLogLine(L"BaseClient.cpp", 2814, true, logStandard
, logMsg)
;
2815 IncMessagesReceived();
2816
2817 Notify_ChatProcessMsg(GUI_ID(GetIP(), GetUserPort()), GetUserName() + wxT("|") + message)MuleNotify::DoNotify(&MuleNotify::ChatProcessMsg, (uint64
)((((uint64)GetIP())<<16) + (uint64)GetUserPort()), GetUserName
() + L"|" + message)
;
2818}
2819
2820bool CUpDownClient::IsMessageFiltered(const wxString& message)
2821{
2822 bool filtered = false;
2823 // If we're chatting to the guy, we don't want to filter!
2824 if (GetChatState() != MS_CHATTING) {
2825 if (thePrefs::MsgOnlyFriends() && !IsFriend()) {
2826 filtered = true;
2827 } else if (thePrefs::MsgOnlySecure() && GetUserName().IsEmpty() ) {
2828 filtered = true;
2829 } else if (thePrefs::MustFilterMessages()) {
2830 filtered = thePrefs::IsMessageFiltered(message);
2831 }
2832 }
2833 if (filtered) {
2834 SetSpammer(true);
2835 }
2836 return filtered;
2837}
2838
2839#endif
2840
2841void CUpDownClient::SendSharedDirectories()
2842{
2843 // This list will contain all (unique) folders.
2844 PathList foldersToSend;
2845
2846 // The shared folders
2847 const unsigned folderCount = theApp->glob_prefs->shareddir_list.size();
2848 for (unsigned i = 0; i < folderCount; ++i) {
2849 foldersToSend.push_back(theApp->glob_prefs->shareddir_list[i]);
2850 }
2851
2852 // ... the categories folders ... (category 0 -> incoming)
2853 for (unsigned i = 0; i < theApp->glob_prefs->GetCatCount(); ++i) {
2854 foldersToSend.push_back(theApp->glob_prefs->GetCategory(i)->path);
2855 }
2856
2857 // Strip duplicates
2858 foldersToSend.sort();
2859 foldersToSend.unique();
2860
2861 // Build packet
2862 CMemFile tempfile(80);
2863 tempfile.WriteUInt32(foldersToSend.size() + 1); // + 1 for the incomplete files
2864
2865 PathList::iterator it = foldersToSend.begin();
2866 for (; it != foldersToSend.end(); ++it) {
2867 // Note: the public shared name contains the 'raw' path, so we can recognize it again.
2868 // the 'raw' path is determined using CPath::GetRaw()
2869 tempfile.WriteString( theApp->sharedfiles->GetPublicSharedDirName(*it), GetUnicodeSupport() );
2870 }
2871
2872 // ... and the Magic thing from the eDonkey Hybrids...
2873 tempfile.WriteString(OP_INCOMPLETE_SHARED_FILESL"!Incomplete Files", GetUnicodeSupport());
2874
2875 // Send the packet.
2876 CPacket* replypacket = new CPacket(tempfile, OP_EDONKEYPROT, OP_ASKSHAREDDIRSANS);
2877 theStats::AddUpOverheadOther(replypacket->GetPacketSize());
2878 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDDIRSANS to ") + GetFullIP() )do {} while (false);
2879 SendPacket(replypacket, true, true);
2880}
2881
2882void CUpDownClient::SendSharedFilesOfDirectory(const wxString& strReqDir)
2883{
2884 CKnownFilePtrList list;
2885
2886 if (strReqDir == OP_INCOMPLETE_SHARED_FILESL"!Incomplete Files") {
2887 // get all shared files from download queue
2888 int iQueuedFiles = theApp->downloadqueue->GetFileCount();
2889 for (int i = 0; i < iQueuedFiles; i++) {
2890 CPartFile* pFile = theApp->downloadqueue->GetFileByIndex(i);
2891 if (pFile == NULL__null || pFile->GetStatus(true) != PS_READY0) {
2892 continue;
2893 }
2894 list.push_back(pFile);
2895 }
2896 } else {
2897 // get all shared files for the requested directory
2898 const CPath *sharedDir = theApp->sharedfiles->GetDirForPublicSharedDirName(strReqDir);
2899 if (sharedDir) {
2900 theApp->sharedfiles->GetSharedFilesByDirectory(sharedDir->GetRaw(), list);
2901 } else {
2902 AddLogLineC(CFormat(_("User %s (%u) requested sharedfiles-list for not existing directory '%s' -> Ignored")) % GetUserName() % GetUserIDHybrid() % strReqDir)theLogger.AddLogLine(L"BaseClient.cpp", 2902, true, logStandard
, CFormat(wxGetTranslation(("User %s (%u) requested sharedfiles-list for not existing directory '%s' -> Ignored"
))) % GetUserName() % GetUserIDHybrid() % strReqDir)
;
2903 }
2904 }
2905
2906 CMemFile tempfile(80);
2907 tempfile.WriteString(strReqDir, GetUnicodeSupport());
2908 tempfile.WriteUInt32(list.size());
2909
2910 while (!list.empty()) {
2911 if (!list.front()->IsLargeFile() || SupportsLargeFiles()) {
2912 list.front()->CreateOfferedFilePacket(&tempfile, NULL__null, this);
2913 }
2914 list.pop_front();
2915 }
2916
2917 CPacket* replypacket = new CPacket(tempfile, OP_EDONKEYPROT, OP_ASKSHAREDFILESDIRANS);
2918 theStats::AddUpOverheadOther(replypacket->GetPacketSize());
2919 AddDebugLogLineN( logLocalClient, wxT("Local Client: OP_ASKSHAREDFILESDIRANS to ") + GetFullIP() )do {} while (false);
2920 SendPacket(replypacket, true, true);
2921}
2922
2923void CUpDownClient::SendFirewallCheckUDPRequest()
2924{
2925 wxASSERT(GetKadState() == KS_FWCHECK_UDP)do { if ( GetKadState() == KS_FWCHECK_UDP ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("BaseClient.cpp", 2925, __FUNCTION__,
"GetKadState() == KS_FWCHECK_UDP", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 )
;
2926
2927 if (!Kademlia::CKademlia::IsRunning()) {
2928 SetKadState(KS_NONE);
2929 return;
2930 } else if (GetUploadState() != US_NONE || GetDownloadState() != DS_NONE || GetChatState() != MS_NONE || GetKadVersion() <= 5 || GetKadPort() == 0) {
2931 Kademlia::CUDPFirewallTester::SetUDPFWCheckResult(false, true, wxUINT32_SWAP_ALWAYS(GetIP())((wxUint32) ( (((wxUint32) (GetIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetIP()) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (GetIP()) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (GetIP()) & (wxUint32) 0xff000000U
) >> 24)))
, 0); // inform the tester that this test was cancelled
2932 SetKadState(KS_NONE);
2933 return;
2934 }
2935
2936 CMemFile data;
2937 data.WriteUInt16(Kademlia::CKademlia::GetPrefs()->GetInternKadPort());
2938 data.WriteUInt16(Kademlia::CKademlia::GetPrefs()->GetExternalKadPort());
2939 data.WriteUInt32(Kademlia::CKademlia::GetPrefs()->GetUDPVerifyKey(GetConnectIP()));
2940 CPacket* packet = new CPacket(data, OP_EMULEPROT, OP_FWCHECKUDPREQ);
2941 theStats::AddUpOverheadKad(packet->GetPacketSize());
2942 SafeSendPacket(packet);
2943}
2944
2945void CUpDownClient::ProcessFirewallCheckUDPRequest(CMemFile* data)
2946{
2947 if (!Kademlia::CKademlia::IsRunning() || Kademlia::CKademlia::GetUDPListener() == NULL__null) {
2948 //DebugLogWarning(_T("Ignored Kad Firewallrequest UDP because Kad is not running (%s)"), GetClientFullInfo());
2949 return;
2950 }
2951
2952 // first search if we know this IP already, if so the result might be biased and we need tell the requester
2953 bool errorAlreadyKnown = false;
2954 if (GetUploadState() != US_NONE || GetDownloadState() != DS_NONE || GetChatState() != MS_NONE) {
2955 errorAlreadyKnown = true;
2956 } else if (Kademlia::CKademlia::GetRoutingZone()->GetContact(wxUINT32_SWAP_ALWAYS(GetConnectIP())((wxUint32) ( (((wxUint32) (GetConnectIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetConnectIP()) & (wxUint32
) 0x0000ff00U) << 8) | (((wxUint32) (GetConnectIP()) &
(wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (GetConnectIP
()) & (wxUint32) 0xff000000U) >> 24)))
, 0, false) != NULL__null) {
2957 errorAlreadyKnown = true;
2958 }
2959
2960 uint16_t remoteInternPort = data->ReadUInt16();
2961 uint16_t remoteExternPort = data->ReadUInt16();
2962 uint32_t senderKey = data->ReadUInt32();
2963 if (remoteInternPort == 0) {
2964 //DebugLogError(_T("UDP Firewallcheck requested with Intern Port == 0 (%s)"), GetClientFullInfo());
2965 return;
2966 }
2967// if (senderKey == 0)
2968// DebugLogWarning(_T("UDP Firewallcheck requested with SenderKey == 0 (%s)"), GetClientFullInfo());
2969
2970 CMemFile testPacket1;
2971 testPacket1.WriteUInt8(errorAlreadyKnown ? 1 : 0);
2972 testPacket1.WriteUInt16(remoteInternPort);
2973 DebugSend(Kad2FirewallUDP, wxUINT32_SWAP_ALWAYS(GetConnectIP()), remoteInternPort)do {} while (false);
2974 Kademlia::CKademlia::GetUDPListener()->SendPacket(testPacket1, KADEMLIA2_FIREWALLUDP, wxUINT32_SWAP_ALWAYS(GetConnectIP())((wxUint32) ( (((wxUint32) (GetConnectIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetConnectIP()) & (wxUint32
) 0x0000ff00U) << 8) | (((wxUint32) (GetConnectIP()) &
(wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (GetConnectIP
()) & (wxUint32) 0xff000000U) >> 24)))
, remoteInternPort, Kademlia::CKadUDPKey(senderKey, theApp->GetPublicIP(false)), NULL__null);
2975
2976 // if the client has a router with PAT (and therefore a different extern port than intern), test this port too
2977 if (remoteExternPort != 0 && remoteExternPort != remoteInternPort) {
2978 CMemFile testPacket2;
2979 testPacket2.WriteUInt8(errorAlreadyKnown ? 1 : 0);
2980 testPacket2.WriteUInt16(remoteExternPort);
2981 DebugSend(Kad2FirewalledUDP, wxUINT32_SWAP_ALWAYS(GetConnectIP()), remoteExternPort)do {} while (false);
2982 Kademlia::CKademlia::GetUDPListener()->SendPacket(testPacket2, KADEMLIA2_FIREWALLUDP, wxUINT32_SWAP_ALWAYS(GetConnectIP())((wxUint32) ( (((wxUint32) (GetConnectIP()) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (GetConnectIP()) & (wxUint32
) 0x0000ff00U) << 8) | (((wxUint32) (GetConnectIP()) &
(wxUint32) 0x00ff0000U) >> 8) | (((wxUint32) (GetConnectIP
()) & (wxUint32) 0xff000000U) >> 24)))
, remoteExternPort, Kademlia::CKadUDPKey(senderKey, theApp->GetPublicIP(false)), NULL__null);
2983 }
2984 //DebugLog(_T("Answered UDP Firewallcheck request (%s)"), GetClientFullInfo());
2985}
2986
2987void CUpDownClient::SetConnectOptions(uint8_t options, bool encryption, bool callback)
2988{
2989 SetCryptLayerSupport((options & 0x01) != 0 && encryption);
2990 SetCryptLayerRequest((options & 0x02) != 0 && encryption);
2991 SetCryptLayerRequires((options & 0x04) != 0 && encryption);
2992 SetDirectUDPCallbackSupport((options & 0x08) != 0 && callback);
2993}
2994
2995
2996#ifdef DEBUG_ZOMBIE_CLIENTS
2997void CUpDownClient::Unlink(const wxString& from)
2998{
2999 std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
3000 if (it != m_linkedFrom.end()) {
3001 m_linkedFrom.erase(it);
3002 }
3003 m_linked--;
3004 if (!m_linked) {
3005 if (m_linkedDebug) {
3006 AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this)theLogger.AddLogLine(L"BaseClient.cpp", 3006, false, logStandard
, CFormat(L"Last reference to client %d %p unlinked, delete it."
) % ECID() % this)
;
3007 }
3008 delete this;
3009 }
3010}
3011
3012#else
3013
3014void CUpDownClient::Unlink()
3015{
3016 m_linked--;
3017 if (!m_linked) {
3018 delete this;
3019 }
3020}
3021#endif
3022
3023
3024// File_checked_for_headers