Upstream tarball 20080929
[amule.git] / src / amule-remote-gui.h
blobcad9ee46c06cbb1869bcded5a73ee9b61a198d68
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 void OnOK(wxCommandEvent& event);
64 DECLARE_EVENT_TABLE()
65 public:
66 CEConnectDlg();
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 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);
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: wxASSERT(0); // 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;
161 break;
162 case FULL_REQ_SENT:
163 ProcessFull(packet);
164 m_state = IDLE;
165 break;
168 public:
169 CRemoteContainer(CRemoteConnect *conn, bool /*inc_tags*/ = false)
171 m_state = IDLE;
173 m_conn = conn;
174 m_item_count = 0;
176 // FIXME:
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;
183 m_inc_tags = false;
186 virtual ~CRemoteContainer()
190 uint32 GetCount()
192 return m_item_count;
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;
201 m_item_count++;
204 T *GetByID(I id)
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;
215 void Flush()
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());
219 m_item_count = 0;
223 // Flush & reload
226 bool FullReload(int cmd)
228 CECPacket req(cmd);
229 std::auto_ptr<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 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 std::auto_ptr<const CECPacket> reply(this->m_conn->SendRecvPacket(&req_sts));
285 if ( !reply.get() ) {
286 return false;
289 if ( !this->Phase1Done(reply.get()) ) {
290 // if derived class choose not to proceed, return - but with good status
291 return true;
294 // Phase 2: update status, mark new files for subsequent query
295 CECPacket req_full(cmd);
297 ProcessUpdate(reply.get(), &req_full, tag);
299 reply.reset();
301 if ( !m_inc_tags ) {
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() ) {
306 return false;
308 ProcessFull(reply.get());
311 return true;
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);
321 AddItem(item);
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 ) {
331 continue;
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);
338 } else {
339 if ( m_inc_tags ) {
340 T *item = this->CreateItem(tag);
341 AddItem(item);
342 } else {
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];
358 break;
361 m_item_count--;
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);
371 break;
377 virtual T *CreateItem(G *)
379 return 0;
381 virtual void DeleteItem(T *)
384 virtual I GetItemID(T *)
386 return I();
388 virtual void ProcessItemUpdate(G *, T *)
392 virtual bool Phase1Done(const CECPacket *)
394 return true;
398 class CServerConnectRem : public CECPacketHandlerBase {
399 CRemoteConnect *m_Conn;
400 uint32 m_ID;
402 CServer *m_CurrServer;
404 virtual void HandlePacket(const CECPacket *packet);
406 public:
407 CServerConnectRem(CRemoteConnect *);
408 bool ReQuery();
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; }
417 // Actions
419 void ConnectToServer(CServer* server);
420 void ConnectToAnyServer();
421 void StopConnectionTry();
422 void Disconnect();
425 class CServerListRem : public CRemoteContainer<CServer, uint32, CEC_Server_Tag> {
426 uint32 m_TotalUser, m_TotalFile;
428 virtual void HandlePacket(const CECPacket *packet);
429 public:
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();
445 // Actions
447 void RemoveServer(CServer* server);
448 void UpdateServerMetFromURL(wxString url);
449 void SaveServerMet();
450 void FilterServers();
453 // template
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> {
462 int m_viewtype;
463 public:
464 CUpDownClientListRem(CRemoteConnect *, int viewtype);
466 const CClientPtrList& GetList() const { return m_items; };
469 // template
471 CUpDownClient *CreateItem(CEC_UpDownClient_Tag *);
472 void DeleteItem(CUpDownClient *);
473 uint32 GetItemID(CUpDownClient *);
474 void ProcessItemUpdate(CEC_UpDownClient_Tag *, CUpDownClient *);
477 class CUpQueueRem {
478 CUpDownClientListRem m_up_list, m_wait_list;
479 public:
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;
492 public:
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);
503 // User actions
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);
511 // Actions
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);
521 // template
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;
539 wxString m_new_name;
540 public:
541 CSharedFilesRem(CRemoteConnect *);
543 CKnownFile *GetFileByID(CMD4Hash id) { return GetByID(id); }
545 void SetFilePrio(CKnownFile *file, uint8 prio);
548 // Actions
550 void AddFilesFromDirectory(const CPath&);
551 void Reload(bool sendtoserver = true, bool firstload = false);
552 bool RenameFile(CKnownFile* file, const CPath& newName);
555 // template
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;
566 public:
567 CKnownFilesRem(CSharedFilesRem *shared)
569 m_shared_files = shared;
571 requested = 0;
572 transferred = 0;
573 accepted = 0;
576 CKnownFile *FindKnownFileByID(const CMD4Hash& id)
578 return m_shared_files->GetByID(id);
581 uint16 requested;
582 uint32 transferred;
583 uint16 accepted;
586 class CClientCreditsRem {
587 bool m_crypt_avail;
588 public:
589 bool CryptoAvailable() { return m_crypt_avail; }
592 class CClientListRem {
593 CRemoteConnect *m_conn;
596 // map of user_ID -> client
597 std::multimap<uint32, CUpDownClient*> m_client_list;
598 public:
599 CClientListRem(CRemoteConnect *);
601 const std::multimap<uint32, CUpDownClient*>& GetClientList() { return m_client_list; }
604 // Actions
606 void AddClient(CUpDownClient *);
607 void FilterQueues();
610 class CIPFilterRem {
611 CRemoteConnect *m_conn;
612 public:
613 CIPFilterRem(CRemoteConnect *conn);
616 // Actions
618 void Reload();
619 void Update(wxString strURL = wxEmptyString);
622 class CSearchListRem : public CRemoteContainer<CSearchFile, CMD4Hash, CEC_SearchFile_Tag> {
623 virtual void HandlePacket(const CECPacket *);
624 public:
625 CSearchListRem(CRemoteConnect *);
627 int m_curr_search;
628 typedef std::map<long, CSearchResultList> ResultMap;
629 ResultMap m_results;
631 const CSearchResultList& GetSearchResults(long nSearchID);
632 void RemoveResults(long nSearchID);
633 const CSearchResultList& GetSearchResults(long nSearchID) const;
635 // Actions
638 wxString StartNewSearch(uint32* nSearchID, SearchType search_type,
639 const CSearchList::CSearchParams& params);
641 void StopGlobalSearch();
644 // template
646 CSearchFile *CreateItem(CEC_SearchFile_Tag *);
647 void DeleteItem(CSearchFile *);
648 CMD4Hash GetItemID(CSearchFile *);
649 void ProcessItemUpdate(CEC_SearchFile_Tag *, CSearchFile *);
650 bool Phase1Done(const CECPacket *);
653 class CStatsUpdaterRem : public CECPacketHandlerBase {
654 virtual void HandlePacket(const CECPacket *);
655 public:
656 CStatsUpdaterRem() {}
659 class CListenSocketRem {
660 uint32 m_peak_connections;
661 public:
662 uint32 GetPeakConnections() { return m_peak_connections; }
665 class CamuleRemoteGuiApp : public wxApp, public CamuleGuiBase {
666 wxTimer* poll_timer;
668 virtual int InitGui(bool geometry_enable, wxString &geometry_string);
670 bool OnInit();
672 int OnExit();
674 void OnPollTimer(wxTimerEvent& evt);
676 void OnECConnection(wxEvent& event);
677 void OnECInitDone(wxEvent& event);
678 void OnLoggingEvent(CLoggingEvent& evt);
679 void OnNotifyEvent(CMuleGUIEvent& evt);
680 void OnFinishedHTTPDownload(CMuleInternalEvent& event);
682 CStatsUpdaterRem m_stats_updater;
683 public:
685 void Startup();
687 bool ShowConnectionDialog();
689 class CRemoteConnect *m_connect;
691 CEConnectDlg *dialog;
693 bool CopyTextToClipboard(wxString strText);
695 virtual void ShowAlert(wxString msg, wxString title, int flags);
697 void ShutDown(wxCloseEvent &evt);
699 CPreferencesRem *glob_prefs;
700 wxString ConfigDir;
703 // Provide access to core data thru EC
704 CServerConnectRem *serverconnect;
705 CServerListRem *serverlist;
706 CUpQueueRem *uploadqueue;
707 CDownQueueRem *downloadqueue;
708 CSharedFilesRem *sharedfiles;
709 CKnownFilesRem *knownfiles;
710 CClientCreditsRem *clientcredits;
711 CClientListRem *clientlist;
712 CIPFilterRem *ipfilter;
713 CSearchListRem *searchlist;
714 CListenSocketRem *listensocket;
716 CStatistics *m_statistics;
718 bool AddServer(CServer *srv, bool fromUser = false);
720 uint32 GetPublicIP();
721 wxString CreateMagnetLink(const CAbstractFile *f);
722 wxString CreateED2kLink(const CAbstractFile* f, bool add_source = false, bool use_hostname = false, bool addcryptoptions = false);
723 wxString CreateED2kAICHLink(const CKnownFile* f);
725 wxString GetLog(bool reset = false);
726 wxString GetServerLog(bool reset = false);
728 void AddServerMessageLine(wxString &msg);
730 void SetOSFiles(wxString ) { /* onlinesig is created on remote side */ }
732 bool IsConnected() const { return IsConnectedED2K() || IsConnectedKad(); }
733 bool IsFirewalled() const;
734 bool IsConnectedED2K() const;
735 bool IsConnectedKad() const
737 return ((m_ConnState & CONNECTED_KAD_OK)
738 || (m_ConnState & CONNECTED_KAD_FIREWALLED));
740 bool IsFirewalledKad() const { return (m_ConnState & CONNECTED_KAD_FIREWALLED) != 0; }
742 bool IsKadRunning() const { return ((m_ConnState & CONNECTED_KAD_OK)
743 || (m_ConnState & CONNECTED_KAD_FIREWALLED)
744 || (m_ConnState & CONNECTED_KAD_NOT)); }
746 void StartKad();
747 void StopKad();
749 /** Bootstraps kad from the specified IP (must be in hostorder). */
750 void BootstrapKad(uint32 ip, uint16 port);
751 /** Updates the nodes.dat file from the specified url. */
752 void UpdateNotesDat(const wxString& str);
754 void DisconnectED2K();
756 bool CryptoAvailable() const;
758 uint32 GetED2KID() const;
759 uint32 GetID() const;
760 void ShowUserCount();
762 uint8 m_ConnState;
763 uint32 m_clientID;
765 wxLocale m_locale;
767 DECLARE_EVENT_TABLE()
770 DECLARE_APP(CamuleRemoteGuiApp)
771 #ifdef AMULE_REMOTE_GUI_CPP
772 CamuleRemoteGuiApp *theApp;
773 #else
774 extern CamuleRemoteGuiApp *theApp;
775 #endif
778 #endif /* AMULE_REMOTE_GUI_H */
780 // File_checked_for_headers