2 // This file is part of the aMule Project.
4 // Copyright (c) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )
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
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.
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
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
50 #include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD
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
);
85 wxString
CEConnectDlg::PassHash()
91 BEGIN_EVENT_TABLE(CEConnectDlg
, wxDialog
)
92 EVT_BUTTON(wxID_OK
, CEConnectDlg::OnOK
)
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();
112 DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE
)
115 BEGIN_EVENT_TABLE(CamuleRemoteGuiApp
, wxApp
)
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
)
131 IMPLEMENT_APP(CamuleRemoteGuiApp
)
134 int CamuleRemoteGuiApp::OnExit()
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()) {
151 switch (request_step
) {
153 serverconnect
->ReQuery();
154 serverlist
->UpdateUserFileStatus(serverconnect
->GetCurrentServer());
158 CECPacket
stats_req(EC_OP_STAT_REQ
);
159 m_connect
->SendRequest(&m_stats_updater
, &stats_req
);
160 amuledlg
->ShowTransferRate();
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)) {
183 stattree
->DoRequery();
194 // Check for new links once per second.
195 static uint32 lastED2KLinkCheck
= 0;
196 if (GetTickCount() - lastED2KLinkCheck
>= 1000) {
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.
215 void CamuleRemoteGuiApp::ShutDown(wxCloseEvent
&WXUNUSED(evt
))
217 // Stop the Core Timer
221 // Destroy the EC socket
222 m_connect
->Destroy();
227 amuledlg
->DlgShutDown();
231 delete m_allUploadingKnownFile
;
236 bool CamuleRemoteGuiApp::OnInit()
242 theApp
= &wxGetApp();
244 // Handle uncaught exceptions
245 InstallMuleExceptionHandler();
247 // Parse cmdline arguments.
248 if (!InitCommon(AMULE_APP_BASE::argc
, AMULE_APP_BASE::argv
)) {
252 // Create the polling timer
253 poll_timer
= new wxTimer(this,ID_CORE_TIMER_EVENT
);
255 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer"));
259 m_connect
= new CRemoteConnect(this);
261 glob_prefs
= new CPreferencesRem(m_connect
);
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..."));
278 bool CamuleRemoteGuiApp::CryptoAvailable() const
280 return thePrefs::IsSecureIdentEnabled(); // good enough
284 bool CamuleRemoteGuiApp::ShowConnectionDialog()
286 dialog
= new CEConnectDlg
;
288 if (m_skipConnectionDialog
) {
291 } else if (dialog
->ShowModal() != wxID_OK
) {
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
);
309 void CamuleRemoteGuiApp::OnECConnection(wxEvent
& event
) {
310 wxECSocketEvent
& evt
= *((wxECSocketEvent
*)&event
);
311 AddLogLineNS(_("Remote GUI EC event handler"));
312 wxString reply
= evt
.GetServerReply();
314 if (evt
.GetResult() == true) {
315 // Connected - go to next init step
316 glob_prefs
->LoadRemote();
318 AddLogLineNS(_("Going down"));
319 if (dialog
) { // connect failed
321 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog
->Host() % dialog
->Port()) + reply
,
323 } else { // server disconnected (probably terminated) later
324 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK
);
331 void CamuleRemoteGuiApp::OnECInitDone(wxEvent
& )
337 void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent
& evt
)
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());
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();
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
413 bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText
)
415 return CamuleGuiBase::CopyTextToClipboard(strText
);
419 uint32
CamuleRemoteGuiApp::GetPublicIP()
425 wxString
CamuleRemoteGuiApp::GetLog(bool 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
);
455 bool CamuleRemoteGuiApp::IsFirewalled() const
457 if (IsConnectedED2K() && !serverconnect
->IsLowID()) {
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
518 void CamuleRemoteGuiApp::ShowUserCount() {
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());
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
)
549 // Settings queried from remote side
551 m_exchange_send_selected_prefs
=
553 EC_PREFS_CONNECTIONS
|
554 EC_PREFS_MESSAGEFILTER
|
559 EC_PREFS_DIRECTORIES
|
561 EC_PREFS_CORETWEAKS
|
562 EC_PREFS_REMOTECONTROLS
|
564 m_exchange_recv_selected_prefs
=
565 m_exchange_send_selected_prefs
|
570 void CPreferencesRem::HandlePacket(const CECPacket
*packet
)
572 ((CEC_Prefs_Packet
*)packet
)->Apply();
574 const CECTag
*cat_tags
= packet
->GetTagByName(EC_TAG_PREFS_CATEGORIES
);
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
);
587 Category_Struct
*cat
= new Category_Struct
;
588 cat
->title
= _("All");
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
);
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(),
637 cs
->path
= CPath(pathTag
->GetStringData());
638 theApp
->amuledlg
->m_transferwnd
->UpdateCategory(cat
);
639 theApp
->amuledlg
->m_transferwnd
->downloadlistctrl
->Refresh();
646 bool CPreferencesRem::CreateCategory(
647 Category_Struct
*& category
,
648 const wxString
& name
,
650 const wxString
& comment
,
654 CECPacket
req(EC_OP_CREATE_CATEGORY
);
655 CEC_Category_Tag
tag(0xffffffff, name
, path
.GetRaw(), comment
, color
, prio
);
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
;
672 bool CPreferencesRem::UpdateCategory(
674 const wxString
& name
,
676 const wxString
& comment
,
680 CECPacket
req(EC_OP_UPDATE_CATEGORY
);
681 CEC_Category_Tag
tag(cat
, name
, path
.GetRaw(), comment
, color
, prio
);
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
;
696 void CPreferencesRem::RemoveCat(uint8 cat
)
698 CECPacket
req(EC_OP_DELETE_CATEGORY
);
699 CEC_Category_Tag
tag(cat
, EC_DETAIL_CMD
);
701 m_conn
->SendPacket(&req
);
702 CPreferences::RemoveCat(cat
);
707 // Container implementation
709 CServerConnectRem::CServerConnectRem(CRemoteConnect
*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
);
751 void CServerConnectRem::HandlePacket(const CECPacket
*packet
)
753 CEC_ConnState_Tag
*tag
=
754 (CEC_ConnState_Tag
*)packet
->GetTagByName(EC_TAG_CONNSTATE
);
759 theApp
->m_ConnState
= 0;
761 m_ID
= tag
->GetEd2kId();
762 theApp
->m_clientID
= tag
->GetClientId();
764 if (tag
->IsConnectedED2K()) {
765 CECTag
*srvtag
= tag
->GetTagByName(EC_TAG_SERVER
);
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
;
779 if ( m_CurrServer
) {
780 theApp
->amuledlg
->m_serverwnd
->serverlistctrl
->
781 HighlightServer(m_CurrServer
, false);
786 if (tag
->IsConnectedKademlia()) {
787 if (tag
->IsKadFirewalled()) {
788 theApp
->m_ConnState
|= CONNECTED_KAD_FIREWALLED
;
790 theApp
->m_ConnState
|= CONNECTED_KAD_OK
;
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
);
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
)
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
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
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
881 void CServerListRem::ReloadControl()
883 for(iterator it
= begin(); it
!= end(); it
++) {
885 theApp
->amuledlg
->m_serverwnd
->serverlistctrl
->RefreshServer(srv
);
890 CIPFilterRem::CIPFilterRem(CRemoteConnect
* 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
);
915 CSharedFilesRem::CSharedFilesRem(CRemoteConnect
*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
);
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
);
981 uint32
CKnownFilesRem::GetItemID(CKnownFile
*file
)
987 void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag
*tag
, CKnownFile
*file
)
989 CECTag
*parttag
= tag
->GetTagByName(EC_TAG_PARTFILE_PART_STATUS
);
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
];
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;
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)
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
]);
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
);
1081 newFile
= new CKnownFile(tag
);
1082 ProcessItemUpdate(tag
, newFile
);
1083 (*theApp
->sharedfiles
)[id
] = newFile
;
1084 theApp
->amuledlg
->m_sharedfileswnd
->sharedfilesctrl
->ShowFile(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)
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;
1124 m_bEmuleProtocol
= false;
1136 m_identState
= IS_NOTAVAILABLE
;
1137 m_obfuscationStatus
= 0;
1139 m_nSourceFrom
= SF_NONE
;
1143 m_nCurSessionUp
= 0;
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());
1205 CUpDownClient::~CUpDownClient()
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
);
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
;
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
);
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
;
1256 if (tag
->SoftVerStr(client
->m_clientVerString
) || sw_updated
) {
1257 if (client
->m_clientVersionString
== _("Unknown")) {
1258 client
->m_fullClientVerString
= client
->m_clientVersionString
;
1260 client
->m_fullClientVerString
= client
->m_clientVersionString
+ wxT(" ") + client
->m_clientVerString
;
1264 tag
->UserHash(&client
->m_UserHash
);
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
);
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
);
1295 theApp
->m_allUploadingKnownFile
->RemoveUploadingClient(client
);
1299 tag
->SpeedUp(&client
->m_nUpDatarate
);
1300 if ( client
->m_nDownloadState
== DS_DOWNLOADING
) {
1301 tag
->SpeedDown(&client
->kBpsDown
);
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
;
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
);
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());
1361 if (!notified
&& client
->m_reqfile
&& client
->m_reqfile
->ShowSources()) {
1362 SourceItemType type
;
1363 switch (client
->GetDownloadState()) {
1364 case DS_DOWNLOADING
:
1366 // We will send A4AF, which will be checked.
1370 type
= UNAVAILABLE_SOURCE
;
1374 Notify_SourceCtrlUpdateSource(client
, type
);
1379 if (tag
->UploadFile(fileID
)) {
1380 if (client
->m_uploadingfile
) {
1381 client
->m_uploadingfile
->RemoveUploadingClient(client
); // this notifies
1383 client
->m_uploadingfile
= NULL
;
1384 //client->m_downPartStatus.clear();
1386 CKnownFile
* kf
= theApp
->knownfiles
->GetByID(fileID
);
1388 client
->m_uploadingfile
= kf
;
1389 client
->m_uploadingfile
->AddUploadingClient(client
); // this notifies
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()) {
1401 case US_ONUPLOADQUEUE
:
1402 type
= AVAILABLE_SOURCE
;
1405 type
= UNAVAILABLE_SOURCE
;
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
);
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)
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
)
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;
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
;
1495 ArrayOfUInts64 gaps
;
1496 encoder
.DecodeGaps(gaptag
, gaps
);
1497 int gap_size
= gaps
.size() / 2;
1499 file
->m_gaplist
.Init(file
->GetFileSize(), false);
1502 for (int j
= 0; j
< gap_size
; j
++) {
1503 file
->m_gaplist
.AddGap(gaps
[2*j
], gaps
[2*j
+1]);
1507 encoder
.DecodeParts(parttag
, file
->m_SrcpartFrequency
);
1509 wxASSERT (file
->m_SrcpartFrequency
.size() == file
->GetPartCount());
1512 ArrayOfUInts64 reqs
;
1513 encoder
.DecodeReqs(reqtag
, reqs
);
1514 int req_size
= reqs
.size() / 2;
1516 DeleteContents(file
->m_requestedblocks_list
);
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
);
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();
1538 SourcenameItem
&item
= map
[key
];
1540 const CECTag
*nametag
= it
->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES
);
1542 item
.name
= nametag
->GetStringData();
1549 CECTag
*commenttag
= tag
->GetTagByName(EC_TAG_PARTFILE_COMMENTS
);
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
);
1566 file
->ClearA4AFList();
1568 for (CECTag::const_iterator it
= a4aftag
->begin(); it
!= a4aftag
->end(); it
++) {
1569 if (it
->GetTagName() != EC_TAG_ECID
) { // should always be this
1572 uint32 id
= it
->GetInt();
1573 CUpDownClient
* src
= theApp
->clientlist
->GetByID(id
);
1575 file
->AddA4AFSource(src
);
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
++;
1586 CUpDownClient
* src
= theApp
->clientlist
->GetByID(id
);
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
)
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)
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;
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.
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());
1720 CRemoteContainer
<CSearchFile
, uint32
, CEC_SearchFile_Tag
>::HandlePacket(packet
);
1725 CSearchFile::CSearchFile(CEC_SearchFile_Tag
*tag
)
1729 m_showChildren(false),
1731 m_completeSourceCount(0),
1733 m_downloadStatus(NEW
),
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
);
1764 void CSearchListRem::DeleteItem(CSearchFile
*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
);
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
) {
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()) {
1824 // TODO: Should we assert in this case?
1825 static CSearchResultList 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()
1844 bool CUpDownClient::SwapToAnotherFile(
1845 bool WXUNUSED(bIgnoreNoNeeded
),
1846 bool WXUNUSED(ignoreSuspensions
),
1847 bool WXUNUSED(bRemoveCompletely
),
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
);
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*/)
1870 bool CKnownFile::LoadFromFile(const class CFileDataIO
*)
1877 void CKnownFile::UpdatePartsInfo()
1883 CPacket
* CPartFile::CreateSrcInfoPacket(CUpDownClient
const *, uint8
/*byRequestedVersion*/, uint16
/*nRequestedOptions*/)
1890 void CPartFile::UpdatePartsInfo()
1897 void CPartFile::UpdateFileRatingCommentAvail()
1899 bool prevComment
= m_hasComment
;
1900 int prevRating
= m_iUserRating
;
1902 m_hasComment
= false;
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
;
1916 wxASSERT(rating
<= 5);
1919 m_iUserRating
+= rating
;
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
);
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