1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 //
24
25
26 #include <wx/ipc.h>
27 #include <wx/cmdline.h> // Needed for wxCmdLineParser
28 #include <wx/config.h> // Do_not_auto_remove (win32)
29 #include <wx/fileconf.h> // Needed for wxFileConfig
30 #include <wx/socket.h> // Needed for wxSocketBase
31
32
33 #include <common/Format.h>
34 #include <common/StringFunctions.h>
35 #include <common/MD5Sum.h>
36
37
38 #include <include/common/EventIDs.h>
39
40
41 #include "amule.h" // Interface declarations.
42 #include "amuleDlg.h" // Needed for CamuleDlg
43 #include "ClientCredits.h"
44 #include "SourceListCtrl.h"
45 #include "ChatWnd.h"
46 #include "DataToText.h" // Needed for GetSoftName()
47 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
48 #include "Friend.h"
49 #include "GetTickCount.h" // Needed for GetTickCount
50 #include "GuiEvents.h"
51 #ifdef ENABLE_IP2COUNTRY
52 #include "IP2Country.h" // Needed for IP2Country
53 #endif
54 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
55 #include "Logger.h"
56 #include "muuli_wdr.h" // Needed for IDs
57 #include "PartFile.h" // Needed for CPartFile
58 #include "SearchDlg.h" // Needed for CSearchDlg
59 #include "Server.h" // Needed for GetListName
60 #include "ServerWnd.h" // Needed for CServerWnd
61 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
62 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
63 #include "TransferWnd.h" // Needed for CTransferWnd
64 #include "UpDownClientEC.h" // Needed for CUpDownClient
65 #include "ServerListCtrl.h" // Needed for CServerListCtrl
66 #include "ScopedPtr.h"
67 #include "StatisticsDlg.h" // Needed for CStatisticsDlg
68
69
CEConnectDlg()70 CEConnectDlg::CEConnectDlg()
71 :
72 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
73 {
74 CoreConnect(this, true);
75
76 wxString pref_host, pref_port;
77 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
78 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
79 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
80
81 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
82 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
83 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
84
85 CentreOnParent();
86 }
87
88
PassHash()89 wxString CEConnectDlg::PassHash()
90 {
91 return pwd_hash;
92 }
93
94
BEGIN_EVENT_TABLE(CEConnectDlg,wxDialog)95 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
96 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
97 END_EVENT_TABLE()
98
99
100 void CEConnectDlg::OnOK(wxCommandEvent& evt)
101 {
102 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
103 port = StrToLong(s_port);
104
105 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
106 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
107
108 if (passwd != pwd_hash) {
109 pwd_hash = MD5Sum(passwd).GetHash();
110 }
111 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
112 evt.Skip();
113 }
114
115
116 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
117
118
BEGIN_EVENT_TABLE(CamuleRemoteGuiApp,wxApp)119 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
120 // Core timer
121 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
122
123 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
124 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
125
126 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
127
128 #ifdef ENABLE_IP2COUNTRY
129 // HTTPDownload finished
130 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
131 #endif
132 END_EVENT_TABLE()
133
134
135 IMPLEMENT_APP(CamuleRemoteGuiApp)
136
137
138 int CamuleRemoteGuiApp::OnExit()
139 {
140 StopTickTimer();
141
142 wxSocketBase::Shutdown(); // needed because we also called Initialize() manually
143
144 return wxApp::OnExit();
145 }
146
147
OnPollTimer(wxTimerEvent &)148 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
149 {
150 static int request_step = 0;
151 static uint32 msPrevStats = 0;
152
153 if (m_connect->RequestFifoFull()) {
154 return;
155 }
156
157 switch (request_step) {
158 case 0:
159 // We used to update the connection state here, but that's done with the stats in the next step now.
160 request_step++;
161 break;
162 case 1: {
163 CECPacket stats_req(EC_OP_STAT_REQ, EC_DETAIL_INC_UPDATE);
164 m_connect->SendRequest(&m_stats_updater, &stats_req);
165 request_step++;
166 break;
167 }
168 case 2:
169 if (amuledlg->m_sharedfileswnd->IsShown()
170 || amuledlg->m_chatwnd->IsShown()
171 || amuledlg->m_serverwnd->IsShown()) {
172 // update downloads, shared files and servers
173 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
174 } else if (amuledlg->m_transferwnd->IsShown()) {
175 // update both downloads and shared files
176 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
177 } else if (amuledlg->m_searchwnd->IsShown()) {
178 if (searchlist->m_curr_search != -1) {
179 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
180 }
181 } else if (amuledlg->m_statisticswnd->IsShown()) {
182 int sStatsUpdate = thePrefs::GetStatsInterval();
183 uint32 msCur = theStats::GetUptimeMillis();
184 if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) {
185 msPrevStats = msCur;
186 stattree->DoRequery();
187 }
188 }
189 // Back to the roots
190 request_step = 0;
191 break;
192 default:
193 wxFAIL;
194 request_step = 0;
195 }
196
197 // Check for new links once per second.
198 static uint32 lastED2KLinkCheck = 0;
199 if (GetTickCount() - lastED2KLinkCheck >= 1000) {
200 AddLinksFromFile();
201 lastED2KLinkCheck = GetTickCount();
202 }
203 }
204
205
OnFinishedHTTPDownload(CMuleInternalEvent & event)206 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
207 {
208 if (event.GetInt() == HTTP_GeoIP) {
209 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
210 // If we updated, the dialog is already up. Redraw it to show the flags.
211 amuledlg->Refresh();
212 }
213 }
214
215
ShutDown(wxCloseEvent & WXUNUSED (evt))216 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
217 {
218 // Stop the Core Timer
219 delete poll_timer;
220 poll_timer = NULL;
221
222 #ifdef ASIO_SOCKETS
223 m_AsioService->Stop();
224 delete m_AsioService;
225 m_AsioService = NULL;
226 #endif
227
228 // Destroy the EC socket
229 m_connect->Destroy();
230 m_connect = NULL;
231
232 //
233 if (amuledlg) {
234 amuledlg->DlgShutDown();
235 amuledlg->Destroy();
236 amuledlg = NULL;
237 }
238 delete m_allUploadingKnownFile;
239 delete stattree;
240 }
241
242
OnInit()243 bool CamuleRemoteGuiApp::OnInit()
244 {
245 StartTickTimer();
246 amuledlg = NULL;
247
248 // Get theApp
249 theApp = &wxGetApp();
250
251 // Handle uncaught exceptions
252 InstallMuleExceptionHandler();
253
254 // Parse cmdline arguments.
255 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
256 return false;
257 }
258
259 // Initialize wx sockets (needed for http download in background with Asio sockets)
260 wxSocketBase::Initialize();
261
262 // Create the polling timer
263 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
264 if (!poll_timer) {
265 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
266 OnExit();
267 }
268
269 m_connect = new CRemoteConnect(this);
270
271 #ifdef ASIO_SOCKETS
272 m_AsioService = new CAsioService;
273 #endif
274
275 glob_prefs = new CPreferencesRem(m_connect);
276 long enableZLIB;
277 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
278 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification
279
280 InitCustomLanguages();
281 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
282
283 if (ShowConnectionDialog()) {
284 AddLogLineNS(_("Going to event loop..."));
285 return true;
286 }
287
288 return false;
289 }
290
291
CryptoAvailable() const292 bool CamuleRemoteGuiApp::CryptoAvailable() const
293 {
294 return thePrefs::IsSecureIdentEnabled(); // good enough
295 }
296
297
ShowConnectionDialog()298 bool CamuleRemoteGuiApp::ShowConnectionDialog()
299 {
300 dialog = new CEConnectDlg;
301
302 if (m_skipConnectionDialog) {
303 wxCommandEvent evt;
304 dialog->OnOK(evt);
305 } else if (dialog->ShowModal() != wxID_OK) {
306 dialog->Destroy();
307
308 return false;
309 }
310 AddLogLineNS(_("Connecting..."));
311 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
312 dialog->Login(), dialog->PassHash(),
313 wxT("amule-remote"), wxT("0x0001"))) {
314 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
315
316 return false;
317 }
318
319 return true;
320 }
321
322
OnECConnection(wxEvent & event)323 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
324 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
325 AddLogLineNS(_("Remote GUI EC event handler"));
326 wxString reply = evt.GetServerReply();
327 AddLogLineC(reply);
328 if (evt.GetResult() == true) {
329 // Connected - go to next init step
330 glob_prefs->LoadRemote();
331 } else {
332 AddLogLineNS(_("Going down"));
333 if (dialog) { // connect failed
334 wxMessageBox(
335 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
336 _("ERROR"), wxOK);
337 } else { // server disconnected (probably terminated) later
338 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
339 }
340 wxCloseEvent ev;
341 ShutDown(ev);
342 ExitMainLoop();
343 }
344 }
345
346
OnECInitDone(wxEvent &)347 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
348 {
349 Startup();
350 }
351
352
OnNotifyEvent(CMuleGUIEvent & evt)353 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
354 {
355 evt.Notify();
356 }
357
358
Startup()359 void CamuleRemoteGuiApp::Startup() {
360
361 if (dialog->SaveUserPass()) {
362 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
363 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
364 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
365 }
366 dialog->Destroy();
367 dialog = NULL;
368
369 m_ConnState = 0;
370 m_clientID = 0;
371
372 serverconnect = new CServerConnectRem(m_connect);
373 m_statistics = new CStatistics(*m_connect);
374 stattree = new CStatTreeRem(m_connect);
375
376 clientlist = new CUpDownClientListRem(m_connect);
377 searchlist = new CSearchListRem(m_connect);
378 serverlist = new CServerListRem(m_connect);
379 friendlist = new CFriendListRem(m_connect);
380
381
382 sharedfiles = new CSharedFilesRem(m_connect);
383 knownfiles = new CKnownFilesRem(m_connect);
384
385 downloadqueue = new CDownQueueRem(m_connect);
386 ipfilter = new CIPFilterRem(m_connect);
387
388 m_allUploadingKnownFile = new CKnownFile;
389
390 // Create main dialog
391 InitGui(m_geometryEnabled, m_geometryString);
392
393 // Forward wxLog events to CLogger
394 wxLog::SetActiveTarget(new CLoggerTarget);
395 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
396
397 // Start the Poll Timer
398 poll_timer->Start(1000);
399 amuledlg->StartGuiTimer();
400
401 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
402 #ifdef ENABLE_IP2COUNTRY
403 if (thePrefs::IsGeoIPEnabled()) {
404 amuledlg->m_IP2Country->Enable();
405 }
406 #endif
407 }
408
409
ShowAlert(wxString msg,wxString title,int flags)410 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
411 {
412 return CamuleGuiBase::ShowAlert(msg, title, flags);
413 }
414
415
AddRemoteLogLine(const wxString & line)416 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
417 {
418 amuledlg->AddLogLine(line);
419 }
420
InitGui(bool geometry_enabled,wxString & geom_string)421 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
422 {
423 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
424 SetTopWindow(amuledlg);
425 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
426 return 0;
427 }
428
429
CopyTextToClipboard(wxString strText)430 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
431 {
432 return CamuleGuiBase::CopyTextToClipboard(strText);
433 }
434
435
GetPublicIP()436 uint32 CamuleRemoteGuiApp::GetPublicIP()
437 {
438 return 0;
439 }
440
441
GetLog(bool reset)442 wxString CamuleRemoteGuiApp::GetLog(bool reset)
443 {
444 if (reset) {
445 amuledlg->ResetLog(ID_LOGVIEW);
446 CECPacket req(EC_OP_RESET_LOG);
447 m_connect->SendPacket(&req);
448 }
449 return wxEmptyString;
450 }
451
452
GetServerLog(bool)453 wxString CamuleRemoteGuiApp::GetServerLog(bool)
454 {
455 return wxEmptyString;
456 }
457
458
AddServer(CServer * server,bool)459 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
460 {
461 CECPacket req(EC_OP_SERVER_ADD);
462 req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort()));
463 req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName()));
464 m_connect->SendPacket(&req);
465
466 return true;
467 }
468
469
IsFirewalled() const470 bool CamuleRemoteGuiApp::IsFirewalled() const
471 {
472 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
473 return false;
474 }
475
476 return IsFirewalledKad();
477 }
478
479
IsConnectedED2K() const480 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
481 return serverconnect && serverconnect->IsConnected();
482 }
483
484
StartKad()485 void CamuleRemoteGuiApp::StartKad() {
486 m_connect->StartKad();
487 }
488
489
StopKad()490 void CamuleRemoteGuiApp::StopKad() {
491 m_connect->StopKad();
492 }
493
494
BootstrapKad(uint32 ip,uint16 port)495 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
496 {
497 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
498 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
499 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
500
501 m_connect->SendPacket(&req);
502 }
503
504
UpdateNotesDat(const wxString & url)505 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
506 {
507 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
508 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
509
510 m_connect->SendPacket(&req);
511 }
512
513
DisconnectED2K()514 void CamuleRemoteGuiApp::DisconnectED2K() {
515 if (IsConnectedED2K()) {
516 m_connect->DisconnectED2K();
517 }
518 }
519
520
GetED2KID() const521 uint32 CamuleRemoteGuiApp::GetED2KID() const
522 {
523 return serverconnect ? serverconnect->GetClientID() : 0;
524 }
525
526
GetID() const527 uint32 CamuleRemoteGuiApp::GetID() const
528 {
529 return m_clientID;
530 }
531
532
ShowUserCount()533 void CamuleRemoteGuiApp::ShowUserCount() {
534 wxString buffer;
535
536 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
537 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
538
539 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
540 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
541 } else if (thePrefs::GetNetworkED2K()) {
542 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
543 } else if (thePrefs::GetNetworkKademlia()) {
544 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
545 } else {
546 buffer = _("No networks selected");
547 }
548
549 Notify_ShowUserCount(buffer);
550 }
551
552
553 /*
554 * Preferences: holds both local and remote settings.
555 *
556 * First, everything is loaded from local config file. Later, settings
557 * that are relevant on remote side only are loaded thru EC
558 */
CPreferencesRem(CRemoteConnect * conn)559 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
560 {
561 m_conn = conn;
562
563 //
564 // Settings queried from remote side
565 //
566 m_exchange_send_selected_prefs =
567 EC_PREFS_GENERAL |
568 EC_PREFS_CONNECTIONS |
569 EC_PREFS_MESSAGEFILTER |
570 EC_PREFS_ONLINESIG |
571 EC_PREFS_SERVERS |
572 EC_PREFS_FILES |
573 EC_PREFS_DIRECTORIES |
574 EC_PREFS_SECURITY |
575 EC_PREFS_CORETWEAKS |
576 EC_PREFS_REMOTECONTROLS |
577 EC_PREFS_KADEMLIA;
578 m_exchange_recv_selected_prefs =
579 m_exchange_send_selected_prefs |
580 EC_PREFS_CATEGORIES;
581 }
582
583
HandlePacket(const CECPacket * packet)584 void CPreferencesRem::HandlePacket(const CECPacket *packet)
585 {
586 static_cast<const CEC_Prefs_Packet *>(packet)->Apply();
587
588 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
589 if (cat_tags) {
590 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); ++it) {
591 const CECTag &cat_tag = *it;
592 Category_Struct *cat = new Category_Struct;
593 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
594 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
595 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
596 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
597 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
598 theApp->glob_prefs->AddCat(cat);
599 }
600 } else {
601 Category_Struct *cat = new Category_Struct;
602 cat->title = _("All");
603 cat->color = 0;
604 cat->prio = PR_NORMAL;
605 theApp->glob_prefs->AddCat(cat);
606 }
607 wxECInitDoneEvent event;
608 theApp->AddPendingEvent(event);
609
610 }
611
612
LoadRemote()613 bool CPreferencesRem::LoadRemote()
614 {
615 //
616 // override local settings with remote
617 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
618
619 // bring categories too
620 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
621
622 m_conn->SendRequest(this, &req);
623
624 return true;
625 }
626
627
SendToRemote()628 void CPreferencesRem::SendToRemote()
629 {
630 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
631 m_conn->SendPacket(&pref_packet);
632 }
633
634
635 class CCatHandler : public CECPacketHandlerBase {
636 virtual void HandlePacket(const CECPacket *packet);
637 };
638
639
HandlePacket(const CECPacket * packet)640 void CCatHandler::HandlePacket(const CECPacket *packet)
641 {
642 if (packet->GetOpCode() == EC_OP_FAILED) {
643 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
644 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
645 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
646 int cat = catTag->GetInt();
647 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
648 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
649 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
650 _("ERROR"), wxOK);
651 cs->path = CPath(pathTag->GetStringData());
652 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
653 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
654 }
655 }
656 delete this;
657 }
658
659
CreateCategory(Category_Struct * & category,const wxString & name,const CPath & path,const wxString & comment,uint32 color,uint8 prio)660 bool CPreferencesRem::CreateCategory(
661 Category_Struct *& category,
662 const wxString& name,
663 const CPath& path,
664 const wxString& comment,
665 uint32 color,
666 uint8 prio)
667 {
668 CECPacket req(EC_OP_CREATE_CATEGORY);
669 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
670 req.AddTag(tag);
671 m_conn->SendRequest(new CCatHandler, &req);
672
673 category = new Category_Struct();
674 category->path = path;
675 category->title = name;
676 category->comment = comment;
677 category->color = color;
678 category->prio = prio;
679
680 AddCat(category);
681
682 return true;
683 }
684
685
UpdateCategory(uint8 cat,const wxString & name,const CPath & path,const wxString & comment,uint32 color,uint8 prio)686 bool CPreferencesRem::UpdateCategory(
687 uint8 cat,
688 const wxString& name,
689 const CPath& path,
690 const wxString& comment,
691 uint32 color,
692 uint8 prio)
693 {
694 CECPacket req(EC_OP_UPDATE_CATEGORY);
695 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
696 req.AddTag(tag);
697 m_conn->SendRequest(new CCatHandler, &req);
698
699 Category_Struct *category = m_CatList[cat];
700 category->path = path;
701 category->title = name;
702 category->comment = comment;
703 category->color = color;
704 category->prio = prio;
705
706 return true;
707 }
708
709
RemoveCat(uint8 cat)710 void CPreferencesRem::RemoveCat(uint8 cat)
711 {
712 CECPacket req(EC_OP_DELETE_CATEGORY);
713 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
714 req.AddTag(tag);
715 m_conn->SendPacket(&req);
716 CPreferences::RemoveCat(cat);
717 }
718
719
720 //
721 // Container implementation
722 //
CServerConnectRem(CRemoteConnect * conn)723 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
724 {
725 m_CurrServer = 0;
726 m_Conn = conn;
727 }
728
729
ConnectToAnyServer()730 void CServerConnectRem::ConnectToAnyServer()
731 {
732 CECPacket req(EC_OP_SERVER_CONNECT);
733 m_Conn->SendPacket(&req);
734 }
735
736
StopConnectionTry()737 void CServerConnectRem::StopConnectionTry()
738 {
739 // lfroen: isn't Disconnect the same ?
740 }
741
742
Disconnect()743 void CServerConnectRem::Disconnect()
744 {
745 CECPacket req(EC_OP_SERVER_DISCONNECT);
746 m_Conn->SendPacket(&req);
747 }
748
749
ConnectToServer(CServer * server)750 void CServerConnectRem::ConnectToServer(CServer *server)
751 {
752 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
753 }
754
755
HandlePacket(const CECPacket * packet)756 void CServerConnectRem::HandlePacket(const CECPacket *packet)
757 {
758 const CEC_ConnState_Tag *tag = static_cast<const CEC_ConnState_Tag *>(packet->GetTagByName(EC_TAG_CONNSTATE));
759 if (!tag) {
760 return;
761 }
762
763 theApp->m_ConnState = 0;
764 CServer *server;
765 m_ID = tag->GetEd2kId();
766 theApp->m_clientID = tag->GetClientId();
767 tag->GetKadID(theApp->m_kadID);
768
769 if (tag->IsConnectedED2K()) {
770 const CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
771 if (srvtag) {
772 server = theApp->serverlist->GetByID(srvtag->GetInt());
773 if (server != m_CurrServer) {
774 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(server, true);
775 m_CurrServer = server;
776 }
777 }
778 theApp->m_ConnState |= CONNECTED_ED2K;
779 } else if ( m_CurrServer ) {
780 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(m_CurrServer, false);
781 m_CurrServer = 0;
782 }
783
784 if (tag->IsConnectedKademlia()) {
785 if (tag->IsKadFirewalled()) {
786 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
787 } else {
788 theApp->m_ConnState |= CONNECTED_KAD_OK;
789 }
790 } else {
791 if (tag->IsKadRunning()) {
792 theApp->m_ConnState |= CONNECTED_KAD_NOT;
793 }
794 }
795
796 theApp->amuledlg->ShowConnectionState();
797 }
798
799
800 /*
801 * Server list: host list of ed2k servers.
802 */
CServerListRem(CRemoteConnect * conn)803 CServerListRem::CServerListRem(CRemoteConnect *conn)
804 :
805 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true)
806 {
807 }
808
809
HandlePacket(const CECPacket *)810 void CServerListRem::HandlePacket(const CECPacket *)
811 {
812 // There is no packet for the server list, it is part of the general update packet
813 wxFAIL;
814 // CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
815 }
816
817
UpdateServerMetFromURL(wxString url)818 void CServerListRem::UpdateServerMetFromURL(wxString url)
819 {
820 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
821 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
822
823 m_conn->SendPacket(&req);
824 }
825
826
SetStaticServer(CServer * server,bool isStatic)827 void CServerListRem::SetStaticServer(CServer* server, bool isStatic)
828 {
829 // update display right away
830 server->SetIsStaticMember(isStatic);
831 Notify_ServerRefresh(server);
832
833 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
834 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
835 req.AddTag(CECTag(EC_TAG_SERVER_STATIC, isStatic));
836
837 m_conn->SendPacket(&req);
838 }
839
840
SetServerPrio(CServer * server,uint32 prio)841 void CServerListRem::SetServerPrio(CServer* server, uint32 prio)
842 {
843 // update display right away
844 server->SetPreference(prio);
845 Notify_ServerRefresh(server);
846
847 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
848 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
849 req.AddTag(CECTag(EC_TAG_SERVER_PRIO, prio));
850
851 m_conn->SendPacket(&req);
852 }
853
854
RemoveServer(CServer * server)855 void CServerListRem::RemoveServer(CServer* server)
856 {
857 m_conn->RemoveServer(server->GetIP(),server->GetPort());
858 }
859
860
UpdateUserFileStatus(CServer * server)861 void CServerListRem::UpdateUserFileStatus(CServer *server)
862 {
863 if (server) {
864 m_TotalUser = server->GetUsers();
865 m_TotalFile = server->GetFiles();
866 }
867 }
868
869
GetServerByAddress(const wxString & WXUNUSED (address),uint16 WXUNUSED (port)) const870 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
871 {
872 // It's ok to return 0 for context where this code is used in remote gui
873 return 0;
874 }
875
GetServerByIPTCP(uint32 WXUNUSED (nIP),uint16 WXUNUSED (nPort)) const876 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
877 {
878 // It's ok to return 0 for context where this code is used in remote gui
879 return 0;
880 }
881
CreateItem(const CEC_Server_Tag * tag)882 CServer *CServerListRem::CreateItem(const CEC_Server_Tag *tag)
883 {
884 CServer * server = new CServer(tag);
885 ProcessItemUpdate(tag, server);
886 return server;
887 }
888
889
DeleteItem(CServer * in_srv)890 void CServerListRem::DeleteItem(CServer *in_srv)
891 {
892 CScopedPtr<CServer> srv(in_srv);
893 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
894 }
895
896
GetItemID(CServer * server)897 uint32 CServerListRem::GetItemID(CServer *server)
898 {
899 return server->ECID();
900 }
901
902
ProcessItemUpdate(const CEC_Server_Tag * tag,CServer * server)903 void CServerListRem::ProcessItemUpdate(const CEC_Server_Tag * tag, CServer * server)
904 {
905 if (!tag->HasChildTags()) {
906 return;
907 }
908 tag->ServerName(& server->listname);
909 tag->ServerDesc(& server->description);
910 tag->ServerVersion(& server->m_strVersion);
911 tag->GetMaxUsers(& server->maxusers);
912
913 tag->GetFiles(& server->files);
914 tag->GetUsers(& server->users);
915
916 tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok
917 tag->GetStatic(& server->staticservermember);
918
919 tag->GetPing(& server->ping);
920 tag->GetFailed(& server->failedcount);
921
922 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server);
923 }
924
925
CServer(const CEC_Server_Tag * tag)926 CServer::CServer(const CEC_Server_Tag *tag) : CECID(tag->GetInt())
927 {
928 ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt();
929 port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt();
930
931 Init();
932 }
933
934
935 /*
936 * IP filter
937 */
CIPFilterRem(CRemoteConnect * conn)938 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
939 {
940 m_conn = conn;
941 }
942
943
Reload()944 void CIPFilterRem::Reload()
945 {
946 CECPacket req(EC_OP_IPFILTER_RELOAD);
947 m_conn->SendPacket(&req);
948 }
949
950
Update(wxString url)951 void CIPFilterRem::Update(wxString url)
952 {
953 CECPacket req(EC_OP_IPFILTER_UPDATE);
954 req.AddTag(CECTag(EC_TAG_STRING, url));
955
956 m_conn->SendPacket(&req);
957 }
958
959
960 /*
961 * Shared files list
962 */
CSharedFilesRem(CRemoteConnect * conn)963 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
964 {
965 m_conn = conn;
966 }
967
968
Reload(bool,bool)969 void CSharedFilesRem::Reload(bool, bool)
970 {
971 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
972
973 m_conn->SendPacket(&req);
974 }
975
976
RenameFile(CKnownFile * file,const CPath & newName)977 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
978 {
979 // We use the printable name, as the filename originated from user input,
980 // and the filesystem name might not be valid on the remote host.
981 const wxString strNewName = newName.GetPrintable();
982
983 CECPacket request(EC_OP_RENAME_FILE);
984 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
985 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
986
987 m_conn->SendPacket(&request);
988
989 return true;
990 }
991
992
SetFileCommentRating(CKnownFile * file,const wxString & newComment,int8 newRating)993 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
994 {
995 CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT);
996 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
997 request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment));
998 request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating));
999
1000 m_conn->SendPacket(&request);
1001 }
1002
1003
CopyFileList(std::vector<CKnownFile * > & out_list) const1004 void CSharedFilesRem::CopyFileList(std::vector<CKnownFile*>& out_list) const
1005 {
1006 out_list.reserve(size());
1007 for (const_iterator it = begin(); it != end(); ++it) {
1008 out_list.push_back(it->second);
1009 }
1010 }
1011
1012
DeleteItem(CKnownFile * file)1013 void CKnownFilesRem::DeleteItem(CKnownFile * file)
1014 {
1015 uint32 id = file->ECID();
1016 if (theApp->sharedfiles->count(id)) {
1017 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
1018 theApp->sharedfiles->erase(id);
1019 }
1020 if (theApp->downloadqueue->count(id)) {
1021 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile(static_cast<CPartFile *>(file));
1022 theApp->downloadqueue->erase(id);
1023 }
1024 delete file;
1025 }
1026
1027
GetItemID(CKnownFile * file)1028 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
1029 {
1030 return file->ECID();
1031 }
1032
1033
ProcessItemUpdate(const CEC_SharedFile_Tag * tag,CKnownFile * file)1034 void CKnownFilesRem::ProcessItemUpdate(const CEC_SharedFile_Tag *tag, CKnownFile *file)
1035 {
1036 const CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1037 if (parttag) {
1038 const uint8 *data = file->m_partStatus.Decode(
1039 (uint8 *)parttag->GetTagData(),
1040 parttag->GetTagDataLen());
1041 for(int i = 0; i < file->GetPartCount(); ++i) {
1042 file->m_AvailPartFrequency[i] = data[i];
1043 }
1044 }
1045 wxString fileName;
1046 if (tag->FileName(fileName)) {
1047 file->SetFileName(CPath(fileName));
1048 }
1049 if (tag->FilePath(fileName)) {
1050 file->m_filePath = CPath(fileName);
1051 }
1052 tag->UpPrio(&file->m_iUpPriorityEC);
1053 tag->GetAICHHash(file->m_AICHMasterHash);
1054 // Bad thing - direct writing another class' members
1055 tag->GetRequests(&file->statistic.requested);
1056 tag->GetAllRequests(&file->statistic.alltimerequested);
1057 tag->GetAccepts(&file->statistic.accepted);
1058 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
1059 tag->GetXferred(&file->statistic.transferred);
1060 tag->GetAllXferred(&file->statistic.alltimetransferred);
1061 tag->UpPrio(&file->m_iUpPriorityEC);
1062 if (file->m_iUpPriorityEC >= 10) {
1063 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1064 file->m_bAutoUpPriority = true;
1065 } else {
1066 file->m_iUpPriority = file->m_iUpPriorityEC;
1067 file->m_bAutoUpPriority = false;
1068 }
1069 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1070 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1071 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1072
1073 tag->GetOnQueue(&file->m_queuedCount);
1074
1075 tag->GetComment(file->m_strComment);
1076 tag->GetRating(file->m_iRating);
1077
1078 requested += file->statistic.requested;
1079 transferred += file->statistic.transferred;
1080 accepted += file->statistic.transferred;
1081
1082 if (!m_initialUpdate) {
1083 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1084 }
1085
1086 if (file->IsPartFile()) {
1087 ProcessItemUpdatePartfile(static_cast<const CEC_PartFile_Tag *>(tag), static_cast<CPartFile *>(file));
1088 }
1089 }
1090
SetFilePrio(CKnownFile * file,uint8 prio)1091 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1092 {
1093 CECPacket req(EC_OP_SHARED_SET_PRIO);
1094
1095 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1096 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1097
1098 req.AddTag(hashtag);
1099
1100 m_conn->SendPacket(&req);
1101 }
1102
ProcessUpdate(const CECTag * reply,CECPacket *,int)1103 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1104 {
1105 requested = 0;
1106 transferred = 0;
1107 accepted = 0;
1108
1109 std::set<uint32> core_files;
1110 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); ++it) {
1111 const CECTag * curTag = &*it;
1112 ec_tagname_t tagname = curTag->GetTagName();
1113 if (tagname == EC_TAG_CLIENT) {
1114 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1115 } else if (tagname == EC_TAG_SERVER) {
1116 theApp->serverlist->ProcessUpdate(curTag, NULL, EC_TAG_SERVER);
1117 } else if (tagname == EC_TAG_FRIEND) {
1118 theApp->friendlist->ProcessUpdate(curTag, NULL, EC_TAG_FRIEND);
1119 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1120 const CEC_SharedFile_Tag *tag = static_cast<const CEC_SharedFile_Tag *>(curTag);
1121 uint32 id = tag->ID();
1122 bool isNew = true;
1123 if (!m_initialUpdate) {
1124 core_files.insert(id);
1125 std::map<uint32, CKnownFile*>::iterator it2 = m_items_hash.find(id);
1126 if (it2 != m_items_hash.end() ) {
1127 // Item already known: update it
1128 if (tag->HasChildTags()) {
1129 ProcessItemUpdate(tag, it2->second);
1130 }
1131 isNew = false;
1132 }
1133 }
1134 if (isNew) {
1135 CKnownFile * newFile;
1136 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1137 CPartFile *file = new CPartFile(static_cast<const CEC_PartFile_Tag *>(tag));
1138 ProcessItemUpdate(tag, file);
1139 (*theApp->downloadqueue)[id] = file;
1140 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1141 newFile = file;
1142 } else {
1143 newFile = new CKnownFile(tag);
1144 ProcessItemUpdate(tag, newFile);
1145 (*theApp->sharedfiles)[id] = newFile;
1146 if (!m_initialUpdate) {
1147 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1148 }
1149 }
1150 AddItem(newFile);
1151 }
1152 }
1153 }
1154
1155 if (m_initialUpdate) {
1156 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFileList();
1157 m_initialUpdate = false;
1158 } else {
1159 // remove items no longer present
1160 for(iterator it = begin(); it != end();) {
1161 iterator it2 = it++;
1162 if (!core_files.count(GetItemID(*it2))) {
1163 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1164 }
1165 }
1166 }
1167 }
1168
CKnownFilesRem(CRemoteConnect * conn)1169 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1170 {
1171 requested = 0;
1172 transferred = 0;
1173 accepted = 0;
1174 m_initialUpdate = true;
1175 }
1176
1177
1178 /*
1179 * List of uploading and waiting clients.
1180 */
CUpDownClientListRem(CRemoteConnect * conn)1181 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1182 :
1183 CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true)
1184 {
1185 }
1186
1187
CClientRef(const CEC_UpDownClient_Tag * tag)1188 CClientRef::CClientRef(const CEC_UpDownClient_Tag *tag)
1189 {
1190 m_client = new CUpDownClient(tag);
1191 #ifdef DEBUG_ZOMBIE_CLIENTS
1192 m_client->Link(wxT("TAG"));
1193 #else
1194 m_client->Link();
1195 #endif
1196 }
1197
1198
CUpDownClient(const CEC_UpDownClient_Tag * tag)1199 CUpDownClient::CUpDownClient(const CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1200 {
1201 m_linked = 0;
1202 #ifdef DEBUG_ZOMBIE_CLIENTS
1203 m_linkedDebug = false;
1204 #endif
1205 // Clients start up empty, then get asked for their data.
1206 // So all data here is processed in ProcessItemUpdate and thus updatable.
1207 m_bEmuleProtocol = false;
1208 m_AvailPartCount = 0;
1209 m_clientSoft = 0;
1210 m_nDownloadState = 0;
1211 m_Friend = NULL;
1212 m_bFriendSlot = false;
1213 m_nKadPort = 0;
1214 m_kBpsDown = 0;
1215 m_dwUserIP = 0;
1216 m_lastDownloadingPart = 0xffff;
1217 m_nextRequestedPart = 0xffff;
1218 m_obfuscationStatus = 0;
1219 m_nOldRemoteQueueRank = 0;
1220 m_nRemoteQueueRank = 0;
1221 m_reqfile = NULL;
1222 m_score = 0;
1223 m_dwServerIP = 0;
1224 m_nServerPort = 0;
1225 m_nSourceFrom = SF_NONE;
1226 m_nTransferredDown = 0;
1227 m_nTransferredUp = 0;
1228 m_nUpDatarate = 0;
1229 m_uploadingfile = NULL;
1230 m_waitingPosition = 0;
1231 m_nUploadState = 0;
1232 m_nUserIDHybrid = 0;
1233 m_nUserPort = 0;
1234 m_nClientVersion = 0;
1235 m_fNoViewSharedFiles = true;
1236 m_identState = IS_NOTAVAILABLE;
1237 m_bRemoteQueueFull = false;
1238
1239 credits = new CClientCredits(new CreditStruct());
1240 }
1241
1242 #ifdef DEBUG_ZOMBIE_CLIENTS
Unlink(const wxString & from)1243 void CUpDownClient::Unlink(const wxString& from)
1244 {
1245 std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
1246 if (it != m_linkedFrom.end()) {
1247 m_linkedFrom.erase(it);
1248 }
1249 m_linked--;
1250 if (!m_linked) {
1251 if (m_linkedDebug) {
1252 AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this);
1253 }
1254 delete this;
1255 }
1256 }
1257
1258 #else
1259
Unlink()1260 void CUpDownClient::Unlink()
1261 {
1262 m_linked--;
1263 if (!m_linked) {
1264 delete this;
1265 }
1266 }
1267 #endif
1268
1269
GetDownloadedTotal() const1270 uint64 CUpDownClient::GetDownloadedTotal() const
1271 {
1272 return credits->GetDownloadedTotal();
1273 }
1274
1275
GetUploadedTotal() const1276 uint64 CUpDownClient::GetUploadedTotal() const
1277 {
1278 return credits->GetUploadedTotal();
1279 }
1280
1281
GetScoreRatio() const1282 double CUpDownClient::GetScoreRatio() const
1283 {
1284 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1285 }
1286
1287 /* End Warning */
1288
1289
~CUpDownClient()1290 CUpDownClient::~CUpDownClient()
1291 {
1292 delete credits;
1293 }
1294
1295
CreateItem(const CEC_UpDownClient_Tag * tag)1296 CClientRef *CUpDownClientListRem::CreateItem(const CEC_UpDownClient_Tag *tag)
1297 {
1298 CClientRef *client = new CClientRef(tag);
1299 ProcessItemUpdate(tag, client);
1300
1301 return client;
1302 }
1303
1304
DeleteItem(CClientRef * clientref)1305 void CUpDownClientListRem::DeleteItem(CClientRef *clientref)
1306 {
1307 CUpDownClient* client = clientref->GetClient();
1308 if (client->m_reqfile) {
1309 client->m_reqfile->DelSource(client);
1310 client->m_reqfile = NULL;
1311 }
1312 Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL);
1313
1314 if (client->m_uploadingfile) {
1315 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1316 client->m_uploadingfile = NULL;
1317 }
1318 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); // in case it vanished directly while uploading
1319 Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL);
1320
1321 if (client->m_Friend) {
1322 client->m_Friend->UnLinkClient(); // this notifies
1323 client->m_Friend = NULL;
1324 }
1325
1326 #ifdef DEBUG_ZOMBIE_CLIENTS
1327 if (client->m_linked > 1) {
1328 AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % client->ECID() % (client->m_linked - 1) % client->GetLinkedFrom());
1329 client->m_linkedDebug = true;
1330 }
1331 #endif
1332
1333 delete clientref;
1334 }
1335
1336
GetItemID(CClientRef * client)1337 uint32 CUpDownClientListRem::GetItemID(CClientRef *client)
1338 {
1339 return client->ECID();
1340 }
1341
1342
ProcessItemUpdate(const CEC_UpDownClient_Tag * tag,CClientRef * clientref)1343 void CUpDownClientListRem::ProcessItemUpdate(
1344 const CEC_UpDownClient_Tag *tag,
1345 CClientRef *clientref)
1346 {
1347 if (!tag->HasChildTags()) {
1348 return; // speed exit for clients without any change
1349 }
1350 CUpDownClient *client = clientref->GetClient();
1351
1352 tag->UserID(&client->m_nUserIDHybrid);
1353 tag->ClientName(&client->m_Username);
1354 // Client Software
1355 bool sw_updated = false;
1356 if (tag->ClientSoftware(client->m_clientSoft)) {
1357 client->m_clientSoftString = GetSoftName(client->m_clientSoft);
1358 sw_updated = true;
1359 }
1360 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1361 if (client->m_clientSoftString == _("Unknown")) {
1362 client->m_fullClientVerString = client->m_clientSoftString;
1363 } else {
1364 client->m_fullClientVerString = client->m_clientSoftString + wxT(" ") + client->m_clientVerString;
1365 }
1366 }
1367 // User hash
1368 tag->UserHash(&client->m_UserHash);
1369
1370 // User IP:Port
1371 tag->UserIP(client->m_dwUserIP);
1372 tag->UserPort(&client->m_nUserPort);
1373
1374 // Server IP:Port
1375 tag->ServerIP(&client->m_dwServerIP);
1376 tag->ServerPort(&client->m_nServerPort);
1377 tag->ServerName(&client->m_ServerName);
1378
1379 tag->KadPort(client->m_nKadPort);
1380 tag->FriendSlot(client->m_bFriendSlot);
1381
1382 tag->GetCurrentIdentState(&client->m_identState);
1383 tag->ObfuscationStatus(client->m_obfuscationStatus);
1384 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1385
1386 tag->WaitingPosition(&client->m_waitingPosition);
1387 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1388 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1389 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1390
1391 tag->ClientDownloadState(client->m_nDownloadState);
1392 if (tag->ClientUploadState(client->m_nUploadState)) {
1393 if (client->m_nUploadState == US_UPLOADING) {
1394 theApp->m_allUploadingKnownFile->AddUploadingClient(client);
1395 } else {
1396 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);
1397 }
1398 }
1399
1400 tag->SpeedUp(&client->m_nUpDatarate);
1401 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1402 tag->SpeedDown(&client->m_kBpsDown);
1403 } else {
1404 client->m_kBpsDown = 0;
1405 }
1406
1407 //tag->WaitTime(&client->m_WaitTime);
1408 //tag->XferTime(&client->m_UpStartTimeDelay);
1409 //tag->LastReqTime(&client->m_dwLastUpRequest);
1410 //tag->QueueTime(&client->m_WaitStartTime);
1411
1412 CreditStruct *credit_struct = const_cast<CreditStruct *>(client->credits->GetDataStruct());
1413 tag->XferUp(&credit_struct->uploaded);
1414 tag->XferUpSession(&client->m_nTransferredUp);
1415
1416 tag->XferDown(&credit_struct->downloaded);
1417 tag->XferDownSession(&client->m_nTransferredDown);
1418
1419 tag->Score(&client->m_score);
1420
1421 tag->NextRequestedPart(client->m_nextRequestedPart);
1422 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1423
1424 uint8 sourceFrom = 0;
1425 if (tag->GetSourceFrom(sourceFrom)) {
1426 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1427 }
1428
1429 tag->RemoteFilename(client->m_clientFilename);
1430 tag->DisableViewShared(client->m_fNoViewSharedFiles);
1431 tag->Version(client->m_nClientVersion);
1432 tag->ModVersion(client->m_strModVersion);
1433 tag->OSInfo(client->m_sClientOSInfo);
1434 tag->AvailableParts(client->m_AvailPartCount);
1435
1436 // Download client
1437 uint32 fileID;
1438 bool notified = false;
1439 if (tag->RequestFile(fileID)) {
1440 if (client->m_reqfile) {
1441 Notify_SourceCtrlRemoveSource(client->ECID(), client->m_reqfile);
1442 client->m_reqfile->DelSource(client);
1443 client->m_reqfile = NULL;
1444 client->m_downPartStatus.clear();
1445 }
1446 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1447 if (kf && kf->IsCPartFile()) {
1448 client->m_reqfile = static_cast<CPartFile *>(kf);
1449 client->m_reqfile->AddSource(client);
1450 client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1451 Notify_SourceCtrlAddSource(client->m_reqfile, CCLIENTREF(client, wxT("AddSource")), A4AF_SOURCE);
1452 notified = true;
1453 }
1454 }
1455
1456 // Part status
1457 const CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1458 if (partStatusTag) {
1459 if (partStatusTag->GetTagDataLen() == 0) {
1460 // empty tag means full source
1461 client->m_downPartStatus.SetAllTrue();
1462 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1463 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1464 }
1465 notified = false;
1466 }
1467
1468 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1469 SourceItemType type;
1470 switch (client->GetDownloadState()) {
1471 case DS_DOWNLOADING:
1472 case DS_ONQUEUE:
1473 // We will send A4AF, which will be checked.
1474 type = A4AF_SOURCE;
1475 break;
1476 default:
1477 type = UNAVAILABLE_SOURCE;
1478 break;
1479 }
1480
1481 Notify_SourceCtrlUpdateSource(client->ECID(), type);
1482 }
1483
1484 // Upload client
1485 notified = false;
1486 if (tag->UploadFile(fileID)) {
1487 if (client->m_uploadingfile) {
1488 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1489 notified = true;
1490 client->m_uploadingfile = NULL;
1491 }
1492 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1493 if (kf) {
1494 client->m_uploadingfile = kf;
1495 client->m_upPartStatus.setsize(kf->GetPartCount(), 0);
1496 client->m_uploadingfile->AddUploadingClient(client); // this notifies
1497 notified = true;
1498 }
1499 }
1500
1501 // Part status
1502 partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_UPLOAD_PART_STATUS);
1503 if (partStatusTag) {
1504 if (partStatusTag->GetTagDataLen() == client->m_upPartStatus.SizeBuffer()) {
1505 client->m_upPartStatus.SetBuffer(partStatusTag->GetTagData());
1506 }
1507 notified = false;
1508 }
1509
1510 if (!notified && client->m_uploadingfile
1511 && (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) {
1512 // notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode)
1513 SourceItemType type;
1514 switch (client->GetUploadState()) {
1515 case US_UPLOADING:
1516 case US_ONUPLOADQUEUE:
1517 type = AVAILABLE_SOURCE;
1518 break;
1519 default:
1520 type = UNAVAILABLE_SOURCE;
1521 break;
1522 }
1523 Notify_SharedCtrlRefreshClient(client->ECID(), type);
1524 }
1525 }
1526
1527
1528 /*
1529 * Download queue container: hold PartFiles with progress status
1530 *
1531 */
1532
1533
AddLink(const wxString & link,uint8 cat)1534 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1535 {
1536 CECPacket req(EC_OP_ADD_LINK);
1537 CECTag link_tag(EC_TAG_STRING, link);
1538 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1539 req.AddTag(link_tag);
1540
1541 m_conn->SendPacket(&req);
1542 return true;
1543 }
1544
1545
ResetCatParts(int cat)1546 void CDownQueueRem::ResetCatParts(int cat)
1547 {
1548 // Called when category is deleted. Command will be performed on the remote side,
1549 // but files still should be updated here right away, or drawing errors (colour not available)
1550 // will happen.
1551 for (iterator it = begin(); it != end(); ++it) {
1552 CPartFile* file = it->second;
1553 file->RemoveCategory(cat);
1554 }
1555 }
1556
1557
1558
ProcessItemUpdatePartfile(const CEC_PartFile_Tag * tag,CPartFile * file)1559 void CKnownFilesRem::ProcessItemUpdatePartfile(const CEC_PartFile_Tag *tag, CPartFile *file)
1560 {
1561 //
1562 // update status
1563 //
1564 tag->Speed(&file->m_kbpsDown);
1565 file->kBpsDown = file->m_kbpsDown / 1024.0;
1566
1567 tag->SizeXfer(&file->transferred);
1568 tag->SizeDone(&file->completedsize);
1569 tag->SourceXferCount(&file->transferingsrc);
1570 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1571 tag->SourceCount(&file->m_source_count);
1572 tag->SourceCountA4AF(&file->m_a4af_source_count);
1573 tag->FileStatus(&file->status);
1574 tag->Stopped(&file->m_stopped);
1575
1576 tag->LastSeenComplete(&file->lastseencomplete);
1577 tag->LastDateChanged(&file->m_lastDateChanged);
1578 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1579 tag->AvailablePartCount(&file->m_availablePartsCount);
1580 tag->Shared(&file->m_isShared);
1581 tag->A4AFAuto(file->m_is_A4AF_auto);
1582 tag->HashingProgress(file->m_hashingProgress);
1583
1584 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1585 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1586 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1587
1588 tag->FileCat(&file->m_category);
1589
1590 tag->DownPrio(&file->m_iDownPriorityEC);
1591 if ( file->m_iDownPriorityEC >= 10 ) {
1592 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1593 file->m_bAutoDownPriority = true;
1594 } else {
1595 file->m_iDownPriority = file->m_iDownPriorityEC;
1596 file->m_bAutoDownPriority = false;
1597 }
1598
1599 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1600
1601 //
1602 // Copy part/gap status
1603 //
1604 const CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1605 const CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1606 const CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1607 if (gaptag || parttag || reqtag) {
1608 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1609
1610 if (gaptag) {
1611 ArrayOfUInts64 gaps;
1612 encoder.DecodeGaps(gaptag, gaps);
1613 int gap_size = gaps.size() / 2;
1614 // clear gaplist
1615 file->m_gaplist.Init(file->GetFileSize(), false);
1616
1617 // and refill it
1618 for (int j = 0; j < gap_size; j++) {
1619 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1620 }
1621 }
1622 if (parttag) {
1623 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1624 // sanity check
1625 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1626 }
1627 if (reqtag) {
1628 ArrayOfUInts64 reqs;
1629 encoder.DecodeReqs(reqtag, reqs);
1630 int req_size = reqs.size() / 2;
1631 // clear reqlist
1632 DeleteContents(file->m_requestedblocks_list);
1633
1634 // and refill it
1635 for (int j = 0; j < req_size; j++) {
1636 Requested_Block_Struct* block = new Requested_Block_Struct;
1637 block->StartOffset = reqs[2*j];
1638 block->EndOffset = reqs[2*j+1];
1639 file->m_requestedblocks_list.push_back(block);
1640 }
1641 }
1642 }
1643
1644 // Get source names and counts
1645 const CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1646 if (srcnametag) {
1647 SourcenameItemMap &map = file->GetSourcenameItemMap();
1648 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); ++it) {
1649 uint32 key = it->GetInt();
1650 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1651 if (count == 0) {
1652 map.erase(key);
1653 } else {
1654 SourcenameItem &item = map[key];
1655 item.count = count;
1656 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1657 if (nametag) {
1658 item.name = nametag->GetStringData();
1659 }
1660 }
1661 }
1662 }
1663
1664 // Get comments
1665 const CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1666 if (commenttag) {
1667 file->ClearFileRatingList();
1668 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1669 wxString u = (it++)->GetStringData();
1670 wxString f = (it++)->GetStringData();
1671 int r = (it++)->GetInt();
1672 wxString c = (it++)->GetStringData();
1673 file->AddFileRatingList(u, f, r, c);
1674 }
1675 file->UpdateFileRatingCommentAvail();
1676 }
1677
1678 // Update A4AF sources
1679 ListOfUInts32 & clientIDs = file->GetA4AFClientIDs();
1680 const CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES);
1681 if (a4aftag) {
1682 file->ClearA4AFList();
1683 clientIDs.clear();
1684 for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); ++it) {
1685 if (it->GetTagName() != EC_TAG_ECID) { // should always be this
1686 continue;
1687 }
1688 uint32 id = it->GetInt();
1689 CClientRef * src = theApp->clientlist->GetByID(id);
1690 if (src) {
1691 file->AddA4AFSource(src->GetClient());
1692 } else {
1693 // client wasn't transmitted yet, try it later
1694 clientIDs.push_back(id);
1695 }
1696 }
1697 } else if (!clientIDs.empty()) {
1698 // Process clients from the last pass whose ids were still unknown then
1699 for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) {
1700 ListOfUInts32::iterator it1 = it++;
1701 uint32 id = *it1;
1702 CClientRef * src = theApp->clientlist->GetByID(id);
1703 if (src) {
1704 file->AddA4AFSource(src->GetClient());
1705 clientIDs.erase(it1);
1706 }
1707 }
1708 }
1709
1710 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1711
1712 // If file is shared check if it is already listed in shared files.
1713 // If not, add it and show it.
1714 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1715 (*theApp->sharedfiles)[file->ECID()] = file;
1716 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1717 }
1718 }
1719
1720
SendFileCommand(CPartFile * file,ec_tagname_t cmd)1721 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1722 {
1723 CECPacket req(cmd);
1724 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1725
1726 m_conn->SendPacket(&req);
1727 }
1728
1729
Prio(CPartFile * file,uint8 prio)1730 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1731 {
1732 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1733
1734 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1735 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1736 req.AddTag(hashtag);
1737
1738 m_conn->SendPacket(&req);
1739 }
1740
1741
AutoPrio(CPartFile * file,bool flag)1742 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1743 {
1744 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1745
1746 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1747
1748 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1749 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1750 req.AddTag(hashtag);
1751
1752 m_conn->SendPacket(&req);
1753 }
1754
1755
Category(CPartFile * file,uint8 cat)1756 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1757 {
1758 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1759 file->SetCategory(cat);
1760
1761 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1762 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1763 req.AddTag(hashtag);
1764
1765 m_conn->SendPacket(&req);
1766 }
1767
1768
AddSearchToDownload(CSearchFile * file,uint8 category)1769 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1770 {
1771 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1772 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1773 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1774 req.AddTag(hashtag);
1775
1776 m_conn->SendPacket(&req);
1777 }
1778
1779
ClearCompleted(const ListOfUInts32 & ecids)1780 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
1781 {
1782 CECPacket req(EC_OP_CLEAR_COMPLETED);
1783 for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); ++it) {
1784 req.AddTag(CECTag(EC_TAG_ECID, *it));
1785 }
1786
1787 m_conn->SendPacket(&req);
1788 }
1789
1790
1791 /*
1792 * List of friends.
1793 */
CFriendListRem(CRemoteConnect * conn)1794 CFriendListRem::CFriendListRem(CRemoteConnect *conn)
1795 :
1796 CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true)
1797 {
1798 }
1799
1800
HandlePacket(const CECPacket *)1801 void CFriendListRem::HandlePacket(const CECPacket *)
1802 {
1803 wxFAIL; // not needed
1804 }
1805
1806
CreateItem(const CEC_Friend_Tag * tag)1807 CFriend * CFriendListRem::CreateItem(const CEC_Friend_Tag * tag)
1808 {
1809 CFriend * Friend = new CFriend(tag->ID());
1810 ProcessItemUpdate(tag, Friend);
1811 return Friend;
1812 }
1813
1814
DeleteItem(CFriend * Friend)1815 void CFriendListRem::DeleteItem(CFriend * Friend)
1816 {
1817 Friend->UnLinkClient(false);
1818 Notify_ChatRemoveFriend(Friend);
1819 }
1820
1821
GetItemID(CFriend * Friend)1822 uint32 CFriendListRem::GetItemID(CFriend * Friend)
1823 {
1824 return Friend->ECID();
1825 }
1826
1827
ProcessItemUpdate(const CEC_Friend_Tag * tag,CFriend * Friend)1828 void CFriendListRem::ProcessItemUpdate(const CEC_Friend_Tag * tag, CFriend * Friend)
1829 {
1830 if (!tag->HasChildTags()) {
1831 return;
1832 }
1833 tag->Name(Friend->m_strName);
1834 tag->UserHash(Friend->m_UserHash);
1835 tag->IP(Friend->m_dwLastUsedIP);
1836 tag->Port(Friend->m_nLastUsedPort);
1837 uint32 clientID;
1838 bool notified = false;
1839 if (tag->Client(clientID)) {
1840 if (clientID) {
1841 CClientRef * client = theApp->clientlist->GetByID(clientID);
1842 if (client) {
1843 Friend->LinkClient(*client); // this notifies
1844 notified = true;
1845 }
1846 } else {
1847 // Unlink
1848 Friend->UnLinkClient(false);
1849 }
1850 }
1851 if (!notified) {
1852 Notify_ChatUpdateFriend(Friend);
1853 }
1854 }
1855
1856
AddFriend(const CClientRef & toadd)1857 void CFriendListRem::AddFriend(const CClientRef& toadd)
1858 {
1859 CECPacket req(EC_OP_FRIEND);
1860
1861 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1862 addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID()));
1863 req.AddTag(addtag);
1864
1865 m_conn->SendPacket(&req);
1866 }
1867
1868
AddFriend(const CMD4Hash & userhash,uint32 lastUsedIP,uint32 lastUsedPort,const wxString & name)1869 void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name)
1870 {
1871 CECPacket req(EC_OP_FRIEND);
1872
1873 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1874 addtag.AddTag(CECTag(EC_TAG_FRIEND_HASH, userhash));
1875 addtag.AddTag(CECTag(EC_TAG_FRIEND_IP, lastUsedIP));
1876 addtag.AddTag(CECTag(EC_TAG_FRIEND_PORT, lastUsedPort));
1877 addtag.AddTag(CECTag(EC_TAG_FRIEND_NAME, name));
1878 req.AddTag(addtag);
1879
1880 m_conn->SendPacket(&req);
1881 }
1882
1883
RemoveFriend(CFriend * toremove)1884 void CFriendListRem::RemoveFriend(CFriend* toremove)
1885 {
1886 CECPacket req(EC_OP_FRIEND);
1887
1888 CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE);
1889 removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID()));
1890 req.AddTag(removetag);
1891
1892 m_conn->SendPacket(&req);
1893 }
1894
1895
SetFriendSlot(CFriend * Friend,bool new_state)1896 void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state)
1897 {
1898 CECPacket req(EC_OP_FRIEND);
1899
1900 CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state);
1901 slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1902 req.AddTag(slottag);
1903
1904 m_conn->SendPacket(&req);
1905 }
1906
1907
RequestSharedFileList(CFriend * Friend)1908 void CFriendListRem::RequestSharedFileList(CFriend* Friend)
1909 {
1910 CECPacket req(EC_OP_FRIEND);
1911
1912 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1913 sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1914 req.AddTag(sharedtag);
1915
1916 m_conn->SendPacket(&req);
1917 }
1918
1919
RequestSharedFileList(CClientRef & client)1920 void CFriendListRem::RequestSharedFileList(CClientRef& client)
1921 {
1922 CECPacket req(EC_OP_FRIEND);
1923
1924 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1925 sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID()));
1926 req.AddTag(sharedtag);
1927
1928 m_conn->SendPacket(&req);
1929 }
1930
1931
1932
1933 /*
1934 * Search results
1935 */
CSearchListRem(CRemoteConnect * conn)1936 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1937 {
1938 m_curr_search = -1;
1939 }
1940
1941
StartNewSearch(uint32 * nSearchID,SearchType search_type,const CSearchList::CSearchParams & params)1942 wxString CSearchListRem::StartNewSearch(
1943 uint32* nSearchID, SearchType search_type,
1944 const CSearchList::CSearchParams& params)
1945 {
1946 CECPacket search_req(EC_OP_SEARCH_START);
1947 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1948 switch(search_type) {
1949 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1950 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1951 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1952 }
1953 search_req.AddTag(
1954 CEC_Search_Tag(params.searchString, ec_search_type,
1955 params.typeText, params.extension, params.availability,
1956 params.minSize, params.maxSize));
1957
1958 m_conn->SendPacket(&search_req);
1959 m_curr_search = *(nSearchID); // No kad remote search yet.
1960
1961 Flush();
1962
1963 return wxEmptyString; // EC reply will have the error mesg is needed.
1964 }
1965
1966
StopSearch(bool)1967 void CSearchListRem::StopSearch(bool)
1968 {
1969 if (m_curr_search != -1) {
1970 CECPacket search_req(EC_OP_SEARCH_STOP);
1971 m_conn->SendPacket(&search_req);
1972 }
1973 }
1974
1975
HandlePacket(const CECPacket * packet)1976 void CSearchListRem::HandlePacket(const CECPacket *packet)
1977 {
1978 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1979 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1980 } else {
1981 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1982 }
1983 }
1984
1985
CSearchFile(const CEC_SearchFile_Tag * tag)1986 CSearchFile::CSearchFile(const CEC_SearchFile_Tag *tag)
1987 :
1988 CECID(tag->ID()),
1989 m_parent(NULL),
1990 m_showChildren(false),
1991 m_sourceCount(0),
1992 m_completeSourceCount(0),
1993 m_kademlia(false),
1994 m_downloadStatus(NEW),
1995 m_clientID(0),
1996 m_clientPort(0),
1997 m_kadPublishInfo(0)
1998 {
1999 SetFileName(CPath(tag->FileName()));
2000 m_abyFileHash = tag->FileHash();
2001 SetFileSize(tag->SizeFull());
2002
2003 m_searchID = theApp->searchlist->m_curr_search;
2004 uint32 parentID = tag->ParentID();
2005 if (parentID) {
2006 CSearchFile * parent = theApp->searchlist->GetByID(parentID);
2007 if (parent) {
2008 parent->AddChild(this);
2009 }
2010 }
2011 }
2012
2013
AddChild(CSearchFile * file)2014 void CSearchFile::AddChild(CSearchFile* file)
2015 {
2016 m_children.push_back(file);
2017 file->m_parent = this;
2018 }
2019
2020
2021 // dtor is virtual - must be implemented
~CSearchFile()2022 CSearchFile::~CSearchFile()
2023 {
2024 }
2025
2026
CreateItem(const CEC_SearchFile_Tag * tag)2027 CSearchFile *CSearchListRem::CreateItem(const CEC_SearchFile_Tag *tag)
2028 {
2029 CSearchFile *file = new CSearchFile(tag);
2030 ProcessItemUpdate(tag, file);
2031
2032 theApp->amuledlg->m_searchwnd->AddResult(file);
2033
2034 return file;
2035 }
2036
2037
DeleteItem(CSearchFile * file)2038 void CSearchListRem::DeleteItem(CSearchFile *file)
2039 {
2040 delete file;
2041 }
2042
2043
GetItemID(CSearchFile * file)2044 uint32 CSearchListRem::GetItemID(CSearchFile *file)
2045 {
2046 return file->ECID();
2047 }
2048
2049
ProcessItemUpdate(const CEC_SearchFile_Tag * tag,CSearchFile * file)2050 void CSearchListRem::ProcessItemUpdate(const CEC_SearchFile_Tag *tag, CSearchFile *file)
2051 {
2052 uint32 sourceCount = file->m_sourceCount;
2053 uint32 completeSourceCount = file->m_completeSourceCount;
2054 CSearchFile::DownloadStatus status = file->m_downloadStatus;
2055 tag->SourceCount(&file->m_sourceCount);
2056 tag->CompleteSourceCount(&file->m_completeSourceCount);
2057 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
2058
2059 if (file->m_sourceCount != sourceCount
2060 || file->m_completeSourceCount != completeSourceCount
2061 || file->m_downloadStatus != status) {
2062 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
2063 theApp->amuledlg->m_searchwnd->UpdateResult(file);
2064 }
2065 }
2066 }
2067
2068
Phase1Done(const CECPacket * WXUNUSED (reply))2069 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
2070 {
2071 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
2072 m_conn->SendRequest(this, &progress_req);
2073
2074 return true;
2075 }
2076
2077
RemoveResults(long nSearchID)2078 void CSearchListRem::RemoveResults(long nSearchID)
2079 {
2080 ResultMap::iterator it = m_results.find(nSearchID);
2081 if (it != m_results.end()) {
2082 CSearchResultList& list = it->second;
2083 for (unsigned int i = 0; i < list.size(); ++i) {
2084 delete list[i];
2085 }
2086 m_results.erase(it);
2087 }
2088 }
2089
2090
GetSearchResults(long nSearchID)2091 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
2092 {
2093 ResultMap::const_iterator it = m_results.find(nSearchID);
2094 if (it != m_results.end()) {
2095 return it->second;
2096 }
2097
2098 // TODO: Should we assert in this case?
2099 static CSearchResultList list;
2100 return list;
2101 }
2102
2103
HandlePacket(const CECPacket * packet)2104 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
2105 {
2106 theStats::UpdateStats(packet);
2107 theApp->amuledlg->ShowTransferRate();
2108 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
2109 // handle the connstate tag which is included in the stats packet
2110 theApp->serverconnect->HandlePacket(packet);
2111 }
2112
2113
RequestSharedFileList()2114 void CUpDownClient::RequestSharedFileList()
2115 {
2116 CClientRef ref = CCLIENTREF(this, wxEmptyString);
2117 theApp->friendlist->RequestSharedFileList(ref);
2118 }
2119
2120
SwapToAnotherFile(bool WXUNUSED (bIgnoreNoNeeded),bool WXUNUSED (ignoreSuspensions),bool WXUNUSED (bRemoveCompletely),CPartFile * toFile)2121 bool CUpDownClient::SwapToAnotherFile(
2122 bool WXUNUSED(bIgnoreNoNeeded),
2123 bool WXUNUSED(ignoreSuspensions),
2124 bool WXUNUSED(bRemoveCompletely),
2125 CPartFile* toFile)
2126 {
2127 CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE);
2128 req.AddTag(CECTag(EC_TAG_CLIENT, ECID()));
2129 req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash()));
2130 theApp->m_connect->SendPacket(&req);
2131
2132 return true;
2133 }
2134
2135
GetString() const2136 wxString CAICHHash::GetString() const
2137 {
2138 return EncodeBase32(m_abyBuffer, HASHSIZE);
2139 }
2140
2141
2142 //
2143 // Those functions are virtual. So even they don't get called they must
2144 // be defined so linker will be happy
2145 //
CreateSrcInfoPacket(const CUpDownClient *,uint8,uint16)2146 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2147 {
2148 wxFAIL;
2149 return 0;
2150 }
2151
2152
LoadFromFile(const class CFileDataIO *)2153 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
2154 {
2155 wxFAIL;
2156 return false;
2157 }
2158
2159
UpdatePartsInfo()2160 void CKnownFile::UpdatePartsInfo()
2161 {
2162 wxFAIL;
2163 }
2164
2165
CreateSrcInfoPacket(CUpDownClient const *,uint8,uint16)2166 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2167 {
2168 wxFAIL;
2169 return 0;
2170 }
2171
2172
UpdatePartsInfo()2173 void CPartFile::UpdatePartsInfo()
2174 {
2175 wxFAIL;
2176 }
2177
2178
2179
UpdateFileRatingCommentAvail()2180 void CPartFile::UpdateFileRatingCommentAvail()
2181 {
2182 bool prevComment = m_hasComment;
2183 int prevRating = m_iUserRating;
2184
2185 m_hasComment = false;
2186 m_iUserRating = 0;
2187 int ratingCount = 0;
2188
2189 FileRatingList::iterator it = m_FileRatingList.begin();
2190 for (; it != m_FileRatingList.end(); ++it) {
2191 SFileRating& cur_rat = *it;
2192
2193 if (!cur_rat.Comment.IsEmpty()) {
2194 m_hasComment = true;
2195 }
2196
2197 uint8 rating = cur_rat.Rating;
2198 if (rating) {
2199 wxASSERT(rating <= 5);
2200
2201 ratingCount++;
2202 m_iUserRating += rating;
2203 }
2204 }
2205
2206 if (ratingCount) {
2207 m_iUserRating /= ratingCount;
2208 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
2209 }
2210
2211 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
2212 UpdateDisplayedInfo();
2213 }
2214 }
2215
2216
DoRequery()2217 void CStatTreeRem::DoRequery()
2218 {
2219 CECPacket request(EC_OP_GET_STATSTREE);
2220 if (thePrefs::GetMaxClientVersions() != 0) {
2221 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
2222 }
2223 m_conn->SendRequest(this, &request);
2224 }
2225
HandlePacket(const CECPacket * p)2226 void CStatTreeRem::HandlePacket(const CECPacket * p)
2227 {
2228 const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE);
2229 if (treeRoot) {
2230 theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot);
2231 theApp->amuledlg->m_statisticswnd->ShowStatistics();
2232 }
2233 }
2234
2235 CamuleRemoteGuiApp *theApp;
2236
2237 //
2238 // since gui is not linked with amule.cpp - define events here
2239 //
2240 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2241 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2242 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2243 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2244 // File_checked_for_headers
2245