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