amulegui: great performance boost when an insane number of files is shared
[amule.git] / src / amule-remote-gui.cpp
blobbf5f2cfd73b21da0cb916f8019cf0323157888cb
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.
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
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
32 #include <common/Format.h>
33 #include <common/StringFunctions.h>
34 #include <common/MD5Sum.h>
37 #include <include/common/EventIDs.h>
40 #include "amule.h" // Interface declarations.
41 #include "amuleDlg.h" // Needed for CamuleDlg
42 #include "ClientCredits.h"
43 #include "SourceListCtrl.h"
44 #include "ChatWnd.h"
45 #include "DataToText.h" // Needed for GetSoftName()
46 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
47 #include "Friend.h"
48 #include "GetTickCount.h" // Needed for GetTickCount
49 #include "GuiEvents.h"
50 #ifdef ENABLE_IP2COUNTRY
51 #include "IP2Country.h" // Needed for IP2Country
52 #endif
53 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
54 #include "Logger.h"
55 #include "muuli_wdr.h" // Needed for IDs
56 #include "PartFile.h" // Needed for CPartFile
57 #include "SearchDlg.h" // Needed for CSearchDlg
58 #include "Server.h" // Needed for GetListName
59 #include "ServerWnd.h" // Needed for CServerWnd
60 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
61 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
62 #include "TransferWnd.h" // Needed for CTransferWnd
63 #include "UpDownClientEC.h" // Needed for CUpDownClient
64 #include "ServerListCtrl.h" // Needed for CServerListCtrl
65 #include "ScopedPtr.h"
66 #include "StatisticsDlg.h" // Needed for CStatisticsDlg
69 CEConnectDlg::CEConnectDlg()
71 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
73 CoreConnect(this, true);
75 wxString pref_host, pref_port;
76 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
77 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
78 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
80 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
81 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
82 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
84 CentreOnParent();
88 wxString CEConnectDlg::PassHash()
90 return pwd_hash;
94 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
95 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
96 END_EVENT_TABLE()
99 void CEConnectDlg::OnOK(wxCommandEvent& evt)
101 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
102 port = StrToLong(s_port);
104 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
105 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
107 if (passwd != pwd_hash) {
108 pwd_hash = MD5Sum(passwd).GetHash();
110 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
111 evt.Skip();
115 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
118 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
119 // Core timer
120 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
122 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
123 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
125 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
127 #ifdef ENABLE_IP2COUNTRY
128 // HTTPDownload finished
129 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
130 #endif
131 END_EVENT_TABLE()
134 IMPLEMENT_APP(CamuleRemoteGuiApp)
137 int CamuleRemoteGuiApp::OnExit()
139 StopTickTimer();
141 return wxApp::OnExit();
145 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
147 static int request_step = 0;
148 static uint32 msPrevStats = 0;
150 if (m_connect->RequestFifoFull()) {
151 return;
154 switch (request_step) {
155 case 0:
156 // We used to update the connection state here, but that's done with the stats in the next step now.
157 request_step++;
158 break;
159 case 1: {
160 CECPacket stats_req(EC_OP_STAT_REQ, EC_DETAIL_INC_UPDATE);
161 m_connect->SendRequest(&m_stats_updater, &stats_req);
162 request_step++;
163 break;
165 case 2:
166 if (amuledlg->m_sharedfileswnd->IsShown()
167 || amuledlg->m_chatwnd->IsShown()
168 || amuledlg->m_serverwnd->IsShown()) {
169 // update downloads, shared files and servers
170 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
171 } else if (amuledlg->m_transferwnd->IsShown()) {
172 // update both downloads and shared files
173 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
174 } else if (amuledlg->m_searchwnd->IsShown()) {
175 if (searchlist->m_curr_search != -1) {
176 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
178 } else if (amuledlg->m_statisticswnd->IsShown()) {
179 int sStatsUpdate = thePrefs::GetStatsInterval();
180 uint32 msCur = theStats::GetUptimeMillis();
181 if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) {
182 msPrevStats = msCur;
183 stattree->DoRequery();
186 // Back to the roots
187 request_step = 0;
188 break;
189 default:
190 wxFAIL;
191 request_step = 0;
194 // Check for new links once per second.
195 static uint32 lastED2KLinkCheck = 0;
196 if (GetTickCount() - lastED2KLinkCheck >= 1000) {
197 AddLinksFromFile();
198 lastED2KLinkCheck = GetTickCount();
203 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
205 if (event.GetInt() == HTTP_GeoIP) {
206 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
207 // If we updated, the dialog is already up. Redraw it to show the flags.
208 amuledlg->Refresh();
213 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
215 // Stop the Core Timer
216 delete poll_timer;
217 poll_timer = NULL;
219 // Destroy the EC socket
220 m_connect->Destroy();
221 m_connect = NULL;
224 if (amuledlg) {
225 amuledlg->DlgShutDown();
226 amuledlg->Destroy();
227 amuledlg = NULL;
229 delete m_allUploadingKnownFile;
230 delete stattree;
234 bool CamuleRemoteGuiApp::OnInit()
236 StartTickTimer();
237 amuledlg = NULL;
239 // Get theApp
240 theApp = &wxGetApp();
242 // Handle uncaught exceptions
243 InstallMuleExceptionHandler();
245 // Parse cmdline arguments.
246 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
247 return false;
250 // Create the polling timer
251 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
252 if (!poll_timer) {
253 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
254 OnExit();
257 m_connect = new CRemoteConnect(this);
259 glob_prefs = new CPreferencesRem(m_connect);
260 long enableZLIB;
261 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
262 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification
264 InitCustomLanguages();
265 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
267 if (ShowConnectionDialog()) {
268 AddLogLineNS(_("Going to event loop..."));
269 return true;
272 return false;
276 bool CamuleRemoteGuiApp::CryptoAvailable() const
278 return thePrefs::IsSecureIdentEnabled(); // good enough
282 bool CamuleRemoteGuiApp::ShowConnectionDialog()
284 dialog = new CEConnectDlg;
286 if (m_skipConnectionDialog) {
287 wxCommandEvent evt;
288 dialog->OnOK(evt);
289 } else if (dialog->ShowModal() != wxID_OK) {
290 dialog->Destroy();
292 return false;
294 AddLogLineNS(_("Connecting..."));
295 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
296 dialog->Login(), dialog->PassHash(),
297 wxT("amule-remote"), wxT("0x0001"))) {
298 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
300 return false;
303 return true;
307 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
308 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
309 AddLogLineNS(_("Remote GUI EC event handler"));
310 wxString reply = evt.GetServerReply();
311 AddLogLineC(reply);
312 if (evt.GetResult() == true) {
313 // Connected - go to next init step
314 glob_prefs->LoadRemote();
315 } else {
316 AddLogLineNS(_("Going down"));
317 if (dialog) { // connect failed
318 wxMessageBox(
319 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
320 _("ERROR"), wxOK);
321 } else { // server disconnected (probably terminated) later
322 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
324 ExitMainLoop();
329 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
331 Startup();
335 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
337 evt.Notify();
341 void CamuleRemoteGuiApp::Startup() {
343 if (dialog->SaveUserPass()) {
344 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
345 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
346 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
348 dialog->Destroy();
349 dialog = NULL;
351 m_ConnState = 0;
352 m_clientID = 0;
354 serverconnect = new CServerConnectRem(m_connect);
355 m_statistics = new CStatistics(*m_connect);
356 stattree = new CStatTreeRem(m_connect);
358 clientlist = new CUpDownClientListRem(m_connect);
359 searchlist = new CSearchListRem(m_connect);
360 serverlist = new CServerListRem(m_connect);
361 friendlist = new CFriendListRem(m_connect);
364 sharedfiles = new CSharedFilesRem(m_connect);
365 knownfiles = new CKnownFilesRem(m_connect);
367 downloadqueue = new CDownQueueRem(m_connect);
368 ipfilter = new CIPFilterRem(m_connect);
370 m_allUploadingKnownFile = new CKnownFile;
372 // Create main dialog
373 InitGui(m_geometryEnabled, m_geometryString);
375 // Forward wxLog events to CLogger
376 wxLog::SetActiveTarget(new CLoggerTarget);
377 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
379 // Start the Poll Timer
380 poll_timer->Start(1000);
381 amuledlg->StartGuiTimer();
383 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
384 #ifdef ENABLE_IP2COUNTRY
385 if (thePrefs::IsGeoIPEnabled()) {
386 amuledlg->m_IP2Country->Enable();
388 #endif
392 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
394 return CamuleGuiBase::ShowAlert(msg, title, flags);
398 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
400 amuledlg->AddLogLine(line);
403 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
405 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
406 SetTopWindow(amuledlg);
407 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
408 return 0;
412 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
414 return CamuleGuiBase::CopyTextToClipboard(strText);
418 uint32 CamuleRemoteGuiApp::GetPublicIP()
420 return 0;
424 wxString CamuleRemoteGuiApp::GetLog(bool reset)
426 if (reset) {
427 amuledlg->ResetLog(ID_LOGVIEW);
428 CECPacket req(EC_OP_RESET_LOG);
429 m_connect->SendPacket(&req);
431 return wxEmptyString;
435 wxString CamuleRemoteGuiApp::GetServerLog(bool)
437 return wxEmptyString;
441 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
443 CECPacket req(EC_OP_SERVER_ADD);
444 req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort()));
445 req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName()));
446 m_connect->SendPacket(&req);
448 return true;
452 bool CamuleRemoteGuiApp::IsFirewalled() const
454 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
455 return false;
458 return IsFirewalledKad();
462 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
463 return serverconnect && serverconnect->IsConnected();
467 void CamuleRemoteGuiApp::StartKad() {
468 m_connect->StartKad();
472 void CamuleRemoteGuiApp::StopKad() {
473 m_connect->StopKad();
477 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
479 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
480 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
481 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
483 m_connect->SendPacket(&req);
487 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
489 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
490 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
492 m_connect->SendPacket(&req);
496 void CamuleRemoteGuiApp::DisconnectED2K() {
497 if (IsConnectedED2K()) {
498 m_connect->DisconnectED2K();
503 uint32 CamuleRemoteGuiApp::GetED2KID() const
505 return serverconnect ? serverconnect->GetClientID() : 0;
509 uint32 CamuleRemoteGuiApp::GetID() const
511 return m_clientID;
515 void CamuleRemoteGuiApp::ShowUserCount() {
516 wxString buffer;
518 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
519 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
521 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
522 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
523 } else if (thePrefs::GetNetworkED2K()) {
524 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
525 } else if (thePrefs::GetNetworkKademlia()) {
526 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
527 } else {
528 buffer = _("No networks selected");
531 Notify_ShowUserCount(buffer);
536 * Preferences: holds both local and remote settings.
538 * First, everything is loaded from local config file. Later, settings
539 * that are relevant on remote side only are loaded thru EC
541 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
543 m_conn = conn;
546 // Settings queried from remote side
548 m_exchange_send_selected_prefs =
549 EC_PREFS_GENERAL |
550 EC_PREFS_CONNECTIONS |
551 EC_PREFS_MESSAGEFILTER |
552 EC_PREFS_ONLINESIG |
553 EC_PREFS_SERVERS |
554 EC_PREFS_FILES |
555 EC_PREFS_SRCDROP |
556 EC_PREFS_DIRECTORIES |
557 EC_PREFS_SECURITY |
558 EC_PREFS_CORETWEAKS |
559 EC_PREFS_REMOTECONTROLS |
560 EC_PREFS_KADEMLIA;
561 m_exchange_recv_selected_prefs =
562 m_exchange_send_selected_prefs |
563 EC_PREFS_CATEGORIES;
567 void CPreferencesRem::HandlePacket(const CECPacket *packet)
569 ((CEC_Prefs_Packet *)packet)->Apply();
571 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
572 if (cat_tags) {
573 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); it++) {
574 const CECTag &cat_tag = *it;
575 Category_Struct *cat = new Category_Struct;
576 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
577 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
578 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
579 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
580 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
581 theApp->glob_prefs->AddCat(cat);
583 } else {
584 Category_Struct *cat = new Category_Struct;
585 cat->title = _("All");
586 cat->color = 0;
587 cat->prio = PR_NORMAL;
588 theApp->glob_prefs->AddCat(cat);
590 wxECInitDoneEvent event;
591 theApp->AddPendingEvent(event);
596 bool CPreferencesRem::LoadRemote()
599 // override local settings with remote
600 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
602 // bring categories too
603 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
605 m_conn->SendRequest(this, &req);
607 return true;
611 void CPreferencesRem::SendToRemote()
613 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
614 m_conn->SendPacket(&pref_packet);
618 class CCatHandler : public CECPacketHandlerBase {
619 virtual void HandlePacket(const CECPacket *packet);
623 void CCatHandler::HandlePacket(const CECPacket *packet)
625 if (packet->GetOpCode() == EC_OP_FAILED) {
626 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
627 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
628 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
629 int cat = catTag->GetInt();
630 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
631 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
632 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
633 _("ERROR"), wxOK);
634 cs->path = CPath(pathTag->GetStringData());
635 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
636 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
639 delete this;
643 bool CPreferencesRem::CreateCategory(
644 Category_Struct *& category,
645 const wxString& name,
646 const CPath& path,
647 const wxString& comment,
648 uint32 color,
649 uint8 prio)
651 CECPacket req(EC_OP_CREATE_CATEGORY);
652 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
653 req.AddTag(tag);
654 m_conn->SendRequest(new CCatHandler, &req);
656 category = new Category_Struct();
657 category->path = path;
658 category->title = name;
659 category->comment = comment;
660 category->color = color;
661 category->prio = prio;
663 AddCat(category);
665 return true;
669 bool CPreferencesRem::UpdateCategory(
670 uint8 cat,
671 const wxString& name,
672 const CPath& path,
673 const wxString& comment,
674 uint32 color,
675 uint8 prio)
677 CECPacket req(EC_OP_UPDATE_CATEGORY);
678 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
679 req.AddTag(tag);
680 m_conn->SendRequest(new CCatHandler, &req);
682 Category_Struct *category = m_CatList[cat];
683 category->path = path;
684 category->title = name;
685 category->comment = comment;
686 category->color = color;
687 category->prio = prio;
689 return true;
693 void CPreferencesRem::RemoveCat(uint8 cat)
695 CECPacket req(EC_OP_DELETE_CATEGORY);
696 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
697 req.AddTag(tag);
698 m_conn->SendPacket(&req);
699 CPreferences::RemoveCat(cat);
704 // Container implementation
706 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
708 m_CurrServer = 0;
709 m_Conn = conn;
713 void CServerConnectRem::ConnectToAnyServer()
715 CECPacket req(EC_OP_SERVER_CONNECT);
716 m_Conn->SendPacket(&req);
720 void CServerConnectRem::StopConnectionTry()
722 // lfroen: isn't Disconnect the same ?
726 void CServerConnectRem::Disconnect()
728 CECPacket req(EC_OP_SERVER_DISCONNECT);
729 m_Conn->SendPacket(&req);
733 void CServerConnectRem::ConnectToServer(CServer *server)
735 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
739 void CServerConnectRem::HandlePacket(const CECPacket *packet)
741 CEC_ConnState_Tag *tag =
742 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
743 if (!tag) {
744 return;
747 theApp->m_ConnState = 0;
748 CServer *server;
749 m_ID = tag->GetEd2kId();
750 theApp->m_clientID = tag->GetClientId();
752 if (tag->IsConnectedED2K()) {
753 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
754 if (srvtag) {
755 server = theApp->serverlist->GetByID(srvtag->GetInt());
756 if (server != m_CurrServer) {
757 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(server, true);
758 m_CurrServer = server;
761 theApp->m_ConnState |= CONNECTED_ED2K;
762 } else if ( m_CurrServer ) {
763 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(m_CurrServer, false);
764 m_CurrServer = 0;
767 if (tag->IsConnectedKademlia()) {
768 if (tag->IsKadFirewalled()) {
769 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
770 } else {
771 theApp->m_ConnState |= CONNECTED_KAD_OK;
773 } else {
774 if (tag->IsKadRunning()) {
775 theApp->m_ConnState |= CONNECTED_KAD_NOT;
779 theApp->amuledlg->ShowConnectionState();
784 * Server list: host list of ed2k servers.
786 CServerListRem::CServerListRem(CRemoteConnect *conn)
788 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true)
793 void CServerListRem::HandlePacket(const CECPacket *)
795 // There is no packet for the server list, it is part of the general update packet
796 wxFAIL;
797 // CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
801 void CServerListRem::UpdateServerMetFromURL(wxString url)
803 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
804 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
806 m_conn->SendPacket(&req);
810 void CServerListRem::SetStaticServer(CServer* server, bool isStatic)
812 // update display right away
813 server->SetIsStaticMember(isStatic);
814 Notify_ServerRefresh(server);
816 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
817 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
818 req.AddTag(CECTag(EC_TAG_SERVER_STATIC, isStatic));
820 m_conn->SendPacket(&req);
824 void CServerListRem::SetServerPrio(CServer* server, uint32 prio)
826 // update display right away
827 server->SetPreference(prio);
828 Notify_ServerRefresh(server);
830 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
831 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
832 req.AddTag(CECTag(EC_TAG_SERVER_PRIO, prio));
834 m_conn->SendPacket(&req);
838 void CServerListRem::RemoveServer(CServer* server)
840 m_conn->RemoveServer(server->GetIP(),server->GetPort());
844 void CServerListRem::UpdateUserFileStatus(CServer *server)
846 if (server) {
847 m_TotalUser = server->GetUsers();
848 m_TotalFile = server->GetFiles();
853 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
855 // It's ok to return 0 for context where this code is used in remote gui
856 return 0;
859 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
861 // It's ok to return 0 for context where this code is used in remote gui
862 return 0;
865 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
867 CServer * server = new CServer(tag);
868 ProcessItemUpdate(tag, server);
869 return server;
873 void CServerListRem::DeleteItem(CServer *in_srv)
875 CScopedPtr<CServer> srv(in_srv);
876 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
880 uint32 CServerListRem::GetItemID(CServer *server)
882 return server->ECID();
886 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag * tag, CServer * server)
888 if (!tag->HasChildTags()) {
889 return;
891 tag->ServerName(& server->listname);
892 tag->ServerDesc(& server->description);
893 tag->ServerVersion(& server->m_strVersion);
894 tag->GetMaxUsers(& server->maxusers);
896 tag->GetFiles(& server->files);
897 tag->GetUsers(& server->users);
899 tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok
900 tag->GetStatic(& server->staticservermember);
902 tag->GetPing(& server->ping);
903 tag->GetFailed(& server->failedcount);
905 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server);
909 CServer::CServer(CEC_Server_Tag *tag) : CECID(tag->GetInt())
911 ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt();
912 port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt();
914 Init();
919 * IP filter
921 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
923 m_conn = conn;
927 void CIPFilterRem::Reload()
929 CECPacket req(EC_OP_IPFILTER_RELOAD);
930 m_conn->SendPacket(&req);
934 void CIPFilterRem::Update(wxString url)
936 CECPacket req(EC_OP_IPFILTER_UPDATE);
937 req.AddTag(CECTag(EC_TAG_STRING, url));
939 m_conn->SendPacket(&req);
944 * Shared files list
946 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
948 m_conn = conn;
952 void CSharedFilesRem::Reload(bool, bool)
954 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
956 m_conn->SendPacket(&req);
960 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
962 // We use the printable name, as the filename originated from user input,
963 // and the filesystem name might not be valid on the remote host.
964 const wxString strNewName = newName.GetPrintable();
966 CECPacket request(EC_OP_RENAME_FILE);
967 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
968 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
970 m_conn->SendPacket(&request);
972 return true;
976 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
978 CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT);
979 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
980 request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment));
981 request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating));
983 m_conn->SendPacket(&request);
987 void CKnownFilesRem::DeleteItem(CKnownFile * file)
989 uint32 id = file->ECID();
990 if (theApp->sharedfiles->count(id)) {
991 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
992 theApp->sharedfiles->erase(id);
994 if (theApp->downloadqueue->count(id)) {
995 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file);
996 theApp->downloadqueue->erase(id);
998 delete file;
1002 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
1004 return file->ECID();
1008 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
1010 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1011 if (parttag) {
1012 const uint8 *data = file->m_partStatus.Decode(
1013 (uint8 *)parttag->GetTagData(),
1014 parttag->GetTagDataLen());
1015 for(int i = 0; i < file->GetPartCount(); ++i) {
1016 file->m_AvailPartFrequency[i] = data[i];
1019 wxString fileName;
1020 if (tag->FileName(fileName)) {
1021 file->SetFileName(CPath(fileName));
1023 if (tag->FilePath(fileName)) {
1024 file->m_filePath = CPath(fileName);
1026 tag->UpPrio(&file->m_iUpPriorityEC);
1027 tag->GetAICHHash(file->m_AICHMasterHash);
1028 tag->GetRequests(&file->statistic.requested);
1029 tag->GetAllRequests(&file->statistic.alltimerequested);
1030 tag->GetAccepts(&file->statistic.accepted);
1031 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
1032 tag->GetXferred(&file->statistic.transferred);
1033 tag->GetAllXferred(&file->statistic.alltimetransferred);
1034 tag->UpPrio(&file->m_iUpPriorityEC);
1035 if (file->m_iUpPriorityEC >= 10) {
1036 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1037 file->m_bAutoUpPriority = true;
1038 } else {
1039 file->m_iUpPriority = file->m_iUpPriorityEC;
1040 file->m_bAutoUpPriority = false;
1042 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1043 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1044 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1046 tag->GetOnQueue(&file->m_queuedCount);
1048 tag->GetComment(file->m_strComment);
1049 tag->GetRating(file->m_iRating);
1051 requested += file->statistic.requested;
1052 transferred += file->statistic.transferred;
1053 accepted += file->statistic.transferred;
1055 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1057 if (file->IsPartFile()) {
1058 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file);
1062 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1064 CECPacket req(EC_OP_SHARED_SET_PRIO);
1066 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1067 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1069 req.AddTag(hashtag);
1071 m_conn->SendPacket(&req);
1074 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1076 requested = 0;
1077 transferred = 0;
1078 accepted = 0;
1080 std::set<uint32> core_files;
1081 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
1082 const CECTag * curTag = &*it;
1083 ec_tagname_t tagname = curTag->GetTagName();
1084 if (tagname == EC_TAG_CLIENT) {
1085 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1086 } else if (tagname == EC_TAG_SERVER) {
1087 theApp->serverlist->ProcessUpdate(curTag, NULL, EC_TAG_SERVER);
1088 } else if (tagname == EC_TAG_FRIEND) {
1089 theApp->friendlist->ProcessUpdate(curTag, NULL, EC_TAG_FRIEND);
1090 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1091 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *) curTag;
1092 uint32 id = tag->ID();
1093 core_files.insert(id);
1094 std::map<uint32, CKnownFile*>::iterator it2 = m_items_hash.find(id);
1095 if (it2 != m_items_hash.end() ) {
1096 // Item already known: update it
1097 if (tag->HasChildTags()) {
1098 ProcessItemUpdate(tag, it2->second);
1100 } else {
1101 CKnownFile * newFile;
1102 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1103 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag);
1104 ProcessItemUpdate(tag, file);
1105 (*theApp->downloadqueue)[id] = file;
1106 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1107 newFile = file;
1108 } else {
1109 newFile = new CKnownFile(tag);
1110 ProcessItemUpdate(tag, newFile);
1111 (*theApp->sharedfiles)[id] = newFile;
1112 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1114 AddItem(newFile);
1118 // remove items no longer present
1119 for(iterator it = begin(); it != end();) {
1120 iterator it2 = it++;
1121 if (!core_files.count(GetItemID(*it2))) {
1122 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1127 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1129 requested = 0;
1130 transferred = 0;
1131 accepted = 0;
1136 * List of uploading and waiting clients.
1138 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1140 CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true)
1145 CClientRef::CClientRef(CEC_UpDownClient_Tag *tag)
1147 m_client = new CUpDownClient(tag);
1148 #ifdef DEBUG_ZOMBIE_CLIENTS
1149 m_client->Link(wxT("TAG"));
1150 #else
1151 m_client->Link();
1152 #endif
1156 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1158 m_linked = 0;
1159 #ifdef DEBUG_ZOMBIE_CLIENTS
1160 m_linkedDebug = false;
1161 #endif
1162 // Clients start up empty, then get asked for their data.
1163 // So all data here is processed in ProcessItemUpdate and thus updatable.
1164 m_bEmuleProtocol = false;
1165 m_AvailPartCount = 0;
1166 m_clientSoft = 0;
1167 m_nDownloadState = 0;
1168 m_Friend = NULL;
1169 m_bFriendSlot = false;
1170 m_nKadPort = 0;
1171 m_kBpsDown = 0;
1172 m_dwUserIP = 0;
1173 m_lastDownloadingPart = 0xffff;
1174 m_nextRequestedPart = 0xffff;
1175 m_obfuscationStatus = 0;
1176 m_nOldRemoteQueueRank = 0;
1177 m_nRemoteQueueRank = 0;
1178 m_reqfile = NULL;
1179 m_score = 0;
1180 m_dwServerIP = 0;
1181 m_nServerPort = 0;
1182 m_nSourceFrom = SF_NONE;
1183 m_nTransferredDown = 0;
1184 m_nTransferredUp = 0;
1185 m_nUpDatarate = 0;
1186 m_uploadingfile = NULL;
1187 m_waitingPosition = 0;
1188 m_nUploadState = 0;
1189 m_nUserIDHybrid = 0;
1190 m_nUserPort = 0;
1191 m_nClientVersion = 0;
1192 m_fNoViewSharedFiles = true;
1193 m_identState = IS_NOTAVAILABLE;
1194 m_bRemoteQueueFull = false;
1196 credits = new CClientCredits(new CreditStruct());
1199 #ifdef DEBUG_ZOMBIE_CLIENTS
1200 void CUpDownClient::Unlink(const wxString& from)
1202 std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
1203 if (it != m_linkedFrom.end()) {
1204 m_linkedFrom.erase(it);
1206 m_linked--;
1207 if (!m_linked) {
1208 if (m_linkedDebug) {
1209 AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this);
1211 delete this;
1215 #else
1217 void CUpDownClient::Unlink()
1219 m_linked--;
1220 if (!m_linked) {
1221 delete this;
1224 #endif
1227 uint64 CUpDownClient::GetDownloadedTotal() const
1229 return credits->GetDownloadedTotal();
1233 uint64 CUpDownClient::GetUploadedTotal() const
1235 return credits->GetUploadedTotal();
1239 double CUpDownClient::GetScoreRatio() const
1241 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1244 /* End Warning */
1247 CUpDownClient::~CUpDownClient()
1249 delete credits;
1253 CClientRef *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1255 CClientRef *client = new CClientRef(tag);
1256 ProcessItemUpdate(tag, client);
1258 return client;
1262 void CUpDownClientListRem::DeleteItem(CClientRef *clientref)
1264 CUpDownClient* client = clientref->GetClient();
1265 if (client->m_reqfile) {
1266 client->m_reqfile->DelSource(client);
1267 client->m_reqfile = NULL;
1269 Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL);
1271 if (client->m_uploadingfile) {
1272 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1273 client->m_uploadingfile = NULL;
1275 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); // in case it vanished directly while uploading
1276 Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL);
1278 if (client->m_Friend) {
1279 client->m_Friend->UnLinkClient(); // this notifies
1280 client->m_Friend = NULL;
1283 #ifdef DEBUG_ZOMBIE_CLIENTS
1284 if (client->m_linked > 1) {
1285 AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % client->ECID() % (client->m_linked - 1) % client->GetLinkedFrom());
1286 client->m_linkedDebug = true;
1288 #endif
1290 delete clientref;
1294 uint32 CUpDownClientListRem::GetItemID(CClientRef *client)
1296 return client->ECID();
1300 void CUpDownClientListRem::ProcessItemUpdate(
1301 CEC_UpDownClient_Tag *tag,
1302 CClientRef *clientref)
1304 if (!tag->HasChildTags()) {
1305 return; // speed exit for clients without any change
1307 CUpDownClient *client = clientref->GetClient();
1309 tag->UserID(&client->m_nUserIDHybrid);
1310 tag->ClientName(&client->m_Username);
1311 // Client Software
1312 bool sw_updated = false;
1313 if (tag->ClientSoftware(client->m_clientSoft)) {
1314 client->m_clientSoftString = GetSoftName(client->m_clientSoft);
1315 sw_updated = true;
1317 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1318 if (client->m_clientSoftString == _("Unknown")) {
1319 client->m_fullClientVerString = client->m_clientSoftString;
1320 } else {
1321 client->m_fullClientVerString = client->m_clientSoftString + wxT(" ") + client->m_clientVerString;
1324 // User hash
1325 tag->UserHash(&client->m_UserHash);
1327 // User IP:Port
1328 tag->UserIP(client->m_dwUserIP);
1329 tag->UserPort(&client->m_nUserPort);
1331 // Server IP:Port
1332 tag->ServerIP(&client->m_dwServerIP);
1333 tag->ServerPort(&client->m_nServerPort);
1334 tag->ServerName(&client->m_ServerName);
1336 tag->KadPort(client->m_nKadPort);
1337 tag->FriendSlot(client->m_bFriendSlot);
1339 tag->GetCurrentIdentState(&client->m_identState);
1340 tag->ObfuscationStatus(client->m_obfuscationStatus);
1341 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1343 tag->WaitingPosition(&client->m_waitingPosition);
1344 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1345 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1346 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1348 tag->ClientDownloadState(client->m_nDownloadState);
1349 if (tag->ClientUploadState(client->m_nUploadState)) {
1350 if (client->m_nUploadState == US_UPLOADING) {
1351 theApp->m_allUploadingKnownFile->AddUploadingClient(client);
1352 } else {
1353 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);
1357 tag->SpeedUp(&client->m_nUpDatarate);
1358 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1359 tag->SpeedDown(&client->m_kBpsDown);
1360 } else {
1361 client->m_kBpsDown = 0;
1364 //tag->WaitTime(&client->m_WaitTime);
1365 //tag->XferTime(&client->m_UpStartTimeDelay);
1366 //tag->LastReqTime(&client->m_dwLastUpRequest);
1367 //tag->QueueTime(&client->m_WaitStartTime);
1369 CreditStruct *credit_struct =
1370 (CreditStruct *)client->credits->GetDataStruct();
1371 tag->XferUp(&credit_struct->uploaded);
1372 tag->XferUpSession(&client->m_nTransferredUp);
1374 tag->XferDown(&credit_struct->downloaded);
1375 tag->XferDownSession(&client->m_nTransferredDown);
1377 tag->Score(&client->m_score);
1379 tag->NextRequestedPart(client->m_nextRequestedPart);
1380 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1382 uint8 sourceFrom = 0;
1383 if (tag->GetSourceFrom(sourceFrom)) {
1384 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1387 tag->RemoteFilename(client->m_clientFilename);
1388 tag->DisableViewShared(client->m_fNoViewSharedFiles);
1389 tag->Version(client->m_nClientVersion);
1390 tag->ModVersion(client->m_strModVersion);
1391 tag->OSInfo(client->m_sClientOSInfo);
1392 tag->AvailableParts(client->m_AvailPartCount);
1394 // Download client
1395 uint32 fileID;
1396 bool notified = false;
1397 if (tag->RequestFile(fileID)) {
1398 if (client->m_reqfile) {
1399 Notify_SourceCtrlRemoveSource(client->ECID(), client->m_reqfile);
1400 client->m_reqfile->DelSource(client);
1401 client->m_reqfile = NULL;
1402 client->m_downPartStatus.clear();
1404 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1405 if (kf && kf->IsCPartFile()) {
1406 client->m_reqfile = (CPartFile *) kf;
1407 client->m_reqfile->AddSource(client);
1408 client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1409 Notify_SourceCtrlAddSource(client->m_reqfile, CCLIENTREF(client, wxT("AddSource")), A4AF_SOURCE);
1410 notified = true;
1414 // Part status
1415 CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1416 if (partStatusTag) {
1417 if (partStatusTag->GetTagDataLen() == 0) {
1418 // empty tag means full source
1419 client->m_downPartStatus.SetAllTrue();
1420 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1421 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1423 notified = false;
1426 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1427 SourceItemType type;
1428 switch (client->GetDownloadState()) {
1429 case DS_DOWNLOADING:
1430 case DS_ONQUEUE:
1431 // We will send A4AF, which will be checked.
1432 type = A4AF_SOURCE;
1433 break;
1434 default:
1435 type = UNAVAILABLE_SOURCE;
1436 break;
1439 Notify_SourceCtrlUpdateSource(client->ECID(), type);
1442 // Upload client
1443 notified = false;
1444 if (tag->UploadFile(fileID)) {
1445 if (client->m_uploadingfile) {
1446 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1447 notified = true;
1448 client->m_uploadingfile = NULL;
1450 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1451 if (kf) {
1452 client->m_uploadingfile = kf;
1453 client->m_upPartStatus.setsize(kf->GetPartCount(), 0);
1454 client->m_uploadingfile->AddUploadingClient(client); // this notifies
1455 notified = true;
1459 // Part status
1460 partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_UPLOAD_PART_STATUS);
1461 if (partStatusTag) {
1462 if (partStatusTag->GetTagDataLen() == client->m_upPartStatus.SizeBuffer()) {
1463 client->m_upPartStatus.SetBuffer(partStatusTag->GetTagData());
1465 notified = false;
1468 if (!notified && client->m_uploadingfile
1469 && (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) {
1470 // notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode)
1471 SourceItemType type;
1472 switch (client->GetUploadState()) {
1473 case US_UPLOADING:
1474 case US_ONUPLOADQUEUE:
1475 type = AVAILABLE_SOURCE;
1476 break;
1477 default:
1478 type = UNAVAILABLE_SOURCE;
1479 break;
1481 Notify_SharedCtrlRefreshClient(client->ECID(), type);
1487 * Download queue container: hold PartFiles with progress status
1492 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1494 CECPacket req(EC_OP_ADD_LINK);
1495 CECTag link_tag(EC_TAG_STRING, link);
1496 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1497 req.AddTag(link_tag);
1499 m_conn->SendPacket(&req);
1500 return true;
1504 void CDownQueueRem::ResetCatParts(int cat)
1506 // Called when category is deleted. Command will be performed on the remote side,
1507 // but files still should be updated here right away, or drawing errors (colour not available)
1508 // will happen.
1509 for (iterator it = begin(); it != end(); it++) {
1510 CPartFile* file = it->second;
1511 file->RemoveCategory(cat);
1517 void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file)
1520 // update status
1522 tag->Speed(&file->m_kbpsDown);
1523 file->kBpsDown = file->m_kbpsDown / 1024.0;
1525 tag->SizeXfer(&file->transferred);
1526 tag->SizeDone(&file->completedsize);
1527 tag->SourceXferCount(&file->transferingsrc);
1528 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1529 tag->SourceCount(&file->m_source_count);
1530 tag->SourceCountA4AF(&file->m_a4af_source_count);
1531 tag->FileStatus(&file->status);
1532 tag->Stopped(&file->m_stopped);
1534 tag->LastSeenComplete(&file->lastseencomplete);
1535 tag->LastDateChanged(&file->m_lastDateChanged);
1536 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1537 tag->AvailablePartCount(&file->m_availablePartsCount);
1538 tag->Shared(&file->m_isShared);
1539 tag->A4AFAuto(file->m_is_A4AF_auto);
1541 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1542 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1543 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1545 tag->FileCat(&file->m_category);
1547 tag->DownPrio(&file->m_iDownPriorityEC);
1548 if ( file->m_iDownPriorityEC >= 10 ) {
1549 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1550 file->m_bAutoDownPriority = true;
1551 } else {
1552 file->m_iDownPriority = file->m_iDownPriorityEC;
1553 file->m_bAutoDownPriority = false;
1556 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1559 // Copy part/gap status
1561 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1562 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1563 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1564 if (gaptag || parttag || reqtag) {
1565 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1567 if (gaptag) {
1568 ArrayOfUInts64 gaps;
1569 encoder.DecodeGaps(gaptag, gaps);
1570 int gap_size = gaps.size() / 2;
1571 // clear gaplist
1572 file->m_gaplist.Init(file->GetFileSize(), false);
1574 // and refill it
1575 for (int j = 0; j < gap_size; j++) {
1576 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1579 if (parttag) {
1580 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1581 // sanity check
1582 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1584 if (reqtag) {
1585 ArrayOfUInts64 reqs;
1586 encoder.DecodeReqs(reqtag, reqs);
1587 int req_size = reqs.size() / 2;
1588 // clear reqlist
1589 DeleteContents(file->m_requestedblocks_list);
1591 // and refill it
1592 for (int j = 0; j < req_size; j++) {
1593 Requested_Block_Struct* block = new Requested_Block_Struct;
1594 block->StartOffset = reqs[2*j];
1595 block->EndOffset = reqs[2*j+1];
1596 file->m_requestedblocks_list.push_back(block);
1601 // Get source names and counts
1602 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1603 if (srcnametag) {
1604 SourcenameItemMap &map = file->GetSourcenameItemMap();
1605 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); it++) {
1606 uint32 key = it->GetInt();
1607 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1608 if (count == 0) {
1609 map.erase(key);
1610 } else {
1611 SourcenameItem &item = map[key];
1612 item.count = count;
1613 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1614 if (nametag) {
1615 item.name = nametag->GetStringData();
1621 // Get comments
1622 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1623 if (commenttag) {
1624 file->ClearFileRatingList();
1625 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1626 wxString u = (it++)->GetStringData();
1627 wxString f = (it++)->GetStringData();
1628 int r = (it++)->GetInt();
1629 wxString c = (it++)->GetStringData();
1630 file->AddFileRatingList(u, f, r, c);
1632 file->UpdateFileRatingCommentAvail();
1635 // Update A4AF sources
1636 ListOfUInts32 & clientIDs = file->GetA4AFClientIDs();
1637 CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES);
1638 if (a4aftag) {
1639 file->ClearA4AFList();
1640 clientIDs.clear();
1641 for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); it++) {
1642 if (it->GetTagName() != EC_TAG_ECID) { // should always be this
1643 continue;
1645 uint32 id = it->GetInt();
1646 CClientRef * src = theApp->clientlist->GetByID(id);
1647 if (src) {
1648 file->AddA4AFSource(src->GetClient());
1649 } else {
1650 // client wasn't transmitted yet, try it later
1651 clientIDs.push_back(id);
1654 } else if (!clientIDs.empty()) {
1655 // Process clients from the last pass whose ids were still unknown then
1656 for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) {
1657 ListOfUInts32::iterator it1 = it++;
1658 uint32 id = *it1;
1659 CClientRef * src = theApp->clientlist->GetByID(id);
1660 if (src) {
1661 file->AddA4AFSource(src->GetClient());
1662 clientIDs.erase(it1);
1667 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1669 // If file is shared check if it is already listed in shared files.
1670 // If not, add it and show it.
1671 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1672 (*theApp->sharedfiles)[file->ECID()] = file;
1673 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1678 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1680 CECPacket req(cmd);
1681 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1683 m_conn->SendPacket(&req);
1687 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1689 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1691 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1692 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1693 req.AddTag(hashtag);
1695 m_conn->SendPacket(&req);
1699 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1701 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1703 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1705 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1706 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1707 req.AddTag(hashtag);
1709 m_conn->SendPacket(&req);
1713 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1715 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1716 file->SetCategory(cat);
1718 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1719 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1720 req.AddTag(hashtag);
1722 m_conn->SendPacket(&req);
1726 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1728 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1729 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1730 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1731 req.AddTag(hashtag);
1733 m_conn->SendPacket(&req);
1737 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
1739 CECPacket req(EC_OP_CLEAR_COMPLETED);
1740 for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); it++) {
1741 req.AddTag(CECTag(EC_TAG_ECID, *it));
1744 m_conn->SendPacket(&req);
1749 * List of friends.
1751 CFriendListRem::CFriendListRem(CRemoteConnect *conn)
1753 CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true)
1758 void CFriendListRem::HandlePacket(const CECPacket *)
1760 wxFAIL; // not needed
1764 CFriend * CFriendListRem::CreateItem(CEC_Friend_Tag * tag)
1766 CFriend * Friend = new CFriend(tag->ID());
1767 ProcessItemUpdate(tag, Friend);
1768 return Friend;
1772 void CFriendListRem::DeleteItem(CFriend * Friend)
1774 Friend->UnLinkClient(false);
1775 Notify_ChatRemoveFriend(Friend);
1779 uint32 CFriendListRem::GetItemID(CFriend * Friend)
1781 return Friend->ECID();
1785 void CFriendListRem::ProcessItemUpdate(CEC_Friend_Tag * tag, CFriend * Friend)
1787 if (!tag->HasChildTags()) {
1788 return;
1790 tag->Name(Friend->m_strName);
1791 tag->UserHash(Friend->m_UserHash);
1792 tag->IP(Friend->m_dwLastUsedIP);
1793 tag->Port(Friend->m_nLastUsedPort);
1794 uint32 clientID;
1795 bool notified = false;
1796 if (tag->Client(clientID)) {
1797 if (clientID) {
1798 CClientRef * client = theApp->clientlist->GetByID(clientID);
1799 if (client) {
1800 Friend->LinkClient(*client); // this notifies
1801 notified = true;
1803 } else {
1804 // Unlink
1805 Friend->UnLinkClient(false);
1808 if (!notified) {
1809 Notify_ChatUpdateFriend(Friend);
1814 void CFriendListRem::AddFriend(const CClientRef& toadd)
1816 CECPacket req(EC_OP_FRIEND);
1818 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1819 addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID()));
1820 req.AddTag(addtag);
1822 m_conn->SendPacket(&req);
1826 void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name)
1828 CECPacket req(EC_OP_FRIEND);
1830 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1831 addtag.AddTag(CECTag(EC_TAG_FRIEND_HASH, userhash));
1832 addtag.AddTag(CECTag(EC_TAG_FRIEND_IP, lastUsedIP));
1833 addtag.AddTag(CECTag(EC_TAG_FRIEND_PORT, lastUsedPort));
1834 addtag.AddTag(CECTag(EC_TAG_FRIEND_NAME, name));
1835 req.AddTag(addtag);
1837 m_conn->SendPacket(&req);
1841 void CFriendListRem::RemoveFriend(CFriend* toremove)
1843 CECPacket req(EC_OP_FRIEND);
1845 CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE);
1846 removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID()));
1847 req.AddTag(removetag);
1849 m_conn->SendPacket(&req);
1853 void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state)
1855 CECPacket req(EC_OP_FRIEND);
1857 CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state);
1858 slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1859 req.AddTag(slottag);
1861 m_conn->SendPacket(&req);
1865 void CFriendListRem::RequestSharedFileList(CFriend* Friend)
1867 CECPacket req(EC_OP_FRIEND);
1869 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1870 sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1871 req.AddTag(sharedtag);
1873 m_conn->SendPacket(&req);
1877 void CFriendListRem::RequestSharedFileList(CClientRef& client)
1879 CECPacket req(EC_OP_FRIEND);
1881 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1882 sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID()));
1883 req.AddTag(sharedtag);
1885 m_conn->SendPacket(&req);
1891 * Search results
1893 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1895 m_curr_search = -1;
1899 wxString CSearchListRem::StartNewSearch(
1900 uint32* nSearchID, SearchType search_type,
1901 const CSearchList::CSearchParams& params)
1903 CECPacket search_req(EC_OP_SEARCH_START);
1904 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1905 switch(search_type) {
1906 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1907 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1908 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1910 search_req.AddTag(
1911 CEC_Search_Tag(params.searchString, ec_search_type,
1912 params.typeText, params.extension, params.availability,
1913 params.minSize, params.maxSize));
1915 m_conn->SendPacket(&search_req);
1916 m_curr_search = *(nSearchID); // No kad remote search yet.
1918 Flush();
1920 return wxEmptyString; // EC reply will have the error mesg is needed.
1924 void CSearchListRem::StopSearch(bool)
1926 if (m_curr_search != -1) {
1927 CECPacket search_req(EC_OP_SEARCH_STOP);
1928 m_conn->SendPacket(&search_req);
1933 void CSearchListRem::HandlePacket(const CECPacket *packet)
1935 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1936 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1937 } else {
1938 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1943 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1945 CECID(tag->ID()),
1946 m_parent(NULL),
1947 m_showChildren(false),
1948 m_sourceCount(0),
1949 m_completeSourceCount(0),
1950 m_kademlia(false),
1951 m_downloadStatus(NEW),
1952 m_clientID(0),
1953 m_clientPort(0),
1954 m_kadPublishInfo(0)
1956 SetFileName(CPath(tag->FileName()));
1957 m_abyFileHash = tag->FileHash();
1958 SetFileSize(tag->SizeFull());
1960 m_searchID = theApp->searchlist->m_curr_search;
1961 uint32 parentID = tag->ParentID();
1962 if (parentID) {
1963 CSearchFile * parent = theApp->searchlist->GetByID(parentID);
1964 if (parent) {
1965 parent->AddChild(this);
1971 void CSearchFile::AddChild(CSearchFile* file)
1973 m_children.push_back(file);
1974 file->m_parent = this;
1978 // dtor is virtual - must be implemented
1979 CSearchFile::~CSearchFile()
1984 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1986 CSearchFile *file = new CSearchFile(tag);
1987 ProcessItemUpdate(tag, file);
1989 theApp->amuledlg->m_searchwnd->AddResult(file);
1991 return file;
1995 void CSearchListRem::DeleteItem(CSearchFile *file)
1997 delete file;
2001 uint32 CSearchListRem::GetItemID(CSearchFile *file)
2003 return file->ECID();
2007 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
2009 uint32 sourceCount = file->m_sourceCount;
2010 uint32 completeSourceCount = file->m_completeSourceCount;
2011 CSearchFile::DownloadStatus status = file->m_downloadStatus;
2012 tag->SourceCount(&file->m_sourceCount);
2013 tag->CompleteSourceCount(&file->m_completeSourceCount);
2014 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
2016 if (file->m_sourceCount != sourceCount
2017 || file->m_completeSourceCount != completeSourceCount
2018 || file->m_downloadStatus != status) {
2019 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
2020 theApp->amuledlg->m_searchwnd->UpdateResult(file);
2026 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
2028 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
2029 m_conn->SendRequest(this, &progress_req);
2031 return true;
2035 void CSearchListRem::RemoveResults(long nSearchID)
2037 ResultMap::iterator it = m_results.find(nSearchID);
2038 if (it != m_results.end()) {
2039 CSearchResultList& list = it->second;
2040 for (unsigned int i = 0; i < list.size(); ++i) {
2041 delete list[i];
2043 m_results.erase(it);
2048 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
2050 ResultMap::const_iterator it = m_results.find(nSearchID);
2051 if (it != m_results.end()) {
2052 return it->second;
2055 // TODO: Should we assert in this case?
2056 static CSearchResultList list;
2057 return list;
2061 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
2063 theStats::UpdateStats(packet);
2064 theApp->amuledlg->ShowTransferRate();
2065 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
2066 // handle the connstate tag which is included in the stats packet
2067 theApp->serverconnect->HandlePacket(packet);
2071 void CUpDownClient::RequestSharedFileList()
2073 CClientRef ref = CCLIENTREF(this, wxEmptyString);
2074 theApp->friendlist->RequestSharedFileList(ref);
2078 bool CUpDownClient::SwapToAnotherFile(
2079 bool WXUNUSED(bIgnoreNoNeeded),
2080 bool WXUNUSED(ignoreSuspensions),
2081 bool WXUNUSED(bRemoveCompletely),
2082 CPartFile* toFile)
2084 CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE);
2085 req.AddTag(CECTag(EC_TAG_CLIENT, ECID()));
2086 req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash()));
2087 theApp->m_connect->SendPacket(&req);
2089 return true;
2093 wxString CAICHHash::GetString() const
2095 return EncodeBase32(m_abyBuffer, HASHSIZE);
2100 // Those functions are virtual. So even they don't get called they must
2101 // be defined so linker will be happy
2103 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2105 wxFAIL;
2106 return 0;
2110 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
2112 wxFAIL;
2113 return false;
2117 void CKnownFile::UpdatePartsInfo()
2119 wxFAIL;
2123 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2125 wxFAIL;
2126 return 0;
2130 void CPartFile::UpdatePartsInfo()
2132 wxFAIL;
2137 void CPartFile::UpdateFileRatingCommentAvail()
2139 bool prevComment = m_hasComment;
2140 int prevRating = m_iUserRating;
2142 m_hasComment = false;
2143 m_iUserRating = 0;
2144 int ratingCount = 0;
2146 FileRatingList::iterator it = m_FileRatingList.begin();
2147 for (; it != m_FileRatingList.end(); ++it) {
2148 SFileRating& cur_rat = *it;
2150 if (!cur_rat.Comment.IsEmpty()) {
2151 m_hasComment = true;
2154 uint8 rating = cur_rat.Rating;
2155 if (rating) {
2156 wxASSERT(rating <= 5);
2158 ratingCount++;
2159 m_iUserRating += rating;
2163 if (ratingCount) {
2164 m_iUserRating /= ratingCount;
2165 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
2168 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
2169 UpdateDisplayedInfo();
2174 void CStatTreeRem::DoRequery()
2176 CECPacket request(EC_OP_GET_STATSTREE);
2177 if (thePrefs::GetMaxClientVersions() != 0) {
2178 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
2180 m_conn->SendRequest(this, &request);
2183 void CStatTreeRem::HandlePacket(const CECPacket * p)
2185 const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE);
2186 if (treeRoot) {
2187 theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot);
2188 theApp->amuledlg->m_statisticswnd->ShowStatistics();
2192 CamuleRemoteGuiApp *theApp;
2195 // since gui is not linked with amule.cpp - define events here
2197 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2198 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2199 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2200 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2201 // File_checked_for_headers