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
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
37 #include "kademlia/utils/UInt128.h" // Needed for CUInt128
52 #include <wx/dialog.h>
54 class CEConnectDlg
: public wxDialog
{
59 wxString login
, passwd
;
60 bool m_save_user_pass
;
66 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 bool CreateCategory(Category_Struct
*& category
, const wxString
& name
, const CPath
& path
,
100 const wxString
& comment
, uint32 color
, uint8 prio
);
101 bool 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
;
129 // .size() is O(N) operation in stl
132 // use incremental tags algorithm
135 // command that will be used in full request
136 int m_full_req_cmd
, m_full_req_tag
;
138 virtual void HandlePacket(const CECPacket
*packet
)
140 switch(this->m_state
) {
141 case IDLE
: wxFAIL
; break; // not expecting anything
142 case STATUS_REQ_SENT
:
143 // if derived class choose not to proceed, return - but with good status
144 this->m_state
= IDLE
;
145 if ( this->Phase1Done(packet
) ) {
146 if (this->m_inc_tags
) {
147 // Incremental tags: new items always carry full info.
148 ProcessUpdate(packet
, NULL
, m_full_req_tag
);
150 // Non-incremental tags: we might get partial info on new items.
151 // Collect all this items in a tag, and then request full info about them.
152 CECPacket
req_full(this->m_full_req_cmd
);
154 ProcessUpdate(packet
, &req_full
, m_full_req_tag
);
156 // Phase 3: request full info about files we don't have yet
157 if ( req_full
.HasChildTags() ) {
158 m_conn
->SendRequest(this, &req_full
);
159 this->m_state
= FULL_REQ_SENT
;
171 CRemoteContainer(CRemoteConnect
*conn
, bool inc_tags
)
175 m_inc_tags(inc_tags
),
180 virtual ~CRemoteContainer()
183 typedef typename
std::list
<T
*>::iterator iterator
;
184 iterator
begin() { return m_items
.begin(); }
185 iterator
end() { return m_items
.end(); }
192 void AddItem(T
*item
)
194 m_items
.push_back(item
);
195 m_items_hash
[GetItemID(item
)] = item
;
201 // avoid creating nodes
202 return m_items_hash
.count(id
) ? m_items_hash
[id
] : NULL
;
208 m_items_hash
.clear();
216 We usually don't keep outdated code as comments, but this blocking implementation
217 shows the overall procedure well. It had to be scattered for the event driven implementation.
219 bool FullReload(int cmd)
222 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req));
223 if ( !reply.get() ) {
226 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
227 this->DeleteItem(*j);
232 ProcessFull(reply.get());
237 void FullReload(int cmd
)
239 if ( this->m_state
!= IDLE
) {
243 for(typename
std::list
<T
*>::iterator j
= this->m_items
.begin(); j
!= this->m_items
.end(); ++j
) {
244 this->DeleteItem(*j
);
250 this->m_conn
->SendRequest(this, &req
);
251 this->m_state
= FULL_REQ_SENT
;
252 this->m_full_req_cmd
= cmd
;
256 // Following are like basicly same code as in webserver. Eventually it must
259 void DoRequery(int cmd
, int tag
)
261 if ( this->m_state
!= IDLE
) {
264 CECPacket
req_sts(cmd
, m_inc_tags
? EC_DETAIL_INC_UPDATE
: EC_DETAIL_UPDATE
);
265 this->m_conn
->SendRequest(this, &req_sts
);
266 this->m_state
= STATUS_REQ_SENT
;
267 this->m_full_req_cmd
= cmd
;
268 this->m_full_req_tag
= tag
;
271 We usually don't keep outdated code as comments, but this blocking implementation
272 shows the overall procedure well. It had to be scattered for the event driven implementation.
274 bool DoRequery(int cmd, int tag)
276 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
279 // Phase 1: request status
280 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
281 if ( !reply.get() ) {
285 if ( !this->Phase1Done(reply.get()) ) {
286 // if derived class choose not to proceed, return - but with good status
290 // Phase 2: update status, mark new files for subsequent query
291 CECPacket req_full(cmd);
293 ProcessUpdate(reply.get(), &req_full, tag);
298 // Phase 3: request full info about files we don't have yet
299 if ( req_full.GetTagCount() ) {
300 reply.reset(this->m_conn->SendRecvPacket(&req_full));
301 if ( !reply.get() ) {
304 ProcessFull(reply.get());
311 void ProcessFull(const CECPacket
*reply
)
313 for (CECPacket::const_iterator it
= reply
->begin(); it
!= reply
->end(); ++it
) {
314 const G
*tag
= static_cast<const G
*>(&*it
);
315 // initialize item data from EC tag
316 AddItem(CreateItem(tag
));
320 void RemoveItem(iterator
& it
)
322 I item_id
= GetItemID(*it
);
326 m_items_hash
.erase(item_id
);
327 // item may contain data that need to be freed externally, before
328 // dtor is called and memory freed
334 virtual void ProcessUpdate(const CECTag
*reply
, CECPacket
*full_req
, int req_type
)
336 std::set
<I
> core_files
;
337 for (CECPacket::const_iterator it
= reply
->begin(); it
!= reply
->end(); ++it
) {
338 const G
*tag
= static_cast<const G
*>(&*it
);
339 if ( tag
->GetTagName() != req_type
) {
343 core_files
.insert(tag
->ID());
344 if ( m_items_hash
.count(tag
->ID()) ) {
345 // Item already known: update it
346 T
*item
= m_items_hash
[tag
->ID()];
347 ProcessItemUpdate(tag
, item
);
351 // Non-incremental mode: we have only partial info
352 // so we need to request full info before we can use the item
353 full_req
->AddTag(CECTag(req_type
, tag
->ID()));
355 // Incremental mode: new items always carry full info,
356 // so we can add it right away
357 AddItem(CreateItem(tag
));
361 for(iterator it
= begin(); it
!= end();) {
363 if ( core_files
.count(GetItemID(*it2
)) == 0 ) {
369 virtual T
*CreateItem(const G
*)
373 virtual void DeleteItem(T
*)
376 virtual I
GetItemID(T
*)
380 virtual void ProcessItemUpdate(const G
*, T
*)
384 virtual bool Phase1Done(const CECPacket
*)
390 class CServerConnectRem
{
391 CRemoteConnect
*m_Conn
;
394 CServer
*m_CurrServer
;
397 void HandlePacket(const CECPacket
*packet
);
399 CServerConnectRem(CRemoteConnect
*);
401 bool IsConnected() { return (m_ID
!= 0) && (m_ID
!= 0xffffffff); }
402 bool IsConnecting() { return m_ID
== 0xffffffff; }
403 bool IsLowID() { return m_ID
< 16777216; }
404 uint32
GetClientID() { return m_ID
; }
405 CServer
*GetCurrentServer() { return m_CurrServer
; }
410 void ConnectToServer(CServer
* server
);
411 void ConnectToAnyServer();
412 void StopConnectionTry();
416 class CServerListRem
: public CRemoteContainer
<CServer
, uint32
, CEC_Server_Tag
> {
417 uint32 m_TotalUser
, m_TotalFile
;
419 virtual void HandlePacket(const CECPacket
*packet
);
421 CServerListRem(CRemoteConnect
*);
422 void GetUserFileStatus(uint32
&total_user
, uint32
&total_file
)
424 total_user
= m_TotalUser
;
425 total_file
= m_TotalFile
;
428 void UpdateUserFileStatus(CServer
*server
);
430 CServer
* GetServerByAddress(const wxString
& address
, uint16 port
) const;
431 CServer
* GetServerByIPTCP(uint32 nIP
, uint16 nPort
) const;
436 void RemoveServer(CServer
* server
);
437 void UpdateServerMetFromURL(wxString url
);
438 void SetStaticServer(CServer
* server
, bool isStatic
);
439 void SetServerPrio(CServer
* server
, uint32 prio
);
440 void SaveServerMet() {} // not needed here
441 void FilterServers() {} // not needed here
446 CServer
*CreateItem(const CEC_Server_Tag
*);
447 void DeleteItem(CServer
*);
448 uint32
GetItemID(CServer
*);
449 void ProcessItemUpdate(const CEC_Server_Tag
*, CServer
*);
452 class CUpDownClientListRem
: public CRemoteContainer
<CClientRef
, uint32
, CEC_UpDownClient_Tag
> {
454 CUpDownClientListRem(CRemoteConnect
*);
456 void FilterQueues() {} // not needed here
460 CClientRef
*CreateItem(const CEC_UpDownClient_Tag
*);
461 void DeleteItem(CClientRef
*);
462 uint32
GetItemID(CClientRef
*);
463 void ProcessItemUpdate(const CEC_UpDownClient_Tag
*, CClientRef
*);
466 class CDownQueueRem
: public std::map
<uint32
, CPartFile
*> {
467 CRemoteConnect
*m_conn
;
469 CDownQueueRem(CRemoteConnect
* conn
) { m_conn
= conn
; }
471 CPartFile
* GetFileByID(uint32 id
);
476 void Prio(CPartFile
*file
, uint8 prio
);
477 void AutoPrio(CPartFile
*file
, bool flag
);
478 void Category(CPartFile
*file
, uint8 cat
);
480 void SendFileCommand(CPartFile
*file
, ec_tagname_t cmd
);
484 void StopUDPRequests() {}
485 void AddFileLinkToDownload(CED2KFileLink
*, uint8
);
486 bool AddLink(const wxString
&link
, uint8 category
= 0);
487 void UnsetCompletedFilesExist();
488 void ResetCatParts(int cat
);
489 void AddSearchToDownload(CSearchFile
* toadd
, uint8 category
);
490 void ClearCompleted(const ListOfUInts32
& ecids
);
493 class CSharedFilesRem
: public std::map
<uint32
, CKnownFile
*> {
494 CRemoteConnect
*m_conn
;
496 CSharedFilesRem(CRemoteConnect
* conn
);
498 CKnownFile
*GetFileByID(uint32 id
);
500 void SetFilePrio(CKnownFile
*file
, uint8 prio
);
505 void Reload(bool sendtoserver
= true, bool firstload
= false);
506 bool RenameFile(CKnownFile
* file
, const CPath
& newName
);
507 void SetFileCommentRating(CKnownFile
* file
, const wxString
& newComment
, int8 newRating
);
508 void CopyFileList(std::vector
<CKnownFile
*>& out_list
) const;
511 class CKnownFilesRem
: public CRemoteContainer
<CKnownFile
, uint32
, CEC_SharedFile_Tag
> {
512 CKnownFile
* CreateKnownFile(const CEC_SharedFile_Tag
*tag
, CKnownFile
*file
= NULL
);
513 CPartFile
* CreatePartFile(const CEC_PartFile_Tag
*tag
);
515 bool m_initialUpdate
; // improved handling for first data transfer
517 CKnownFilesRem(CRemoteConnect
* conn
);
519 CKnownFile
*FindKnownFileByID(uint32 id
) { return GetByID(id
); }
528 CKnownFile
*CreateItem(const CEC_SharedFile_Tag
*) { wxFAIL
; return NULL
; } // unused, required by template
529 void DeleteItem(CKnownFile
*);
530 uint32
GetItemID(CKnownFile
*);
531 void ProcessItemUpdate(const CEC_SharedFile_Tag
*, CKnownFile
*);
532 bool Phase1Done(const CECPacket
*) { return true; }
533 void ProcessUpdate(const CECTag
*reply
, CECPacket
*full_req
, int req_type
);
535 void ProcessItemUpdatePartfile(const CEC_PartFile_Tag
*, CPartFile
*);
539 CRemoteConnect
*m_conn
;
541 CIPFilterRem(CRemoteConnect
*conn
);
547 void Update(wxString strURL
= wxEmptyString
);
548 bool IsReady() const { return true; }
551 class CSearchListRem
: public CRemoteContainer
<CSearchFile
, uint32
, CEC_SearchFile_Tag
> {
552 virtual void HandlePacket(const CECPacket
*);
554 CSearchListRem(CRemoteConnect
*);
557 typedef std::map
<long, CSearchResultList
> ResultMap
;
560 const CSearchResultList
& GetSearchResults(long nSearchID
);
561 void RemoveResults(long nSearchID
);
562 const CSearchResultList
& GetSearchResults(long nSearchID
) const;
567 wxString
StartNewSearch(uint32
* nSearchID
, SearchType search_type
,
568 const CSearchList::CSearchParams
& params
);
570 void StopSearch(bool globalOnly
= false);
575 CSearchFile
*CreateItem(const CEC_SearchFile_Tag
*);
576 void DeleteItem(CSearchFile
*);
577 uint32
GetItemID(CSearchFile
*);
578 void ProcessItemUpdate(const CEC_SearchFile_Tag
*, CSearchFile
*);
579 bool Phase1Done(const CECPacket
*);
582 class CFriendListRem
: public CRemoteContainer
<CFriend
, uint32
, CEC_Friend_Tag
> {
583 virtual void HandlePacket(const CECPacket
*);
585 CFriendListRem(CRemoteConnect
*);
587 void AddFriend(const CClientRef
& toadd
);
588 void AddFriend(const CMD4Hash
& userhash
, uint32 lastUsedIP
, uint32 lastUsedPort
, const wxString
& name
);
589 void RemoveFriend(CFriend
* toremove
);
590 void RequestSharedFileList(CFriend
* Friend
);
591 void RequestSharedFileList(CClientRef
& client
);
592 void SetFriendSlot(CFriend
* Friend
, bool new_state
);
597 CFriend
*CreateItem(const CEC_Friend_Tag
*);
598 void DeleteItem(CFriend
*);
599 uint32
GetItemID(CFriend
*);
600 void ProcessItemUpdate(const CEC_Friend_Tag
*, CFriend
*);
603 class CStatsUpdaterRem
: public CECPacketHandlerBase
{
604 virtual void HandlePacket(const CECPacket
*);
606 CStatsUpdaterRem() {}
609 class CStatTreeRem
: public CECPacketHandlerBase
{
610 virtual void HandlePacket(const CECPacket
*);
611 CRemoteConnect
*m_conn
;
613 CStatTreeRem(CRemoteConnect
* conn
) { m_conn
= conn
; }
617 class CListenSocketRem
{
618 uint32 m_peak_connections
;
620 uint32
GetPeakConnections() { return m_peak_connections
; }
623 class CamuleRemoteGuiApp
: public wxApp
, public CamuleGuiBase
, public CamuleAppCommon
{
626 virtual int InitGui(bool geometry_enable
, wxString
&geometry_string
);
632 void OnPollTimer(wxTimerEvent
& evt
);
634 void OnECConnection(wxEvent
& event
);
635 void OnECInitDone(wxEvent
& event
);
636 void OnNotifyEvent(CMuleGUIEvent
& evt
);
637 void OnFinishedHTTPDownload(CMuleInternalEvent
& event
);
639 CStatsUpdaterRem m_stats_updater
;
644 bool ShowConnectionDialog();
646 class CRemoteConnect
*m_connect
;
648 CEConnectDlg
*dialog
;
650 bool CopyTextToClipboard(wxString strText
);
652 virtual int ShowAlert(wxString msg
, wxString title
, int flags
);
654 void ShutDown(wxCloseEvent
&evt
);
656 CPreferencesRem
*glob_prefs
;
659 CAsioService
* m_AsioService
;
663 // Provide access to core data thru EC
664 CServerConnectRem
*serverconnect
;
665 CServerListRem
*serverlist
;
666 CDownQueueRem
*downloadqueue
;
667 CSharedFilesRem
*sharedfiles
;
668 CKnownFilesRem
*knownfiles
;
669 CUpDownClientListRem
*clientlist
;
670 CIPFilterRem
*ipfilter
;
671 CSearchListRem
*searchlist
;
672 CFriendListRem
*friendlist
;
673 CListenSocketRem
*listensocket
;
674 CStatTreeRem
* stattree
;
676 CStatistics
*m_statistics
;
678 bool AddServer(CServer
*srv
, bool fromUser
= false);
680 uint32
GetPublicIP();
682 wxString
GetLog(bool reset
= false);
683 wxString
GetServerLog(bool reset
= false);
685 void AddServerMessageLine(wxString
&msg
);
686 void AddRemoteLogLine(const wxString
& line
);
688 void SetOSFiles(wxString
) { /* onlinesig is created on remote side */ }
690 bool IsConnected() const { return IsConnectedED2K() || IsConnectedKad(); }
691 bool IsFirewalled() const;
692 bool IsConnectedED2K() const;
693 bool IsConnectedKad() const
695 return ((m_ConnState
& CONNECTED_KAD_OK
)
696 || (m_ConnState
& CONNECTED_KAD_FIREWALLED
));
698 bool IsFirewalledKad() const { return (m_ConnState
& CONNECTED_KAD_FIREWALLED
) != 0; }
700 bool IsKadRunning() const { return ((m_ConnState
& CONNECTED_KAD_OK
)
701 || (m_ConnState
& CONNECTED_KAD_FIREWALLED
)
702 || (m_ConnState
& CONNECTED_KAD_NOT
)); }
704 // Check Kad state (UDP)
705 bool IsFirewalledKadUDP() const { return theStats::IsFirewalledKadUDP(); }
706 bool IsKadRunningInLanMode() const { return theStats::IsKadRunningInLanMode(); }
708 uint32
GetKadUsers() const { return theStats::GetKadUsers(); }
709 uint32
GetKadFiles() const { return theStats::GetKadFiles(); }
710 uint32
GetKadIndexedSources() const { return theStats::GetKadIndexedSources(); }
711 uint32
GetKadIndexedKeywords() const{ return theStats::GetKadIndexedKeywords(); }
712 uint32
GetKadIndexedNotes() const { return theStats::GetKadIndexedNotes(); }
713 uint32
GetKadIndexedLoad() const { return theStats::GetKadIndexedLoad(); }
714 const CUInt128
& GetKadID() const { return m_kadID
; }
715 // True IP of machine
716 uint32
GetKadIPAdress() const { return theStats::GetKadIPAdress(); }
718 uint8
GetBuddyStatus() const { return theStats::GetBuddyStatus(); }
719 uint32
GetBuddyIP() const { return theStats::GetBuddyIP(); }
720 uint32
GetBuddyPort() const { return theStats::GetBuddyPort(); }
725 /** Bootstraps kad from the specified IP (must be in hostorder). */
726 void BootstrapKad(uint32 ip
, uint16 port
);
727 /** Updates the nodes.dat file from the specified url. */
728 void UpdateNotesDat(const wxString
& str
);
730 void DisconnectED2K();
732 bool CryptoAvailable() const;
734 uint32
GetED2KID() const;
735 uint32
GetID() const;
736 void ShowUserCount();
742 // This KnownFile collects all currently uploading clients for display in the upload list control
743 CKnownFile
* m_allUploadingKnownFile
;
747 DECLARE_EVENT_TABLE()
750 DECLARE_APP(CamuleRemoteGuiApp
)
752 extern CamuleRemoteGuiApp
*theApp
;
754 #endif /* AMULE_REMOTE_GUI_H */
756 // File_checked_for_headers