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
25 #ifndef AMULE_REMOTE_GUI_H
26 #define AMULE_REMOTE_GUI_H
29 #include <ec/cpp/RemoteConnect.h> // Needed for CRemoteConnect
32 #include "Statistics.h"
33 #include "Preferences.h"
34 #include "Statistics.h"
36 #include "SearchList.h" // Needed for CSearchFile
52 #include <wx/dialog.h>
54 class CEConnectDlg
: public wxDialog
{
59 wxString login
, passwd
;
60 bool m_save_user_pass
;
62 void OnOK(wxCommandEvent
& event
);
68 wxString
Host() { return host
; }
69 int Port() { return port
; }
71 wxString
Login() { return login
; }
73 bool SaveUserPass() { return m_save_user_pass
; }
76 DECLARE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE
, wxEVT_USER_FIRST
+ 1001)
78 class wxECInitDoneEvent
: public wxEvent
{
80 wxECInitDoneEvent() : wxEvent(-1, wxEVT_EC_INIT_DONE
)
84 wxEvent
*Clone(void) const
86 return new wxECInitDoneEvent(*this);
90 class CPreferencesRem
: public CPreferences
, public CECPacketHandlerBase
{
91 CRemoteConnect
*m_conn
;
92 uint32 m_exchange_send_selected_prefs
;
93 uint32 m_exchange_recv_selected_prefs
;
95 virtual void HandlePacket(const CECPacket
*packet
);
97 CPreferencesRem(CRemoteConnect
*);
99 Category_Struct
*CreateCategory(const wxString
& name
, const CPath
& path
,
100 const wxString
& comment
, uint32 color
, uint8 prio
);
101 void UpdateCategory(uint8 cat
, const wxString
& name
, const CPath
& path
,
102 const wxString
& comment
, uint32 color
, uint8 prio
);
104 void RemoveCat(uint8 cat
);
111 // T - type if item in container
112 // I - type of id of item
113 // G - type of tag used to create/update items
115 template <class T
, class I
, class G
= CECTag
>
116 class CRemoteContainer
: public CECPacketHandlerBase
{
119 IDLE
, // no request in the air
120 STATUS_REQ_SENT
, // sent request for item status
121 FULL_REQ_SENT
// sent request for full info
124 CRemoteConnect
*m_conn
;
126 std::list
<T
*> m_items
;
127 std::map
<I
, T
*> m_items_hash
;
130 std::vector
<T
*> m_idx_items
;
132 // .size() is O(N) operation in stl
135 // use incremental tags algorithm
138 // command that will be used in full request
139 int m_full_req_cmd
, m_full_req_tag
;
141 virtual void HandlePacket(const CECPacket
*packet
)
143 switch(this->m_state
) {
144 case IDLE
: wxFAIL
; // not expecting anything
145 case STATUS_REQ_SENT
:
146 // if derived class choose not to proceed, return - but with good status
147 this->m_state
= IDLE
;
148 if ( this->Phase1Done(packet
) ) {
149 CECPacket
req_full(this->m_full_req_cmd
);
151 ProcessUpdate(packet
, &req_full
, m_full_req_tag
);
153 if ( !this->m_inc_tags
) {
154 // Phase 3: request full info about files we don't have yet
155 if ( req_full
.GetTagCount() ) {
156 m_conn
->SendRequest(this, &req_full
);
157 this->m_state
= FULL_REQ_SENT
;
169 CRemoteContainer(CRemoteConnect
*conn
, bool /*inc_tags*/ = false)
177 // The CRemoteContainer has two ways of transfer: with "inc_tags" or without.
178 // I found that with inc_tags the update of transferred/completed is broken,
179 // therefore I disabled them.
180 // Either the inc-tag-mode should be fixed (but I can't to that without some
181 // more insight how it's supposed to be working), or removed alltogether.
182 //m_inc_tags = inc_tags;
186 virtual ~CRemoteContainer()
195 void AddItem(T
*item
)
197 m_items
.push_back(item
);
198 m_items_hash
[GetItemID(item
)] = item
;
199 m_idx_items
.resize(m_item_count
+1);
200 m_idx_items
[m_item_count
] = item
;
206 // avoid creating nodes
207 return m_items_hash
.count(id
) ? m_items_hash
[id
] : NULL
;
210 T
*GetByIndex(int index
)
212 return ( (index
>= 0) && (index
< m_item_count
) ) ? m_idx_items
[index
] : NULL
;
217 m_items
.erase(this->m_items
.begin(), this->m_items
.end());
218 m_items_hash
.erase(this->m_items_hash
.begin(), this->m_items_hash
.end());
226 bool FullReload(int cmd)
229 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req));
230 if ( !reply.get() ) {
233 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
234 this->DeleteItem(*j);
239 ProcessFull(reply.get());
244 void FullReload(int cmd
)
246 if ( this->m_state
!= IDLE
) {
250 for(typename
std::list
<T
*>::iterator j
= this->m_items
.begin(); j
!= this->m_items
.end(); j
++) {
251 this->DeleteItem(*j
);
257 this->m_conn
->SendRequest(this, &req
);
258 this->m_state
= FULL_REQ_SENT
;
259 this->m_full_req_cmd
= cmd
;
263 // Following are like basicly same code as in webserver. Eventually it must
266 void DoRequery(int cmd
, int tag
)
268 if ( this->m_state
!= IDLE
) {
271 CECPacket
req_sts(cmd
, m_inc_tags
? EC_DETAIL_INC_UPDATE
: EC_DETAIL_UPDATE
);
272 this->m_conn
->SendRequest(this, &req_sts
);
273 this->m_state
= STATUS_REQ_SENT
;
274 this->m_full_req_cmd
= cmd
;
275 this->m_full_req_tag
= tag
;
278 bool DoRequery(int cmd, int tag)
280 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
283 // Phase 1: request status
284 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
285 if ( !reply.get() ) {
289 if ( !this->Phase1Done(reply.get()) ) {
290 // if derived class choose not to proceed, return - but with good status
294 // Phase 2: update status, mark new files for subsequent query
295 CECPacket req_full(cmd);
297 ProcessUpdate(reply.get(), &req_full, tag);
302 // Phase 3: request full info about files we don't have yet
303 if ( req_full.GetTagCount() ) {
304 reply.reset(this->m_conn->SendRecvPacket(&req_full));
305 if ( !reply.get() ) {
308 ProcessFull(reply.get());
315 void ProcessFull(const CECPacket
*reply
)
317 for (size_t i
= 0;i
< reply
->GetTagCount();i
++) {
318 G
*tag
= (G
*)reply
->GetTagByIndex(i
);
319 // initialize item data from EC tag
320 T
*item
= this->CreateItem(tag
);
325 void ProcessUpdate(const CECPacket
*reply
, CECPacket
*full_req
, int req_type
)
327 std::set
<I
> core_files
;
328 for (size_t i
= 0;i
< reply
->GetTagCount();i
++) {
329 G
*tag
= (G
*)reply
->GetTagByIndex(i
);
330 if ( tag
->GetTagName() != req_type
) {
334 core_files
.insert(tag
->ID());
335 if ( m_items_hash
.count(tag
->ID()) ) {
336 T
*item
= m_items_hash
[tag
->ID()];
337 ProcessItemUpdate(tag
, item
);
340 T
*item
= this->CreateItem(tag
);
343 full_req
->AddTag(CECTag(req_type
, tag
->ID()));
347 std::list
<I
> del_ids
;
348 for(typename
std::list
<T
*>::iterator j
= this->m_items
.begin(); j
!= this->m_items
.end(); j
++) {
349 I item_id
= GetItemID(*j
);
350 if ( core_files
.count(item_id
) == 0 ) {
351 del_ids
.push_back(item_id
);
354 for(typename
std::list
<I
>::iterator j
= del_ids
.begin(); j
!= del_ids
.end(); j
++) {
355 for(int idx
= 0;idx
< m_item_count
;idx
++) {
356 if ( this->GetItemID(m_idx_items
[idx
]) == *j
) {
357 m_idx_items
[idx
] = m_idx_items
[m_item_count
-1];
362 m_items_hash
.erase(*j
);
363 for(typename
std::list
<T
*>::iterator k
= this->m_items
.begin(); k
!= this->m_items
.end(); k
++) {
364 if ( *j
== GetItemID(*k
) ) {
365 // item may contain data that need to be freed externally, before
366 // dtor is called and memory freed
367 this->DeleteItem(*k
);
369 this->m_items
.erase(k
);
377 virtual T
*CreateItem(G
*)
381 virtual void DeleteItem(T
*)
384 virtual I
GetItemID(T
*)
388 virtual void ProcessItemUpdate(G
*, T
*)
392 virtual bool Phase1Done(const CECPacket
*)
398 class CServerConnectRem
: public CECPacketHandlerBase
{
399 CRemoteConnect
*m_Conn
;
402 CServer
*m_CurrServer
;
404 virtual void HandlePacket(const CECPacket
*packet
);
407 CServerConnectRem(CRemoteConnect
*);
410 bool IsConnected() { return (m_ID
!= 0) && (m_ID
!= 0xffffffff); }
411 bool IsConnecting() { return m_ID
== 0xffffffff; }
412 bool IsLowID() { return m_ID
< 16777216; }
413 uint32
GetClientID() { return m_ID
; }
414 CServer
*GetCurrentServer() { return m_CurrServer
; }
419 void ConnectToServer(CServer
* server
);
420 void ConnectToAnyServer();
421 void StopConnectionTry();
425 class CServerListRem
: public CRemoteContainer
<CServer
, uint32
, CEC_Server_Tag
> {
426 uint32 m_TotalUser
, m_TotalFile
;
428 virtual void HandlePacket(const CECPacket
*packet
);
430 CServerListRem(CRemoteConnect
*);
431 void GetUserFileStatus(uint32
&total_user
, uint32
&total_file
)
433 total_user
= m_TotalUser
;
434 total_file
= m_TotalFile
;
437 void UpdateUserFileStatus(CServer
*server
);
439 CServer
* GetServerByAddress(const wxString
& address
, uint16 port
) const;
440 CServer
* GetServerByIPTCP(uint32 nIP
, uint16 nPort
) const;
442 void ReloadControl();
447 void RemoveServer(CServer
* server
);
448 void UpdateServerMetFromURL(wxString url
);
449 void SaveServerMet();
450 void FilterServers();
455 CServer
*CreateItem(CEC_Server_Tag
*);
456 void DeleteItem(CServer
*);
457 uint32
GetItemID(CServer
*);
458 void ProcessItemUpdate(CEC_Server_Tag
*, CServer
*);
461 class CUpDownClientListRem
: public CRemoteContainer
<CUpDownClient
, uint32
, CEC_UpDownClient_Tag
> {
464 CUpDownClientListRem(CRemoteConnect
*, int viewtype
);
466 const CClientPtrList
& GetList() const { return m_items
; };
471 CUpDownClient
*CreateItem(CEC_UpDownClient_Tag
*);
472 void DeleteItem(CUpDownClient
*);
473 uint32
GetItemID(CUpDownClient
*);
474 void ProcessItemUpdate(CEC_UpDownClient_Tag
*, CUpDownClient
*);
478 CUpDownClientListRem m_up_list
, m_wait_list
;
480 CUpQueueRem(CRemoteConnect
*);
482 void ReQueryUp() { m_up_list
.DoRequery(EC_OP_GET_ULOAD_QUEUE
, EC_TAG_CLIENT
); }
483 void ReQueryWait() { m_wait_list
.DoRequery(EC_OP_GET_WAIT_QUEUE
, EC_TAG_CLIENT
); }
485 const CClientPtrList
& GetWaitingList() const { return m_wait_list
.GetList(); }
486 const CClientPtrList
& GetUploadingList() const { return m_up_list
.GetList(); }
487 uint16
GetWaitingPosition(const CUpDownClient
*client
) const;
490 class CDownQueueRem
: public CRemoteContainer
<CPartFile
, CMD4Hash
, CEC_PartFile_Tag
> {
491 std::map
<CMD4Hash
, PartFileEncoderData
> m_enc_map
;
493 CDownQueueRem(CRemoteConnect
*);
495 uint32
GetFileCount() { return GetCount(); }
496 CPartFile
* GetFileByID(const CMD4Hash
& id
) { return GetByID(id
); }
497 CPartFile
* GetFileByIndex(unsigned int idx
) { return GetByIndex(idx
); }
499 bool IsPartFile(const CKnownFile
* totest
) const;
500 void OnConnectionState(bool bConnected
);
505 void Prio(CPartFile
*file
, uint8 prio
);
506 void AutoPrio(CPartFile
*file
, bool flag
);
507 void Category(CPartFile
*file
, uint8 cat
);
509 void SendFileCommand(CPartFile
*file
, ec_tagname_t cmd
);
513 void StopUDPRequests();
514 void AddFileLinkToDownload(CED2KFileLink
*, uint8
);
515 bool AddLink(const wxString
&link
, int category
= 0);
516 void UnsetCompletedFilesExist();
517 void ResetCatParts(int cat
);
518 void AddSearchToDownload(CSearchFile
* toadd
, uint8 category
);
523 CPartFile
*CreateItem(CEC_PartFile_Tag
*);
524 void DeleteItem(CPartFile
*);
525 CMD4Hash
GetItemID(CPartFile
*);
526 void ProcessItemUpdate(CEC_PartFile_Tag
*, CPartFile
*);
527 bool Phase1Done(const CECPacket
*);
530 class CSharedFilesRem
: public CRemoteContainer
<CKnownFile
, CMD4Hash
, CEC_SharedFile_Tag
> {
531 std::map
<CMD4Hash
, RLE_Data
> m_enc_map
;
533 virtual void HandlePacket(const CECPacket
*);
536 // For file renaming operation
538 CKnownFile
* m_rename_file
;
541 CSharedFilesRem(CRemoteConnect
*);
543 CKnownFile
*GetFileByID(CMD4Hash id
) { return GetByID(id
); }
545 void SetFilePrio(CKnownFile
*file
, uint8 prio
);
550 void AddFilesFromDirectory(const CPath
&);
551 void Reload(bool sendtoserver
= true, bool firstload
= false);
552 bool RenameFile(CKnownFile
* file
, const CPath
& newName
);
557 CKnownFile
*CreateItem(CEC_SharedFile_Tag
*);
558 void DeleteItem(CKnownFile
*);
559 CMD4Hash
GetItemID(CKnownFile
*);
560 void ProcessItemUpdate(CEC_SharedFile_Tag
*, CKnownFile
*);
561 bool Phase1Done(const CECPacket
*);
564 class CKnownFilesRem
{
565 CSharedFilesRem
*m_shared_files
;
567 CKnownFilesRem(CSharedFilesRem
*shared
)
569 m_shared_files
= shared
;
576 CKnownFile
*FindKnownFileByID(const CMD4Hash
& id
)
578 return m_shared_files
->GetByID(id
);
586 class CClientListRem
{
587 CRemoteConnect
*m_conn
;
590 // map of user_ID -> client
591 std::multimap
<uint32
, CUpDownClient
*> m_client_list
;
593 CClientListRem(CRemoteConnect
*);
595 const std::multimap
<uint32
, CUpDownClient
*>& GetClientList() { return m_client_list
; }
600 void AddClient(CUpDownClient
*);
605 CRemoteConnect
*m_conn
;
607 CIPFilterRem(CRemoteConnect
*conn
);
613 void Update(wxString strURL
= wxEmptyString
);
616 class CSearchListRem
: public CRemoteContainer
<CSearchFile
, CMD4Hash
, CEC_SearchFile_Tag
> {
617 virtual void HandlePacket(const CECPacket
*);
619 CSearchListRem(CRemoteConnect
*);
622 typedef std::map
<long, CSearchResultList
> ResultMap
;
625 const CSearchResultList
& GetSearchResults(long nSearchID
);
626 void RemoveResults(long nSearchID
);
627 const CSearchResultList
& GetSearchResults(long nSearchID
) const;
632 wxString
StartNewSearch(uint32
* nSearchID
, SearchType search_type
,
633 const CSearchList::CSearchParams
& params
);
635 void StopGlobalSearch();
640 CSearchFile
*CreateItem(CEC_SearchFile_Tag
*);
641 void DeleteItem(CSearchFile
*);
642 CMD4Hash
GetItemID(CSearchFile
*);
643 void ProcessItemUpdate(CEC_SearchFile_Tag
*, CSearchFile
*);
644 bool Phase1Done(const CECPacket
*);
647 class CStatsUpdaterRem
: public CECPacketHandlerBase
{
648 virtual void HandlePacket(const CECPacket
*);
650 CStatsUpdaterRem() {}
653 class CListenSocketRem
{
654 uint32 m_peak_connections
;
656 uint32
GetPeakConnections() { return m_peak_connections
; }
659 class CamuleRemoteGuiApp
: public wxApp
, public CamuleGuiBase
{
662 virtual int InitGui(bool geometry_enable
, wxString
&geometry_string
);
668 void OnPollTimer(wxTimerEvent
& evt
);
670 void OnECConnection(wxEvent
& event
);
671 void OnECInitDone(wxEvent
& event
);
672 void OnNotifyEvent(CMuleGUIEvent
& evt
);
673 void OnFinishedHTTPDownload(CMuleInternalEvent
& event
);
675 CStatsUpdaterRem m_stats_updater
;
680 bool ShowConnectionDialog();
682 class CRemoteConnect
*m_connect
;
684 CEConnectDlg
*dialog
;
686 bool CopyTextToClipboard(wxString strText
);
688 virtual void ShowAlert(wxString msg
, wxString title
, int flags
);
690 void ShutDown(wxCloseEvent
&evt
);
692 CPreferencesRem
*glob_prefs
;
696 // Provide access to core data thru EC
697 CServerConnectRem
*serverconnect
;
698 CServerListRem
*serverlist
;
699 CUpQueueRem
*uploadqueue
;
700 CDownQueueRem
*downloadqueue
;
701 CSharedFilesRem
*sharedfiles
;
702 CKnownFilesRem
*knownfiles
;
703 CClientListRem
*clientlist
;
704 CIPFilterRem
*ipfilter
;
705 CSearchListRem
*searchlist
;
706 CListenSocketRem
*listensocket
;
708 CStatistics
*m_statistics
;
710 bool AddServer(CServer
*srv
, bool fromUser
= false);
712 uint32
GetPublicIP();
713 wxString
CreateMagnetLink(const CAbstractFile
*f
);
714 wxString
CreateED2kLink(const CAbstractFile
* f
, bool add_source
= false, bool use_hostname
= false, bool addcryptoptions
= false);
715 wxString
CreateED2kAICHLink(const CKnownFile
* f
);
717 wxString
GetLog(bool reset
= false);
718 wxString
GetServerLog(bool reset
= false);
720 void AddServerMessageLine(wxString
&msg
);
721 void AddRemoteLogLine(const wxString
& line
);
723 void SetOSFiles(wxString
) { /* onlinesig is created on remote side */ }
725 bool IsConnected() const { return IsConnectedED2K() || IsConnectedKad(); }
726 bool IsFirewalled() const;
727 bool IsConnectedED2K() const;
728 bool IsConnectedKad() const
730 return ((m_ConnState
& CONNECTED_KAD_OK
)
731 || (m_ConnState
& CONNECTED_KAD_FIREWALLED
));
733 bool IsFirewalledKad() const { return (m_ConnState
& CONNECTED_KAD_FIREWALLED
) != 0; }
735 bool IsKadRunning() const { return ((m_ConnState
& CONNECTED_KAD_OK
)
736 || (m_ConnState
& CONNECTED_KAD_FIREWALLED
)
737 || (m_ConnState
& CONNECTED_KAD_NOT
)); }
739 // Check Kad state (UDP)
740 bool IsFirewalledKadUDP() const { return theStats::IsFirewalledKadUDP(); }
742 uint32
GetKadUsers() const { return theStats::GetKadUsers(); }
743 uint32
GetKadFiles() const { return theStats::GetKadFiles(); }
744 uint32
GetKadIndexedSources() const { return theStats::GetKadIndexedSources(); }
745 uint32
GetKadIndexedKeywords() const{ return theStats::GetKadIndexedKeywords(); }
746 uint32
GetKadIndexedNotes() const { return theStats::GetKadIndexedNotes(); }
747 uint32
GetKadIndexedLoad() const { return theStats::GetKadIndexedLoad(); }
748 // True IP of machine
749 uint32
GetKadIPAdress() const { return theStats::GetKadIPAdress(); }
751 uint8
GetBuddyStatus() const { return theStats::GetBuddyStatus(); }
752 uint32
GetBuddyIP() const { return theStats::GetBuddyIP(); }
753 uint32
GetBuddyPort() const { return theStats::GetBuddyPort(); }
758 /** Bootstraps kad from the specified IP (must be in hostorder). */
759 void BootstrapKad(uint32 ip
, uint16 port
);
760 /** Updates the nodes.dat file from the specified url. */
761 void UpdateNotesDat(const wxString
& str
);
763 void DisconnectED2K();
765 bool CryptoAvailable() const;
767 uint32
GetED2KID() const;
768 uint32
GetID() const;
769 void ShowUserCount();
776 DECLARE_EVENT_TABLE()
779 DECLARE_APP(CamuleRemoteGuiApp
)
780 #ifdef AMULE_REMOTE_GUI_CPP
781 CamuleRemoteGuiApp
*theApp
;
783 extern CamuleRemoteGuiApp
*theApp
;
787 #endif /* AMULE_REMOTE_GUI_H */
789 // File_checked_for_headers