Deprecating the AddLogLineM macro
[amule.git] / src / amule-remote-gui.cpp
blob3ad6609d05f3d6d6959d199fba87f930538236ca
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"
65 CEConnectDlg::CEConnectDlg()
67 wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition)
69 CoreConnect(this, true);
71 wxString pref_host, pref_port;
72 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost"));
73 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712"));
74 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash);
76 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host);
77 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port);
78 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash);
80 CentreOnParent();
84 wxString CEConnectDlg::PassHash()
86 return pwd_hash;
90 BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog)
91 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK)
92 END_EVENT_TABLE()
95 void CEConnectDlg::OnOK(wxCommandEvent& evt)
97 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue();
98 port = StrToLong(s_port);
100 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue();
101 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue();
103 if (passwd != pwd_hash) {
104 pwd_hash = MD5Sum(passwd).GetHash();
106 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked();
107 evt.Skip();
111 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE)
114 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp)
115 // Core timer
116 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer)
118 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection)
119 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone)
121 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent)
123 #ifdef ENABLE_IP2COUNTRY
124 // HTTPDownload finished
125 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload)
126 #endif
127 END_EVENT_TABLE()
130 IMPLEMENT_APP(CamuleRemoteGuiApp)
133 int CamuleRemoteGuiApp::OnExit()
135 StopTickTimer();
137 return wxApp::OnExit();
141 void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&)
143 static int request_step = 0;
145 if (m_connect->RequestFifoFull()) {
146 return;
149 switch (request_step) {
150 case 0:
151 serverconnect->ReQuery();
152 serverlist->UpdateUserFileStatus(serverconnect->GetCurrentServer());
153 request_step++;
154 break;
155 case 1: {
156 CECPacket stats_req(EC_OP_STAT_REQ);
157 m_connect->SendRequest(&m_stats_updater, &stats_req);
158 amuledlg->ShowTransferRate();
159 request_step++;
160 break;
162 case 2:
163 if (amuledlg->m_sharedfileswnd->IsShown()) {
164 // update both downloads and shared files
165 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
166 } else if (amuledlg->m_serverwnd->IsShown()) {
167 //serverlist->FullReload(EC_OP_GET_SERVER_LIST);
168 } else if (amuledlg->m_transferwnd->IsShown()) {
169 // update both downloads and shared files
170 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
171 if (amuledlg->m_transferwnd->clientlistctrl->GetShowing()) {
172 // Kry_GUI Request the client list.
174 amuledlg->m_transferwnd->ShowQueueCount(theStats::GetWaitingUserCount());
175 } else if (amuledlg->m_searchwnd->IsShown()) {
176 if (searchlist->m_curr_search != -1) {
177 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
180 // Back to the roots
181 request_step = 0;
182 break;
183 default:
184 wxFAIL;
185 request_step = 0;
188 // Check for new links once per second.
189 static uint32 lastED2KLinkCheck = 0;
190 if (GetTickCount() - lastED2KLinkCheck >= 1000) {
191 AddLinksFromFile();
192 lastED2KLinkCheck = GetTickCount();
197 void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
199 #ifdef ENABLE_IP2COUNTRY
200 if (event.GetInt() == HTTP_GeoIP) {
201 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong());
202 // If we updated, the dialog is already up. Redraw it to show the flags.
203 amuledlg->Refresh();
205 #endif
209 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt))
211 // Stop the Core Timer
212 delete poll_timer;
213 poll_timer = NULL;
215 // Destroy the EC socket
216 m_connect->Destroy();
217 m_connect = NULL;
220 if (amuledlg) {
221 amuledlg->DlgShutDown();
222 amuledlg->Destroy();
223 amuledlg = NULL;
228 bool CamuleRemoteGuiApp::OnInit()
230 StartTickTimer();
231 amuledlg = NULL;
233 // Get theApp
234 theApp = &wxGetApp();
236 // Handle uncaught exceptions
237 InstallMuleExceptionHandler();
239 // Parse cmdline arguments.
240 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) {
241 return false;
244 // Create the polling timer
245 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT);
246 if (!poll_timer) {
247 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
248 OnExit();
251 m_connect = new CRemoteConnect(this);
253 glob_prefs = new CPreferencesRem(m_connect);
254 long enableZLIB;
255 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1);
256 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification
258 InitCustomLanguages();
259 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
261 if (ShowConnectionDialog()) {
262 AddLogLineNS(_("Going to event loop..."));
263 return true;
266 return false;
270 bool CamuleRemoteGuiApp::CryptoAvailable() const
272 return thePrefs::IsSecureIdentEnabled(); // good enough
276 bool CamuleRemoteGuiApp::ShowConnectionDialog()
278 dialog = new CEConnectDlg;
280 if (m_skipConnectionDialog) {
281 wxCommandEvent evt;
282 dialog->OnOK(evt);
283 } else if (dialog->ShowModal() != wxID_OK) {
284 dialog->Destroy();
286 return false;
288 AddLogLineNS(_("Connecting..."));
289 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(),
290 dialog->Login(), dialog->PassHash(),
291 wxT("amule-remote"), wxT("0x0001"))) {
292 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK);
294 return false;
297 return true;
301 void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) {
302 wxECSocketEvent& evt = *((wxECSocketEvent*)&event);
303 AddLogLineNS(_("Remote GUI EC event handler"));
304 wxString reply = evt.GetServerReply();
305 AddLogLineC(reply);
306 if (evt.GetResult() == true) {
307 // Connected - go to next init step
308 glob_prefs->LoadRemote();
309 } else {
310 AddLogLineNS(_("Going down"));
311 if (dialog) { // connect failed
312 wxMessageBox(
313 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply,
314 _("ERROR"), wxOK);
315 } else { // server disconnected (probably terminated) later
316 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK);
318 ExitMainLoop();
323 void CamuleRemoteGuiApp::OnECInitDone(wxEvent& )
325 Startup();
329 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt)
331 evt.Notify();
335 void CamuleRemoteGuiApp::Startup() {
337 if (dialog->SaveUserPass()) {
338 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host());
339 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port());
340 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash());
342 dialog->Destroy();
343 dialog = NULL;
345 m_ConnState = 0;
346 m_clientID = 0;
348 serverconnect = new CServerConnectRem(m_connect);
349 m_statistics = new CStatistics(*m_connect);
351 clientlist = new CUpDownClientListRem(m_connect);
352 searchlist = new CSearchListRem(m_connect);
353 serverlist = new CServerListRem(m_connect);
355 sharedfiles = new CSharedFilesRem(m_connect);
356 knownfiles = new CKnownFilesRem(m_connect);
358 downloadqueue = new CDownQueueRem(m_connect);
359 ipfilter = new CIPFilterRem(m_connect);
361 // Create main dialog
362 InitGui(m_geometryEnabled, m_geometryString);
364 // Forward wxLog events to CLogger
365 wxLog::SetActiveTarget(new CLoggerTarget);
366 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
367 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE);
369 // Start the Poll Timer
370 poll_timer->Start(1000);
371 amuledlg->StartGuiTimer();
373 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately
374 #ifdef ENABLE_IP2COUNTRY
375 if (thePrefs::IsGeoIPEnabled()) {
376 amuledlg->m_IP2Country->Enable();
378 #endif
382 int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags)
384 return CamuleGuiBase::ShowAlert(msg, title, flags);
388 void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line)
390 amuledlg->AddLogLine(line);
393 int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string)
395 CamuleGuiBase::InitGui(geometry_enabled, geom_string);
396 SetTopWindow(amuledlg);
397 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before
398 return 0;
402 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText)
404 return CamuleGuiBase::CopyTextToClipboard(strText);
408 uint32 CamuleRemoteGuiApp::GetPublicIP()
410 return 0;
414 wxString CamuleRemoteGuiApp::GetLog(bool)
416 return wxEmptyString;
420 wxString CamuleRemoteGuiApp::GetServerLog(bool)
422 return wxEmptyString;
426 bool CamuleRemoteGuiApp::AddServer(CServer * server, bool)
428 CECPacket req(EC_OP_SERVER_ADD);
429 req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort()));
430 req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName()));
431 m_connect->SendPacket(&req);
433 serverlist->FullReload(EC_OP_GET_SERVER_LIST);
435 return true;
439 bool CamuleRemoteGuiApp::IsFirewalled() const
441 if (IsConnectedED2K() && !serverconnect->IsLowID()) {
442 return false;
445 return IsFirewalledKad();
449 bool CamuleRemoteGuiApp::IsConnectedED2K() const {
450 return serverconnect && serverconnect->IsConnected();
454 void CamuleRemoteGuiApp::StartKad() {
455 m_connect->StartKad();
459 void CamuleRemoteGuiApp::StopKad() {
460 m_connect->StopKad();
464 void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port)
466 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
467 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip));
468 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port));
470 m_connect->SendPacket(&req);
474 void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url)
476 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL);
477 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url));
479 m_connect->SendPacket(&req);
483 void CamuleRemoteGuiApp::DisconnectED2K() {
484 if (IsConnectedED2K()) {
485 m_connect->DisconnectED2K();
490 uint32 CamuleRemoteGuiApp::GetED2KID() const
492 return serverconnect ? serverconnect->GetClientID() : 0;
496 uint32 CamuleRemoteGuiApp::GetID() const
498 return m_clientID;
502 void CamuleRemoteGuiApp::ShowUserCount() {
503 wxString buffer;
505 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
506 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
508 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
509 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles());
510 } else if (thePrefs::GetNetworkED2K()) {
511 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles());
512 } else if (thePrefs::GetNetworkKademlia()) {
513 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles());
514 } else {
515 buffer = _("No networks selected");
518 Notify_ShowUserCount(buffer);
523 * Preferences: holds both local and remote settings.
525 * First, everything is loaded from local config file. Later, settings
526 * that are relevant on remote side only are loaded thru EC
528 CPreferencesRem::CPreferencesRem(CRemoteConnect *conn)
530 m_conn = conn;
533 // Settings queried from remote side
535 m_exchange_send_selected_prefs =
536 EC_PREFS_GENERAL |
537 EC_PREFS_CONNECTIONS |
538 EC_PREFS_MESSAGEFILTER |
539 EC_PREFS_ONLINESIG |
540 EC_PREFS_SERVERS |
541 EC_PREFS_FILES |
542 EC_PREFS_SRCDROP |
543 EC_PREFS_DIRECTORIES |
544 EC_PREFS_SECURITY |
545 EC_PREFS_CORETWEAKS |
546 EC_PREFS_REMOTECONTROLS |
547 EC_PREFS_KADEMLIA;
548 m_exchange_recv_selected_prefs =
549 m_exchange_send_selected_prefs |
550 EC_PREFS_CATEGORIES;
554 void CPreferencesRem::HandlePacket(const CECPacket *packet)
556 ((CEC_Prefs_Packet *)packet)->Apply();
558 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES);
559 if (cat_tags) {
560 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); it++) {
561 const CECTag &cat_tag = *it;
562 Category_Struct *cat = new Category_Struct;
563 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData();
564 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData());
565 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData();
566 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt();
567 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt();
568 theApp->glob_prefs->AddCat(cat);
570 } else {
571 Category_Struct *cat = new Category_Struct;
572 cat->title = _("All");
573 cat->color = 0;
574 cat->prio = PR_NORMAL;
575 theApp->glob_prefs->AddCat(cat);
577 wxECInitDoneEvent event;
578 theApp->AddPendingEvent(event);
583 bool CPreferencesRem::LoadRemote()
586 // override local settings with remote
587 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE);
589 // bring categories too
590 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs));
592 m_conn->SendRequest(this, &req);
594 return true;
598 void CPreferencesRem::SendToRemote()
600 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL);
601 m_conn->SendPacket(&pref_packet);
605 class CCatHandler : public CECPacketHandlerBase {
606 virtual void HandlePacket(const CECPacket *packet);
610 void CCatHandler::HandlePacket(const CECPacket *packet)
612 if (packet->GetOpCode() == EC_OP_FAILED) {
613 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY);
614 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH);
615 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) {
616 int cat = catTag->GetInt();
617 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat);
618 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'."))
619 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(),
620 _("ERROR"), wxOK);
621 cs->path = CPath(pathTag->GetStringData());
622 theApp->amuledlg->m_transferwnd->UpdateCategory(cat);
623 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh();
626 delete this;
630 bool CPreferencesRem::CreateCategory(
631 Category_Struct *& category,
632 const wxString& name,
633 const CPath& path,
634 const wxString& comment,
635 uint32 color,
636 uint8 prio)
638 CECPacket req(EC_OP_CREATE_CATEGORY);
639 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio);
640 req.AddTag(tag);
641 m_conn->SendRequest(new CCatHandler, &req);
643 category = new Category_Struct();
644 category->path = path;
645 category->title = name;
646 category->comment = comment;
647 category->color = color;
648 category->prio = prio;
650 AddCat(category);
652 return true;
656 bool CPreferencesRem::UpdateCategory(
657 uint8 cat,
658 const wxString& name,
659 const CPath& path,
660 const wxString& comment,
661 uint32 color,
662 uint8 prio)
664 CECPacket req(EC_OP_UPDATE_CATEGORY);
665 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio);
666 req.AddTag(tag);
667 m_conn->SendRequest(new CCatHandler, &req);
669 Category_Struct *category = m_CatList[cat];
670 category->path = path;
671 category->title = name;
672 category->comment = comment;
673 category->color = color;
674 category->prio = prio;
676 return true;
680 void CPreferencesRem::RemoveCat(uint8 cat)
682 CECPacket req(EC_OP_DELETE_CATEGORY);
683 CEC_Category_Tag tag(cat, EC_DETAIL_CMD);
684 req.AddTag(tag);
685 m_conn->SendPacket(&req);
686 CPreferences::RemoveCat(cat);
691 // Container implementation
693 CServerConnectRem::CServerConnectRem(CRemoteConnect *conn)
695 m_CurrServer = 0;
696 m_Conn = conn;
700 void CServerConnectRem::ConnectToAnyServer()
702 CECPacket req(EC_OP_SERVER_CONNECT);
703 m_Conn->SendPacket(&req);
707 void CServerConnectRem::StopConnectionTry()
709 // lfroen: isn't Disconnect the same ?
713 void CServerConnectRem::Disconnect()
715 CECPacket req(EC_OP_SERVER_DISCONNECT);
716 m_Conn->SendPacket(&req);
720 void CServerConnectRem::ConnectToServer(CServer *server)
722 m_Conn->ConnectED2K(server->GetIP(), server->GetPort());
726 bool CServerConnectRem::ReQuery()
728 CECPacket stat_req(EC_OP_GET_CONNSTATE);
729 m_Conn->SendRequest(this, &stat_req);
731 return true;
735 void CServerConnectRem::HandlePacket(const CECPacket *packet)
737 CEC_ConnState_Tag *tag =
738 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE);
739 if (!tag) {
740 return;
743 theApp->m_ConnState = 0;
744 CServer *server;
745 m_ID = tag->GetEd2kId();
746 theApp->m_clientID = tag->GetClientId();
748 if (tag->IsConnectedED2K()) {
749 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER);
750 if (!srvtag) {
751 return;
753 server = theApp->serverlist->GetByID(srvtag->GetIPv4Data().IP());
754 if (m_CurrServer && (server != m_CurrServer)) {
755 theApp->amuledlg->m_serverwnd->serverlistctrl->
756 HighlightServer(m_CurrServer, false);
758 theApp->amuledlg->m_serverwnd->serverlistctrl->
759 HighlightServer(server, true);
760 m_CurrServer = server;
761 theApp->m_ConnState |= CONNECTED_ED2K;
762 } else {
763 if ( m_CurrServer ) {
764 theApp->amuledlg->m_serverwnd->serverlistctrl->
765 HighlightServer(m_CurrServer, false);
766 m_CurrServer = 0;
770 if (tag->IsConnectedKademlia()) {
771 if (tag->IsKadFirewalled()) {
772 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED;
773 } else {
774 theApp->m_ConnState |= CONNECTED_KAD_OK;
776 } else {
777 if (tag->IsKadRunning()) {
778 theApp->m_ConnState |= CONNECTED_KAD_NOT;
782 theApp->amuledlg->ShowConnectionState();
787 * Server list: host list of ed2k servers.
789 CServerListRem::CServerListRem(CRemoteConnect *conn)
791 CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, false)
796 void CServerListRem::HandlePacket(const CECPacket *packet)
798 CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet);
799 ReloadControl();
803 void CServerListRem::UpdateServerMetFromURL(wxString url)
805 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL);
806 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url));
808 m_conn->SendPacket(&req);
812 void CServerListRem::SaveServerMet()
814 // lfroen: stub, nothing to do
818 void CServerListRem::FilterServers()
820 // FIXME: add code
821 //wxFAIL;
825 void CServerListRem::RemoveServer(CServer* server)
827 m_conn->RemoveServer(server->GetIP(),server->GetPort());
831 void CServerListRem::UpdateUserFileStatus(CServer *server)
833 if (server) {
834 m_TotalUser = server->GetUsers();
835 m_TotalFile = server->GetFiles();
840 CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const
842 // It's ok to return 0 for context where this code is used in remote gui
843 return 0;
846 CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const
848 // It's ok to return 0 for context where this code is used in remote gui
849 return 0;
852 CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag)
854 return new CServer(tag);
858 void CServerListRem::DeleteItem(CServer *in_srv)
860 CScopedPtr<CServer> srv(in_srv);
861 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get());
865 uint32 CServerListRem::GetItemID(CServer *server)
867 return server->GetIP();
871 void CServerListRem::ProcessItemUpdate(CEC_Server_Tag *, CServer *)
873 // server list is always realoaded from scratch
874 wxFAIL;
878 void CServerListRem::ReloadControl()
880 for(iterator it = begin(); it != end(); it++) {
881 CServer *srv = *it;
882 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(srv);
887 CIPFilterRem::CIPFilterRem(CRemoteConnect* conn)
889 m_conn = conn;
893 void CIPFilterRem::Reload()
895 CECPacket req(EC_OP_IPFILTER_RELOAD);
896 m_conn->SendPacket(&req);
900 void CIPFilterRem::Update(wxString url)
902 CECPacket req(EC_OP_IPFILTER_UPDATE);
903 req.AddTag(CECTag(EC_TAG_STRING, url));
905 m_conn->SendPacket(&req);
910 * Shared files list
912 CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn)
914 m_conn = conn;
918 void CSharedFilesRem::Reload(bool, bool)
920 CECPacket req(EC_OP_SHAREDFILES_RELOAD);
922 m_conn->SendPacket(&req);
926 void CSharedFilesRem::AddFilesFromDirectory(const CPath& path)
928 CECPacket req(EC_OP_SHAREDFILES_ADD_DIRECTORY);
930 req.AddTag(CECTag(EC_TAG_PREFS_DIRECTORIES, path.GetRaw()));
932 m_conn->SendPacket(&req);
936 bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName)
938 // We use the printable name, as the filename originated from user input,
939 // and the filesystem name might not be valid on the remote host.
940 const wxString strNewName = newName.GetPrintable();
942 CECPacket request(EC_OP_RENAME_FILE);
943 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash()));
944 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName));
946 m_conn->SendPacket(&request);
948 return true;
952 void CKnownFilesRem::DeleteItem(CKnownFile * file)
954 uint32 id = file->ECID();
955 if (theApp->sharedfiles->count(id)) {
956 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file);
957 theApp->sharedfiles->erase(id);
959 if (theApp->downloadqueue->count(id)) {
960 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file);
961 theApp->downloadqueue->erase(id);
963 delete file;
967 uint32 CKnownFilesRem::GetItemID(CKnownFile *file)
969 return file->ECID();
973 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file)
975 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
976 if (parttag) {
977 const uint8 *data = file->m_partStatus.Decode(
978 (uint8 *)parttag->GetTagData(),
979 parttag->GetTagDataLen());
980 for(int i = 0; i < file->GetPartCount(); ++i) {
981 file->m_AvailPartFrequency[i] = data[i];
984 wxString fileName;
985 if (tag->FileName(fileName)) {
986 file->SetFileName(CPath(fileName));
988 if (tag->FilePath(fileName)) {
989 file->m_filePath = CPath(fileName);
991 tag->UpPrio(&file->m_iUpPriorityEC);
992 tag->GetAICHHash(file->m_AICHMasterHash);
993 tag->GetRequests(&file->statistic.requested);
994 tag->GetAllRequests(&file->statistic.alltimerequested);
995 tag->GetAccepts(&file->statistic.accepted);
996 tag->GetAllAccepts(&file->statistic.alltimeaccepted);
997 tag->GetXferred(&file->statistic.transferred);
998 tag->GetAllXferred(&file->statistic.alltimetransferred);
999 tag->UpPrio(&file->m_iUpPriorityEC);
1000 if (file->m_iUpPriorityEC >= 10) {
1001 file->m_iUpPriority = file->m_iUpPriorityEC - 10;
1002 file->m_bAutoUpPriority = true;
1003 } else {
1004 file->m_iUpPriority = file->m_iUpPriorityEC;
1005 file->m_bAutoUpPriority = false;
1007 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo);
1008 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi);
1009 tag->GetCompleteSources(&file->m_nCompleteSourcesCount);
1011 tag->GetOnQueue(&file->m_queuedCount);
1013 requested += file->statistic.requested;
1014 transferred += file->statistic.transferred;
1015 accepted += file->statistic.transferred;
1017 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file);
1019 if (file->IsPartFile()) {
1020 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file);
1024 void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio)
1026 CECPacket req(EC_OP_SHARED_SET_PRIO);
1028 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1029 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1031 req.AddTag(hashtag);
1033 m_conn->SendPacket(&req);
1036 void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int)
1038 requested = 0;
1039 transferred = 0;
1040 accepted = 0;
1042 std::set<uint32> core_files;
1043 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
1044 const CECTag * curTag = &*it;
1045 ec_tagname_t tagname = curTag->GetTagName();
1046 if (tagname == EC_TAG_CLIENT) {
1047 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT);
1048 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) {
1049 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *) curTag;
1050 uint32 id = tag->ID();
1051 core_files.insert(id);
1052 if ( m_items_hash.count(id) ) {
1053 // Item already known: update it
1054 ProcessItemUpdate(tag, m_items_hash[id]);
1055 } else {
1056 CKnownFile * newFile;
1057 if (tag->GetTagName() == EC_TAG_PARTFILE) {
1058 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag);
1059 ProcessItemUpdate(tag, file);
1060 // GUI doesn't allow clear finished files well at the moment,
1061 // so don't show finished files for now until GUI gets unlocked.
1062 // Files completing while GUI is open will still show.
1063 if (file->IsPartFile()) {
1064 (*theApp->downloadqueue)[id] = file;
1065 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file);
1067 newFile = file;
1068 } else {
1069 newFile = new CKnownFile(tag);
1070 ProcessItemUpdate(tag, newFile);
1071 (*theApp->sharedfiles)[id] = newFile;
1072 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile);
1074 AddItem(newFile);
1078 // remove items no longer present
1079 for(iterator it = begin(); it != end();) {
1080 iterator it2 = it++;
1081 if (!core_files.count(GetItemID(*it2))) {
1082 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views.
1087 CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true)
1089 requested = 0;
1090 transferred = 0;
1091 accepted = 0;
1096 * List of uploading and waiting clients.
1098 CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn)
1100 CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag>(conn, true)
1105 CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
1107 // Clients start up empty, then get asked for their data.
1108 // So all data here is processed in ProcessItemUpdate and thus updatable.
1109 m_bRemoteQueueFull = false;
1110 m_nUserIDHybrid = 0;
1111 m_clientSoft = 0;
1112 m_bEmuleProtocol = false;
1114 // User IP:Port
1115 m_nConnectIP = 0;
1116 m_dwUserIP = 0;
1117 m_nUserPort = 0;
1118 m_FullUserIP = 0;
1120 // Server IP:Port
1121 m_dwServerIP = 0;
1122 m_nServerPort = 0;
1124 m_waitingPosition = 0;
1125 m_score = 0;
1126 m_identState = IS_NOTAVAILABLE;
1127 m_obfuscationStatus = 0;
1129 m_nSourceFrom = SF_NONE;
1130 m_nKadPort = 0;
1132 m_Friend = 0;
1133 m_nCurSessionUp = 0;
1134 m_reqfile = NULL;
1135 m_uploadingfile = NULL;
1136 m_lastDownloadingPart = 0xffff;
1137 m_nextRequestedPart = 0xffff;
1139 credits = new CClientCredits(new CreditStruct());
1142 /* Warning: do common base */
1145 bool CUpDownClient::IsIdentified() const
1147 return m_identState == IS_IDENTIFIED;
1151 bool CUpDownClient::IsBadGuy() const
1153 return m_identState == IS_IDBADGUY;
1157 bool CUpDownClient::SUIFailed() const
1159 return m_identState == IS_IDFAILED;
1163 bool CUpDownClient::SUINeeded() const
1165 return m_identState == IS_IDNEEDED;
1169 bool CUpDownClient::SUINotSupported() const
1171 return m_identState == IS_NOTAVAILABLE;
1175 uint64 CUpDownClient::GetDownloadedTotal() const
1177 return credits->GetDownloadedTotal();
1181 uint64 CUpDownClient::GetUploadedTotal() const
1183 return credits->GetUploadedTotal();
1187 double CUpDownClient::GetScoreRatio() const
1189 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable());
1192 /* End Warning */
1195 CUpDownClient::~CUpDownClient()
1197 delete credits;
1201 CUpDownClient *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag)
1203 CUpDownClient *client = new CUpDownClient(tag);
1204 ProcessItemUpdate(tag, client);
1205 if (client->m_reqfile) {
1206 Notify_SourceCtrlAddSource(client->m_reqfile, client, A4AF_SOURCE);
1209 return client;
1213 void CUpDownClientListRem::DeleteItem(CUpDownClient *client)
1215 if (client->m_reqfile) {
1216 Notify_SourceCtrlRemoveSource(client, client->m_reqfile);
1217 client->m_reqfile->DelSource(client);
1218 client->m_reqfile = NULL;
1220 delete client;
1224 uint32 CUpDownClientListRem::GetItemID(CUpDownClient *client)
1226 return client->ECID();
1230 void CUpDownClientListRem::ProcessItemUpdate(
1231 CEC_UpDownClient_Tag *tag,
1232 CUpDownClient *client)
1234 if (!tag->HasChildTags()) {
1235 return; // speed exit for clients without any change
1237 tag->UserID(&client->m_nUserIDHybrid);
1238 tag->ClientName(&client->m_Username);
1239 // Client Software
1240 bool sw_updated = false;
1241 if (tag->ClientSoftware(client->m_clientSoft)) {
1242 client->m_clientVersionString = GetSoftName(client->m_clientSoft);
1243 client->m_clientSoftString = client->m_clientVersionString;
1244 sw_updated = true;
1246 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) {
1247 if (client->m_clientVersionString == _("Unknown")) {
1248 client->m_fullClientVerString = client->m_clientVersionString;
1249 } else {
1250 client->m_fullClientVerString = client->m_clientVersionString + wxT(" ") + client->m_clientVerString;
1253 // User hash
1254 tag->UserHash(&client->m_UserHash);
1256 // User IP:Port
1257 if (tag->UserIP(client->m_dwUserIP)) {
1258 client->m_nConnectIP = client->m_dwUserIP;
1259 client->m_FullUserIP = client->m_dwUserIP;
1261 tag->UserPort(&client->m_nUserPort);
1263 // Server IP:Port
1264 tag->ServerIP(&client->m_dwServerIP);
1265 tag->ServerPort(&client->m_nServerPort);
1266 tag->ServerName(&client->m_ServerName);
1268 tag->KadPort(client->m_nKadPort);
1270 tag->GetCurrentIdentState(&client->m_identState);
1271 tag->ObfuscationStatus(client->m_obfuscationStatus);
1272 tag->HasExtendedProtocol(&client->m_bEmuleProtocol);
1274 tag->WaitingPosition(&client->m_waitingPosition);
1275 tag->RemoteQueueRank(&client->m_nRemoteQueueRank);
1276 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff;
1277 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank);
1278 tag->AskedCount(&client->m_cAsked);
1280 tag->ClientDownloadState(&client->m_nDownloadState);
1281 tag->ClientUploadState(&client->m_nUploadState);
1283 tag->SpeedUp(&client->m_nUpDatarate);
1284 if ( client->m_nDownloadState == DS_DOWNLOADING ) {
1285 tag->SpeedDown(&client->kBpsDown);
1286 } else {
1287 client->kBpsDown = 0;
1290 //tag->WaitTime(&client->m_WaitTime);
1291 //tag->XferTime(&client->m_UpStartTimeDelay);
1292 //tag->LastReqTime(&client->m_dwLastUpRequest);
1293 //tag->QueueTime(&client->m_WaitStartTime);
1295 CreditStruct *credit_struct =
1296 (CreditStruct *)client->credits->GetDataStruct();
1297 tag->XferUp(&credit_struct->uploaded);
1298 tag->XferUpSession(&client->m_nTransferredUp);
1300 tag->XferDown(&credit_struct->downloaded);
1301 tag->XferDownSession(&client->m_nTransferredDown);
1303 tag->Score(&client->m_score);
1305 tag->NextRequestedPart(client->m_nextRequestedPart);
1306 tag->LastDownloadingPart(client->m_lastDownloadingPart);
1308 uint8 sourceFrom = 0;
1309 if (tag->GetSourceFrom(sourceFrom)) {
1310 client->m_nSourceFrom = (ESourceFrom)sourceFrom;
1313 // Download client
1314 uint32 fileID;
1315 bool notified = false;
1316 if (tag->RequestFile(fileID)) {
1317 if (client->m_reqfile) {
1318 Notify_SourceCtrlRemoveSource(client, client->m_reqfile);
1319 client->m_reqfile->DelSource(client);
1320 client->m_reqfile = NULL;
1321 client->m_downPartStatus.clear();
1323 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1324 if (kf && kf->IsCPartFile()) {
1325 client->m_reqfile = (CPartFile *) kf;
1326 client->m_reqfile->AddSource(client);
1327 client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1328 Notify_SourceCtrlAddSource(client->m_reqfile, client, A4AF_SOURCE);
1329 notified = true;
1333 // Part status
1334 CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS);
1335 if (partStatusTag) {
1336 if (partStatusTag->GetTagDataLen() == 0) {
1337 // empty tag means full source
1338 client->m_downPartStatus.SetAllTrue();
1339 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) {
1340 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData());
1342 notified = false;
1345 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) {
1346 SourceItemType type = A4AF_SOURCE;
1347 switch (client->GetDownloadState()) {
1348 case DS_DOWNLOADING:
1349 case DS_ONQUEUE:
1350 // We will send A4AF, which will be checked.
1351 break;
1352 default:
1353 type = UNAVAILABLE_SOURCE;
1354 break;
1357 Notify_SourceCtrlUpdateSource(client, type);
1360 // Upload client
1361 if (tag->UploadFile(fileID)) {
1362 if (client->m_uploadingfile) {
1363 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies
1364 client->m_uploadingfile = NULL;
1365 //client->m_downPartStatus.clear();
1367 CKnownFile * kf = theApp->knownfiles->GetByID(fileID);
1368 if (kf) {
1369 client->m_uploadingfile = kf;
1370 client->m_uploadingfile->AddUploadingClient(client); // this notifies
1371 //client->m_downPartStatus.setsize(kf->GetPartCount(), 0);
1378 * Download queue container: hold PartFiles with progress status
1383 bool CDownQueueRem::AddLink(const wxString &link, uint8 cat)
1385 CECPacket req(EC_OP_ADD_LINK);
1386 CECTag link_tag(EC_TAG_STRING, link);
1387 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1388 req.AddTag(link_tag);
1390 m_conn->SendPacket(&req);
1391 return true;
1395 void CDownQueueRem::ResetCatParts(int cat)
1397 // Called when category is deleted. Command will be performed on the remote side,
1398 // but files still should be updated here right away, or drawing errors (colour not available)
1399 // will happen.
1400 for (iterator it = begin(); it != end(); it++) {
1401 CPartFile* file = it->second;
1403 if ( file->GetCategory() == cat ) {
1404 // Reset the category
1405 file->SetCategory( 0 );
1406 } else if ( file->GetCategory() > cat ) {
1407 // Set to the new position of the original category
1408 file->SetCategory( file->GetCategory() - 1 );
1415 void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file)
1418 // update status
1420 tag->Speed(&file->m_kbpsDown);
1421 file->kBpsDown = file->m_kbpsDown / 1024.0;
1423 tag->SizeXfer(&file->transferred);
1424 tag->SizeDone(&file->completedsize);
1425 tag->SourceXferCount(&file->transferingsrc);
1426 tag->SourceNotCurrCount(&file->m_notCurrentSources);
1427 tag->SourceCount(&file->m_source_count);
1428 tag->SourceCountA4AF(&file->m_a4af_source_count);
1429 tag->FileStatus(&file->status);
1430 tag->Stopped(&file->m_stopped);
1432 tag->LastSeenComplete(&file->lastseencomplete);
1433 tag->LastDateChanged(&file->m_lastDateChanged);
1434 tag->DownloadActiveTime(&file->m_nDlActiveTime);
1435 tag->AvailablePartCount(&file->m_availablePartsCount);
1436 tag->Shared(&file->m_isShared);
1437 tag->A4AFAuto(file->m_is_A4AF_auto);
1439 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption);
1440 tag->GetGainDueToCompression(&file->m_iGainDueToCompression);
1441 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH);
1443 tag->FileCat(&file->m_category);
1445 tag->DownPrio(&file->m_iDownPriorityEC);
1446 if ( file->m_iDownPriorityEC >= 10 ) {
1447 file->m_iDownPriority = file->m_iDownPriorityEC - 10;
1448 file->m_bAutoDownPriority = true;
1449 } else {
1450 file->m_iDownPriority = file->m_iDownPriorityEC;
1451 file->m_bAutoDownPriority = false;
1454 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize();
1457 // Copy part/gap status
1459 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
1460 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
1461 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
1462 if (gaptag || parttag || reqtag) {
1463 PartFileEncoderData &encoder = file->m_PartFileEncoderData;
1465 if (gaptag) {
1466 ArrayOfUInts64 gaps;
1467 encoder.DecodeGaps(gaptag, gaps);
1468 int gap_size = gaps.size() / 2;
1469 // clear gaplist
1470 file->m_gaplist.Init(file->GetFileSize(), false);
1472 // and refill it
1473 for (int j = 0; j < gap_size; j++) {
1474 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]);
1477 if (parttag) {
1478 encoder.DecodeParts(parttag, file->m_SrcpartFrequency);
1479 // sanity check
1480 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount());
1482 if (reqtag) {
1483 ArrayOfUInts64 reqs;
1484 encoder.DecodeReqs(reqtag, reqs);
1485 int req_size = reqs.size() / 2;
1486 // clear reqlist
1487 DeleteContents(file->m_requestedblocks_list);
1489 // and refill it
1490 for (int j = 0; j < req_size; j++) {
1491 Requested_Block_Struct* block = new Requested_Block_Struct;
1492 block->StartOffset = reqs[2*j];
1493 block->EndOffset = reqs[2*j+1];
1494 file->m_requestedblocks_list.push_back(block);
1499 // Get source names and counts
1500 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1501 if (srcnametag) {
1502 SourcenameItemMap &map = file->GetSourcenameItemMap();
1503 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); it++) {
1504 uint32 key = it->GetInt();
1505 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt();
1506 if (count == 0) {
1507 map.erase(key);
1508 } else {
1509 SourcenameItem &item = map[key];
1510 item.count = count;
1511 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES);
1512 if (nametag) {
1513 item.name = nametag->GetStringData();
1519 // Get comments
1520 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS);
1521 if (commenttag) {
1522 file->ClearFileRatingList();
1523 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) {
1524 wxString u = (it++)->GetStringData();
1525 wxString f = (it++)->GetStringData();
1526 int r = (it++)->GetInt();
1527 wxString c = (it++)->GetStringData();
1528 file->AddFileRatingList(u, f, r, c);
1530 file->UpdateFileRatingCommentAvail();
1533 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file);
1535 // If file is shared check if it is already listed in shared files.
1536 // If not, add it and show it.
1537 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) {
1538 (*theApp->sharedfiles)[file->ECID()] = file;
1539 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file);
1544 void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd)
1546 CECPacket req(cmd);
1547 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash()));
1549 m_conn->SendPacket(&req);
1553 void CDownQueueRem::Prio(CPartFile *file, uint8 prio)
1555 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1557 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1558 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio));
1559 req.AddTag(hashtag);
1561 m_conn->SendPacket(&req);
1565 void CDownQueueRem::AutoPrio(CPartFile *file, bool flag)
1567 CECPacket req(EC_OP_PARTFILE_PRIO_SET);
1569 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1571 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
1572 (uint8)(flag ? PR_AUTO : file->GetDownPriority())));
1573 req.AddTag(hashtag);
1575 m_conn->SendPacket(&req);
1579 void CDownQueueRem::Category(CPartFile *file, uint8 cat)
1581 CECPacket req(EC_OP_PARTFILE_SET_CAT);
1582 file->SetCategory(cat);
1584 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1585 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
1586 req.AddTag(hashtag);
1588 m_conn->SendPacket(&req);
1592 void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category)
1594 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT);
1595 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash());
1596 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category));
1597 req.AddTag(hashtag);
1599 m_conn->SendPacket(&req);
1603 void CUpDownClientListRem::FilterQueues()
1605 // FIXME: add code
1606 //wxFAIL;
1610 CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true)
1612 m_curr_search = -1;
1616 wxString CSearchListRem::StartNewSearch(
1617 uint32* nSearchID, SearchType search_type,
1618 const CSearchList::CSearchParams& params)
1620 CECPacket search_req(EC_OP_SEARCH_START);
1621 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL;
1622 switch(search_type) {
1623 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break;
1624 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break;
1625 case KadSearch: ec_search_type = EC_SEARCH_KAD; break;
1627 search_req.AddTag(
1628 CEC_Search_Tag(params.searchString, ec_search_type,
1629 params.typeText, params.extension, params.availability,
1630 params.minSize, params.maxSize));
1632 m_conn->SendPacket(&search_req);
1633 m_curr_search = *(nSearchID); // No kad remote search yet.
1635 Flush();
1637 return wxEmptyString; // EC reply will have the error mesg is needed.
1641 void CSearchListRem::StopGlobalSearch()
1643 if (m_curr_search != -1) {
1644 CECPacket search_req(EC_OP_SEARCH_STOP);
1645 m_conn->SendPacket(&search_req);
1650 void CSearchListRem::StopKadSearch()
1652 // FIXME implementation needed
1656 void CSearchListRem::HandlePacket(const CECPacket *packet)
1658 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) {
1659 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt());
1660 } else {
1661 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet);
1666 CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag)
1668 CECID(tag->ID()),
1669 m_parent(NULL),
1670 m_showChildren(false),
1671 m_sourceCount(0),
1672 m_completeSourceCount(0),
1673 m_kademlia(false),
1674 m_downloadStatus(NEW),
1675 m_clientID(0),
1676 m_clientPort(0),
1677 m_kadPublishInfo(0)
1679 SetFileName(CPath(tag->FileName()));
1680 m_abyFileHash = tag->FileHash();
1681 SetFileSize(tag->SizeFull());
1683 m_searchID = theApp->searchlist->m_curr_search;
1688 // dtor is virtual - must be implemented
1689 CSearchFile::~CSearchFile()
1694 CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag)
1696 CSearchFile *file = new CSearchFile(tag);
1697 ProcessItemUpdate(tag, file);
1699 theApp->amuledlg->m_searchwnd->AddResult(file);
1701 return file;
1705 void CSearchListRem::DeleteItem(CSearchFile *file)
1707 delete file;
1711 uint32 CSearchListRem::GetItemID(CSearchFile *file)
1713 return file->ECID();
1717 void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file)
1719 uint32 sourceCount = file->m_sourceCount;
1720 uint32 completeSourceCount = file->m_completeSourceCount;
1721 CSearchFile::DownloadStatus status = file->m_downloadStatus;
1722 tag->SourceCount(&file->m_sourceCount);
1723 tag->CompleteSourceCount(&file->m_completeSourceCount);
1724 tag->DownloadStatus((uint32 *) &file->m_downloadStatus);
1726 if (file->m_sourceCount != sourceCount
1727 || file->m_completeSourceCount != completeSourceCount
1728 || file->m_downloadStatus != status) {
1729 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) {
1730 theApp->amuledlg->m_searchwnd->UpdateResult(file);
1736 bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply))
1738 CECPacket progress_req(EC_OP_SEARCH_PROGRESS);
1739 m_conn->SendRequest(this, &progress_req);
1741 return true;
1745 void CSearchListRem::RemoveResults(long nSearchID)
1747 ResultMap::iterator it = m_results.find(nSearchID);
1748 if (it != m_results.end()) {
1749 CSearchResultList& list = it->second;
1750 for (unsigned int i = 0; i < list.size(); ++i) {
1751 delete list[i];
1753 m_results.erase(it);
1758 const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID)
1760 ResultMap::const_iterator it = m_results.find(nSearchID);
1761 if (it != m_results.end()) {
1762 return it->second;
1765 // TODO: Should we assert in this case?
1766 static CSearchResultList list;
1767 return list;
1771 void CStatsUpdaterRem::HandlePacket(const CECPacket *packet)
1773 theStats::UpdateStats(packet);
1774 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ?
1778 bool CUpDownClient::IsBanned() const
1780 // FIXME: add code
1781 return false;
1786 // Those functions have different implementation in remote gui
1788 void CUpDownClient::Ban()
1790 // FIXME: add code
1791 wxFAIL;
1795 void CUpDownClient::UnBan()
1797 // FIXME: add code
1798 wxFAIL;
1802 void CUpDownClient::RequestSharedFileList()
1804 // FIXME: add code
1805 wxFAIL;
1809 void CKnownFile::SetFileComment(const wxString &)
1811 // FIXME: add code
1812 wxMessageBox(_("Comments and ratings are not supported on remote gui yet"), _("Information"), wxOK | wxICON_INFORMATION);
1816 void CKnownFile::SetFileRating(unsigned char)
1818 // FIXME: add code
1822 bool CUpDownClient::SwapToAnotherFile(
1823 bool WXUNUSED(bIgnoreNoNeeded),
1824 bool WXUNUSED(ignoreSuspensions),
1825 bool WXUNUSED(bRemoveCompletely),
1826 CPartFile* WXUNUSED(toFile))
1828 // FIXME: add code
1829 wxFAIL;
1830 return false;
1835 // Those functions are virtual. So even they don't get called they must
1836 // be defined so linker will be happy
1838 CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1840 wxFAIL;
1841 return 0;
1845 bool CKnownFile::LoadFromFile(const class CFileDataIO*)
1847 wxFAIL;
1848 return false;
1852 void CKnownFile::UpdatePartsInfo()
1854 wxFAIL;
1858 CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/)
1860 wxFAIL;
1861 return 0;
1865 void CPartFile::UpdatePartsInfo()
1867 wxFAIL;
1871 void CPartFile::UpdateFileRatingCommentAvail()
1873 bool prevComment = m_hasComment;
1874 int prevRating = m_iUserRating;
1876 m_hasComment = false;
1877 m_iUserRating = 0;
1878 int ratingCount = 0;
1880 FileRatingList::iterator it = m_FileRatingList.begin();
1881 for (; it != m_FileRatingList.end(); ++it) {
1882 SFileRating& cur_rat = *it;
1884 if (!cur_rat.Comment.IsEmpty()) {
1885 m_hasComment = true;
1888 uint8 rating = cur_rat.Rating;
1889 if (rating) {
1890 wxASSERT(rating <= 5);
1892 ratingCount++;
1893 m_iUserRating += rating;
1897 if (ratingCount) {
1898 m_iUserRating /= ratingCount;
1899 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5);
1902 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) {
1903 UpdateDisplayedInfo();
1907 bool CPartFile::SavePartFile(bool)
1909 wxFAIL;
1910 return false;
1913 CamuleRemoteGuiApp *theApp;
1916 // since gui is not linked with amule.cpp - define events here
1918 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
1919 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
1920 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
1921 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
1922 // File_checked_for_headers