Upstream tarball 10114
[amule.git] / src / amule-remote-gui.h
blob76b7c3279e6767aed16deb650707b2893a66a9d8
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 //
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
8 // respective authors.
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
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"
35 #include "RLE.h"
36 #include "SearchList.h" // Needed for CSearchFile
39 class CED2KFileLink;
40 class CServer;
41 class CKnownFile;
42 class CSearchFile;
43 class CPartFile;
44 class CUpDownClient;
45 class CStatistics;
46 class CPath;
48 class wxEvtHandler;
49 class wxTimer;
50 class wxTimerEvent;
52 #include <wx/dialog.h>
54 class CEConnectDlg : public wxDialog {
55 wxString host;
56 int port;
58 wxString pwd_hash;
59 wxString login, passwd;
60 bool m_save_user_pass;
62 DECLARE_EVENT_TABLE()
63 public:
64 CEConnectDlg();
66 void OnOK(wxCommandEvent& event);
68 wxString Host() { return host; }
69 int Port() { return port; }
71 wxString Login() { return login; }
72 wxString PassHash();
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 {
79 public:
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);
96 public:
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);
106 bool LoadRemote();
107 void SendToRemote();
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 {
117 protected:
118 enum {
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
122 } m_state;
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
130 int m_item_count;
132 // use incremental tags algorithm
133 bool m_inc_tags;
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; // 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);
149 } else {
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;
163 break;
164 case FULL_REQ_SENT:
165 ProcessFull(packet);
166 m_state = IDLE;
167 break;
170 public:
171 CRemoteContainer(CRemoteConnect *conn, bool inc_tags)
173 m_state = IDLE;
175 m_conn = conn;
176 m_item_count = 0;
177 m_inc_tags = inc_tags;
180 virtual ~CRemoteContainer()
184 typedef typename std::list<T *>::iterator iterator;
185 iterator begin() { return m_items.begin(); }
186 iterator end() { return m_items.end(); }
188 uint32 GetCount()
190 return m_item_count;
193 void AddItem(T *item)
195 m_items.push_back(item);
196 m_items_hash[GetItemID(item)] = item;
197 m_item_count++;
200 T *GetByID(I id)
202 // avoid creating nodes
203 return m_items_hash.count(id) ? m_items_hash[id] : NULL;
206 void Flush()
208 m_items.clear();
209 m_items_hash.clear();
210 m_item_count = 0;
214 // Flush & reload
217 We usually don't keep outdated code as comments, but this blocking implementation
218 shows the overall procedure well. It had to be scattered for the event driven implementation.
220 bool FullReload(int cmd)
222 CECPacket req(cmd);
223 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req));
224 if ( !reply.get() ) {
225 return false;
227 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
228 this->DeleteItem(*j);
231 Flush();
233 ProcessFull(reply.get());
235 return true;
238 void FullReload(int cmd)
240 if ( this->m_state != IDLE ) {
241 return;
244 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
245 this->DeleteItem(*j);
248 Flush();
250 CECPacket req(cmd);
251 this->m_conn->SendRequest(this, &req);
252 this->m_state = FULL_REQ_SENT;
253 this->m_full_req_cmd = cmd;
257 // Following are like basicly same code as in webserver. Eventually it must
258 // be same class
260 void DoRequery(int cmd, int tag)
262 if ( this->m_state != IDLE ) {
263 return;
265 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
266 this->m_conn->SendRequest(this, &req_sts);
267 this->m_state = STATUS_REQ_SENT;
268 this->m_full_req_cmd = cmd;
269 this->m_full_req_tag = tag;
272 We usually don't keep outdated code as comments, but this blocking implementation
273 shows the overall procedure well. It had to be scattered for the event driven implementation.
275 bool DoRequery(int cmd, int tag)
277 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
280 // Phase 1: request status
281 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
282 if ( !reply.get() ) {
283 return false;
286 if ( !this->Phase1Done(reply.get()) ) {
287 // if derived class choose not to proceed, return - but with good status
288 return true;
291 // Phase 2: update status, mark new files for subsequent query
292 CECPacket req_full(cmd);
294 ProcessUpdate(reply.get(), &req_full, tag);
296 reply.reset();
298 if ( !m_inc_tags ) {
299 // Phase 3: request full info about files we don't have yet
300 if ( req_full.GetTagCount() ) {
301 reply.reset(this->m_conn->SendRecvPacket(&req_full));
302 if ( !reply.get() ) {
303 return false;
305 ProcessFull(reply.get());
308 return true;
312 void ProcessFull(const CECPacket *reply)
314 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
315 G *tag = (G *) & *it;
316 // initialize item data from EC tag
317 AddItem(CreateItem(tag));
321 void RemoveItem(iterator & it)
323 I item_id = GetItemID(*it);
324 // reduce count
325 m_item_count--;
326 // remove from map
327 m_items_hash.erase(item_id);
328 // item may contain data that need to be freed externally, before
329 // dtor is called and memory freed
330 DeleteItem(*it);
332 m_items.erase(it);
335 virtual void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type)
337 std::set<I> core_files;
338 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) {
339 G *tag = (G *) & *it;
340 if ( tag->GetTagName() != req_type ) {
341 continue;
344 core_files.insert(tag->ID());
345 if ( m_items_hash.count(tag->ID()) ) {
346 // Item already known: update it
347 T *item = m_items_hash[tag->ID()];
348 ProcessItemUpdate(tag, item);
349 } else {
350 // New item
351 if (full_req) {
352 // Non-incremental mode: we have only partial info
353 // so we need to request full info before we can use the item
354 full_req->AddTag(CECTag(req_type, tag->ID()));
355 } else {
356 // Incremental mode: new items always carry full info,
357 // so we can add it right away
358 AddItem(CreateItem(tag));
362 for(iterator it = begin(); it != end();) {
363 iterator it2 = it++;
364 if ( core_files.count(GetItemID(*it2)) == 0 ) {
365 RemoveItem(it2);
370 virtual T *CreateItem(G *)
372 return 0;
374 virtual void DeleteItem(T *)
377 virtual I GetItemID(T *)
379 return I();
381 virtual void ProcessItemUpdate(G *, T *)
385 virtual bool Phase1Done(const CECPacket *)
387 return true;
391 class CServerConnectRem : public CECPacketHandlerBase {
392 CRemoteConnect *m_Conn;
393 uint32 m_ID;
395 CServer *m_CurrServer;
397 virtual void HandlePacket(const CECPacket *packet);
399 public:
400 CServerConnectRem(CRemoteConnect *);
401 bool ReQuery();
403 bool IsConnected() { return (m_ID != 0) && (m_ID != 0xffffffff); }
404 bool IsConnecting() { return m_ID == 0xffffffff; }
405 bool IsLowID() { return m_ID < 16777216; }
406 uint32 GetClientID() { return m_ID; }
407 CServer *GetCurrentServer() { return m_CurrServer; }
410 // Actions
412 void ConnectToServer(CServer* server);
413 void ConnectToAnyServer();
414 void StopConnectionTry();
415 void Disconnect();
418 class CServerListRem : public CRemoteContainer<CServer, uint32, CEC_Server_Tag> {
419 uint32 m_TotalUser, m_TotalFile;
421 virtual void HandlePacket(const CECPacket *packet);
422 public:
423 CServerListRem(CRemoteConnect *);
424 void GetUserFileStatus(uint32 &total_user, uint32 &total_file)
426 total_user = m_TotalUser;
427 total_file = m_TotalFile;
430 void UpdateUserFileStatus(CServer *server);
432 CServer* GetServerByAddress(const wxString& address, uint16 port) const;
433 CServer* GetServerByIPTCP(uint32 nIP, uint16 nPort) const;
435 void ReloadControl();
438 // Actions
440 void RemoveServer(CServer* server);
441 void UpdateServerMetFromURL(wxString url);
442 void SaveServerMet();
443 void FilterServers();
446 // template
448 CServer *CreateItem(CEC_Server_Tag *);
449 void DeleteItem(CServer *);
450 uint32 GetItemID(CServer *);
451 void ProcessItemUpdate(CEC_Server_Tag *, CServer *);
454 class CUpDownClientListRem : public CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag> {
455 int m_viewtype;
456 public:
457 CUpDownClientListRem(CRemoteConnect *, int viewtype);
459 const CClientPtrList& GetList() const { return m_items; };
462 // template
464 CUpDownClient *CreateItem(CEC_UpDownClient_Tag *);
465 void DeleteItem(CUpDownClient *);
466 uint32 GetItemID(CUpDownClient *);
467 void ProcessItemUpdate(CEC_UpDownClient_Tag *, CUpDownClient *);
470 class CUpQueueRem {
471 CUpDownClientListRem m_up_list, m_wait_list;
472 public:
473 CUpQueueRem(CRemoteConnect *);
475 void ReQueryUp() { m_up_list.DoRequery(EC_OP_GET_ULOAD_QUEUE, EC_TAG_CLIENT); }
476 void ReQueryWait() { m_wait_list.DoRequery(EC_OP_GET_WAIT_QUEUE, EC_TAG_CLIENT); }
478 const CClientPtrList& GetWaitingList() const { return m_wait_list.GetList(); }
479 const CClientPtrList& GetUploadingList() const { return m_up_list.GetList(); }
480 uint16 GetWaitingPosition(const CUpDownClient *client) const;
483 class CDownQueueRem : public std::map<uint32, CPartFile*> {
484 CRemoteConnect *m_conn;
485 public:
486 CDownQueueRem(CRemoteConnect * conn) { m_conn = conn; }
488 CPartFile* GetFileByID(uint32 id);
489 CPartFile* GetFileByIndex(unsigned int idx); // to be deleted when GUI is unlocked!
490 uint32 GetFileCount() { return size(); } // this too !
493 // User actions
495 void Prio(CPartFile *file, uint8 prio);
496 void AutoPrio(CPartFile *file, bool flag);
497 void Category(CPartFile *file, uint8 cat);
499 void SendFileCommand(CPartFile *file, ec_tagname_t cmd);
501 // Actions
503 void StopUDPRequests() {}
504 void AddFileLinkToDownload(CED2KFileLink*, uint8);
505 bool AddLink(const wxString &link, uint8 category = 0);
506 void UnsetCompletedFilesExist();
507 void ResetCatParts(int cat);
508 void AddSearchToDownload(CSearchFile* toadd, uint8 category);
511 class CSharedFilesRem : public std::map<uint32, CKnownFile*> {
512 CRemoteConnect *m_conn;
513 public:
514 CSharedFilesRem(CRemoteConnect * conn);
516 CKnownFile *GetFileByID(uint32 id);
518 void SetFilePrio(CKnownFile *file, uint8 prio);
521 // Actions
523 void AddFilesFromDirectory(const CPath&);
524 void Reload(bool sendtoserver = true, bool firstload = false);
525 bool RenameFile(CKnownFile* file, const CPath& newName);
528 class CKnownFilesRem : public CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag> {
529 CKnownFile * CreateKnownFile(CEC_SharedFile_Tag *tag, CKnownFile *file = NULL);
530 CPartFile * CreatePartFile(CEC_PartFile_Tag *tag);
532 public:
533 CKnownFilesRem(CRemoteConnect * conn);
535 CKnownFile *FindKnownFileByID(uint32 id) { return GetByID(id); }
537 uint16 requested;
538 uint32 transferred;
539 uint16 accepted;
542 // template
544 CKnownFile *CreateItem(CEC_SharedFile_Tag *) { wxFAIL; return NULL; } // unused, required by template
545 void DeleteItem(CKnownFile *);
546 uint32 GetItemID(CKnownFile *);
547 void ProcessItemUpdate(CEC_SharedFile_Tag *, CKnownFile *);
548 bool Phase1Done(const CECPacket *) { return true; }
549 void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type);
551 void ProcessItemUpdatePartfile(CEC_PartFile_Tag *, CPartFile *);
554 class CClientListRem {
555 CRemoteConnect *m_conn;
558 // map of user_ID -> client
559 std::multimap<uint32, CUpDownClient*> m_client_list;
560 public:
561 CClientListRem(CRemoteConnect *);
563 const std::multimap<uint32, CUpDownClient*>& GetClientList() { return m_client_list; }
566 // Actions
568 void AddClient(CUpDownClient *);
569 void FilterQueues();
572 class CIPFilterRem {
573 CRemoteConnect *m_conn;
574 public:
575 CIPFilterRem(CRemoteConnect *conn);
578 // Actions
580 void Reload();
581 void Update(wxString strURL = wxEmptyString);
584 class CSearchListRem : public CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag> {
585 virtual void HandlePacket(const CECPacket *);
586 public:
587 CSearchListRem(CRemoteConnect *);
589 int m_curr_search;
590 typedef std::map<long, CSearchResultList> ResultMap;
591 ResultMap m_results;
593 const CSearchResultList& GetSearchResults(long nSearchID);
594 void RemoveResults(long nSearchID);
595 const CSearchResultList& GetSearchResults(long nSearchID) const;
597 // Actions
600 wxString StartNewSearch(uint32* nSearchID, SearchType search_type,
601 const CSearchList::CSearchParams& params);
603 void StopGlobalSearch();
604 void StopKadSearch();
607 // template
609 CSearchFile *CreateItem(CEC_SearchFile_Tag *);
610 void DeleteItem(CSearchFile *);
611 uint32 GetItemID(CSearchFile *);
612 void ProcessItemUpdate(CEC_SearchFile_Tag *, CSearchFile *);
613 bool Phase1Done(const CECPacket *);
616 class CStatsUpdaterRem : public CECPacketHandlerBase {
617 virtual void HandlePacket(const CECPacket *);
618 public:
619 CStatsUpdaterRem() {}
622 class CListenSocketRem {
623 uint32 m_peak_connections;
624 public:
625 uint32 GetPeakConnections() { return m_peak_connections; }
628 class CamuleRemoteGuiApp : public wxApp, public CamuleGuiBase, public CamuleAppCommon {
629 wxTimer* poll_timer;
631 virtual int InitGui(bool geometry_enable, wxString &geometry_string);
633 bool OnInit();
635 int OnExit();
637 void OnPollTimer(wxTimerEvent& evt);
639 void OnECConnection(wxEvent& event);
640 void OnECInitDone(wxEvent& event);
641 void OnNotifyEvent(CMuleGUIEvent& evt);
642 void OnFinishedHTTPDownload(CMuleInternalEvent& event);
644 CStatsUpdaterRem m_stats_updater;
645 public:
647 void Startup();
649 bool ShowConnectionDialog();
651 class CRemoteConnect *m_connect;
653 CEConnectDlg *dialog;
655 bool CopyTextToClipboard(wxString strText);
657 virtual int ShowAlert(wxString msg, wxString title, int flags);
659 void ShutDown(wxCloseEvent &evt);
661 CPreferencesRem *glob_prefs;
664 // Provide access to core data thru EC
665 CServerConnectRem *serverconnect;
666 CServerListRem *serverlist;
667 CUpQueueRem *uploadqueue;
668 CDownQueueRem *downloadqueue;
669 CSharedFilesRem *sharedfiles;
670 CKnownFilesRem *knownfiles;
671 CClientListRem *clientlist;
672 CIPFilterRem *ipfilter;
673 CSearchListRem *searchlist;
674 CListenSocketRem *listensocket;
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 // Kad stats
707 uint32 GetKadUsers() const { return theStats::GetKadUsers(); }
708 uint32 GetKadFiles() const { return theStats::GetKadFiles(); }
709 uint32 GetKadIndexedSources() const { return theStats::GetKadIndexedSources(); }
710 uint32 GetKadIndexedKeywords() const{ return theStats::GetKadIndexedKeywords(); }
711 uint32 GetKadIndexedNotes() const { return theStats::GetKadIndexedNotes(); }
712 uint32 GetKadIndexedLoad() const { return theStats::GetKadIndexedLoad(); }
713 // True IP of machine
714 uint32 GetKadIPAdress() const { return theStats::GetKadIPAdress(); }
715 // Buddy status
716 uint8 GetBuddyStatus() const { return theStats::GetBuddyStatus(); }
717 uint32 GetBuddyIP() const { return theStats::GetBuddyIP(); }
718 uint32 GetBuddyPort() const { return theStats::GetBuddyPort(); }
720 void StartKad();
721 void StopKad();
723 /** Bootstraps kad from the specified IP (must be in hostorder). */
724 void BootstrapKad(uint32 ip, uint16 port);
725 /** Updates the nodes.dat file from the specified url. */
726 void UpdateNotesDat(const wxString& str);
728 void DisconnectED2K();
730 bool CryptoAvailable() const;
732 uint32 GetED2KID() const;
733 uint32 GetID() const;
734 void ShowUserCount();
736 uint8 m_ConnState;
737 uint32 m_clientID;
739 wxLocale m_locale;
741 DECLARE_EVENT_TABLE()
744 DECLARE_APP(CamuleRemoteGuiApp)
746 extern CamuleRemoteGuiApp *theApp;
748 #endif /* AMULE_REMOTE_GUI_H */
750 // File_checked_for_headers