Upstream tarball 9882
[amule.git] / src / amule-remote-gui.h
blobe579275b2c0875f4b12f5f791665e22e911e1c6d
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 std::vector<T *> m_idx_items;
132 // .size() is O(N) operation in stl
133 int m_item_count;
135 // use incremental tags algorithm
136 bool m_inc_tags;
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 if (this->m_inc_tags) {
150 // Incremental tags: new items always carry full info.
151 ProcessUpdate(packet, NULL, m_full_req_tag);
152 } else {
153 // Non-incremental tags: we might get partial info on new items.
154 // Collect all this items in a tag, and then request full info about them.
155 CECPacket req_full(this->m_full_req_cmd);
157 ProcessUpdate(packet, &req_full, m_full_req_tag);
159 // Phase 3: request full info about files we don't have yet
160 if ( req_full.GetTagCount() ) {
161 m_conn->SendRequest(this, &req_full);
162 this->m_state = FULL_REQ_SENT;
166 break;
167 case FULL_REQ_SENT:
168 ProcessFull(packet);
169 m_state = IDLE;
170 break;
173 public:
174 CRemoteContainer(CRemoteConnect *conn, bool inc_tags = false)
176 m_state = IDLE;
178 m_conn = conn;
179 m_item_count = 0;
180 m_inc_tags = inc_tags;
183 virtual ~CRemoteContainer()
187 uint32 GetCount()
189 return m_item_count;
192 void AddItem(T *item)
194 m_items.push_back(item);
195 m_items_hash[GetItemID(item)] = item;
196 m_idx_items.resize(m_item_count+1);
197 m_idx_items[m_item_count] = item;
198 m_item_count++;
201 T *GetByID(I id)
203 // avoid creating nodes
204 return m_items_hash.count(id) ? m_items_hash[id] : NULL;
207 T *GetByIndex(int index)
209 return ( (index >= 0) && (index < m_item_count) ) ? m_idx_items[index] : NULL;
212 void Flush()
214 m_items.erase(this->m_items.begin(), this->m_items.end());
215 m_items_hash.erase(this->m_items_hash.begin(), this->m_items_hash.end());
216 m_item_count = 0;
220 // Flush & reload
223 We usually don't keep outdated code as comments, but this blocking implementation
224 shows the overall procedure well. It had to be scattered for the event driven implementation.
226 bool FullReload(int cmd)
228 CECPacket req(cmd);
229 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req));
230 if ( !reply.get() ) {
231 return false;
233 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
234 this->DeleteItem(*j);
237 Flush();
239 ProcessFull(reply.get());
241 return true;
244 void FullReload(int cmd)
246 if ( this->m_state != IDLE ) {
247 return;
250 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
251 this->DeleteItem(*j);
254 Flush();
256 CECPacket req(cmd);
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
264 // be same class
266 void DoRequery(int cmd, int tag)
268 if ( this->m_state != IDLE ) {
269 return;
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 We usually don't keep outdated code as comments, but this blocking implementation
279 shows the overall procedure well. It had to be scattered for the event driven implementation.
281 bool DoRequery(int cmd, int tag)
283 CECPacket req_sts(cmd, m_inc_tags ? EC_DETAIL_INC_UPDATE : EC_DETAIL_UPDATE);
286 // Phase 1: request status
287 CScopedPtr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
288 if ( !reply.get() ) {
289 return false;
292 if ( !this->Phase1Done(reply.get()) ) {
293 // if derived class choose not to proceed, return - but with good status
294 return true;
297 // Phase 2: update status, mark new files for subsequent query
298 CECPacket req_full(cmd);
300 ProcessUpdate(reply.get(), &req_full, tag);
302 reply.reset();
304 if ( !m_inc_tags ) {
305 // Phase 3: request full info about files we don't have yet
306 if ( req_full.GetTagCount() ) {
307 reply.reset(this->m_conn->SendRecvPacket(&req_full));
308 if ( !reply.get() ) {
309 return false;
311 ProcessFull(reply.get());
314 return true;
318 void ProcessFull(const CECPacket *reply)
320 for (size_t i = 0;i < reply->GetTagCount();i++) {
321 G *tag = (G *)reply->GetTagByIndex(i);
322 // initialize item data from EC tag
323 T *item = this->CreateItem(tag);
324 AddItem(item);
328 void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type)
330 std::set<I> core_files;
331 for (size_t i = 0;i < reply->GetTagCount();i++) {
332 G *tag = (G *)reply->GetTagByIndex(i);
333 if ( tag->GetTagName() != req_type ) {
334 continue;
337 core_files.insert(tag->ID());
338 if ( m_items_hash.count(tag->ID()) ) {
339 // Item already known: update it
340 T *item = m_items_hash[tag->ID()];
341 ProcessItemUpdate(tag, item);
342 } else {
343 // New item
344 if (full_req) {
345 // Non-incremental mode: we have only partial info
346 // so we need to request full info before we can use the item
347 full_req->AddTag(CECTag(req_type, tag->ID()));
348 } else {
349 // Incremental mode: new items always carry full info,
350 // so we can add it right away
351 T *item = this->CreateItem(tag);
352 AddItem(item);
356 std::list<I> del_ids;
357 for(typename std::list<T *>::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) {
358 I item_id = GetItemID(*j);
359 if ( core_files.count(item_id) == 0 ) {
360 del_ids.push_back(item_id);
363 for(typename std::list<I>::iterator j = del_ids.begin(); j != del_ids.end(); j++) {
364 for(int idx = 0;idx < m_item_count;idx++) {
365 if ( this->GetItemID(m_idx_items[idx]) == *j ) {
366 m_idx_items[idx] = m_idx_items[m_item_count-1];
367 break;
370 m_item_count--;
371 m_items_hash.erase(*j);
372 for(typename std::list<T *>::iterator k = this->m_items.begin(); k != this->m_items.end(); k++) {
373 if ( *j == GetItemID(*k) ) {
374 // item may contain data that need to be freed externally, before
375 // dtor is called and memory freed
376 this->DeleteItem(*k);
378 this->m_items.erase(k);
380 break;
386 virtual T *CreateItem(G *)
388 return 0;
390 virtual void DeleteItem(T *)
393 virtual I GetItemID(T *)
395 return I();
397 virtual void ProcessItemUpdate(G *, T *)
401 virtual bool Phase1Done(const CECPacket *)
403 return true;
407 class CServerConnectRem : public CECPacketHandlerBase {
408 CRemoteConnect *m_Conn;
409 uint32 m_ID;
411 CServer *m_CurrServer;
413 virtual void HandlePacket(const CECPacket *packet);
415 public:
416 CServerConnectRem(CRemoteConnect *);
417 bool ReQuery();
419 bool IsConnected() { return (m_ID != 0) && (m_ID != 0xffffffff); }
420 bool IsConnecting() { return m_ID == 0xffffffff; }
421 bool IsLowID() { return m_ID < 16777216; }
422 uint32 GetClientID() { return m_ID; }
423 CServer *GetCurrentServer() { return m_CurrServer; }
426 // Actions
428 void ConnectToServer(CServer* server);
429 void ConnectToAnyServer();
430 void StopConnectionTry();
431 void Disconnect();
434 class CServerListRem : public CRemoteContainer<CServer, uint32, CEC_Server_Tag> {
435 uint32 m_TotalUser, m_TotalFile;
437 virtual void HandlePacket(const CECPacket *packet);
438 public:
439 CServerListRem(CRemoteConnect *);
440 void GetUserFileStatus(uint32 &total_user, uint32 &total_file)
442 total_user = m_TotalUser;
443 total_file = m_TotalFile;
446 void UpdateUserFileStatus(CServer *server);
448 CServer* GetServerByAddress(const wxString& address, uint16 port) const;
449 CServer* GetServerByIPTCP(uint32 nIP, uint16 nPort) const;
451 void ReloadControl();
454 // Actions
456 void RemoveServer(CServer* server);
457 void UpdateServerMetFromURL(wxString url);
458 void SaveServerMet();
459 void FilterServers();
462 // template
464 CServer *CreateItem(CEC_Server_Tag *);
465 void DeleteItem(CServer *);
466 uint32 GetItemID(CServer *);
467 void ProcessItemUpdate(CEC_Server_Tag *, CServer *);
470 class CUpDownClientListRem : public CRemoteContainer<CUpDownClient, uint32, CEC_UpDownClient_Tag> {
471 int m_viewtype;
472 public:
473 CUpDownClientListRem(CRemoteConnect *, int viewtype);
475 const CClientPtrList& GetList() const { return m_items; };
478 // template
480 CUpDownClient *CreateItem(CEC_UpDownClient_Tag *);
481 void DeleteItem(CUpDownClient *);
482 uint32 GetItemID(CUpDownClient *);
483 void ProcessItemUpdate(CEC_UpDownClient_Tag *, CUpDownClient *);
486 class CUpQueueRem {
487 CUpDownClientListRem m_up_list, m_wait_list;
488 public:
489 CUpQueueRem(CRemoteConnect *);
491 void ReQueryUp() { m_up_list.DoRequery(EC_OP_GET_ULOAD_QUEUE, EC_TAG_CLIENT); }
492 void ReQueryWait() { m_wait_list.DoRequery(EC_OP_GET_WAIT_QUEUE, EC_TAG_CLIENT); }
494 const CClientPtrList& GetWaitingList() const { return m_wait_list.GetList(); }
495 const CClientPtrList& GetUploadingList() const { return m_up_list.GetList(); }
496 uint16 GetWaitingPosition(const CUpDownClient *client) const;
499 class CDownQueueRem : public CRemoteContainer<CPartFile, CMD4Hash, CEC_PartFile_Tag> {
500 std::map<CMD4Hash, PartFileEncoderData> m_enc_map;
501 public:
502 CDownQueueRem(CRemoteConnect *);
504 uint32 GetFileCount() { return GetCount(); }
505 CPartFile* GetFileByID(const CMD4Hash& id) { return GetByID(id); }
506 CPartFile* GetFileByIndex(unsigned int idx) { return GetByIndex(idx); }
508 bool IsPartFile(const CKnownFile* totest) const;
509 void OnConnectionState(bool bConnected);
512 // User actions
514 void Prio(CPartFile *file, uint8 prio);
515 void AutoPrio(CPartFile *file, bool flag);
516 void Category(CPartFile *file, uint8 cat);
518 void SendFileCommand(CPartFile *file, ec_tagname_t cmd);
520 // Actions
522 void StopUDPRequests();
523 void AddFileLinkToDownload(CED2KFileLink*, uint8);
524 bool AddLink(const wxString &link, uint8 category = 0);
525 void UnsetCompletedFilesExist();
526 void ResetCatParts(int cat);
527 void AddSearchToDownload(CSearchFile* toadd, uint8 category);
530 // template
532 CPartFile *CreateItem(CEC_PartFile_Tag *);
533 void DeleteItem(CPartFile *);
534 CMD4Hash GetItemID(CPartFile *);
535 void ProcessItemUpdate(CEC_PartFile_Tag *, CPartFile *);
536 bool Phase1Done(const CECPacket *);
539 class CSharedFilesRem : public CRemoteContainer<CKnownFile, CMD4Hash, CEC_SharedFile_Tag> {
540 std::map<CMD4Hash, RLE_Data> m_enc_map;
542 virtual void HandlePacket(const CECPacket *);
545 // For file renaming operation
547 CKnownFile* m_rename_file;
548 wxString m_new_name;
549 public:
550 CSharedFilesRem(CRemoteConnect *);
552 CKnownFile *GetFileByID(CMD4Hash id) { return GetByID(id); }
554 void SetFilePrio(CKnownFile *file, uint8 prio);
557 // Actions
559 void AddFilesFromDirectory(const CPath&);
560 void Reload(bool sendtoserver = true, bool firstload = false);
561 bool RenameFile(CKnownFile* file, const CPath& newName);
564 // template
566 CKnownFile *CreateItem(CEC_SharedFile_Tag *);
567 void DeleteItem(CKnownFile *);
568 CMD4Hash GetItemID(CKnownFile *);
569 void ProcessItemUpdate(CEC_SharedFile_Tag *, CKnownFile *);
570 bool Phase1Done(const CECPacket *);
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(const CMD4Hash& 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;
671 bool m_skipConnectionDialog;
672 wxString m_geom_string;
674 virtual int InitGui(bool geometry_enable, wxString &geometry_string);
676 bool OnInit();
678 int OnExit();
680 void OnPollTimer(wxTimerEvent& evt);
682 void OnECConnection(wxEvent& event);
683 void OnECInitDone(wxEvent& event);
684 void OnNotifyEvent(CMuleGUIEvent& evt);
685 void OnFinishedHTTPDownload(CMuleInternalEvent& event);
686 void OnInitCmdLine(wxCmdLineParser& cmdline);
687 bool OnCmdLineParsed(wxCmdLineParser& parser);
689 CStatsUpdaterRem m_stats_updater;
690 public:
692 void Startup();
694 bool ShowConnectionDialog();
696 class CRemoteConnect *m_connect;
698 CEConnectDlg *dialog;
700 bool CopyTextToClipboard(wxString strText);
702 virtual int ShowAlert(wxString msg, wxString title, int flags);
704 void ShutDown(wxCloseEvent &evt);
706 CPreferencesRem *glob_prefs;
707 wxString ConfigDir;
710 // Provide access to core data thru EC
711 CServerConnectRem *serverconnect;
712 CServerListRem *serverlist;
713 CUpQueueRem *uploadqueue;
714 CDownQueueRem *downloadqueue;
715 CSharedFilesRem *sharedfiles;
716 CKnownFilesRem *knownfiles;
717 CClientListRem *clientlist;
718 CIPFilterRem *ipfilter;
719 CSearchListRem *searchlist;
720 CListenSocketRem *listensocket;
722 CStatistics *m_statistics;
724 bool AddServer(CServer *srv, bool fromUser = false);
726 uint32 GetPublicIP();
728 wxString GetLog(bool reset = false);
729 wxString GetServerLog(bool reset = false);
731 void AddServerMessageLine(wxString &msg);
732 void AddRemoteLogLine(const wxString& line);
734 void SetOSFiles(wxString ) { /* onlinesig is created on remote side */ }
736 bool IsConnected() const { return IsConnectedED2K() || IsConnectedKad(); }
737 bool IsFirewalled() const;
738 bool IsConnectedED2K() const;
739 bool IsConnectedKad() const
741 return ((m_ConnState & CONNECTED_KAD_OK)
742 || (m_ConnState & CONNECTED_KAD_FIREWALLED));
744 bool IsFirewalledKad() const { return (m_ConnState & CONNECTED_KAD_FIREWALLED) != 0; }
746 bool IsKadRunning() const { return ((m_ConnState & CONNECTED_KAD_OK)
747 || (m_ConnState & CONNECTED_KAD_FIREWALLED)
748 || (m_ConnState & CONNECTED_KAD_NOT)); }
750 // Check Kad state (UDP)
751 bool IsFirewalledKadUDP() const { return theStats::IsFirewalledKadUDP(); }
752 // Kad stats
753 uint32 GetKadUsers() const { return theStats::GetKadUsers(); }
754 uint32 GetKadFiles() const { return theStats::GetKadFiles(); }
755 uint32 GetKadIndexedSources() const { return theStats::GetKadIndexedSources(); }
756 uint32 GetKadIndexedKeywords() const{ return theStats::GetKadIndexedKeywords(); }
757 uint32 GetKadIndexedNotes() const { return theStats::GetKadIndexedNotes(); }
758 uint32 GetKadIndexedLoad() const { return theStats::GetKadIndexedLoad(); }
759 // True IP of machine
760 uint32 GetKadIPAdress() const { return theStats::GetKadIPAdress(); }
761 // Buddy status
762 uint8 GetBuddyStatus() const { return theStats::GetBuddyStatus(); }
763 uint32 GetBuddyIP() const { return theStats::GetBuddyIP(); }
764 uint32 GetBuddyPort() const { return theStats::GetBuddyPort(); }
766 void StartKad();
767 void StopKad();
769 /** Bootstraps kad from the specified IP (must be in hostorder). */
770 void BootstrapKad(uint32 ip, uint16 port);
771 /** Updates the nodes.dat file from the specified url. */
772 void UpdateNotesDat(const wxString& str);
774 void DisconnectED2K();
776 bool CryptoAvailable() const;
778 uint32 GetED2KID() const;
779 uint32 GetID() const;
780 void ShowUserCount();
782 uint8 m_ConnState;
783 uint32 m_clientID;
785 wxLocale m_locale;
787 DECLARE_EVENT_TABLE()
790 DECLARE_APP(CamuleRemoteGuiApp)
791 #ifdef AMULE_REMOTE_GUI_CPP
792 CamuleRemoteGuiApp *theApp;
793 #else
794 extern CamuleRemoteGuiApp *theApp;
795 #endif
798 #endif /* AMULE_REMOTE_GUI_H */
800 // File_checked_for_headers