Upstream tarball 10059
[amule.git] / src / amule-remote-gui.h
blob51f03cf045231037c5a1c9a3dfc6016aeab561a5
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 // for GetByIndex
130 // fixme, remove this when GUI is unlocked (replace with iterator)
131 std::vector<T *> m_idx_items;
133 // .size() is O(N) operation in stl
134 int m_item_count;
136 // use incremental tags algorithm
137 bool m_inc_tags;
139 // command that will be used in full request
140 int m_full_req_cmd, m_full_req_tag;
142 virtual void HandlePacket(const CECPacket *packet)
144 switch(this->m_state) {
145 case IDLE: wxFAIL; // not expecting anything
146 case STATUS_REQ_SENT:
147 // if derived class choose not to proceed, return - but with good status
148 this->m_state = IDLE;
149 if ( this->Phase1Done(packet) ) {
150 if (this->m_inc_tags) {
151 // Incremental tags: new items always carry full info.
152 ProcessUpdate(packet, NULL, m_full_req_tag);
153 } else {
154 // Non-incremental tags: we might get partial info on new items.
155 // Collect all this items in a tag, and then request full info about them.
156 CECPacket req_full(this->m_full_req_cmd);
158 ProcessUpdate(packet, &req_full, m_full_req_tag);
160 // Phase 3: request full info about files we don't have yet
161 if ( req_full.GetTagCount() ) {
162 m_conn->SendRequest(this, &req_full);
163 this->m_state = FULL_REQ_SENT;
167 break;
168 case FULL_REQ_SENT:
169 ProcessFull(packet);
170 m_state = IDLE;
171 break;
174 public:
175 CRemoteContainer(CRemoteConnect *conn, bool inc_tags)
177 m_state = IDLE;
179 m_conn = conn;
180 m_item_count = 0;
181 m_inc_tags = inc_tags;
184 virtual ~CRemoteContainer()
188 typedef typename std::list<T *>::iterator iterator;
189 iterator begin() { return m_items.begin(); }
190 iterator end() { return m_items.end(); }
192 uint32 GetCount()
194 return m_item_count;
197 void AddItem(T *item)
199 m_items.push_back(item);
200 m_items_hash[GetItemID(item)] = item;
201 m_idx_items.resize(m_item_count+1);
202 m_idx_items[m_item_count] = item;
203 m_item_count++;
206 T *GetByID(I id)
208 // avoid creating nodes
209 return m_items_hash.count(id) ? m_items_hash[id] : NULL;
212 T *GetByIndex(int index)
214 return ( (index >= 0) && (index < m_item_count) ) ? m_idx_items[index] : NULL;
217 void Flush()
219 m_items.clear();
220 m_items_hash.clear();
221 m_item_count = 0;
225 // Flush & reload
228 We usually don't keep outdated code as comments, but this blocking implementation
229 shows the overall procedure well. It had to be scattered for the event driven implementation.
231 bool FullReload(int cmd)
233 CECPacket req(cmd);
234 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req));
235 if ( !reply.get() ) {
236 return false;
238 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
239 this->DeleteItem(*j);
242 Flush();
244 ProcessFull(reply.get());
246 return true;
249 void FullReload(int cmd)
251 if ( this->m_state != IDLE ) {
252 return;
255 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
256 this->DeleteItem(*j);
259 Flush();
261 CECPacket req(cmd);
262 this->m_conn->SendRequest(this, &req);
263 this->m_state = FULL_REQ_SENT;
264 this->m_full_req_cmd = cmd;
268 // Following are like basicly same code as in webserver. Eventually it must
269 // be same class
271 void DoRequery(int cmd, int tag)
273 if ( this->m_state != IDLE ) {
274 return;
276 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
277 this->m_conn->SendRequest(this, &req_sts);
278 this->m_state = STATUS_REQ_SENT;
279 this->m_full_req_cmd = cmd;
280 this->m_full_req_tag = tag;
283 We usually don't keep outdated code as comments, but this blocking implementation
284 shows the overall procedure well. It had to be scattered for the event driven implementation.
286 bool DoRequery(int cmd, int tag)
288 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
291 // Phase 1: request status
292 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
293 if ( !reply.get() ) {
294 return false;
297 if ( !this->Phase1Done(reply.get()) ) {
298 // if derived class choose not to proceed, return - but with good status
299 return true;
302 // Phase 2: update status, mark new files for subsequent query
303 CECPacket req_full(cmd);
305 ProcessUpdate(reply.get(), &req_full, tag);
307 reply.reset();
309 if ( !m_inc_tags ) {
310 // Phase 3: request full info about files we don't have yet
311 if ( req_full.GetTagCount() ) {
312 reply.reset(this->m_conn->SendRecvPacket(&req_full));
313 if ( !reply.get() ) {
314 return false;
316 ProcessFull(reply.get());
319 return true;
323 void ProcessFull(const CECPacket *reply)
325 for (size_t i = 0;i < reply->GetTagCount();i++) {
326 G *tag = (G *)reply->GetTagByIndex(i);
327 // initialize item data from EC tag
328 AddItem(CreateItem(tag));
332 void RemoveItem(iterator & it)
334 I item_id = GetItemID(*it);
335 // remove item from m_idx_items
336 for(int idx = 0;idx < m_item_count;idx++) {
337 if ( this->GetItemID(m_idx_items[idx]) == item_id ) {
338 m_idx_items[idx] = m_idx_items[m_item_count-1];
339 break;
342 // reduce count
343 m_item_count--;
344 // remove from map
345 m_items_hash.erase(item_id);
346 // item may contain data that need to be freed externally, before
347 // dtor is called and memory freed
348 DeleteItem(*it);
350 m_items.erase(it);
353 virtual void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type)
355 std::set<I> core_files;
356 for (size_t i = 0;i < reply->GetTagCount();i++) {
357 G *tag = (G *)reply->GetTagByIndex(i);
358 if ( tag->GetTagName() != req_type ) {
359 continue;
362 core_files.insert(tag->ID());
363 if ( m_items_hash.count(tag->ID()) ) {
364 // Item already known: update it
365 T *item = m_items_hash[tag->ID()];
366 ProcessItemUpdate(tag, item);
367 } else {
368 // New item
369 if (full_req) {
370 // Non-incremental mode: we have only partial info
371 // so we need to request full info before we can use the item
372 full_req->AddTag(CECTag(req_type, tag->ID()));
373 } else {
374 // Incremental mode: new items always carry full info,
375 // so we can add it right away
376 AddItem(CreateItem(tag));
380 for(iterator it = begin(); it != end();) {
381 iterator it2 = it++;
382 if ( core_files.count(GetItemID(*it2)) == 0 ) {
383 RemoveItem(it2);
388 virtual T *CreateItem(G *)
390 return 0;
392 virtual void DeleteItem(T *)
395 virtual I GetItemID(T *)
397 return I();
399 virtual void ProcessItemUpdate(G *, T *)
403 virtual bool Phase1Done(const CECPacket *)
405 return true;
409 class CServerConnectRem : public CECPacketHandlerBase {
410 CRemoteConnect *m_Conn;
411 uint32 m_ID;
413 CServer *m_CurrServer;
415 virtual void HandlePacket(const CECPacket *packet);
417 public:
418 CServerConnectRem(CRemoteConnect *);
419 bool ReQuery();
421 bool IsConnected() { return (m_ID != 0) && (m_ID != 0xffffffff); }
422 bool IsConnecting() { return m_ID == 0xffffffff; }
423 bool IsLowID() { return m_ID < 16777216; }
424 uint32 GetClientID() { return m_ID; }
425 CServer *GetCurrentServer() { return m_CurrServer; }
428 // Actions
430 void ConnectToServer(CServer* server);
431 void ConnectToAnyServer();
432 void StopConnectionTry();
433 void Disconnect();
436 class CServerListRem : public CRemoteContainer<CServer, uint32, CEC_Server_Tag> {
437 uint32 m_TotalUser, m_TotalFile;
439 virtual void HandlePacket(const CECPacket *packet);
440 public:
441 CServerListRem(CRemoteConnect *);
442 void GetUserFileStatus(uint32 &total_user, uint32 &total_file)
444 total_user = m_TotalUser;
445 total_file = m_TotalFile;
448 void UpdateUserFileStatus(CServer *server);
450 CServer* GetServerByAddress(const wxString& address, uint16 port) const;
451 CServer* GetServerByIPTCP(uint32 nIP, uint16 nPort) const;
453 void ReloadControl();
456 // Actions
458 void RemoveServer(CServer* server);
459 void UpdateServerMetFromURL(wxString url);
460 void SaveServerMet();
461 void FilterServers();
464 // template
466 CServer *CreateItem(CEC_Server_Tag *);
467 void DeleteItem(CServer *);
468 uint32 GetItemID(CServer *);
469 void ProcessItemUpdate(CEC_Server_Tag *, CServer *);
472 class CUpDownClientListRem : public CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag> {
473 int m_viewtype;
474 public:
475 CUpDownClientListRem(CRemoteConnect *, int viewtype);
477 const CClientPtrList& GetList() const { return m_items; };
480 // template
482 CUpDownClient *CreateItem(CEC_UpDownClient_Tag *);
483 void DeleteItem(CUpDownClient *);
484 uint32 GetItemID(CUpDownClient *);
485 void ProcessItemUpdate(CEC_UpDownClient_Tag *, CUpDownClient *);
488 class CUpQueueRem {
489 CUpDownClientListRem m_up_list, m_wait_list;
490 public:
491 CUpQueueRem(CRemoteConnect *);
493 void ReQueryUp() { m_up_list.DoRequery(EC_OP_GET_ULOAD_QUEUE, EC_TAG_CLIENT); }
494 void ReQueryWait() { m_wait_list.DoRequery(EC_OP_GET_WAIT_QUEUE, EC_TAG_CLIENT); }
496 const CClientPtrList& GetWaitingList() const { return m_wait_list.GetList(); }
497 const CClientPtrList& GetUploadingList() const { return m_up_list.GetList(); }
498 uint16 GetWaitingPosition(const CUpDownClient *client) const;
501 class CDownQueueRem : public CRemoteContainer<CPartFile, uint32, CEC_PartFile_Tag> {
502 std::map<uint32, PartFileEncoderData> m_enc_map;
503 public:
504 CDownQueueRem(CRemoteConnect *);
506 uint32 GetFileCount() { return GetCount(); }
507 CPartFile* GetFileByID(uint32 id) { return GetByID(id); }
508 CPartFile* GetFileByIndex(unsigned int idx) { return GetByIndex(idx); }
511 // User actions
513 void Prio(CPartFile *file, uint8 prio);
514 void AutoPrio(CPartFile *file, bool flag);
515 void Category(CPartFile *file, uint8 cat);
517 void SendFileCommand(CPartFile *file, ec_tagname_t cmd);
519 // Actions
521 void StopUDPRequests() {}
522 void AddFileLinkToDownload(CED2KFileLink*, uint8);
523 bool AddLink(const wxString &link, uint8 category = 0);
524 void UnsetCompletedFilesExist();
525 void ResetCatParts(int cat);
526 void AddSearchToDownload(CSearchFile* toadd, uint8 category);
529 // template
531 CPartFile *CreateItem(CEC_PartFile_Tag *);
532 void DeleteItem(CPartFile *);
533 uint32 GetItemID(CPartFile *);
534 void ProcessItemUpdate(CEC_PartFile_Tag *, CPartFile *);
535 bool Phase1Done(const CECPacket *);
538 class CSharedFilesRem : public CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag> {
539 std::map<uint32, RLE_Data> m_enc_map;
541 virtual void HandlePacket(const CECPacket *);
544 // For file renaming operation
546 CKnownFile* m_rename_file;
547 wxString m_new_name;
548 public:
549 CSharedFilesRem(CRemoteConnect *);
551 CKnownFile *GetFileByID(uint32 id) { return GetByID(id); }
553 void SetFilePrio(CKnownFile *file, uint8 prio);
556 // Actions
558 void AddFilesFromDirectory(const CPath&);
559 void Reload(bool sendtoserver = true, bool firstload = false);
560 bool RenameFile(CKnownFile* file, const CPath& newName);
563 // template
565 CKnownFile *CreateItem(CEC_SharedFile_Tag *);
566 void DeleteItem(CKnownFile *);
567 uint32 GetItemID(CKnownFile *);
568 void ProcessItemUpdate(CEC_SharedFile_Tag *, CKnownFile *);
569 bool Phase1Done(const CECPacket *);
570 void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type);
573 class CKnownFilesRem {
574 CSharedFilesRem *m_shared_files;
575 public:
576 CKnownFilesRem(CSharedFilesRem *shared)
578 m_shared_files = shared;
580 requested = 0;
581 transferred = 0;
582 accepted = 0;
585 CKnownFile *FindKnownFileByID(uint32 id)
587 return m_shared_files->GetByID(id);
590 uint16 requested;
591 uint32 transferred;
592 uint16 accepted;
595 class CClientListRem {
596 CRemoteConnect *m_conn;
599 // map of user_ID -> client
600 std::multimap<uint32, CUpDownClient*> m_client_list;
601 public:
602 CClientListRem(CRemoteConnect *);
604 const std::multimap<uint32, CUpDownClient*>& GetClientList() { return m_client_list; }
607 // Actions
609 void AddClient(CUpDownClient *);
610 void FilterQueues();
613 class CIPFilterRem {
614 CRemoteConnect *m_conn;
615 public:
616 CIPFilterRem(CRemoteConnect *conn);
619 // Actions
621 void Reload();
622 void Update(wxString strURL = wxEmptyString);
625 class CSearchListRem : public CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag> {
626 virtual void HandlePacket(const CECPacket *);
627 public:
628 CSearchListRem(CRemoteConnect *);
630 int m_curr_search;
631 typedef std::map<long, CSearchResultList> ResultMap;
632 ResultMap m_results;
634 const CSearchResultList& GetSearchResults(long nSearchID);
635 void RemoveResults(long nSearchID);
636 const CSearchResultList& GetSearchResults(long nSearchID) const;
638 // Actions
641 wxString StartNewSearch(uint32* nSearchID, SearchType search_type,
642 const CSearchList::CSearchParams& params);
644 void StopGlobalSearch();
645 void StopKadSearch();
648 // template
650 CSearchFile *CreateItem(CEC_SearchFile_Tag *);
651 void DeleteItem(CSearchFile *);
652 CMD4Hash GetItemID(CSearchFile *);
653 void ProcessItemUpdate(CEC_SearchFile_Tag *, CSearchFile *);
654 bool Phase1Done(const CECPacket *);
657 class CStatsUpdaterRem : public CECPacketHandlerBase {
658 virtual void HandlePacket(const CECPacket *);
659 public:
660 CStatsUpdaterRem() {}
663 class CListenSocketRem {
664 uint32 m_peak_connections;
665 public:
666 uint32 GetPeakConnections() { return m_peak_connections; }
669 class CamuleRemoteGuiApp : public wxApp, public CamuleGuiBase, public CamuleAppCommon {
670 wxTimer* poll_timer;
672 virtual int InitGui(bool geometry_enable, wxString &geometry_string);
674 bool OnInit();
676 int OnExit();
678 void OnPollTimer(wxTimerEvent& evt);
680 void OnECConnection(wxEvent& event);
681 void OnECInitDone(wxEvent& event);
682 void OnNotifyEvent(CMuleGUIEvent& evt);
683 void OnFinishedHTTPDownload(CMuleInternalEvent& event);
685 CStatsUpdaterRem m_stats_updater;
686 public:
688 void Startup();
690 bool ShowConnectionDialog();
692 class CRemoteConnect *m_connect;
694 CEConnectDlg *dialog;
696 bool CopyTextToClipboard(wxString strText);
698 virtual int ShowAlert(wxString msg, wxString title, int flags);
700 void ShutDown(wxCloseEvent &evt);
702 CPreferencesRem *glob_prefs;
705 // Provide access to core data thru EC
706 CServerConnectRem *serverconnect;
707 CServerListRem *serverlist;
708 CUpQueueRem *uploadqueue;
709 CDownQueueRem *downloadqueue;
710 CSharedFilesRem *sharedfiles;
711 CKnownFilesRem *knownfiles;
712 CClientListRem *clientlist;
713 CIPFilterRem *ipfilter;
714 CSearchListRem *searchlist;
715 CListenSocketRem *listensocket;
717 CStatistics *m_statistics;
719 bool AddServer(CServer *srv, bool fromUser = false);
721 uint32 GetPublicIP();
723 wxString GetLog(bool reset = false);
724 wxString GetServerLog(bool reset = false);
726 void AddServerMessageLine(wxString &msg);
727 void AddRemoteLogLine(const wxString& line);
729 void SetOSFiles(wxString ) { /* onlinesig is created on remote side */ }
731 bool IsConnected() const { return IsConnectedED2K() || IsConnectedKad(); }
732 bool IsFirewalled() const;
733 bool IsConnectedED2K() const;
734 bool IsConnectedKad() const
736 return ((m_ConnState & CONNECTED_KAD_OK)
737 || (m_ConnState & CONNECTED_KAD_FIREWALLED));
739 bool IsFirewalledKad() const { return (m_ConnState & CONNECTED_KAD_FIREWALLED) != 0; }
741 bool IsKadRunning() const { return ((m_ConnState & CONNECTED_KAD_OK)
742 || (m_ConnState & CONNECTED_KAD_FIREWALLED)
743 || (m_ConnState & CONNECTED_KAD_NOT)); }
745 // Check Kad state (UDP)
746 bool IsFirewalledKadUDP() const { return theStats::IsFirewalledKadUDP(); }
747 // Kad stats
748 uint32 GetKadUsers() const { return theStats::GetKadUsers(); }
749 uint32 GetKadFiles() const { return theStats::GetKadFiles(); }
750 uint32 GetKadIndexedSources() const { return theStats::GetKadIndexedSources(); }
751 uint32 GetKadIndexedKeywords() const{ return theStats::GetKadIndexedKeywords(); }
752 uint32 GetKadIndexedNotes() const { return theStats::GetKadIndexedNotes(); }
753 uint32 GetKadIndexedLoad() const { return theStats::GetKadIndexedLoad(); }
754 // True IP of machine
755 uint32 GetKadIPAdress() const { return theStats::GetKadIPAdress(); }
756 // Buddy status
757 uint8 GetBuddyStatus() const { return theStats::GetBuddyStatus(); }
758 uint32 GetBuddyIP() const { return theStats::GetBuddyIP(); }
759 uint32 GetBuddyPort() const { return theStats::GetBuddyPort(); }
761 void StartKad();
762 void StopKad();
764 /** Bootstraps kad from the specified IP (must be in hostorder). */
765 void BootstrapKad(uint32 ip, uint16 port);
766 /** Updates the nodes.dat file from the specified url. */
767 void UpdateNotesDat(const wxString& str);
769 void DisconnectED2K();
771 bool CryptoAvailable() const;
773 uint32 GetED2KID() const;
774 uint32 GetID() const;
775 void ShowUserCount();
777 uint8 m_ConnState;
778 uint32 m_clientID;
780 wxLocale m_locale;
782 DECLARE_EVENT_TABLE()
785 DECLARE_APP(CamuleRemoteGuiApp)
787 extern CamuleRemoteGuiApp *theApp;
789 #endif /* AMULE_REMOTE_GUI_H */
791 // File_checked_for_headers