Add ability to stop Kad search from aMuleGUI
[amule.git] / src / amule-remote-gui.cpp
blob4a9f67d74cc4ed8b8b4cdd52c6ad75aff867287b
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 "DataToText.h" // Needed for GetSoftName()
45 #include "DownloadListCtrl.h" // Needed for CDownloadListCtrl
46 #include "GuiEvents.h"
47 #ifdef ENABLE_IP2COUNTRY
48 #include "IP2Country.h" // Needed for IP2Country
49 #endif
50 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
51 #include "Logger.h"
52 #include "muuli_wdr.h" // Needed for IDs
53 #include "PartFile.h" // Needed for CPartFile
54 #include "SearchDlg.h" // Needed for CSearchDlg
55 #include "Server.h" // Needed for GetListName
56 #include "ServerWnd.h" // Needed for CServerWnd
57 #include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl
58 #include "SharedFilesWnd.h" // Needed for CSharedFilesWnd
59 #include "TransferWnd.h" // Needed for CTransferWnd
60 #include "updownclient.h"
61 #include "ServerListCtrl.h" // Needed for CServerListCtrl
62 #include "ScopedPtr.h"
63 #include "StatisticsDlg.h" // Needed for CStatisticsDlg
66 CEConnectDlg::CEConnectDlg()
68 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
70 CoreConnect(this, true);
72 wxString pref_host, pref_port;
73 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
74 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
75 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
77 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
78 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
79 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
81 CentreOnParent();
85 wxString CEConnectDlg::PassHash()
87 return pwd_hash;
91 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
92 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
93 END_EVENT_TABLE()
96 void CEConnectDlg::OnOK(wxCommandEvent& evt)
98 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
99 port = StrToLong(s_port);
101 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
102 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
104 if (passwd != pwd_hash) {
105 pwd_hash = MD5Sum(passwd).GetHash();
107 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
108 evt.Skip();
112 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
115 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
116 // Core timer
117 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
119 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
120 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
122 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
124 #ifdef ENABLE_IP2COUNTRY
125 // HTTPDownload finished
126 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
127 #endif
128 END_EVENT_TABLE()
131 IMPLEMENT_APP(CamuleRemoteGuiApp)
134 int CamuleRemoteGuiApp::OnExit()
136 StopTickTimer();
138 return wxApp::OnExit();
142 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
144 static int request_step = 0;
145 static uint32 msPrevStats = 0;
147 if (m_connect->RequestFifoFull()) {
148 return;
151 switch (request_step) {
152 case 0:
153 serverconnect->ReQuery();
154 serverlist->UpdateUserFileStatus(serverconnect->GetCurrentServer());
155 request_step++;
156 break;
157 case 1: {
158 CECPacket stats_req(EC_OP_STAT_REQ);
159 m_connect->SendRequest(&m_stats_updater, &stats_req);
160 amuledlg->ShowTransferRate();
161 request_step++;
162 break;
164 case 2:
165 if (amuledlg->m_sharedfileswnd->IsShown()) {
166 // update both downloads and shared files
167 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
168 } else if (amuledlg->m_serverwnd->IsShown()) {
169 //serverlist->FullReload(EC_OP_GET_SERVER_LIST);
170 } else if (amuledlg->m_transferwnd->IsShown()) {
171 // update both downloads and shared files
172 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
173 amuledlg->m_transferwnd->ShowQueueCount(theStats::GetWaitingUserCount());
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 #ifdef ENABLE_IP2COUNTRY
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();
211 #endif
215 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
217 // Stop the Core Timer
218 delete poll_timer;
219 poll_timer = NULL;
221 // Destroy the EC socket
222 m_connect->Destroy();
223 m_connect = NULL;
226 if (amuledlg) {
227 amuledlg->DlgShutDown();
228 amuledlg->Destroy();
229 amuledlg = NULL;
231 delete m_allUploadingKnownFile;
232 delete stattree;
236 bool CamuleRemoteGuiApp::OnInit()
238 StartTickTimer();
239 amuledlg = NULL;
241 // Get theApp
242 theApp = &wxGetApp();
244 // Handle uncaught exceptions
245 InstallMuleExceptionHandler();
247 // Parse cmdline arguments.
248 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
249 return false;
252 // Create the polling timer
253 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
254 if (!poll_timer) {
255 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
256 OnExit();
259 m_connect = new CRemoteConnect(this);
261 glob_prefs = new CPreferencesRem(m_connect);
262 long enableZLIB;
263 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
264 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification
266 InitCustomLanguages();
267 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
269 if (ShowConnectionDialog()) {
270 AddLogLineNS(_("Going to event loop..."));
271 return true;
274 return false;
278 bool CamuleRemoteGuiApp::CryptoAvailable() const
280 return thePrefs::IsSecureIdentEnabled(); // good enough
284 bool CamuleRemoteGuiApp::ShowConnectionDialog()
286 dialog = new CEConnectDlg;
288 if (m_skipConnectionDialog) {
289 wxCommandEvent evt;
290 dialog->OnOK(evt);
291 } else if (dialog->ShowModal() != wxID_OK) {
292 dialog->Destroy();
294 return false;
296 AddLogLineNS(_("Connecting..."));
297 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
298 dialog->Login(), dialog->PassHash(),
299 wxT("amule-remote"), wxT("0x0001"))) {
300 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
302 return false;
305 return true;
309 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
310 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
311 AddLogLineNS(_("Remote GUI EC event handler"));
312 wxString reply = evt.GetServerReply();
313 AddLogLineC(reply);
314 if (evt.GetResult() == true) {
315 // Connected - go to next init step
316 glob_prefs->LoadRemote();
317 } else {
318 AddLogLineNS(_("Going down"));
319 if (dialog) { // connect failed
320 wxMessageBox(
321 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
322 _("ERROR"), wxOK);
323 } else { // server disconnected (probably terminated) later
324 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
326 ExitMainLoop();
331 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
333 Startup();
337 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
339 evt.Notify();
343 void CamuleRemoteGuiApp::Startup() {
345 if (dialog->SaveUserPass()) {
346 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
347 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
348 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
350 dialog->Destroy();
351 dialog = NULL;
353 m_ConnState = 0;
354 m_clientID = 0;
356 serverconnect = new CServerConnectRem(m_connect);
357 m_statistics = new CStatistics(*m_connect);
358 stattree = new CStatTreeRem(m_connect);
360 clientlist = new CUpDownClientListRem(m_connect);
361 searchlist = new CSearchListRem(m_connect);
362 serverlist = new CServerListRem(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 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
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 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
451 return true;
455 bool CamuleRemoteGuiApp::IsFirewalled() const
457 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
458 return false;
461 return IsFirewalledKad();
465 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
466 return serverconnect && serverconnect->IsConnected();
470 void CamuleRemoteGuiApp::StartKad() {
471 m_connect->StartKad();
475 void CamuleRemoteGuiApp::StopKad() {
476 m_connect->StopKad();
480 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
482 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
483 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
484 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
486 m_connect->SendPacket(&req);
490 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
492 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
493 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
495 m_connect->SendPacket(&req);
499 void CamuleRemoteGuiApp::DisconnectED2K() {
500 if (IsConnectedED2K()) {
501 m_connect->DisconnectED2K();
506 uint32 CamuleRemoteGuiApp::GetED2KID() const
508 return serverconnect ? serverconnect->GetClientID() : 0;
512 uint32 CamuleRemoteGuiApp::GetID() const
514 return m_clientID;
518 void CamuleRemoteGuiApp::ShowUserCount() {
519 wxString buffer;
521 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
522 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
524 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
525 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
526 } else if (thePrefs::GetNetworkED2K()) {
527 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
528 } else if (thePrefs::GetNetworkKademlia()) {
529 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
530 } else {
531 buffer = _("No networks selected");
534 Notify_ShowUserCount(buffer);
539 * Preferences: holds both local and remote settings.
541 * First, everything is loaded from local config file. Later, settings
542 * that are relevant on remote side only are loaded thru EC
544 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
546 m_conn = conn;
549 // Settings queried from remote side
551 m_exchange_send_selected_prefs =
552 EC_PREFS_GENERAL |
553 EC_PREFS_CONNECTIONS |
554 EC_PREFS_MESSAGEFILTER |
555 EC_PREFS_ONLINESIG |
556 EC_PREFS_SERVERS |
557 EC_PREFS_FILES |
558 EC_PREFS_SRCDROP |
559 EC_PREFS_DIRECTORIES |
560 EC_PREFS_SECURITY |
561 EC_PREFS_CORETWEAKS |
562 EC_PREFS_REMOTECONTROLS |
563 EC_PREFS_KADEMLIA;
564 m_exchange_recv_selected_prefs =
565 m_exchange_send_selected_prefs |
566 EC_PREFS_CATEGORIES;
570 void CPreferencesRem::HandlePacket(const CECPacket *packet)
572 ((CEC_Prefs_Packet *)packet)->Apply();
574 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
575 if (cat_tags) {
576 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); it++) {
577 const CECTag &cat_tag = *it;
578 Category_Struct *cat = new Category_Struct;
579 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
580 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
581 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
582 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
583 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
584 theApp->glob_prefs->AddCat(cat);
586 } else {
587 Category_Struct *cat = new Category_Struct;
588 cat->title = _("All");
589 cat->color = 0;
590 cat->prio = PR_NORMAL;
591 theApp->glob_prefs->AddCat(cat);
593 wxECInitDoneEvent event;
594 theApp->AddPendingEvent(event);
599 bool CPreferencesRem::LoadRemote()
602 // override local settings with remote
603 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
605 // bring categories too
606 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
608 m_conn->SendRequest(this, &req);
610 return true;
614 void CPreferencesRem::SendToRemote()
616 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
617 m_conn->SendPacket(&pref_packet);
621 class CCatHandler : public CECPacketHandlerBase {
622 virtual void HandlePacket(const CECPacket *packet);
626 void CCatHandler::HandlePacket(const CECPacket *packet)
628 if (packet->GetOpCode() == EC_OP_FAILED) {
629 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
630 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
631 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
632 int cat = catTag->GetInt();
633 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
634 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
635 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
636 _("ERROR"), wxOK);
637 cs->path = CPath(pathTag->GetStringData());
638 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
639 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
642 delete this;
646 bool CPreferencesRem::CreateCategory(
647 Category_Struct *& category,
648 const wxString& name,
649 const CPath& path,
650 const wxString& comment,
651 uint32 color,
652 uint8 prio)
654 CECPacket req(EC_OP_CREATE_CATEGORY);
655 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
656 req.AddTag(tag);
657 m_conn->SendRequest(new CCatHandler, &req);
659 category = new Category_Struct();
660 category->path = path;
661 category->title = name;
662 category->comment = comment;
663 category->color = color;
664 category->prio = prio;
666 AddCat(category);
668 return true;
672 bool CPreferencesRem::UpdateCategory(
673 uint8 cat,
674 const wxString& name,
675 const CPath& path,
676 const wxString& comment,
677 uint32 color,
678 uint8 prio)
680 CECPacket req(EC_OP_UPDATE_CATEGORY);
681 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
682 req.AddTag(tag);
683 m_conn->SendRequest(new CCatHandler, &req);
685 Category_Struct *category = m_CatList[cat];
686 category->path = path;
687 category->title = name;
688 category->comment = comment;
689 category->color = color;
690 category->prio = prio;
692 return true;
696 void CPreferencesRem::RemoveCat(uint8 cat)
698 CECPacket req(EC_OP_DELETE_CATEGORY);
699 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
700 req.AddTag(tag);
701 m_conn->SendPacket(&req);
702 CPreferences::RemoveCat(cat);
707 // Container implementation
709 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
711 m_CurrServer = 0;
712 m_Conn = conn;
716 void CServerConnectRem::ConnectToAnyServer()
718 CECPacket req(EC_OP_SERVER_CONNECT);
719 m_Conn->SendPacket(&req);
723 void CServerConnectRem::StopConnectionTry()
725 // lfroen: isn't Disconnect the same ?
729 void CServerConnectRem::Disconnect()
731 CECPacket req(EC_OP_SERVER_DISCONNECT);
732 m_Conn->SendPacket(&req);
736 void CServerConnectRem::ConnectToServer(CServer *server)
738 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
742 bool CServerConnectRem::ReQuery()
744 CECPacket stat_req(EC_OP_GET_CONNSTATE);
745 m_Conn->SendRequest(this, &stat_req);
747 return true;
751 void CServerConnectRem::HandlePacket(const CECPacket *packet)
753 CEC_ConnState_Tag *tag =
754 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
755 if (!tag) {
756 return;
759 theApp->m_ConnState = 0;
760 CServer *server;
761 m_ID = tag->GetEd2kId();
762 theApp->m_clientID = tag->GetClientId();
764 if (tag->IsConnectedED2K()) {
765 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
766 if (!srvtag) {
767 return;
769 server = theApp->serverlist->GetByID(srvtag->GetIPv4Data().IP());
770 if (m_CurrServer && (server != m_CurrServer)) {
771 theApp->amuledlg->m_serverwnd->serverlistctrl->
772 HighlightServer(m_CurrServer, false);
774 theApp->amuledlg->m_serverwnd->serverlistctrl->
775 HighlightServer(server, true);
776 m_CurrServer = server;
777 theApp->m_ConnState |= CONNECTED_ED2K;
778 } else {
779 if ( m_CurrServer ) {
780 theApp->amuledlg->m_serverwnd->serverlistctrl->
781 HighlightServer(m_CurrServer, false);
782 m_CurrServer = 0;
786 if (tag->IsConnectedKademlia()) {
787 if (tag->IsKadFirewalled()) {
788 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
789 } else {
790 theApp->m_ConnState |= CONNECTED_KAD_OK;
792 } else {
793 if (tag->IsKadRunning()) {
794 theApp->m_ConnState |= CONNECTED_KAD_NOT;
798 theApp->amuledlg->ShowConnectionState();
803 * Server list: host list of ed2k servers.
805 CServerListRem::CServerListRem(CRemoteConnect *conn)
807 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, false)
812 void CServerListRem::HandlePacket(const CECPacket *packet)
814 CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
815 ReloadControl();
819 void CServerListRem::UpdateServerMetFromURL(wxString url)
821 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
822 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
824 m_conn->SendPacket(&req);
828 void CServerListRem::RemoveServer(CServer* server)
830 m_conn->RemoveServer(server->GetIP(),server->GetPort());
834 void CServerListRem::UpdateUserFileStatus(CServer *server)
836 if (server) {
837 m_TotalUser = server->GetUsers();
838 m_TotalFile = server->GetFiles();
843 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
845 // It's ok to return 0 for context where this code is used in remote gui
846 return 0;
849 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
851 // It's ok to return 0 for context where this code is used in remote gui
852 return 0;
855 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
857 return new CServer(tag);
861 void CServerListRem::DeleteItem(CServer *in_srv)
863 CScopedPtr<CServer> srv(in_srv);
864 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
868 uint32 CServerListRem::GetItemID(CServer *server)
870 return server->GetIP();
874 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag *, CServer *)
876 // server list is always realoaded from scratch
877 wxFAIL;
881 void CServerListRem::ReloadControl()
883 for(iterator it = begin(); it != end(); it++) {
884 CServer *srv = *it;
885 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(srv);
890 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
892 m_conn = conn;
896 void CIPFilterRem::Reload()
898 CECPacket req(EC_OP_IPFILTER_RELOAD);
899 m_conn->SendPacket(&req);
903 void CIPFilterRem::Update(wxString url)
905 CECPacket req(EC_OP_IPFILTER_UPDATE);
906 req.AddTag(CECTag(EC_TAG_STRING, url));
908 m_conn->SendPacket(&req);
913 * Shared files list
915 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
917 m_conn = conn;
921 void CSharedFilesRem::Reload(bool, bool)
923 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
925 m_conn->SendPacket(&req);
929 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
931 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
933 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
935 m_conn->SendPacket(&req);
939 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
941 // We use the printable name, as the filename originated from user input,
942 // and the filesystem name might not be valid on the remote host.
943 const wxString strNewName = newName.GetPrintable();
945 CECPacket request(EC_OP_RENAME_FILE);
946 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
947 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
949 m_conn->SendPacket(&request);
951 return true;
955 void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating)
957 CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT);
958 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
959 request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment));
960 request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating));
962 m_conn->SendPacket(&request);
966 void CKnownFilesRem::DeleteItem(CKnownFile * file)
968 uint32 id = file->ECID();
969 if (theApp->sharedfiles->count(id)) {
970 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
971 theApp->sharedfiles->erase(id);
973 if (theApp->downloadqueue->count(id)) {
974 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file);
975 theApp->downloadqueue->erase(id);
977 delete file;
981 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
983 return file->ECID();
987 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
989 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
990 if (parttag) {
991 const uint8 *data = file->m_partStatus.Decode(
992 (uint8 *)parttag->GetTagData(),
993 parttag->GetTagDataLen());
994 for(int i = 0; i < file->GetPartCount(); ++i) {
995 file->m_AvailPartFrequency[i] = data[i];
998 wxString fileName;
999 if (tag->FileName(fileName)) {
1000 file->SetFileName(CPath(fileName));
1002 if (tag->FilePath(fileName)) {
1003 file->m_filePath = CPath(fileName);
1005 tag->UpPrio(&file->m_iUpPriorityEC);
1006 tag->GetAICHHash(file->m_AICHMasterHash);
1007 tag->GetRequests(&file->statistic.requested);
1008 tag->GetAllRequests(&file->statistic.alltimerequested);
1009 tag->GetAccepts(&file->statistic.accepted);
1010 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
1011 tag->GetXferred(&file->statistic.transferred);
1012 tag->GetAllXferred(&file->statistic.alltimetransferred);
1013 tag->UpPrio(&file->m_iUpPriorityEC);
1014 if (file->m_iUpPriorityEC >= 10) {
1015 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1016 file->m_bAutoUpPriority = true;
1017 } else {
1018 file->m_iUpPriority = file->m_iUpPriorityEC;
1019 file->m_bAutoUpPriority = false;
1021 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1022 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1023 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1025 tag->GetOnQueue(&file->m_queuedCount);
1027 tag->GetComment(file->m_strComment);
1028 tag->GetRating(file->m_iRating);
1030 requested += file->statistic.requested;
1031 transferred += file->statistic.transferred;
1032 accepted += file->statistic.transferred;
1034 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1036 if (file->IsPartFile()) {
1037 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file);
1041 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1043 CECPacket req(EC_OP_SHARED_SET_PRIO);
1045 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1046 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1048 req.AddTag(hashtag);
1050 m_conn->SendPacket(&req);
1053 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1055 requested = 0;
1056 transferred = 0;
1057 accepted = 0;
1059 std::set<uint32> core_files;
1060 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
1061 const CECTag * curTag = &*it;
1062 ec_tagname_t tagname = curTag->GetTagName();
1063 if (tagname == EC_TAG_CLIENT) {
1064 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1065 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1066 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *) curTag;
1067 uint32 id = tag->ID();
1068 core_files.insert(id);
1069 if ( m_items_hash.count(id) ) {
1070 // Item already known: update it
1071 ProcessItemUpdate(tag, m_items_hash[id]);
1072 } else {
1073 CKnownFile * newFile;
1074 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1075 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag);
1076 ProcessItemUpdate(tag, file);
1077 (*theApp->downloadqueue)[id] = file;
1078 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1079 newFile = file;
1080 } else {
1081 newFile = new CKnownFile(tag);
1082 ProcessItemUpdate(tag, newFile);
1083 (*theApp->sharedfiles)[id] = newFile;
1084 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1086 AddItem(newFile);
1090 // remove items no longer present
1091 for(iterator it = begin(); it != end();) {
1092 iterator it2 = it++;
1093 if (!core_files.count(GetItemID(*it2))) {
1094 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1099 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1101 requested = 0;
1102 transferred = 0;
1103 accepted = 0;
1108 * List of uploading and waiting clients.
1110 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1112 CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag>(conn, true)
1117 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1119 // Clients start up empty, then get asked for their data.
1120 // So all data here is processed in ProcessItemUpdate and thus updatable.
1121 m_bRemoteQueueFull = false;
1122 m_nUserIDHybrid = 0;
1123 m_clientSoft = 0;
1124 m_bEmuleProtocol = false;
1126 // User IP:Port
1127 m_nConnectIP = 0;
1128 m_dwUserIP = 0;
1129 m_nUserPort = 0;
1130 m_FullUserIP = 0;
1132 // Server IP:Port
1133 m_dwServerIP = 0;
1134 m_nServerPort = 0;
1136 m_identState = IS_NOTAVAILABLE;
1137 m_obfuscationStatus = 0;
1139 m_nSourceFrom = SF_NONE;
1140 m_nKadPort = 0;
1142 m_Friend = 0;
1143 m_nCurSessionUp = 0;
1144 m_reqfile = NULL;
1145 m_uploadingfile = NULL;
1146 m_lastDownloadingPart = 0xffff;
1147 m_nextRequestedPart = 0xffff;
1149 credits = new CClientCredits(new CreditStruct());
1152 /* Warning: do common base */
1155 bool CUpDownClient::IsIdentified() const
1157 return m_identState == IS_IDENTIFIED;
1161 bool CUpDownClient::IsBadGuy() const
1163 return m_identState == IS_IDBADGUY;
1167 bool CUpDownClient::SUIFailed() const
1169 return m_identState == IS_IDFAILED;
1173 bool CUpDownClient::SUINeeded() const
1175 return m_identState == IS_IDNEEDED;
1179 bool CUpDownClient::SUINotSupported() const
1181 return m_identState == IS_NOTAVAILABLE;
1185 uint64 CUpDownClient::GetDownloadedTotal() const
1187 return credits->GetDownloadedTotal();
1191 uint64 CUpDownClient::GetUploadedTotal() const
1193 return credits->GetUploadedTotal();
1197 double CUpDownClient::GetScoreRatio() const
1199 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1202 /* End Warning */
1205 CUpDownClient::~CUpDownClient()
1207 delete credits;
1211 CUpDownClient *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1213 CUpDownClient *client = new CUpDownClient(tag);
1214 ProcessItemUpdate(tag, client);
1215 if (client->m_reqfile) {
1216 Notify_SourceCtrlAddSource(client->m_reqfile, client, A4AF_SOURCE);
1219 return client;
1223 void CUpDownClientListRem::DeleteItem(CUpDownClient *client)
1225 if (client->m_reqfile) {
1226 Notify_SourceCtrlRemoveSource(client, client->m_reqfile);
1227 client->m_reqfile->DelSource(client);
1228 client->m_reqfile = NULL;
1230 delete client;
1234 uint32 CUpDownClientListRem::GetItemID(CUpDownClient *client)
1236 return client->ECID();
1240 void CUpDownClientListRem::ProcessItemUpdate(
1241 CEC_UpDownClient_Tag *tag,
1242 CUpDownClient *client)
1244 if (!tag->HasChildTags()) {
1245 return; // speed exit for clients without any change
1247 tag->UserID(&client->m_nUserIDHybrid);
1248 tag->ClientName(&client->m_Username);
1249 // Client Software
1250 bool sw_updated = false;
1251 if (tag->ClientSoftware(client->m_clientSoft)) {
1252 client->m_clientVersionString = GetSoftName(client->m_clientSoft);
1253 client->m_clientSoftString = client->m_clientVersionString;
1254 sw_updated = true;
1256 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1257 if (client->m_clientVersionString == _("Unknown")) {
1258 client->m_fullClientVerString = client->m_clientVersionString;
1259 } else {
1260 client->m_fullClientVerString = client->m_clientVersionString + wxT(" ") + client->m_clientVerString;
1263 // User hash
1264 tag->UserHash(&client->m_UserHash);
1266 // User IP:Port
1267 if (tag->UserIP(client->m_dwUserIP)) {
1268 client->m_nConnectIP = client->m_dwUserIP;
1269 client->m_FullUserIP = client->m_dwUserIP;
1271 tag->UserPort(&client->m_nUserPort);
1273 // Server IP:Port
1274 tag->ServerIP(&client->m_dwServerIP);
1275 tag->ServerPort(&client->m_nServerPort);
1276 tag->ServerName(&client->m_ServerName);
1278 tag->KadPort(client->m_nKadPort);
1280 tag->GetCurrentIdentState(&client->m_identState);
1281 tag->ObfuscationStatus(client->m_obfuscationStatus);
1282 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1284 tag->WaitingPosition(&client->m_waitingPosition);
1285 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1286 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1287 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1288 tag->AskedCount(&client->m_cAsked);
1290 tag->ClientDownloadState(client->m_nDownloadState);
1291 if (tag->ClientUploadState(client->m_nUploadState)) {
1292 if (client->m_nUploadState == US_UPLOADING) {
1293 theApp->m_allUploadingKnownFile->AddUploadingClient(client);
1294 } else {
1295 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client);
1299 tag->SpeedUp(&client->m_nUpDatarate);
1300 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1301 tag->SpeedDown(&client->kBpsDown);
1302 } else {
1303 client->kBpsDown = 0;
1306 //tag->WaitTime(&client->m_WaitTime);
1307 //tag->XferTime(&client->m_UpStartTimeDelay);
1308 //tag->LastReqTime(&client->m_dwLastUpRequest);
1309 //tag->QueueTime(&client->m_WaitStartTime);
1311 CreditStruct *credit_struct =
1312 (CreditStruct *)client->credits->GetDataStruct();
1313 tag->XferUp(&credit_struct->uploaded);
1314 tag->XferUpSession(&client->m_nTransferredUp);
1316 tag->XferDown(&credit_struct->downloaded);
1317 tag->XferDownSession(&client->m_nTransferredDown);
1319 tag->Score(&client->m_score);
1321 tag->NextRequestedPart(client->m_nextRequestedPart);
1322 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1324 uint8 sourceFrom = 0;
1325 if (tag->GetSourceFrom(sourceFrom)) {
1326 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1329 // Download client
1330 uint32 fileID;
1331 bool notified = false;
1332 if (tag->RequestFile(fileID)) {
1333 if (client->m_reqfile) {
1334 Notify_SourceCtrlRemoveSource(client, client->m_reqfile);
1335 client->m_reqfile->DelSource(client);
1336 client->m_reqfile = NULL;
1337 client->m_downPartStatus.clear();
1339 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1340 if (kf && kf->IsCPartFile()) {
1341 client->m_reqfile = (CPartFile *) kf;
1342 client->m_reqfile->AddSource(client);
1343 client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1344 Notify_SourceCtrlAddSource(client->m_reqfile, client, A4AF_SOURCE);
1345 notified = true;
1349 // Part status
1350 CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1351 if (partStatusTag) {
1352 if (partStatusTag->GetTagDataLen() == 0) {
1353 // empty tag means full source
1354 client->m_downPartStatus.SetAllTrue();
1355 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1356 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1358 notified = false;
1361 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1362 SourceItemType type;
1363 switch (client->GetDownloadState()) {
1364 case DS_DOWNLOADING:
1365 case DS_ONQUEUE:
1366 // We will send A4AF, which will be checked.
1367 type = A4AF_SOURCE;
1368 break;
1369 default:
1370 type = UNAVAILABLE_SOURCE;
1371 break;
1374 Notify_SourceCtrlUpdateSource(client, type);
1377 // Upload client
1378 notified = false;
1379 if (tag->UploadFile(fileID)) {
1380 if (client->m_uploadingfile) {
1381 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1382 notified = true;
1383 client->m_uploadingfile = NULL;
1384 //client->m_downPartStatus.clear();
1386 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1387 if (kf) {
1388 client->m_uploadingfile = kf;
1389 client->m_uploadingfile->AddUploadingClient(client); // this notifies
1390 notified = true;
1391 //client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1395 if (!notified && client->m_uploadingfile
1396 && (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) {
1397 // notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode)
1398 SourceItemType type;
1399 switch (client->GetUploadState()) {
1400 case US_UPLOADING:
1401 case US_ONUPLOADQUEUE:
1402 type = AVAILABLE_SOURCE;
1403 break;
1404 default:
1405 type = UNAVAILABLE_SOURCE;
1406 break;
1408 Notify_SharedCtrlRefreshClient(client, type);
1414 * Download queue container: hold PartFiles with progress status
1419 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1421 CECPacket req(EC_OP_ADD_LINK);
1422 CECTag link_tag(EC_TAG_STRING, link);
1423 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1424 req.AddTag(link_tag);
1426 m_conn->SendPacket(&req);
1427 return true;
1431 void CDownQueueRem::ResetCatParts(int cat)
1433 // Called when category is deleted. Command will be performed on the remote side,
1434 // but files still should be updated here right away, or drawing errors (colour not available)
1435 // will happen.
1436 for (iterator it = begin(); it != end(); it++) {
1437 CPartFile* file = it->second;
1438 file->RemoveCategory(cat);
1444 void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file)
1447 // update status
1449 tag->Speed(&file->m_kbpsDown);
1450 file->kBpsDown = file->m_kbpsDown / 1024.0;
1452 tag->SizeXfer(&file->transferred);
1453 tag->SizeDone(&file->completedsize);
1454 tag->SourceXferCount(&file->transferingsrc);
1455 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1456 tag->SourceCount(&file->m_source_count);
1457 tag->SourceCountA4AF(&file->m_a4af_source_count);
1458 tag->FileStatus(&file->status);
1459 tag->Stopped(&file->m_stopped);
1461 tag->LastSeenComplete(&file->lastseencomplete);
1462 tag->LastDateChanged(&file->m_lastDateChanged);
1463 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1464 tag->AvailablePartCount(&file->m_availablePartsCount);
1465 tag->Shared(&file->m_isShared);
1466 tag->A4AFAuto(file->m_is_A4AF_auto);
1468 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1469 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1470 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1472 tag->FileCat(&file->m_category);
1474 tag->DownPrio(&file->m_iDownPriorityEC);
1475 if ( file->m_iDownPriorityEC >= 10 ) {
1476 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1477 file->m_bAutoDownPriority = true;
1478 } else {
1479 file->m_iDownPriority = file->m_iDownPriorityEC;
1480 file->m_bAutoDownPriority = false;
1483 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1486 // Copy part/gap status
1488 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1489 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1490 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1491 if (gaptag || parttag || reqtag) {
1492 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1494 if (gaptag) {
1495 ArrayOfUInts64 gaps;
1496 encoder.DecodeGaps(gaptag, gaps);
1497 int gap_size = gaps.size() / 2;
1498 // clear gaplist
1499 file->m_gaplist.Init(file->GetFileSize(), false);
1501 // and refill it
1502 for (int j = 0; j < gap_size; j++) {
1503 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1506 if (parttag) {
1507 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1508 // sanity check
1509 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1511 if (reqtag) {
1512 ArrayOfUInts64 reqs;
1513 encoder.DecodeReqs(reqtag, reqs);
1514 int req_size = reqs.size() / 2;
1515 // clear reqlist
1516 DeleteContents(file->m_requestedblocks_list);
1518 // and refill it
1519 for (int j = 0; j < req_size; j++) {
1520 Requested_Block_Struct* block = new Requested_Block_Struct;
1521 block->StartOffset = reqs[2*j];
1522 block->EndOffset = reqs[2*j+1];
1523 file->m_requestedblocks_list.push_back(block);
1528 // Get source names and counts
1529 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1530 if (srcnametag) {
1531 SourcenameItemMap &map = file->GetSourcenameItemMap();
1532 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); it++) {
1533 uint32 key = it->GetInt();
1534 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1535 if (count == 0) {
1536 map.erase(key);
1537 } else {
1538 SourcenameItem &item = map[key];
1539 item.count = count;
1540 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1541 if (nametag) {
1542 item.name = nametag->GetStringData();
1548 // Get comments
1549 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1550 if (commenttag) {
1551 file->ClearFileRatingList();
1552 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1553 wxString u = (it++)->GetStringData();
1554 wxString f = (it++)->GetStringData();
1555 int r = (it++)->GetInt();
1556 wxString c = (it++)->GetStringData();
1557 file->AddFileRatingList(u, f, r, c);
1559 file->UpdateFileRatingCommentAvail();
1562 // Update A4AF sources
1563 ListOfUInts32 & clientIDs = file->GetA4AFClientIDs();
1564 CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES);
1565 if (a4aftag) {
1566 file->ClearA4AFList();
1567 clientIDs.clear();
1568 for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); it++) {
1569 if (it->GetTagName() != EC_TAG_ECID) { // should always be this
1570 continue;
1572 uint32 id = it->GetInt();
1573 CUpDownClient * src = theApp->clientlist->GetByID(id);
1574 if (src) {
1575 file->AddA4AFSource(src);
1576 } else {
1577 // client wasn't transmitted yet, try it later
1578 clientIDs.push_back(id);
1581 } else if (!clientIDs.empty()) {
1582 // Process clients from the last pass whose ids were still unknown then
1583 for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) {
1584 ListOfUInts32::iterator it1 = it++;
1585 uint32 id = *it1;
1586 CUpDownClient * src = theApp->clientlist->GetByID(id);
1587 if (src) {
1588 file->AddA4AFSource(src);
1589 clientIDs.erase(it1);
1594 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1596 // If file is shared check if it is already listed in shared files.
1597 // If not, add it and show it.
1598 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1599 (*theApp->sharedfiles)[file->ECID()] = file;
1600 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1605 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1607 CECPacket req(cmd);
1608 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1610 m_conn->SendPacket(&req);
1614 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1616 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1618 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1619 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1620 req.AddTag(hashtag);
1622 m_conn->SendPacket(&req);
1626 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1628 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1630 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1632 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1633 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1634 req.AddTag(hashtag);
1636 m_conn->SendPacket(&req);
1640 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1642 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1643 file->SetCategory(cat);
1645 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1646 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1647 req.AddTag(hashtag);
1649 m_conn->SendPacket(&req);
1653 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1655 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1656 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1657 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1658 req.AddTag(hashtag);
1660 m_conn->SendPacket(&req);
1664 void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids)
1666 CECPacket req(EC_OP_CLEAR_COMPLETED);
1667 for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); it++) {
1668 req.AddTag(CECTag(EC_TAG_ECID, *it));
1671 m_conn->SendPacket(&req);
1675 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1677 m_curr_search = -1;
1681 wxString CSearchListRem::StartNewSearch(
1682 uint32* nSearchID, SearchType search_type,
1683 const CSearchList::CSearchParams& params)
1685 CECPacket search_req(EC_OP_SEARCH_START);
1686 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1687 switch(search_type) {
1688 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1689 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1690 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1692 search_req.AddTag(
1693 CEC_Search_Tag(params.searchString, ec_search_type,
1694 params.typeText, params.extension, params.availability,
1695 params.minSize, params.maxSize));
1697 m_conn->SendPacket(&search_req);
1698 m_curr_search = *(nSearchID); // No kad remote search yet.
1700 Flush();
1702 return wxEmptyString; // EC reply will have the error mesg is needed.
1706 void CSearchListRem::StopSearch(bool)
1708 if (m_curr_search != -1) {
1709 CECPacket search_req(EC_OP_SEARCH_STOP);
1710 m_conn->SendPacket(&search_req);
1715 void CSearchListRem::HandlePacket(const CECPacket *packet)
1717 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1718 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1719 } else {
1720 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1725 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1727 CECID(tag->ID()),
1728 m_parent(NULL),
1729 m_showChildren(false),
1730 m_sourceCount(0),
1731 m_completeSourceCount(0),
1732 m_kademlia(false),
1733 m_downloadStatus(NEW),
1734 m_clientID(0),
1735 m_clientPort(0),
1736 m_kadPublishInfo(0)
1738 SetFileName(CPath(tag->FileName()));
1739 m_abyFileHash = tag->FileHash();
1740 SetFileSize(tag->SizeFull());
1742 m_searchID = theApp->searchlist->m_curr_search;
1747 // dtor is virtual - must be implemented
1748 CSearchFile::~CSearchFile()
1753 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1755 CSearchFile *file = new CSearchFile(tag);
1756 ProcessItemUpdate(tag, file);
1758 theApp->amuledlg->m_searchwnd->AddResult(file);
1760 return file;
1764 void CSearchListRem::DeleteItem(CSearchFile *file)
1766 delete file;
1770 uint32 CSearchListRem::GetItemID(CSearchFile *file)
1772 return file->ECID();
1776 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
1778 uint32 sourceCount = file->m_sourceCount;
1779 uint32 completeSourceCount = file->m_completeSourceCount;
1780 CSearchFile::DownloadStatus status = file->m_downloadStatus;
1781 tag->SourceCount(&file->m_sourceCount);
1782 tag->CompleteSourceCount(&file->m_completeSourceCount);
1783 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
1785 if (file->m_sourceCount != sourceCount
1786 || file->m_completeSourceCount != completeSourceCount
1787 || file->m_downloadStatus != status) {
1788 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
1789 theApp->amuledlg->m_searchwnd->UpdateResult(file);
1795 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
1797 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
1798 m_conn->SendRequest(this, &progress_req);
1800 return true;
1804 void CSearchListRem::RemoveResults(long nSearchID)
1806 ResultMap::iterator it = m_results.find(nSearchID);
1807 if (it != m_results.end()) {
1808 CSearchResultList& list = it->second;
1809 for (unsigned int i = 0; i < list.size(); ++i) {
1810 delete list[i];
1812 m_results.erase(it);
1817 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
1819 ResultMap::const_iterator it = m_results.find(nSearchID);
1820 if (it != m_results.end()) {
1821 return it->second;
1824 // TODO: Should we assert in this case?
1825 static CSearchResultList list;
1826 return list;
1830 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
1832 theStats::UpdateStats(packet);
1833 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
1837 void CUpDownClient::RequestSharedFileList()
1839 // FIXME: add code
1840 wxFAIL;
1844 bool CUpDownClient::SwapToAnotherFile(
1845 bool WXUNUSED(bIgnoreNoNeeded),
1846 bool WXUNUSED(ignoreSuspensions),
1847 bool WXUNUSED(bRemoveCompletely),
1848 CPartFile* toFile)
1850 CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE);
1851 req.AddTag(CECTag(EC_TAG_CLIENT, ECID()));
1852 req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash()));
1853 theApp->m_connect->SendPacket(&req);
1855 return true;
1860 // Those functions are virtual. So even they don't get called they must
1861 // be defined so linker will be happy
1863 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1865 wxFAIL;
1866 return 0;
1870 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
1872 wxFAIL;
1873 return false;
1877 void CKnownFile::UpdatePartsInfo()
1879 wxFAIL;
1883 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1885 wxFAIL;
1886 return 0;
1890 void CPartFile::UpdatePartsInfo()
1892 wxFAIL;
1897 void CPartFile::UpdateFileRatingCommentAvail()
1899 bool prevComment = m_hasComment;
1900 int prevRating = m_iUserRating;
1902 m_hasComment = false;
1903 m_iUserRating = 0;
1904 int ratingCount = 0;
1906 FileRatingList::iterator it = m_FileRatingList.begin();
1907 for (; it != m_FileRatingList.end(); ++it) {
1908 SFileRating& cur_rat = *it;
1910 if (!cur_rat.Comment.IsEmpty()) {
1911 m_hasComment = true;
1914 uint8 rating = cur_rat.Rating;
1915 if (rating) {
1916 wxASSERT(rating <= 5);
1918 ratingCount++;
1919 m_iUserRating += rating;
1923 if (ratingCount) {
1924 m_iUserRating /= ratingCount;
1925 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
1928 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
1929 UpdateDisplayedInfo();
1934 void CStatTreeRem::DoRequery()
1936 CECPacket request(EC_OP_GET_STATSTREE);
1937 if (thePrefs::GetMaxClientVersions() != 0) {
1938 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions()));
1940 m_conn->SendRequest(this, &request);
1943 void CStatTreeRem::HandlePacket(const CECPacket * p)
1945 const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE);
1946 if (treeRoot) {
1947 theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot);
1948 theApp->amuledlg->m_statisticswnd->ShowStatistics();
1952 CamuleRemoteGuiApp *theApp;
1955 // since gui is not linked with amule.cpp - define events here
1957 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
1958 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
1959 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
1960 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
1961 // File_checked_for_headers