Remove do-nothing function
[amule.git] / src / amule-remote-gui.cpp
blobbeaa46193725a0629305d486c69df091aac94dd8
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2008 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 serverconnect->ReQuery();
157 request_step++;
158 break;
159 case 1: {
160 CECPacket stats_req(EC_OP_STAT_REQ);
161 m_connect->SendRequest(&m_stats_updater, &stats_req);
162 amuledlg->ShowTransferRate();
163 request_step++;
164 break;
166 case 2:
167 if (amuledlg->m_sharedfileswnd->IsShown()
168 || amuledlg->m_chatwnd->IsShown()
169 || amuledlg->m_serverwnd->IsShown()) {
170 // update downloads, shared files and servers
171 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
172 } else if (amuledlg->m_transferwnd->IsShown()) {
173 // update both downloads and shared files
174 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
175 } else if (amuledlg->m_searchwnd->IsShown()) {
176 if (searchlist->m_curr_search != -1) {
177 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
179 } else if (amuledlg->m_statisticswnd->IsShown()) {
180 int sStatsUpdate = thePrefs::GetStatsInterval();
181 uint32 msCur = theStats::GetUptimeMillis();
182 if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) {
183 msPrevStats = msCur;
184 stattree->DoRequery();
187 // Back to the roots
188 request_step = 0;
189 break;
190 default:
191 wxFAIL;
192 request_step = 0;
195 // Check for new links once per second.
196 static uint32 lastED2KLinkCheck = 0;
197 if (GetTickCount() - lastED2KLinkCheck >= 1000) {
198 AddLinksFromFile();
199 lastED2KLinkCheck = GetTickCount();
204 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
206 if (event.GetInt() == HTTP_GeoIP) {
207 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
208 // If we updated, the dialog is already up. Redraw it to show the flags.
209 amuledlg->Refresh();
214 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
216 // Stop the Core Timer
217 delete poll_timer;
218 poll_timer = NULL;
220 // Destroy the EC socket
221 m_connect->Destroy();
222 m_connect = NULL;
225 if (amuledlg) {
226 amuledlg->DlgShutDown();
227 amuledlg->Destroy();
228 amuledlg = NULL;
230 delete m_allUploadingKnownFile;
231 delete stattree;
235 bool CamuleRemoteGuiApp::OnInit()
237 StartTickTimer();
238 amuledlg = NULL;
240 // Get theApp
241 theApp = &wxGetApp();
243 // Handle uncaught exceptions
244 InstallMuleExceptionHandler();
246 // Parse cmdline arguments.
247 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
248 return false;
251 // Create the polling timer
252 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
253 if (!poll_timer) {
254 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
255 OnExit();
258 m_connect = new CRemoteConnect(this);
260 glob_prefs = new CPreferencesRem(m_connect);
261 long enableZLIB;
262 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
263 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification
265 InitCustomLanguages();
266 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
268 if (ShowConnectionDialog()) {
269 AddLogLineNS(_("Going to event loop..."));
270 return true;
273 return false;
277 bool CamuleRemoteGuiApp::CryptoAvailable() const
279 return thePrefs::IsSecureIdentEnabled(); // good enough
283 bool CamuleRemoteGuiApp::ShowConnectionDialog()
285 dialog = new CEConnectDlg;
287 if (m_skipConnectionDialog) {
288 wxCommandEvent evt;
289 dialog->OnOK(evt);
290 } else if (dialog->ShowModal() != wxID_OK) {
291 dialog->Destroy();
293 return false;
295 AddLogLineNS(_("Connecting..."));
296 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
297 dialog->Login(), dialog->PassHash(),
298 wxT("amule-remote"), wxT("0x0001"))) {
299 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
301 return false;
304 return true;
308 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
309 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
310 AddLogLineNS(_("Remote GUI EC event handler"));
311 wxString reply = evt.GetServerReply();
312 AddLogLineC(reply);
313 if (evt.GetResult() == true) {
314 // Connected - go to next init step
315 glob_prefs->LoadRemote();
316 } else {
317 AddLogLineNS(_("Going down"));
318 if (dialog) { // connect failed
319 wxMessageBox(
320 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
321 _("ERROR"), wxOK);
322 } else { // server disconnected (probably terminated) later
323 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
325 ExitMainLoop();
330 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
332 Startup();
336 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
338 evt.Notify();
342 void CamuleRemoteGuiApp::Startup() {
344 if (dialog->SaveUserPass()) {
345 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
346 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
347 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
349 dialog->Destroy();
350 dialog = NULL;
352 m_ConnState = 0;
353 m_clientID = 0;
355 serverconnect = new CServerConnectRem(m_connect);
356 m_statistics = new CStatistics(*m_connect);
357 stattree = new CStatTreeRem(m_connect);
359 clientlist = new CUpDownClientListRem(m_connect);
360 searchlist = new CSearchListRem(m_connect);
361 serverlist = new CServerListRem(m_connect);
362 friendlist = new CFriendListRem(m_connect);
365 sharedfiles = new CSharedFilesRem(m_connect);
366 knownfiles = new CKnownFilesRem(m_connect);
368 downloadqueue = new CDownQueueRem(m_connect);
369 ipfilter = new CIPFilterRem(m_connect);
371 m_allUploadingKnownFile = new CKnownFile;
373 // Create main dialog
374 InitGui(m_geometryEnabled, m_geometryString);
376 // Forward wxLog events to CLogger
377 wxLog::SetActiveTarget(new CLoggerTarget);
378 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
380 // Start the Poll Timer
381 poll_timer->Start(1000);
382 amuledlg->StartGuiTimer();
384 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
385 #ifdef ENABLE_IP2COUNTRY
386 if (thePrefs::IsGeoIPEnabled()) {
387 amuledlg->m_IP2Country->Enable();
389 #endif
393 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
395 return CamuleGuiBase::ShowAlert(msg, title, flags);
399 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
401 amuledlg->AddLogLine(line);
404 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
406 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
407 SetTopWindow(amuledlg);
408 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
409 return 0;
413 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
415 return CamuleGuiBase::CopyTextToClipboard(strText);
419 uint32 CamuleRemoteGuiApp::GetPublicIP()
421 return 0;
425 wxString CamuleRemoteGuiApp::GetLog(bool reset)
427 if (reset) {
428 amuledlg->ResetLog(ID_LOGVIEW);
429 CECPacket req(EC_OP_RESET_LOG);
430 m_connect->SendPacket(&req);
432 return wxEmptyString;
436 wxString CamuleRemoteGuiApp::GetServerLog(bool)
438 return wxEmptyString;
442 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
444 CECPacket req(EC_OP_SERVER_ADD);
445 req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort()));
446 req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName()));
447 m_connect->SendPacket(&req);
449 return true;
453 bool CamuleRemoteGuiApp::IsFirewalled() const
455 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
456 return false;
459 return IsFirewalledKad();
463 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
464 return serverconnect && serverconnect->IsConnected();
468 void CamuleRemoteGuiApp::StartKad() {
469 m_connect->StartKad();
473 void CamuleRemoteGuiApp::StopKad() {
474 m_connect->StopKad();
478 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
480 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
481 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
482 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
484 m_connect->SendPacket(&req);
488 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
490 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
491 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
493 m_connect->SendPacket(&req);
497 void CamuleRemoteGuiApp::DisconnectED2K() {
498 if (IsConnectedED2K()) {
499 m_connect->DisconnectED2K();
504 uint32 CamuleRemoteGuiApp::GetED2KID() const
506 return serverconnect ? serverconnect->GetClientID() : 0;
510 uint32 CamuleRemoteGuiApp::GetID() const
512 return m_clientID;
516 void CamuleRemoteGuiApp::ShowUserCount() {
517 wxString buffer;
519 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
520 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
522 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
523 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
524 } else if (thePrefs::GetNetworkED2K()) {
525 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
526 } else if (thePrefs::GetNetworkKademlia()) {
527 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
528 } else {
529 buffer = _("No networks selected");
532 Notify_ShowUserCount(buffer);
537 * Preferences: holds both local and remote settings.
539 * First, everything is loaded from local config file. Later, settings
540 * that are relevant on remote side only are loaded thru EC
542 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
544 m_conn = conn;
547 // Settings queried from remote side
549 m_exchange_send_selected_prefs =
550 EC_PREFS_GENERAL |
551 EC_PREFS_CONNECTIONS |
552 EC_PREFS_MESSAGEFILTER |
553 EC_PREFS_ONLINESIG |
554 EC_PREFS_SERVERS |
555 EC_PREFS_FILES |
556 EC_PREFS_SRCDROP |
557 EC_PREFS_DIRECTORIES |
558 EC_PREFS_SECURITY |
559 EC_PREFS_CORETWEAKS |
560 EC_PREFS_REMOTECONTROLS |
561 EC_PREFS_KADEMLIA;
562 m_exchange_recv_selected_prefs =
563 m_exchange_send_selected_prefs |
564 EC_PREFS_CATEGORIES;
568 void CPreferencesRem::HandlePacket(const CECPacket *packet)
570 ((CEC_Prefs_Packet *)packet)->Apply();
572 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
573 if (cat_tags) {
574 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); it++) {
575 const CECTag &cat_tag = *it;
576 Category_Struct *cat = new Category_Struct;
577 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
578 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
579 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
580 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
581 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
582 theApp->glob_prefs->AddCat(cat);
584 } else {
585 Category_Struct *cat = new Category_Struct;
586 cat->title = _("All");
587 cat->color = 0;
588 cat->prio = PR_NORMAL;
589 theApp->glob_prefs->AddCat(cat);
591 wxECInitDoneEvent event;
592 theApp->AddPendingEvent(event);
597 bool CPreferencesRem::LoadRemote()
600 // override local settings with remote
601 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
603 // bring categories too
604 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
606 m_conn->SendRequest(this, &req);
608 return true;
612 void CPreferencesRem::SendToRemote()
614 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
615 m_conn->SendPacket(&pref_packet);
619 class CCatHandler : public CECPacketHandlerBase {
620 virtual void HandlePacket(const CECPacket *packet);
624 void CCatHandler::HandlePacket(const CECPacket *packet)
626 if (packet->GetOpCode() == EC_OP_FAILED) {
627 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
628 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
629 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
630 int cat = catTag->GetInt();
631 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
632 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
633 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
634 _("ERROR"), wxOK);
635 cs->path = CPath(pathTag->GetStringData());
636 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
637 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
640 delete this;
644 bool CPreferencesRem::CreateCategory(
645 Category_Struct *& category,
646 const wxString& name,
647 const CPath& path,
648 const wxString& comment,
649 uint32 color,
650 uint8 prio)
652 CECPacket req(EC_OP_CREATE_CATEGORY);
653 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
654 req.AddTag(tag);
655 m_conn->SendRequest(new CCatHandler, &req);
657 category = new Category_Struct();
658 category->path = path;
659 category->title = name;
660 category->comment = comment;
661 category->color = color;
662 category->prio = prio;
664 AddCat(category);
666 return true;
670 bool CPreferencesRem::UpdateCategory(
671 uint8 cat,
672 const wxString& name,
673 const CPath& path,
674 const wxString& comment,
675 uint32 color,
676 uint8 prio)
678 CECPacket req(EC_OP_UPDATE_CATEGORY);
679 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
680 req.AddTag(tag);
681 m_conn->SendRequest(new CCatHandler, &req);
683 Category_Struct *category = m_CatList[cat];
684 category->path = path;
685 category->title = name;
686 category->comment = comment;
687 category->color = color;
688 category->prio = prio;
690 return true;
694 void CPreferencesRem::RemoveCat(uint8 cat)
696 CECPacket req(EC_OP_DELETE_CATEGORY);
697 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
698 req.AddTag(tag);
699 m_conn->SendPacket(&req);
700 CPreferences::RemoveCat(cat);
705 // Container implementation
707 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
709 m_CurrServer = 0;
710 m_Conn = conn;
714 void CServerConnectRem::ConnectToAnyServer()
716 CECPacket req(EC_OP_SERVER_CONNECT);
717 m_Conn->SendPacket(&req);
721 void CServerConnectRem::StopConnectionTry()
723 // lfroen: isn't Disconnect the same ?
727 void CServerConnectRem::Disconnect()
729 CECPacket req(EC_OP_SERVER_DISCONNECT);
730 m_Conn->SendPacket(&req);
734 void CServerConnectRem::ConnectToServer(CServer *server)
736 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
740 bool CServerConnectRem::ReQuery()
742 CECPacket stat_req(EC_OP_GET_CONNSTATE);
743 m_Conn->SendRequest(this, &stat_req);
745 return true;
749 void CServerConnectRem::HandlePacket(const CECPacket *packet)
751 CEC_ConnState_Tag *tag =
752 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
753 if (!tag) {
754 return;
757 theApp->m_ConnState = 0;
758 CServer *server;
759 m_ID = tag->GetEd2kId();
760 theApp->m_clientID = tag->GetClientId();
762 if (tag->IsConnectedED2K()) {
763 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
764 if (srvtag) {
765 server = theApp->serverlist->GetByID(srvtag->GetInt());
766 if (server != m_CurrServer) {
767 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(server, true);
768 m_CurrServer = server;
771 theApp->m_ConnState |= CONNECTED_ED2K;
772 } else if ( m_CurrServer ) {
773 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(m_CurrServer, false);
774 m_CurrServer = 0;
777 if (tag->IsConnectedKademlia()) {
778 if (tag->IsKadFirewalled()) {
779 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
780 } else {
781 theApp->m_ConnState |= CONNECTED_KAD_OK;
783 } else {
784 if (tag->IsKadRunning()) {
785 theApp->m_ConnState |= CONNECTED_KAD_NOT;
789 theApp->amuledlg->ShowConnectionState();
794 * Server list: host list of ed2k servers.
796 CServerListRem::CServerListRem(CRemoteConnect *conn)
798 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true)
803 void CServerListRem::HandlePacket(const CECPacket *)
805 // There is no packet for the server list, it is part of the general update packet
806 wxFAIL;
807 // CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
811 void CServerListRem::UpdateServerMetFromURL(wxString url)
813 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
814 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
816 m_conn->SendPacket(&req);
820 void CServerListRem::SetStaticServer(CServer* server, bool isStatic)
822 // update display right away
823 server->SetIsStaticMember(isStatic);
824 Notify_ServerRefresh(server);
826 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
827 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
828 req.AddTag(CECTag(EC_TAG_SERVER_STATIC, isStatic));
830 m_conn->SendPacket(&req);
834 void CServerListRem::SetServerPrio(CServer* server, uint32 prio)
836 // update display right away
837 server->SetPreference(prio);
838 Notify_ServerRefresh(server);
840 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO);
841 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID()));
842 req.AddTag(CECTag(EC_TAG_SERVER_PRIO, prio));
844 m_conn->SendPacket(&req);
848 void CServerListRem::RemoveServer(CServer* server)
850 m_conn->RemoveServer(server->GetIP(),server->GetPort());
854 void CServerListRem::UpdateUserFileStatus(CServer *server)
856 if (server) {
857 m_TotalUser = server->GetUsers();
858 m_TotalFile = server->GetFiles();
863 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
865 // It's ok to return 0 for context where this code is used in remote gui
866 return 0;
869 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
871 // It's ok to return 0 for context where this code is used in remote gui
872 return 0;
875 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
877 CServer * server = new CServer(tag);
878 ProcessItemUpdate(tag, server);
879 return server;
883 void CServerListRem::DeleteItem(CServer *in_srv)
885 CScopedPtr<CServer> srv(in_srv);
886 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
890 uint32 CServerListRem::GetItemID(CServer *server)
892 return server->ECID();
896 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag * tag, CServer * server)
898 if (!tag->HasChildTags()) {
899 return;
901 tag->ServerName(& server->listname);
902 tag->ServerDesc(& server->description);
903 tag->ServerVersion(& server->m_strVersion);
904 tag->GetMaxUsers(& server->maxusers);
906 tag->GetFiles(& server->files);
907 tag->GetUsers(& server->users);
909 tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok
910 tag->GetStatic(& server->staticservermember);
912 tag->GetPing(& server->ping);
913 tag->GetFailed(& server->failedcount);
915 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server);
919 CServer::CServer(CEC_Server_Tag *tag) : CECID(tag->GetInt())
921 ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt();
922 port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt();
924 Init();
929 * IP filter
931 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
933 m_conn = conn;
937 void CIPFilterRem::Reload()
939 CECPacket req(EC_OP_IPFILTER_RELOAD);
940 m_conn->SendPacket(&req);
944 void CIPFilterRem::Update(wxString url)
946 CECPacket req(EC_OP_IPFILTER_UPDATE);
947 req.AddTag(CECTag(EC_TAG_STRING, url));
949 m_conn->SendPacket(&req);
954 * Shared files list
956 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
958 m_conn = conn;
962 void CSharedFilesRem::Reload(bool, bool)
964 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
966 m_conn->SendPacket(&req);
970 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
972 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
974 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
976 m_conn->SendPacket(&req);
980 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
982 // We use the printable name, as the filename originated from user input,
983 // and the filesystem name might not be valid on the remote host.
984 const wxString strNewName = newName.GetPrintable();
986 CECPacket request(EC_OP_RENAME_FILE);
987 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
988 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
990 m_conn->SendPacket(&request);
992 return true;
996 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
998 CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT);
999 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
1000 request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment));
1001 request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating));
1003 m_conn->SendPacket(&request);
1007 void CKnownFilesRem::DeleteItem(CKnownFile * file)
1009 uint32 id = file->ECID();
1010 if (theApp->sharedfiles->count(id)) {
1011 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
1012 theApp->sharedfiles->erase(id);
1014 if (theApp->downloadqueue->count(id)) {
1015 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file);
1016 theApp->downloadqueue->erase(id);
1018 delete file;
1022 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
1024 return file->ECID();
1028 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
1030 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1031 if (parttag) {
1032 const uint8 *data = file->m_partStatus.Decode(
1033 (uint8 *)parttag->GetTagData(),
1034 parttag->GetTagDataLen());
1035 for(int i = 0; i < file->GetPartCount(); ++i) {
1036 file->m_AvailPartFrequency[i] = data[i];
1039 wxString fileName;
1040 if (tag->FileName(fileName)) {
1041 file->SetFileName(CPath(fileName));
1043 if (tag->FilePath(fileName)) {
1044 file->m_filePath = CPath(fileName);
1046 tag->UpPrio(&file->m_iUpPriorityEC);
1047 tag->GetAICHHash(file->m_AICHMasterHash);
1048 tag->GetRequests(&file->statistic.requested);
1049 tag->GetAllRequests(&file->statistic.alltimerequested);
1050 tag->GetAccepts(&file->statistic.accepted);
1051 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
1052 tag->GetXferred(&file->statistic.transferred);
1053 tag->GetAllXferred(&file->statistic.alltimetransferred);
1054 tag->UpPrio(&file->m_iUpPriorityEC);
1055 if (file->m_iUpPriorityEC >= 10) {
1056 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1057 file->m_bAutoUpPriority = true;
1058 } else {
1059 file->m_iUpPriority = file->m_iUpPriorityEC;
1060 file->m_bAutoUpPriority = false;
1062 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1063 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1064 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1066 tag->GetOnQueue(&file->m_queuedCount);
1068 tag->GetComment(file->m_strComment);
1069 tag->GetRating(file->m_iRating);
1071 requested += file->statistic.requested;
1072 transferred += file->statistic.transferred;
1073 accepted += file->statistic.transferred;
1075 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1077 if (file->IsPartFile()) {
1078 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file);
1082 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1084 CECPacket req(EC_OP_SHARED_SET_PRIO);
1086 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1087 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1089 req.AddTag(hashtag);
1091 m_conn->SendPacket(&req);
1094 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1096 requested = 0;
1097 transferred = 0;
1098 accepted = 0;
1100 std::set<uint32> core_files;
1101 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
1102 const CECTag * curTag = &*it;
1103 ec_tagname_t tagname = curTag->GetTagName();
1104 if (tagname == EC_TAG_CLIENT) {
1105 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1106 } else if (tagname == EC_TAG_SERVER) {
1107 theApp->serverlist->ProcessUpdate(curTag, NULL, EC_TAG_SERVER);
1108 } else if (tagname == EC_TAG_FRIEND) {
1109 theApp->friendlist->ProcessUpdate(curTag, NULL, EC_TAG_FRIEND);
1110 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1111 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *) curTag;
1112 uint32 id = tag->ID();
1113 core_files.insert(id);
1114 if ( m_items_hash.count(id) ) {
1115 // Item already known: update it
1116 ProcessItemUpdate(tag, m_items_hash[id]);
1117 } else {
1118 CKnownFile * newFile;
1119 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1120 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag);
1121 ProcessItemUpdate(tag, file);
1122 (*theApp->downloadqueue)[id] = file;
1123 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1124 newFile = file;
1125 } else {
1126 newFile = new CKnownFile(tag);
1127 ProcessItemUpdate(tag, newFile);
1128 (*theApp->sharedfiles)[id] = newFile;
1129 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1131 AddItem(newFile);
1135 // remove items no longer present
1136 for(iterator it = begin(); it != end();) {
1137 iterator it2 = it++;
1138 if (!core_files.count(GetItemID(*it2))) {
1139 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1144 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1146 requested = 0;
1147 transferred = 0;
1148 accepted = 0;
1153 * List of uploading and waiting clients.
1155 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1157 CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true)
1162 CClientRef::CClientRef(CEC_UpDownClient_Tag *tag)
1164 m_client = new CUpDownClient(tag);
1165 #ifdef DEBUG_ZOMBIE_CLIENTS
1166 m_client->Link(wxT("TAG"));
1167 #else
1168 m_client->Link();
1169 #endif
1173 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1175 m_linked = 0;
1176 #ifdef DEBUG_ZOMBIE_CLIENTS
1177 m_linkedDebug = false;
1178 #endif
1179 // Clients start up empty, then get asked for their data.
1180 // So all data here is processed in ProcessItemUpdate and thus updatable.
1181 m_bEmuleProtocol = false;
1182 m_AvailPartCount = 0;
1183 m_clientSoft = 0;
1184 m_nDownloadState = 0;
1185 m_Friend = NULL;
1186 m_bFriendSlot = false;
1187 m_nKadPort = 0;
1188 m_kBpsDown = 0;
1189 m_dwUserIP = 0;
1190 m_lastDownloadingPart = 0xffff;
1191 m_nextRequestedPart = 0xffff;
1192 m_obfuscationStatus = 0;
1193 m_nOldRemoteQueueRank = 0;
1194 m_nRemoteQueueRank = 0;
1195 m_reqfile = NULL;
1196 m_score = 0;
1197 m_dwServerIP = 0;
1198 m_nServerPort = 0;
1199 m_nSourceFrom = SF_NONE;
1200 m_nTransferredDown = 0;
1201 m_nTransferredUp = 0;
1202 m_nUpDatarate = 0;
1203 m_uploadingfile = NULL;
1204 m_waitingPosition = 0;
1205 m_nUploadState = 0;
1206 m_nUserIDHybrid = 0;
1207 m_nUserPort = 0;
1208 m_nClientVersion = 0;
1209 m_fNoViewSharedFiles = false;
1210 m_identState = IS_NOTAVAILABLE;
1211 m_bRemoteQueueFull = false;
1213 credits = new CClientCredits(new CreditStruct());
1216 #ifdef DEBUG_ZOMBIE_CLIENTS
1217 void CUpDownClient::Unlink(const wxString& from)
1219 std::multiset<wxString>::iterator it = m_linkedFrom.find(from);
1220 if (it != m_linkedFrom.end()) {
1221 m_linkedFrom.erase(it);
1223 m_linked--;
1224 if (!m_linked) {
1225 if (m_linkedDebug) {
1226 AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this);
1228 delete this;
1232 #else
1234 void CUpDownClient::Unlink()
1236 m_linked--;
1237 if (!m_linked) {
1238 delete this;
1241 #endif
1244 uint64 CUpDownClient::GetDownloadedTotal() const
1246 return credits->GetDownloadedTotal();
1250 uint64 CUpDownClient::GetUploadedTotal() const
1252 return credits->GetUploadedTotal();
1256 double CUpDownClient::GetScoreRatio() const
1258 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1261 /* End Warning */
1264 CUpDownClient::~CUpDownClient()
1266 delete credits;
1270 CClientRef *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1272 CClientRef *client = new CClientRef(tag);
1273 ProcessItemUpdate(tag, client);
1275 return client;
1279 void CUpDownClientListRem::DeleteItem(CClientRef *clientref)
1281 CUpDownClient* client = clientref->GetClient();
1282 if (client->m_reqfile) {
1283 client->m_reqfile->DelSource(client);
1284 client->m_reqfile = NULL;
1286 Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL);
1288 if (client->m_uploadingfile) {
1289 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1290 client->m_uploadingfile = NULL;
1292 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); // in case it vanished directly while uploading
1293 Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL);
1295 if (client->m_Friend) {
1296 client->m_Friend->UnLinkClient(); // this notifies
1297 client->m_Friend = NULL;
1300 #ifdef DEBUG_ZOMBIE_CLIENTS
1301 if (client->m_linked > 1) {
1302 AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % client->ECID() % (client->m_linked - 1) % client->GetLinkedFrom());
1303 client->m_linkedDebug = true;
1305 #endif
1307 delete clientref;
1311 uint32 CUpDownClientListRem::GetItemID(CClientRef *client)
1313 return client->ECID();
1317 void CUpDownClientListRem::ProcessItemUpdate(
1318 CEC_UpDownClient_Tag *tag,
1319 CClientRef *clientref)
1321 if (!tag->HasChildTags()) {
1322 return; // speed exit for clients without any change
1324 CUpDownClient *client = clientref->GetClient();
1326 tag->UserID(&client->m_nUserIDHybrid);
1327 tag->ClientName(&client->m_Username);
1328 // Client Software
1329 bool sw_updated = false;
1330 if (tag->ClientSoftware(client->m_clientSoft)) {
1331 client->m_clientSoftString = GetSoftName(client->m_clientSoft);
1332 sw_updated = true;
1334 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1335 if (client->m_clientSoftString == _("Unknown")) {
1336 client->m_fullClientVerString = client->m_clientSoftString;
1337 } else {
1338 client->m_fullClientVerString = client->m_clientSoftString + wxT(" ") + client->m_clientVerString;
1341 // User hash
1342 tag->UserHash(&client->m_UserHash);
1344 // User IP:Port
1345 tag->UserIP(client->m_dwUserIP);
1346 tag->UserPort(&client->m_nUserPort);
1348 // Server IP:Port
1349 tag->ServerIP(&client->m_dwServerIP);
1350 tag->ServerPort(&client->m_nServerPort);
1351 tag->ServerName(&client->m_ServerName);
1353 tag->KadPort(client->m_nKadPort);
1354 tag->FriendSlot(client->m_bFriendSlot);
1356 tag->GetCurrentIdentState(&client->m_identState);
1357 tag->ObfuscationStatus(client->m_obfuscationStatus);
1358 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1360 tag->WaitingPosition(&client->m_waitingPosition);
1361 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1362 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1363 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1365 tag->ClientDownloadState(client->m_nDownloadState);
1366 if (tag->ClientUploadState(client->m_nUploadState)) {
1367 if (client->m_nUploadState == US_UPLOADING) {
1368 theApp->m_allUploadingKnownFile->AddUploadingClient(client);
1369 } else {
1370 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);
1374 tag->SpeedUp(&client->m_nUpDatarate);
1375 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1376 tag->SpeedDown(&client->m_kBpsDown);
1377 } else {
1378 client->m_kBpsDown = 0;
1381 //tag->WaitTime(&client->m_WaitTime);
1382 //tag->XferTime(&client->m_UpStartTimeDelay);
1383 //tag->LastReqTime(&client->m_dwLastUpRequest);
1384 //tag->QueueTime(&client->m_WaitStartTime);
1386 CreditStruct *credit_struct =
1387 (CreditStruct *)client->credits->GetDataStruct();
1388 tag->XferUp(&credit_struct->uploaded);
1389 tag->XferUpSession(&client->m_nTransferredUp);
1391 tag->XferDown(&credit_struct->downloaded);
1392 tag->XferDownSession(&client->m_nTransferredDown);
1394 tag->Score(&client->m_score);
1396 tag->NextRequestedPart(client->m_nextRequestedPart);
1397 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1399 uint8 sourceFrom = 0;
1400 if (tag->GetSourceFrom(sourceFrom)) {
1401 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1404 tag->RemoteFilename(client->m_clientFilename);
1405 tag->DisableViewShared(client->m_fNoViewSharedFiles);
1406 tag->Version(client->m_nClientVersion);
1407 tag->ModVersion(client->m_strModVersion);
1408 tag->OSInfo(client->m_sClientOSInfo);
1409 tag->AvailableParts(client->m_AvailPartCount);
1411 // Download client
1412 uint32 fileID;
1413 bool notified = false;
1414 if (tag->RequestFile(fileID)) {
1415 if (client->m_reqfile) {
1416 Notify_SourceCtrlRemoveSource(client->ECID(), client->m_reqfile);
1417 client->m_reqfile->DelSource(client);
1418 client->m_reqfile = NULL;
1419 client->m_downPartStatus.clear();
1421 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1422 if (kf && kf->IsCPartFile()) {
1423 client->m_reqfile = (CPartFile *) kf;
1424 client->m_reqfile->AddSource(client);
1425 client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1426 Notify_SourceCtrlAddSource(client->m_reqfile, CCLIENTREF(client, wxT("AddSource")), A4AF_SOURCE);
1427 notified = true;
1431 // Part status
1432 CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1433 if (partStatusTag) {
1434 if (partStatusTag->GetTagDataLen() == 0) {
1435 // empty tag means full source
1436 client->m_downPartStatus.SetAllTrue();
1437 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1438 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1440 notified = false;
1443 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1444 SourceItemType type;
1445 switch (client->GetDownloadState()) {
1446 case DS_DOWNLOADING:
1447 case DS_ONQUEUE:
1448 // We will send A4AF, which will be checked.
1449 type = A4AF_SOURCE;
1450 break;
1451 default:
1452 type = UNAVAILABLE_SOURCE;
1453 break;
1456 Notify_SourceCtrlUpdateSource(client->ECID(), type);
1459 // Upload client
1460 notified = false;
1461 if (tag->UploadFile(fileID)) {
1462 if (client->m_uploadingfile) {
1463 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1464 notified = true;
1465 client->m_uploadingfile = NULL;
1467 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1468 if (kf) {
1469 client->m_uploadingfile = kf;
1470 client->m_upPartStatus.setsize(kf->GetPartCount(), 0);
1471 client->m_uploadingfile->AddUploadingClient(client); // this notifies
1472 notified = true;
1476 // Part status
1477 partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_UPLOAD_PART_STATUS);
1478 if (partStatusTag) {
1479 if (partStatusTag->GetTagDataLen() == client->m_upPartStatus.SizeBuffer()) {
1480 client->m_upPartStatus.SetBuffer(partStatusTag->GetTagData());
1482 notified = false;
1485 if (!notified && client->m_uploadingfile
1486 && (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) {
1487 // notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode)
1488 SourceItemType type;
1489 switch (client->GetUploadState()) {
1490 case US_UPLOADING:
1491 case US_ONUPLOADQUEUE:
1492 type = AVAILABLE_SOURCE;
1493 break;
1494 default:
1495 type = UNAVAILABLE_SOURCE;
1496 break;
1498 Notify_SharedCtrlRefreshClient(client->ECID(), type);
1504 * Download queue container: hold PartFiles with progress status
1509 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1511 CECPacket req(EC_OP_ADD_LINK);
1512 CECTag link_tag(EC_TAG_STRING, link);
1513 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1514 req.AddTag(link_tag);
1516 m_conn->SendPacket(&req);
1517 return true;
1521 void CDownQueueRem::ResetCatParts(int cat)
1523 // Called when category is deleted. Command will be performed on the remote side,
1524 // but files still should be updated here right away, or drawing errors (colour not available)
1525 // will happen.
1526 for (iterator it = begin(); it != end(); it++) {
1527 CPartFile* file = it->second;
1528 file->RemoveCategory(cat);
1534 void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file)
1537 // update status
1539 tag->Speed(&file->m_kbpsDown);
1540 file->kBpsDown = file->m_kbpsDown / 1024.0;
1542 tag->SizeXfer(&file->transferred);
1543 tag->SizeDone(&file->completedsize);
1544 tag->SourceXferCount(&file->transferingsrc);
1545 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1546 tag->SourceCount(&file->m_source_count);
1547 tag->SourceCountA4AF(&file->m_a4af_source_count);
1548 tag->FileStatus(&file->status);
1549 tag->Stopped(&file->m_stopped);
1551 tag->LastSeenComplete(&file->lastseencomplete);
1552 tag->LastDateChanged(&file->m_lastDateChanged);
1553 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1554 tag->AvailablePartCount(&file->m_availablePartsCount);
1555 tag->Shared(&file->m_isShared);
1556 tag->A4AFAuto(file->m_is_A4AF_auto);
1558 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1559 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1560 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1562 tag->FileCat(&file->m_category);
1564 tag->DownPrio(&file->m_iDownPriorityEC);
1565 if ( file->m_iDownPriorityEC >= 10 ) {
1566 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1567 file->m_bAutoDownPriority = true;
1568 } else {
1569 file->m_iDownPriority = file->m_iDownPriorityEC;
1570 file->m_bAutoDownPriority = false;
1573 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1576 // Copy part/gap status
1578 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1579 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1580 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1581 if (gaptag || parttag || reqtag) {
1582 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1584 if (gaptag) {
1585 ArrayOfUInts64 gaps;
1586 encoder.DecodeGaps(gaptag, gaps);
1587 int gap_size = gaps.size() / 2;
1588 // clear gaplist
1589 file->m_gaplist.Init(file->GetFileSize(), false);
1591 // and refill it
1592 for (int j = 0; j < gap_size; j++) {
1593 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1596 if (parttag) {
1597 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1598 // sanity check
1599 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1601 if (reqtag) {
1602 ArrayOfUInts64 reqs;
1603 encoder.DecodeReqs(reqtag, reqs);
1604 int req_size = reqs.size() / 2;
1605 // clear reqlist
1606 DeleteContents(file->m_requestedblocks_list);
1608 // and refill it
1609 for (int j = 0; j < req_size; j++) {
1610 Requested_Block_Struct* block = new Requested_Block_Struct;
1611 block->StartOffset = reqs[2*j];
1612 block->EndOffset = reqs[2*j+1];
1613 file->m_requestedblocks_list.push_back(block);
1618 // Get source names and counts
1619 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1620 if (srcnametag) {
1621 SourcenameItemMap &map = file->GetSourcenameItemMap();
1622 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); it++) {
1623 uint32 key = it->GetInt();
1624 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1625 if (count == 0) {
1626 map.erase(key);
1627 } else {
1628 SourcenameItem &item = map[key];
1629 item.count = count;
1630 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1631 if (nametag) {
1632 item.name = nametag->GetStringData();
1638 // Get comments
1639 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1640 if (commenttag) {
1641 file->ClearFileRatingList();
1642 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1643 wxString u = (it++)->GetStringData();
1644 wxString f = (it++)->GetStringData();
1645 int r = (it++)->GetInt();
1646 wxString c = (it++)->GetStringData();
1647 file->AddFileRatingList(u, f, r, c);
1649 file->UpdateFileRatingCommentAvail();
1652 // Update A4AF sources
1653 ListOfUInts32 & clientIDs = file->GetA4AFClientIDs();
1654 CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES);
1655 if (a4aftag) {
1656 file->ClearA4AFList();
1657 clientIDs.clear();
1658 for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); it++) {
1659 if (it->GetTagName() != EC_TAG_ECID) { // should always be this
1660 continue;
1662 uint32 id = it->GetInt();
1663 CClientRef * src = theApp->clientlist->GetByID(id);
1664 if (src) {
1665 file->AddA4AFSource(src->GetClient());
1666 } else {
1667 // client wasn't transmitted yet, try it later
1668 clientIDs.push_back(id);
1671 } else if (!clientIDs.empty()) {
1672 // Process clients from the last pass whose ids were still unknown then
1673 for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) {
1674 ListOfUInts32::iterator it1 = it++;
1675 uint32 id = *it1;
1676 CClientRef * src = theApp->clientlist->GetByID(id);
1677 if (src) {
1678 file->AddA4AFSource(src->GetClient());
1679 clientIDs.erase(it1);
1684 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1686 // If file is shared check if it is already listed in shared files.
1687 // If not, add it and show it.
1688 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1689 (*theApp->sharedfiles)[file->ECID()] = file;
1690 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1695 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1697 CECPacket req(cmd);
1698 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1700 m_conn->SendPacket(&req);
1704 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1706 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1708 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1709 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1710 req.AddTag(hashtag);
1712 m_conn->SendPacket(&req);
1716 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1718 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1720 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1722 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1723 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1724 req.AddTag(hashtag);
1726 m_conn->SendPacket(&req);
1730 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1732 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1733 file->SetCategory(cat);
1735 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1736 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1737 req.AddTag(hashtag);
1739 m_conn->SendPacket(&req);
1743 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1745 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1746 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1747 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1748 req.AddTag(hashtag);
1750 m_conn->SendPacket(&req);
1754 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
1756 CECPacket req(EC_OP_CLEAR_COMPLETED);
1757 for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); it++) {
1758 req.AddTag(CECTag(EC_TAG_ECID, *it));
1761 m_conn->SendPacket(&req);
1766 * List of friends.
1768 CFriendListRem::CFriendListRem(CRemoteConnect *conn)
1770 CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true)
1775 void CFriendListRem::HandlePacket(const CECPacket *)
1777 wxFAIL; // not needed
1781 CFriend * CFriendListRem::CreateItem(CEC_Friend_Tag * tag)
1783 CFriend * Friend = new CFriend(tag->ID());
1784 ProcessItemUpdate(tag, Friend);
1785 return Friend;
1789 void CFriendListRem::DeleteItem(CFriend * Friend)
1791 Friend->UnLinkClient(false);
1792 Notify_ChatRemoveFriend(Friend);
1796 uint32 CFriendListRem::GetItemID(CFriend * Friend)
1798 return Friend->ECID();
1802 void CFriendListRem::ProcessItemUpdate(CEC_Friend_Tag * tag, CFriend * Friend)
1804 if (!tag->HasChildTags()) {
1805 return;
1807 tag->Name(Friend->m_strName);
1808 tag->UserHash(Friend->m_UserHash);
1809 tag->IP(Friend->m_dwLastUsedIP);
1810 tag->Port(Friend->m_nLastUsedPort);
1811 uint32 clientID;
1812 bool notified = false;
1813 if (tag->Client(clientID)) {
1814 if (clientID) {
1815 CClientRef * client = theApp->clientlist->GetByID(clientID);
1816 if (client) {
1817 Friend->LinkClient(*client); // this notifies
1818 notified = true;
1820 } else {
1821 // Unlink
1822 Friend->UnLinkClient(false);
1825 if (!notified) {
1826 Notify_ChatUpdateFriend(Friend);
1831 void CFriendListRem::AddFriend(const CClientRef& toadd)
1833 CECPacket req(EC_OP_FRIEND);
1835 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1836 addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID()));
1837 req.AddTag(addtag);
1839 m_conn->SendPacket(&req);
1843 void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name)
1845 CECPacket req(EC_OP_FRIEND);
1847 CECEmptyTag addtag(EC_TAG_FRIEND_ADD);
1848 addtag.AddTag(CECTag(EC_TAG_FRIEND_HASH, userhash));
1849 addtag.AddTag(CECTag(EC_TAG_FRIEND_IP, lastUsedIP));
1850 addtag.AddTag(CECTag(EC_TAG_FRIEND_PORT, lastUsedPort));
1851 addtag.AddTag(CECTag(EC_TAG_FRIEND_NAME, name));
1852 req.AddTag(addtag);
1854 m_conn->SendPacket(&req);
1858 void CFriendListRem::RemoveFriend(CFriend* toremove)
1860 CECPacket req(EC_OP_FRIEND);
1862 CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE);
1863 removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID()));
1864 req.AddTag(removetag);
1866 m_conn->SendPacket(&req);
1870 void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state)
1872 CECPacket req(EC_OP_FRIEND);
1874 CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state);
1875 slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1876 req.AddTag(slottag);
1878 m_conn->SendPacket(&req);
1882 void CFriendListRem::RequestSharedFileList(CFriend* Friend)
1884 CECPacket req(EC_OP_FRIEND);
1886 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1887 sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID()));
1888 req.AddTag(sharedtag);
1890 m_conn->SendPacket(&req);
1894 void CFriendListRem::RequestSharedFileList(CClientRef& client)
1896 CECPacket req(EC_OP_FRIEND);
1898 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED);
1899 sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID()));
1900 req.AddTag(sharedtag);
1902 m_conn->SendPacket(&req);
1908 * Search results
1910 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1912 m_curr_search = -1;
1916 wxString CSearchListRem::StartNewSearch(
1917 uint32* nSearchID, SearchType search_type,
1918 const CSearchList::CSearchParams& params)
1920 CECPacket search_req(EC_OP_SEARCH_START);
1921 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1922 switch(search_type) {
1923 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1924 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1925 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1927 search_req.AddTag(
1928 CEC_Search_Tag(params.searchString, ec_search_type,
1929 params.typeText, params.extension, params.availability,
1930 params.minSize, params.maxSize));
1932 m_conn->SendPacket(&search_req);
1933 m_curr_search = *(nSearchID); // No kad remote search yet.
1935 Flush();
1937 return wxEmptyString; // EC reply will have the error mesg is needed.
1941 void CSearchListRem::StopSearch(bool)
1943 if (m_curr_search != -1) {
1944 CECPacket search_req(EC_OP_SEARCH_STOP);
1945 m_conn->SendPacket(&search_req);
1950 void CSearchListRem::HandlePacket(const CECPacket *packet)
1952 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1953 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1954 } else {
1955 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1960 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1962 CECID(tag->ID()),
1963 m_parent(NULL),
1964 m_showChildren(false),
1965 m_sourceCount(0),
1966 m_completeSourceCount(0),
1967 m_kademlia(false),
1968 m_downloadStatus(NEW),
1969 m_clientID(0),
1970 m_clientPort(0),
1971 m_kadPublishInfo(0)
1973 SetFileName(CPath(tag->FileName()));
1974 m_abyFileHash = tag->FileHash();
1975 SetFileSize(tag->SizeFull());
1977 m_searchID = theApp->searchlist->m_curr_search;
1978 uint32 parentID = tag->ParentID();
1979 if (parentID) {
1980 CSearchFile * parent = theApp->searchlist->GetByID(parentID);
1981 if (parent) {
1982 parent->AddChild(this);
1988 void CSearchFile::AddChild(CSearchFile* file)
1990 m_children.push_back(file);
1991 file->m_parent = this;
1995 // dtor is virtual - must be implemented
1996 CSearchFile::~CSearchFile()
2001 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
2003 CSearchFile *file = new CSearchFile(tag);
2004 ProcessItemUpdate(tag, file);
2006 theApp->amuledlg->m_searchwnd->AddResult(file);
2008 return file;
2012 void CSearchListRem::DeleteItem(CSearchFile *file)
2014 delete file;
2018 uint32 CSearchListRem::GetItemID(CSearchFile *file)
2020 return file->ECID();
2024 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
2026 uint32 sourceCount = file->m_sourceCount;
2027 uint32 completeSourceCount = file->m_completeSourceCount;
2028 CSearchFile::DownloadStatus status = file->m_downloadStatus;
2029 tag->SourceCount(&file->m_sourceCount);
2030 tag->CompleteSourceCount(&file->m_completeSourceCount);
2031 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
2033 if (file->m_sourceCount != sourceCount
2034 || file->m_completeSourceCount != completeSourceCount
2035 || file->m_downloadStatus != status) {
2036 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
2037 theApp->amuledlg->m_searchwnd->UpdateResult(file);
2043 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
2045 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
2046 m_conn->SendRequest(this, &progress_req);
2048 return true;
2052 void CSearchListRem::RemoveResults(long nSearchID)
2054 ResultMap::iterator it = m_results.find(nSearchID);
2055 if (it != m_results.end()) {
2056 CSearchResultList& list = it->second;
2057 for (unsigned int i = 0; i < list.size(); ++i) {
2058 delete list[i];
2060 m_results.erase(it);
2065 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
2067 ResultMap::const_iterator it = m_results.find(nSearchID);
2068 if (it != m_results.end()) {
2069 return it->second;
2072 // TODO: Should we assert in this case?
2073 static CSearchResultList list;
2074 return list;
2078 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
2080 theStats::UpdateStats(packet);
2081 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
2085 void CUpDownClient::RequestSharedFileList()
2087 CClientRef ref = CCLIENTREF(this, wxEmptyString);
2088 theApp->friendlist->RequestSharedFileList(ref);
2092 bool CUpDownClient::SwapToAnotherFile(
2093 bool WXUNUSED(bIgnoreNoNeeded),
2094 bool WXUNUSED(ignoreSuspensions),
2095 bool WXUNUSED(bRemoveCompletely),
2096 CPartFile* toFile)
2098 CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE);
2099 req.AddTag(CECTag(EC_TAG_CLIENT, ECID()));
2100 req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash()));
2101 theApp->m_connect->SendPacket(&req);
2103 return true;
2107 wxString CAICHHash::GetString() const
2109 return EncodeBase32(m_abyBuffer, HASHSIZE);
2114 // Those functions are virtual. So even they don't get called they must
2115 // be defined so linker will be happy
2117 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2119 wxFAIL;
2120 return 0;
2124 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
2126 wxFAIL;
2127 return false;
2131 void CKnownFile::UpdatePartsInfo()
2133 wxFAIL;
2137 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
2139 wxFAIL;
2140 return 0;
2144 void CPartFile::UpdatePartsInfo()
2146 wxFAIL;
2151 void CPartFile::UpdateFileRatingCommentAvail()
2153 bool prevComment = m_hasComment;
2154 int prevRating = m_iUserRating;
2156 m_hasComment = false;
2157 m_iUserRating = 0;
2158 int ratingCount = 0;
2160 FileRatingList::iterator it = m_FileRatingList.begin();
2161 for (; it != m_FileRatingList.end(); ++it) {
2162 SFileRating& cur_rat = *it;
2164 if (!cur_rat.Comment.IsEmpty()) {
2165 m_hasComment = true;
2168 uint8 rating = cur_rat.Rating;
2169 if (rating) {
2170 wxASSERT(rating <= 5);
2172 ratingCount++;
2173 m_iUserRating += rating;
2177 if (ratingCount) {
2178 m_iUserRating /= ratingCount;
2179 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
2182 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
2183 UpdateDisplayedInfo();
2188 void CStatTreeRem::DoRequery()
2190 CECPacket request(EC_OP_GET_STATSTREE);
2191 if (thePrefs::GetMaxClientVersions() != 0) {
2192 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
2194 m_conn->SendRequest(this, &request);
2197 void CStatTreeRem::HandlePacket(const CECPacket * p)
2199 const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE);
2200 if (treeRoot) {
2201 theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot);
2202 theApp->amuledlg->m_statisticswnd->ShowStatistics();
2206 CamuleRemoteGuiApp *theApp;
2209 // since gui is not linked with amule.cpp - define events here
2211 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2212 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2213 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2214 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2215 // File_checked_for_headers