1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2005-2011 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. 14// 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 23// 24 25 26#include <wx/ipc.h> 27#include <wx/cmdline.h> // Needed for wxCmdLineParser 28#include <wx/config.h> // Do_not_auto_remove (win32) 29#include <wx/fileconf.h> // Needed for wxFileConfig 30 31 32#include <common/Format.h> 33#include <common/StringFunctions.h> 34#include <common/MD5Sum.h> 35 36 37#include <include/common/EventIDs.h> 38 39 40#include "amule.h" // Interface declarations. 41#include "amuleDlg.h" // Needed for CamuleDlg 42#include "ClientCredits.h" 43#include "SourceListCtrl.h" 44#include "ChatWnd.h" 45#include "DataToText.h" // Needed for GetSoftName() 46#include "DownloadListCtrl.h" // Needed for CDownloadListCtrl 47#include "Friend.h" 48#include "GetTickCount.h" // Needed for GetTickCount 49#include "GuiEvents.h" 50#ifdef ENABLE_IP2COUNTRY 51 #include "IP2Country.h" // Needed for IP2Country 52#endif 53#include "InternalEvents.h" // Needed for wxEVT_CORE_FINISHED_HTTP_DOWNLOAD 54#include "Logger.h" 55#include "muuli_wdr.h" // Needed for IDs 56#include "PartFile.h" // Needed for CPartFile 57#include "SearchDlg.h" // Needed for CSearchDlg 58#include "Server.h" // Needed for GetListName 59#include "ServerWnd.h" // Needed for CServerWnd 60#include "SharedFilesCtrl.h" // Needed for CSharedFilesCtrl 61#include "SharedFilesWnd.h" // Needed for CSharedFilesWnd 62#include "TransferWnd.h" // Needed for CTransferWnd 63#include "UpDownClientEC.h" // Needed for CUpDownClient 64#include "ServerListCtrl.h" // Needed for CServerListCtrl 65#include "ScopedPtr.h" 66#include "StatisticsDlg.h" // Needed for CStatisticsDlg 67 68 69CEConnectDlg::CEConnectDlg() 70: 71wxDialog(theApp->amuledlg, -1, _("Connect to remote amule"), wxDefaultPosition) 72{ 73 CoreConnect(this, true); 74 75 wxString pref_host, pref_port; 76 wxConfig::Get()->Read(wxT("/EC/Host"), &pref_host, wxT("localhost")); 77 wxConfig::Get()->Read(wxT("/EC/Port"), &pref_port, wxT("4712")); 78 wxConfig::Get()->Read(wxT("/EC/Password"), &pwd_hash); 79 80 CastChild(ID_REMOTE_HOST, wxTextCtrl)->SetValue(pref_host); 81 CastChild(ID_REMOTE_PORT, wxTextCtrl)->SetValue(pref_port); 82 CastChild(ID_EC_PASSWD, wxTextCtrl)->SetValue(pwd_hash); 83 84 CentreOnParent(); 85} 86 87 88wxString CEConnectDlg::PassHash() 89{ 90 return pwd_hash; 91} 92 93 94BEGIN_EVENT_TABLE(CEConnectDlg, wxDialog) 95 EVT_BUTTON(wxID_OK, CEConnectDlg::OnOK) 96END_EVENT_TABLE() 97 98 99void CEConnectDlg::OnOK(wxCommandEvent& evt) 100{ 101 wxString s_port = CastChild(ID_REMOTE_PORT, wxTextCtrl)->GetValue(); 102 port = StrToLong(s_port); 103 104 host = CastChild(ID_REMOTE_HOST, wxTextCtrl)->GetValue(); 105 passwd = CastChild(ID_EC_PASSWD, wxTextCtrl)->GetValue(); 106 107 if (passwd != pwd_hash) { 108 pwd_hash = MD5Sum(passwd).GetHash(); 109 } 110 m_save_user_pass = CastChild(ID_EC_SAVE, wxCheckBox)->IsChecked(); 111 evt.Skip(); 112} 113 114 115DEFINE_LOCAL_EVENT_TYPE(wxEVT_EC_INIT_DONE) 116 117 118BEGIN_EVENT_TABLE(CamuleRemoteGuiApp, wxApp) 119 // Core timer 120 EVT_TIMER(ID_CORE_TIMER_EVENT, CamuleRemoteGuiApp::OnPollTimer) 121 122 EVT_CUSTOM(wxEVT_EC_CONNECTION, -1, CamuleRemoteGuiApp::OnECConnection) 123 EVT_CUSTOM(wxEVT_EC_INIT_DONE, -1, CamuleRemoteGuiApp::OnECInitDone) 124 125 EVT_MULE_NOTIFY(CamuleRemoteGuiApp::OnNotifyEvent) 126 127#ifdef ENABLE_IP2COUNTRY 128 // HTTPDownload finished 129 EVT_MULE_INTERNAL(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD, -1, CamuleRemoteGuiApp::OnFinishedHTTPDownload) 130#endif 131END_EVENT_TABLE() 132 133 134IMPLEMENT_APP(CamuleRemoteGuiApp) 135 136 137int CamuleRemoteGuiApp::OnExit() 138{ 139 StopTickTimer(); 140 141 return wxApp::OnExit(); 142} 143 144 145void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&) 146{ 147 static int request_step = 0; 148 static uint32 msPrevStats = 0; 149 150 if (m_connect->RequestFifoFull()) { 151 return; 152 } 153 154 switch (request_step) { 155 case 0: 156 // We used to update the connection state here, but that's done with the stats in the next step now. 157 request_step++; 158 break; 159 case 1: { 160 CECPacket stats_req(EC_OP_STAT_REQ, EC_DETAIL_INC_UPDATE); 161 m_connect->SendRequest(&m_stats_updater, &stats_req); 162 request_step++; 163 break; 164 } 165 case 2: 166 if (amuledlg->m_sharedfileswnd->IsShown() 167 || amuledlg->m_chatwnd->IsShown() 168 || amuledlg->m_serverwnd->IsShown()) { 169 // update downloads, shared files and servers 170 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); 171 } else if (amuledlg->m_transferwnd->IsShown()) { 172 // update both downloads and shared files 173 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); 174 } else if (amuledlg->m_searchwnd->IsShown()) { 175 if (searchlist->m_curr_search != -1) { 176 searchlist->DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE); 177 } 178 } else if (amuledlg->m_statisticswnd->IsShown()) { 179 int sStatsUpdate = thePrefs::GetStatsInterval(); 180 uint32 msCur = theStats::GetUptimeMillis(); 181 if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) { 182 msPrevStats = msCur; 183 stattree->DoRequery(); 184 } 185 } 186 // Back to the roots 187 request_step = 0; 188 break; 189 default: 190 wxFAIL; 191 request_step = 0; 192 } 193 194 // Check for new links once per second. 195 static uint32 lastED2KLinkCheck = 0; 196 if (GetTickCount() - lastED2KLinkCheck >= 1000) { 197 AddLinksFromFile(); 198 lastED2KLinkCheck = GetTickCount(); 199 } 200} 201 202 203void CamuleRemoteGuiApp::OnFinishedHTTPDownload(CMuleInternalEvent& event) 204{ 205 if (event.GetInt() == HTTP_GeoIP) { 206 amuledlg->IP2CountryDownloadFinished(event.GetExtraLong()); 207 // If we updated, the dialog is already up. Redraw it to show the flags. 208 amuledlg->Refresh(); 209 } 210} 211 212 213void CamuleRemoteGuiApp::ShutDown(wxCloseEvent &WXUNUSED(evt)) 214{ 215 // Stop the Core Timer 216 delete poll_timer; 217 poll_timer = NULL; 218 219 // Destroy the EC socket 220 m_connect->Destroy(); 221 m_connect = NULL; 222 223 // 224 if (amuledlg) { 225 amuledlg->DlgShutDown(); 226 amuledlg->Destroy(); 227 amuledlg = NULL; 228 } 229 delete m_allUploadingKnownFile; 230 delete stattree; 231} 232 233 234bool CamuleRemoteGuiApp::OnInit() 235{ 236 StartTickTimer(); 237 amuledlg = NULL; 238 239 // Get theApp 240 theApp = &wxGetApp(); 241 242 // Handle uncaught exceptions 243 InstallMuleExceptionHandler(); 244 245 // Parse cmdline arguments. 246 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) { 247 return false; 248 } 249 250 // Create the polling timer 251 poll_timer = new wxTimer(this,ID_CORE_TIMER_EVENT); 252 if (!poll_timer) { 253 AddLogLineCS(_("Fatal Error: Failed to create Poll Timer")); 254 OnExit(); 255 } 256 257 m_connect = new CRemoteConnect(this); 258 259 glob_prefs = new CPreferencesRem(m_connect); 260 long enableZLIB; 261 wxConfig::Get()->Read(wxT("/EC/ZLIB"), &enableZLIB, 1); 262 m_connect->SetCapabilities(enableZLIB != 0, true, false); // ZLIB, UTF8 numbers, notification 263 264 InitCustomLanguages(); 265 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID())); 266 267 if (ShowConnectionDialog()) { 268 AddLogLineNS(_("Going to event loop...")); 269 return true; 270 } 271 272 return false; 273} 274 275 276bool CamuleRemoteGuiApp::CryptoAvailable() const 277{ 278 return thePrefs::IsSecureIdentEnabled(); // good enough 279} 280 281 282bool CamuleRemoteGuiApp::ShowConnectionDialog() 283{ 284 dialog = new CEConnectDlg; 285 286 if (m_skipConnectionDialog) { 287 wxCommandEvent evt; 288 dialog->OnOK(evt); 289 } else if (dialog->ShowModal() != wxID_OK) { 290 dialog->Destroy(); 291 292 return false; 293 } 294 AddLogLineNS(_("Connecting...")); 295 if (!m_connect->ConnectToCore(dialog->Host(), dialog->Port(), 296 dialog->Login(), dialog->PassHash(), 297 wxT("amule-remote"), wxT("0x0001"))) { 298 wxMessageBox(_("Connection failed "),_("ERROR"),wxOK); 299 300 return false; 301 } 302 303 return true; 304} 305 306 307void CamuleRemoteGuiApp::OnECConnection(wxEvent& event) { 308 wxECSocketEvent& evt = *((wxECSocketEvent*)&event); 309 AddLogLineNS(_("Remote GUI EC event handler")); 310 wxString reply = evt.GetServerReply(); 311 AddLogLineC(reply); 312 if (evt.GetResult() == true) { 313 // Connected - go to next init step 314 glob_prefs->LoadRemote(); 315 } else { 316 AddLogLineNS(_("Going down")); 317 if (dialog) { // connect failed 318 wxMessageBox( 319 (CFormat(_("Connection Failed. Unable to connect to %s:%d\n")) % dialog->Host() % dialog->Port()) + reply, 320 _("ERROR"), wxOK); 321 } else { // server disconnected (probably terminated) later 322 wxMessageBox(_("Connection closed - aMule has terminated probably."), _("ERROR"), wxOK); 323 } 324 ExitMainLoop(); 325 } 326} 327 328 329void CamuleRemoteGuiApp::OnECInitDone(wxEvent& ) 330{ 331 Startup(); 332} 333 334 335void CamuleRemoteGuiApp::OnNotifyEvent(CMuleGUIEvent& evt) 336{ 337 evt.Notify(); 338} 339 340 341void CamuleRemoteGuiApp::Startup() { 342 343 if (dialog->SaveUserPass()) { 344 wxConfig::Get()->Write(wxT("/EC/Host"), dialog->Host()); 345 wxConfig::Get()->Write(wxT("/EC/Port"), dialog->Port()); 346 wxConfig::Get()->Write(wxT("/EC/Password"), dialog->PassHash()); 347 } 348 dialog->Destroy(); 349 dialog = NULL; 350 351 m_ConnState = 0; 352 m_clientID = 0; 353 354 serverconnect = new CServerConnectRem(m_connect); 355 m_statistics = new CStatistics(*m_connect); 356 stattree = new CStatTreeRem(m_connect); 357 358 clientlist = new CUpDownClientListRem(m_connect); 359 searchlist = new CSearchListRem(m_connect); 360 serverlist = new CServerListRem(m_connect); 361 friendlist = new CFriendListRem(m_connect); 362 363 364 sharedfiles = new CSharedFilesRem(m_connect); 365 knownfiles = new CKnownFilesRem(m_connect); 366 367 downloadqueue = new CDownQueueRem(m_connect); 368 ipfilter = new CIPFilterRem(m_connect); 369 370 m_allUploadingKnownFile = new CKnownFile; 371 372 // Create main dialog 373 InitGui(m_geometryEnabled, m_geometryString); 374 375 // Forward wxLog events to CLogger 376 wxLog::SetActiveTarget(new CLoggerTarget); 377 knownfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); 378 379 // Start the Poll Timer 380 poll_timer->Start(1000); 381 amuledlg->StartGuiTimer(); 382 383 // Now activate GeoIP, so that the download dialog doesn't get destroyed immediately 384#ifdef ENABLE_IP2COUNTRY 385 if (thePrefs::IsGeoIPEnabled()) { 386 amuledlg->m_IP2Country->Enable(); 387 } 388#endif 389} 390 391 392int CamuleRemoteGuiApp::ShowAlert(wxString msg, wxString title, int flags) 393{ 394 return CamuleGuiBase::ShowAlert(msg, title, flags); 395} 396 397 398void CamuleRemoteGuiApp::AddRemoteLogLine(const wxString& line) 399{ 400 amuledlg->AddLogLine(line); 401} 402 403int CamuleRemoteGuiApp::InitGui(bool geometry_enabled, wxString &geom_string) 404{ 405 CamuleGuiBase::InitGui(geometry_enabled, geom_string); 406 SetTopWindow(amuledlg); 407 AddLogLineN(_("Ready")); // The first log line after the window is up triggers output of all the ones before 408 return 0; 409} 410 411 412bool CamuleRemoteGuiApp::CopyTextToClipboard(wxString strText) 413{ 414 return CamuleGuiBase::CopyTextToClipboard(strText); 415} 416 417 418uint32 CamuleRemoteGuiApp::GetPublicIP() 419{ 420 return 0; 421} 422 423 424wxString CamuleRemoteGuiApp::GetLog(bool reset) 425{ 426 if (reset) { 427 amuledlg->ResetLog(ID_LOGVIEW); 428 CECPacket req(EC_OP_RESET_LOG); 429 m_connect->SendPacket(&req); 430 } 431 return wxEmptyString; 432} 433 434 435wxString CamuleRemoteGuiApp::GetServerLog(bool) 436{ 437 return wxEmptyString; 438} 439 440 441bool CamuleRemoteGuiApp::AddServer(CServer * server, bool) 442{ 443 CECPacket req(EC_OP_SERVER_ADD); 444 req.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, CFormat(wxT("%s:%d")) % server->GetAddress() % server->GetPort())); 445 req.AddTag(CECTag(EC_TAG_SERVER_NAME, server->GetListName())); 446 m_connect->SendPacket(&req); 447 448 return true; 449} 450 451 452bool CamuleRemoteGuiApp::IsFirewalled() const 453{ 454 if (IsConnectedED2K() && !serverconnect->IsLowID()) { 455 return false; 456 } 457 458 return IsFirewalledKad(); 459} 460 461 462bool CamuleRemoteGuiApp::IsConnectedED2K() const { 463 return serverconnect && serverconnect->IsConnected(); 464} 465 466 467void CamuleRemoteGuiApp::StartKad() { 468 m_connect->StartKad(); 469} 470 471 472void CamuleRemoteGuiApp::StopKad() { 473 m_connect->StopKad(); 474} 475 476 477void CamuleRemoteGuiApp::BootstrapKad(uint32 ip, uint16 port) 478{ 479 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP); 480 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ip)); 481 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, port)); 482 483 m_connect->SendPacket(&req); 484} 485 486 487void CamuleRemoteGuiApp::UpdateNotesDat(const wxString& url) 488{ 489 CECPacket req(EC_OP_KAD_UPDATE_FROM_URL); 490 req.AddTag(CECTag(EC_TAG_KADEMLIA_UPDATE_URL, url)); 491 492 m_connect->SendPacket(&req); 493} 494 495 496void CamuleRemoteGuiApp::DisconnectED2K() { 497 if (IsConnectedED2K()) { 498 m_connect->DisconnectED2K(); 499 } 500} 501 502 503uint32 CamuleRemoteGuiApp::GetED2KID() const 504{ 505 return serverconnect ? serverconnect->GetClientID() : 0; 506} 507 508 509uint32 CamuleRemoteGuiApp::GetID() const 510{ 511 return m_clientID; 512} 513 514 515void CamuleRemoteGuiApp::ShowUserCount() { 516 wxString buffer; 517 518 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s"); 519 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s"); 520 521 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) { 522 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetED2KFiles()) % CastItoIShort(theStats::GetKadFiles()); 523 } else if (thePrefs::GetNetworkED2K()) { 524 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetED2KUsers()) % CastItoIShort(theStats::GetED2KFiles()); 525 } else if (thePrefs::GetNetworkKademlia()) { 526 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(theStats::GetKadUsers()) % CastItoIShort(theStats::GetKadFiles()); 527 } else { 528 buffer = _("No networks selected"); 529 } 530 531 Notify_ShowUserCount(buffer); 532} 533 534 535/* 536 * Preferences: holds both local and remote settings. 537 * 538 * First, everything is loaded from local config file. Later, settings 539 * that are relevant on remote side only are loaded thru EC 540 */ 541CPreferencesRem::CPreferencesRem(CRemoteConnect *conn) 542{ 543 m_conn = conn; 544 545 // 546 // Settings queried from remote side 547 // 548 m_exchange_send_selected_prefs = 549 EC_PREFS_GENERAL | 550 EC_PREFS_CONNECTIONS | 551 EC_PREFS_MESSAGEFILTER | 552 EC_PREFS_ONLINESIG | 553 EC_PREFS_SERVERS | 554 EC_PREFS_FILES | 555 EC_PREFS_SRCDROP | 556 EC_PREFS_DIRECTORIES | 557 EC_PREFS_SECURITY | 558 EC_PREFS_CORETWEAKS | 559 EC_PREFS_REMOTECONTROLS | 560 EC_PREFS_KADEMLIA; 561 m_exchange_recv_selected_prefs = 562 m_exchange_send_selected_prefs | 563 EC_PREFS_CATEGORIES; 564} 565 566 567void CPreferencesRem::HandlePacket(const CECPacket *packet) 568{ 569 ((CEC_Prefs_Packet *)packet)->Apply(); 570 571 const CECTag *cat_tags = packet->GetTagByName(EC_TAG_PREFS_CATEGORIES); 572 if (cat_tags) { 573 for (CECTag::const_iterator it = cat_tags->begin(); it != cat_tags->end(); it++) { 574 const CECTag &cat_tag = *it; 575 Category_Struct *cat = new Category_Struct; 576 cat->title = cat_tag.GetTagByName(EC_TAG_CATEGORY_TITLE)->GetStringData(); 577 cat->path = CPath(cat_tag.GetTagByName(EC_TAG_CATEGORY_PATH)->GetStringData()); 578 cat->comment = cat_tag.GetTagByName(EC_TAG_CATEGORY_COMMENT)->GetStringData(); 579 cat->color = cat_tag.GetTagByName(EC_TAG_CATEGORY_COLOR)->GetInt(); 580 cat->prio = cat_tag.GetTagByName(EC_TAG_CATEGORY_PRIO)->GetInt(); 581 theApp->glob_prefs->AddCat(cat); 582 } 583 } else { 584 Category_Struct *cat = new Category_Struct; 585 cat->title = _("All"); 586 cat->color = 0; 587 cat->prio = PR_NORMAL; 588 theApp->glob_prefs->AddCat(cat); 589 } 590 wxECInitDoneEvent event; 591 theApp->AddPendingEvent(event); 592 593} 594 595 596bool CPreferencesRem::LoadRemote() 597{ 598 // 599 // override local settings with remote 600 CECPacket req(EC_OP_GET_PREFERENCES, EC_DETAIL_UPDATE); 601 602 // bring categories too 603 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, m_exchange_recv_selected_prefs)); 604 605 m_conn->SendRequest(this, &req); 606 607 return true; 608} 609 610 611void CPreferencesRem::SendToRemote() 612{ 613 CEC_Prefs_Packet pref_packet(m_exchange_send_selected_prefs, EC_DETAIL_UPDATE, EC_DETAIL_FULL); 614 m_conn->SendPacket(&pref_packet); 615} 616 617 618class CCatHandler : public CECPacketHandlerBase { 619 virtual void HandlePacket(const CECPacket *packet); 620}; 621 622 623void CCatHandler::HandlePacket(const CECPacket *packet) 624{ 625 if (packet->GetOpCode() == EC_OP_FAILED) { 626 const CECTag * catTag = packet->GetTagByName(EC_TAG_CATEGORY); 627 const CECTag * pathTag = packet->GetTagByName(EC_TAG_CATEGORY_PATH); 628 if (catTag && pathTag && catTag->GetInt() < theApp->glob_prefs->GetCatCount()) { 629 int cat = catTag->GetInt(); 630 Category_Struct* cs = theApp->glob_prefs->GetCategory(cat); 631 wxMessageBox(CFormat(_("Can't create directory '%s' for category '%s', keeping directory '%s'.")) 632 % cs->path.GetPrintable() % cs->title % pathTag->GetStringData(), 633 _("ERROR"), wxOK); 634 cs->path = CPath(pathTag->GetStringData()); 635 theApp->amuledlg->m_transferwnd->UpdateCategory(cat); 636 theApp->amuledlg->m_transferwnd->downloadlistctrl->Refresh(); 637 } 638 } 639 delete this; 640} 641 642 643bool CPreferencesRem::CreateCategory( 644 Category_Struct *& category, 645 const wxString& name, 646 const CPath& path, 647 const wxString& comment, 648 uint32 color, 649 uint8 prio) 650{ 651 CECPacket req(EC_OP_CREATE_CATEGORY); 652 CEC_Category_Tag tag(0xffffffff, name, path.GetRaw(), comment, color, prio); 653 req.AddTag(tag); 654 m_conn->SendRequest(new CCatHandler, &req); 655 656 category = new Category_Struct(); 657 category->path = path; 658 category->title = name; 659 category->comment = comment; 660 category->color = color; 661 category->prio = prio; 662 663 AddCat(category); 664 665 return true; 666} 667 668 669bool CPreferencesRem::UpdateCategory( 670 uint8 cat, 671 const wxString& name, 672 const CPath& path, 673 const wxString& comment, 674 uint32 color, 675 uint8 prio) 676{ 677 CECPacket req(EC_OP_UPDATE_CATEGORY); 678 CEC_Category_Tag tag(cat, name, path.GetRaw(), comment, color, prio); 679 req.AddTag(tag); 680 m_conn->SendRequest(new CCatHandler, &req); 681 682 Category_Struct *category = m_CatList[cat]; 683 category->path = path; 684 category->title = name; 685 category->comment = comment; 686 category->color = color; 687 category->prio = prio; 688 689 return true; 690} 691 692 693void CPreferencesRem::RemoveCat(uint8 cat) 694{ 695 CECPacket req(EC_OP_DELETE_CATEGORY); 696 CEC_Category_Tag tag(cat, EC_DETAIL_CMD); 697 req.AddTag(tag); 698 m_conn->SendPacket(&req); 699 CPreferences::RemoveCat(cat); 700} 701 702 703// 704// Container implementation 705// 706CServerConnectRem::CServerConnectRem(CRemoteConnect *conn) 707{ 708 m_CurrServer = 0; 709 m_Conn = conn; 710} 711 712 713void CServerConnectRem::ConnectToAnyServer() 714{ 715 CECPacket req(EC_OP_SERVER_CONNECT); 716 m_Conn->SendPacket(&req); 717} 718 719 720void CServerConnectRem::StopConnectionTry() 721{ 722 // lfroen: isn't Disconnect the same ? 723} 724 725 726void CServerConnectRem::Disconnect() 727{ 728 CECPacket req(EC_OP_SERVER_DISCONNECT); 729 m_Conn->SendPacket(&req); 730} 731 732 733void CServerConnectRem::ConnectToServer(CServer *server) 734{ 735 m_Conn->ConnectED2K(server->GetIP(), server->GetPort()); 736} 737 738 739void CServerConnectRem::HandlePacket(const CECPacket *packet) 740{ 741 CEC_ConnState_Tag *tag = 742 (CEC_ConnState_Tag *)packet->GetTagByName(EC_TAG_CONNSTATE); 743 if (!tag) { 744 return; 745 } 746 747 theApp->m_ConnState = 0; 748 CServer *server; 749 m_ID = tag->GetEd2kId(); 750 theApp->m_clientID = tag->GetClientId(); 751 752 if (tag->IsConnectedED2K()) { 753 CECTag *srvtag = tag->GetTagByName(EC_TAG_SERVER); 754 if (srvtag) { 755 server = theApp->serverlist->GetByID(srvtag->GetInt()); 756 if (server != m_CurrServer) { 757 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(server, true); 758 m_CurrServer = server; 759 } 760 } 761 theApp->m_ConnState |= CONNECTED_ED2K; 762 } else if ( m_CurrServer ) { 763 theApp->amuledlg->m_serverwnd->serverlistctrl->HighlightServer(m_CurrServer, false); 764 m_CurrServer = 0; 765 } 766 767 if (tag->IsConnectedKademlia()) { 768 if (tag->IsKadFirewalled()) { 769 theApp->m_ConnState |= CONNECTED_KAD_FIREWALLED; 770 } else { 771 theApp->m_ConnState |= CONNECTED_KAD_OK; 772 } 773 } else { 774 if (tag->IsKadRunning()) { 775 theApp->m_ConnState |= CONNECTED_KAD_NOT; 776 } 777 } 778 779 theApp->amuledlg->ShowConnectionState(); 780} 781 782 783/* 784 * Server list: host list of ed2k servers. 785 */ 786CServerListRem::CServerListRem(CRemoteConnect *conn) 787: 788CRemoteContainer<CServer, uint32, CEC_Server_Tag>(conn, true) 789{ 790} 791 792 793void CServerListRem::HandlePacket(const CECPacket *) 794{ 795 // There is no packet for the server list, it is part of the general update packet 796 wxFAIL; 797 // CRemoteContainer<CServer, uint32, CEC_Server_Tag>::HandlePacket(packet); 798} 799 800 801void CServerListRem::UpdateServerMetFromURL(wxString url) 802{ 803 CECPacket req(EC_OP_SERVER_UPDATE_FROM_URL); 804 req.AddTag(CECTag(EC_TAG_SERVERS_UPDATE_URL, url)); 805 806 m_conn->SendPacket(&req); 807} 808 809 810void CServerListRem::SetStaticServer(CServer* server, bool isStatic) 811{ 812 // update display right away 813 server->SetIsStaticMember(isStatic); 814 Notify_ServerRefresh(server); 815 816 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO); 817 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID())); 818 req.AddTag(CECTag(EC_TAG_SERVER_STATIC, isStatic)); 819 820 m_conn->SendPacket(&req); 821} 822 823 824void CServerListRem::SetServerPrio(CServer* server, uint32 prio) 825{ 826 // update display right away 827 server->SetPreference(prio); 828 Notify_ServerRefresh(server); 829 830 CECPacket req(EC_OP_SERVER_SET_STATIC_PRIO); 831 req.AddTag(CECTag(EC_TAG_SERVER, server->ECID())); 832 req.AddTag(CECTag(EC_TAG_SERVER_PRIO, prio)); 833 834 m_conn->SendPacket(&req); 835} 836 837 838void CServerListRem::RemoveServer(CServer* server) 839{ 840 m_conn->RemoveServer(server->GetIP(),server->GetPort()); 841} 842 843 844void CServerListRem::UpdateUserFileStatus(CServer *server) 845{ 846 if (server) { 847 m_TotalUser = server->GetUsers(); 848 m_TotalFile = server->GetFiles(); 849 } 850} 851 852 853CServer *CServerListRem::GetServerByAddress(const wxString& WXUNUSED(address), uint16 WXUNUSED(port)) const 854{ 855 // It's ok to return 0 for context where this code is used in remote gui 856 return 0; 857} 858 859CServer *CServerListRem::GetServerByIPTCP(uint32 WXUNUSED(nIP), uint16 WXUNUSED(nPort)) const 860{ 861 // It's ok to return 0 for context where this code is used in remote gui 862 return 0; 863} 864 865CServer *CServerListRem::CreateItem(CEC_Server_Tag *tag) 866{ 867 CServer * server = new CServer(tag); 868 ProcessItemUpdate(tag, server); 869 return server; 870} 871 872 873void CServerListRem::DeleteItem(CServer *in_srv) 874{ 875 CScopedPtr<CServer> srv(in_srv); 876 theApp->amuledlg->m_serverwnd->serverlistctrl->RemoveServer(srv.get()); 877} 878 879 880uint32 CServerListRem::GetItemID(CServer *server) 881{ 882 return server->ECID(); 883} 884 885 886void CServerListRem::ProcessItemUpdate(CEC_Server_Tag * tag, CServer * server) 887{ 888 if (!tag->HasChildTags()) { 889 return; 890 } 891 tag->ServerName(& server->listname); 892 tag->ServerDesc(& server->description); 893 tag->ServerVersion(& server->m_strVersion); 894 tag->GetMaxUsers(& server->maxusers); 895 896 tag->GetFiles(& server->files); 897 tag->GetUsers(& server->users); 898 899 tag->GetPrio(& server->preferences); // SRV_PR_NORMAL = 0, so it's ok 900 tag->GetStatic(& server->staticservermember); 901 902 tag->GetPing(& server->ping); 903 tag->GetFailed(& server->failedcount); 904 905 theApp->amuledlg->m_serverwnd->serverlistctrl->RefreshServer(server); 906} 907 908 909CServer::CServer(CEC_Server_Tag *tag) : CECID(tag->GetInt()) 910{ 911 ip = tag->GetTagByNameSafe(EC_TAG_SERVER_IP)->GetInt(); 912 port = tag->GetTagByNameSafe(EC_TAG_SERVER_PORT)->GetInt(); 913 914 Init(); 915} 916 917 918/* 919 * IP filter 920 */ 921CIPFilterRem::CIPFilterRem(CRemoteConnect* conn) 922{ 923 m_conn = conn; 924} 925 926 927void CIPFilterRem::Reload() 928{ 929 CECPacket req(EC_OP_IPFILTER_RELOAD); 930 m_conn->SendPacket(&req); 931} 932 933 934void CIPFilterRem::Update(wxString url) 935{ 936 CECPacket req(EC_OP_IPFILTER_UPDATE); 937 req.AddTag(CECTag(EC_TAG_STRING, url)); 938 939 m_conn->SendPacket(&req); 940} 941 942 943/* 944 * Shared files list 945 */ 946CSharedFilesRem::CSharedFilesRem(CRemoteConnect *conn) 947{ 948 m_conn = conn; 949} 950 951 952void CSharedFilesRem::Reload(bool, bool) 953{ 954 CECPacket req(EC_OP_SHAREDFILES_RELOAD); 955 956 m_conn->SendPacket(&req); 957} 958 959 960bool CSharedFilesRem::RenameFile(CKnownFile* file, const CPath& newName) 961{ 962 // We use the printable name, as the filename originated from user input, 963 // and the filesystem name might not be valid on the remote host. 964 const wxString strNewName = newName.GetPrintable(); 965 966 CECPacket request(EC_OP_RENAME_FILE); 967 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash())); 968 request.AddTag(CECTag(EC_TAG_PARTFILE_NAME, strNewName)); 969 970 m_conn->SendPacket(&request); 971 972 return true; 973} 974 975 976void CSharedFilesRem::SetFileCommentRating(CKnownFile* file, const wxString& newComment, int8 newRating) 977{ 978 CECPacket request(EC_OP_SHARED_FILE_SET_COMMENT); 979 request.AddTag(CECTag(EC_TAG_KNOWNFILE, file->GetFileHash())); 980 request.AddTag(CECTag(EC_TAG_KNOWNFILE_COMMENT, newComment)); 981 request.AddTag(CECTag(EC_TAG_KNOWNFILE_RATING, newRating)); 982 983 m_conn->SendPacket(&request); 984} 985 986 987void CSharedFilesRem::CopyFileList(std::vector<CKnownFile*>& out_list) const 988{ 989 out_list.reserve(size()); 990 for (const_iterator it = begin(); it != end(); it++) { 991 out_list.push_back(it->second); 992 } 993} 994 995 996void CKnownFilesRem::DeleteItem(CKnownFile * file) 997{ 998 uint32 id = file->ECID(); 999 if (theApp->sharedfiles->count(id)) { 1000 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->RemoveFile(file); 1001 theApp->sharedfiles->erase(id); 1002 } 1003 if (theApp->downloadqueue->count(id)) { 1004 theApp->amuledlg->m_transferwnd->downloadlistctrl->RemoveFile((CPartFile *) file); 1005 theApp->downloadqueue->erase(id); 1006 } 1007 delete file; 1008} 1009 1010 1011uint32 CKnownFilesRem::GetItemID(CKnownFile *file) 1012{ 1013 return file->ECID(); 1014} 1015 1016 1017void CKnownFilesRem::ProcessItemUpdate(CEC_SharedFile_Tag *tag, CKnownFile *file) 1018{ 1019 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS); 1020 if (parttag) { 1021 const uint8 *data = file->m_partStatus.Decode( 1022 (uint8 *)parttag->GetTagData(), 1023 parttag->GetTagDataLen()); 1024 for(int i = 0; i < file->GetPartCount(); ++i) { 1025 file->m_AvailPartFrequency[i] = data[i]; 1026 } 1027 } 1028 wxString fileName; 1029 if (tag->FileName(fileName)) { 1030 file->SetFileName(CPath(fileName)); 1031 } 1032 if (tag->FilePath(fileName)) { 1033 file->m_filePath = CPath(fileName); 1034 } 1035 tag->UpPrio(&file->m_iUpPriorityEC); 1036 tag->GetAICHHash(file->m_AICHMasterHash); 1037 tag->GetRequests(&file->statistic.requested); 1038 tag->GetAllRequests(&file->statistic.alltimerequested); 1039 tag->GetAccepts(&file->statistic.accepted); 1040 tag->GetAllAccepts(&file->statistic.alltimeaccepted); 1041 tag->GetXferred(&file->statistic.transferred); 1042 tag->GetAllXferred(&file->statistic.alltimetransferred); 1043 tag->UpPrio(&file->m_iUpPriorityEC); 1044 if (file->m_iUpPriorityEC >= 10) { 1045 file->m_iUpPriority = file->m_iUpPriorityEC - 10; 1046 file->m_bAutoUpPriority = true; 1047 } else { 1048 file->m_iUpPriority = file->m_iUpPriorityEC; 1049 file->m_bAutoUpPriority = false; 1050 } 1051 tag->GetCompleteSourcesLow(&file->m_nCompleteSourcesCountLo); 1052 tag->GetCompleteSourcesHigh(&file->m_nCompleteSourcesCountHi); 1053 tag->GetCompleteSources(&file->m_nCompleteSourcesCount); 1054 1055 tag->GetOnQueue(&file->m_queuedCount); 1056 1057 tag->GetComment(file->m_strComment); 1058 tag->GetRating(file->m_iRating); 1059 1060 requested += file->statistic.requested; 1061 transferred += file->statistic.transferred; 1062 accepted += file->statistic.transferred; 1063 1064 if (!m_initialUpdate) { 1065 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->UpdateItem(file); 1066 } 1067 1068 if (file->IsPartFile()) { 1069 ProcessItemUpdatePartfile((CEC_PartFile_Tag *) tag, (CPartFile *) file); 1070 } 1071} 1072 1073void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio) 1074{ 1075 CECPacket req(EC_OP_SHARED_SET_PRIO); 1076 1077 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash()); 1078 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio)); 1079 1080 req.AddTag(hashtag); 1081 1082 m_conn->SendPacket(&req); 1083} 1084 1085void CKnownFilesRem::ProcessUpdate(const CECTag *reply, CECPacket *, int) 1086{ 1087 requested = 0; 1088 transferred = 0; 1089 accepted = 0; 1090 1091 std::set<uint32> core_files; 1092 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); it++) { 1093 const CECTag * curTag = &*it; 1094 ec_tagname_t tagname = curTag->GetTagName(); 1095 if (tagname == EC_TAG_CLIENT) { 1096 theApp->clientlist->ProcessUpdate(curTag, NULL, EC_TAG_CLIENT); 1097 } else if (tagname == EC_TAG_SERVER) { 1098 theApp->serverlist->ProcessUpdate(curTag, NULL, EC_TAG_SERVER); 1099 } else if (tagname == EC_TAG_FRIEND) { 1100 theApp->friendlist->ProcessUpdate(curTag, NULL, EC_TAG_FRIEND); 1101 } else if (tagname == EC_TAG_KNOWNFILE || tagname == EC_TAG_PARTFILE) { 1102 CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *) curTag; 1103 uint32 id = tag->ID(); 1104 bool isNew = true; 1105 if (!m_initialUpdate) { 1106 core_files.insert(id); 1107 std::map<uint32, CKnownFile*>::iterator it2 = m_items_hash.find(id); 1108 if (it2 != m_items_hash.end() ) { 1109 // Item already known: update it 1110 if (tag->HasChildTags()) { 1111 ProcessItemUpdate(tag, it2->second); 1112 } 1113 isNew = false; 1114 } 1115 } 1116 if (isNew) { 1117 CKnownFile * newFile; 1118 if (tag->GetTagName() == EC_TAG_PARTFILE) { 1119 CPartFile *file = new CPartFile((CEC_PartFile_Tag *) tag); 1120 ProcessItemUpdate(tag, file); 1121 (*theApp->downloadqueue)[id] = file; 1122 theApp->amuledlg->m_transferwnd->downloadlistctrl->AddFile(file); 1123 newFile = file; 1124 } else { 1125 newFile = new CKnownFile(tag); 1126 ProcessItemUpdate(tag, newFile); 1127 (*theApp->sharedfiles)[id] = newFile; 1128 if (!m_initialUpdate) { 1129 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(newFile); 1130 } 1131 } 1132 AddItem(newFile); 1133 } 1134 } 1135 } 1136 1137 if (m_initialUpdate) { 1138 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFileList(); 1139 m_initialUpdate = false; 1140 } else { 1141 // remove items no longer present 1142 for(iterator it = begin(); it != end();) { 1143 iterator it2 = it++; 1144 if (!core_files.count(GetItemID(*it2))) { 1145 RemoveItem(it2); // This calls DeleteItem, where it is removed from lists and views. 1146 } 1147 } 1148 } 1149} 1150 1151CKnownFilesRem::CKnownFilesRem(CRemoteConnect * conn) : CRemoteContainer<CKnownFile, uint32, CEC_SharedFile_Tag>(conn, true) 1152{ 1153 requested = 0; 1154 transferred = 0; 1155 accepted = 0; 1156 m_initialUpdate = true; 1157} 1158 1159 1160/* 1161 * List of uploading and waiting clients. 1162 */ 1163CUpDownClientListRem::CUpDownClientListRem(CRemoteConnect *conn) 1164: 1165CRemoteContainer<CClientRef, uint32, CEC_UpDownClient_Tag>(conn, true) 1166{ 1167} 1168 1169 1170CClientRef::CClientRef(CEC_UpDownClient_Tag *tag) 1171{ 1172 m_client = new CUpDownClient(tag); 1173#ifdef DEBUG_ZOMBIE_CLIENTS 1174 m_client->Link(wxT("TAG")); 1175#else 1176 m_client->Link(); 1177#endif 1178} 1179 1180 1181CUpDownClient::CUpDownClient(CEC_UpDownClient_Tag *tag) : CECID(tag->ID()) 1182{ 1183 m_linked = 0; 1184#ifdef DEBUG_ZOMBIE_CLIENTS 1185 m_linkedDebug = false; 1186#endif 1187 // Clients start up empty, then get asked for their data. 1188 // So all data here is processed in ProcessItemUpdate and thus updatable. 1189 m_bEmuleProtocol = false; 1190 m_AvailPartCount = 0; 1191 m_clientSoft = 0; 1192 m_nDownloadState = 0; 1193 m_Friend = NULL; 1194 m_bFriendSlot = false; 1195 m_nKadPort = 0; 1196 m_kBpsDown = 0; 1197 m_dwUserIP = 0; 1198 m_lastDownloadingPart = 0xffff; 1199 m_nextRequestedPart = 0xffff; 1200 m_obfuscationStatus = 0; 1201 m_nOldRemoteQueueRank = 0; 1202 m_nRemoteQueueRank = 0; 1203 m_reqfile = NULL; 1204 m_score = 0; 1205 m_dwServerIP = 0; 1206 m_nServerPort = 0; 1207 m_nSourceFrom = SF_NONE; 1208 m_nTransferredDown = 0; 1209 m_nTransferredUp = 0; 1210 m_nUpDatarate = 0; 1211 m_uploadingfile = NULL; 1212 m_waitingPosition = 0; 1213 m_nUploadState = 0; 1214 m_nUserIDHybrid = 0; 1215 m_nUserPort = 0; 1216 m_nClientVersion = 0; 1217 m_fNoViewSharedFiles = true; 1218 m_identState = IS_NOTAVAILABLE; 1219 m_bRemoteQueueFull = false; 1220 1221 credits = new CClientCredits(new CreditStruct()); 1222} 1223 1224#ifdef DEBUG_ZOMBIE_CLIENTS 1225void CUpDownClient::Unlink(const wxString& from) 1226{ 1227 std::multiset<wxString>::iterator it = m_linkedFrom.find(from); 1228 if (it != m_linkedFrom.end()) { 1229 m_linkedFrom.erase(it); 1230 } 1231 m_linked--; 1232 if (!m_linked) { 1233 if (m_linkedDebug) { 1234 AddLogLineN(CFormat(wxT("Last reference to client %d %p unlinked, delete it.")) % ECID() % this); 1235 } 1236 delete this; 1237 } 1238} 1239 1240#else 1241 1242void CUpDownClient::Unlink() 1243{ 1244 m_linked--; 1245 if (!m_linked) { 1246 delete this; 1247 } 1248} 1249#endif 1250 1251 1252uint64 CUpDownClient::GetDownloadedTotal() const 1253{ 1254 return credits->GetDownloadedTotal(); 1255} 1256 1257 1258uint64 CUpDownClient::GetUploadedTotal() const 1259{ 1260 return credits->GetUploadedTotal(); 1261} 1262 1263 1264double CUpDownClient::GetScoreRatio() const 1265{ 1266 return credits->GetScoreRatio(GetIP(), theApp->CryptoAvailable()); 1267} 1268 1269/* End Warning */ 1270 1271 1272CUpDownClient::~CUpDownClient() 1273{ 1274 delete credits; 1275} 1276 1277 1278CClientRef *CUpDownClientListRem::CreateItem(CEC_UpDownClient_Tag *tag) 1279{ 1280 CClientRef *client = new CClientRef(tag); 1281 ProcessItemUpdate(tag, client); 1282 1283 return client; 1284} 1285 1286 1287void CUpDownClientListRem::DeleteItem(CClientRef *clientref) 1288{ 1289 CUpDownClient* client = clientref->GetClient(); 1290 if (client->m_reqfile) { 1291 client->m_reqfile->DelSource(client); 1292 client->m_reqfile = NULL; 1293 } 1294 Notify_SourceCtrlRemoveSource(client->ECID(), (CPartFile*) NULL); 1295 1296 if (client->m_uploadingfile) { 1297 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies 1298 client->m_uploadingfile = NULL; 1299 } 1300 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); // in case it vanished directly while uploading 1301 Notify_SharedCtrlRemoveClient(client->ECID(), (CKnownFile*) NULL); 1302 1303 if (client->m_Friend) { 1304 client->m_Friend->UnLinkClient(); // this notifies 1305 client->m_Friend = NULL; 1306 } 1307 1308#ifdef DEBUG_ZOMBIE_CLIENTS 1309 if (client->m_linked > 1) { 1310 AddLogLineC(CFormat(wxT("Client %d still linked in %d places: %s")) % client->ECID() % (client->m_linked - 1) % client->GetLinkedFrom()); 1311 client->m_linkedDebug = true; 1312 } 1313#endif 1314 1315 delete clientref; 1316} 1317 1318 1319uint32 CUpDownClientListRem::GetItemID(CClientRef *client) 1320{ 1321 return client->ECID(); 1322} 1323 1324 1325void CUpDownClientListRem::ProcessItemUpdate( 1326 CEC_UpDownClient_Tag *tag, 1327 CClientRef *clientref) 1328{ 1329 if (!tag->HasChildTags()) { 1330 return; // speed exit for clients without any change 1331 } 1332 CUpDownClient *client = clientref->GetClient(); 1333 1334 tag->UserID(&client->m_nUserIDHybrid); 1335 tag->ClientName(&client->m_Username); 1336 // Client Software 1337 bool sw_updated = false; 1338 if (tag->ClientSoftware(client->m_clientSoft)) { 1339 client->m_clientSoftString = GetSoftName(client->m_clientSoft); 1340 sw_updated = true; 1341 } 1342 if (tag->SoftVerStr(client->m_clientVerString) || sw_updated) { 1343 if (client->m_clientSoftString == _("Unknown")) { 1344 client->m_fullClientVerString = client->m_clientSoftString; 1345 } else { 1346 client->m_fullClientVerString = client->m_clientSoftString + wxT(" ") + client->m_clientVerString; 1347 } 1348 } 1349 // User hash 1350 tag->UserHash(&client->m_UserHash); 1351 1352 // User IP:Port 1353 tag->UserIP(client->m_dwUserIP); 1354 tag->UserPort(&client->m_nUserPort); 1355 1356 // Server IP:Port 1357 tag->ServerIP(&client->m_dwServerIP); 1358 tag->ServerPort(&client->m_nServerPort); 1359 tag->ServerName(&client->m_ServerName); 1360 1361 tag->KadPort(client->m_nKadPort); 1362 tag->FriendSlot(client->m_bFriendSlot); 1363 1364 tag->GetCurrentIdentState(&client->m_identState); 1365 tag->ObfuscationStatus(client->m_obfuscationStatus); 1366 tag->HasExtendedProtocol(&client->m_bEmuleProtocol); 1367 1368 tag->WaitingPosition(&client->m_waitingPosition); 1369 tag->RemoteQueueRank(&client->m_nRemoteQueueRank); 1370 client->m_bRemoteQueueFull = client->m_nRemoteQueueRank == 0xffff; 1371 tag->OldRemoteQueueRank(&client->m_nOldRemoteQueueRank); 1372 1373 tag->ClientDownloadState(client->m_nDownloadState); 1374 if (tag->ClientUploadState(client->m_nUploadState)) { 1375 if (client->m_nUploadState == US_UPLOADING) { 1376 theApp->m_allUploadingKnownFile->AddUploadingClient(client); 1377 } else { 1378 theApp->m_allUploadingKnownFile->RemoveUploadingClient(client); 1379 } 1380 } 1381 1382 tag->SpeedUp(&client->m_nUpDatarate); 1383 if ( client->m_nDownloadState == DS_DOWNLOADING ) { 1384 tag->SpeedDown(&client->m_kBpsDown); 1385 } else { 1386 client->m_kBpsDown = 0; 1387 } 1388 1389 //tag->WaitTime(&client->m_WaitTime); 1390 //tag->XferTime(&client->m_UpStartTimeDelay); 1391 //tag->LastReqTime(&client->m_dwLastUpRequest); 1392 //tag->QueueTime(&client->m_WaitStartTime); 1393 1394 CreditStruct *credit_struct = 1395 (CreditStruct *)client->credits->GetDataStruct(); 1396 tag->XferUp(&credit_struct->uploaded); 1397 tag->XferUpSession(&client->m_nTransferredUp); 1398 1399 tag->XferDown(&credit_struct->downloaded); 1400 tag->XferDownSession(&client->m_nTransferredDown); 1401 1402 tag->Score(&client->m_score); 1403 1404 tag->NextRequestedPart(client->m_nextRequestedPart); 1405 tag->LastDownloadingPart(client->m_lastDownloadingPart); 1406 1407 uint8 sourceFrom = 0; 1408 if (tag->GetSourceFrom(sourceFrom)) { 1409 client->m_nSourceFrom = (ESourceFrom)sourceFrom; 1410 } 1411 1412 tag->RemoteFilename(client->m_clientFilename); 1413 tag->DisableViewShared(client->m_fNoViewSharedFiles); 1414 tag->Version(client->m_nClientVersion); 1415 tag->ModVersion(client->m_strModVersion); 1416 tag->OSInfo(client->m_sClientOSInfo); 1417 tag->AvailableParts(client->m_AvailPartCount); 1418 1419 // Download client 1420 uint32 fileID; 1421 bool notified = false; 1422 if (tag->RequestFile(fileID)) { 1423 if (client->m_reqfile) { 1424 Notify_SourceCtrlRemoveSource(client->ECID(), client->m_reqfile); 1425 client->m_reqfile->DelSource(client); 1426 client->m_reqfile = NULL; 1427 client->m_downPartStatus.clear(); 1428 } 1429 CKnownFile * kf = theApp->knownfiles->GetByID(fileID); 1430 if (kf && kf->IsCPartFile()) { 1431 client->m_reqfile = (CPartFile *) kf; 1432 client->m_reqfile->AddSource(client); 1433 client->m_downPartStatus.setsize(kf->GetPartCount(), 0); 1434 Notify_SourceCtrlAddSource(client->m_reqfile, CCLIENTREF(client, wxT("AddSource")), A4AF_SOURCE); 1435 notified = true; 1436 } 1437 } 1438 1439 // Part status 1440 CECTag * partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_PART_STATUS); 1441 if (partStatusTag) { 1442 if (partStatusTag->GetTagDataLen() == 0) { 1443 // empty tag means full source 1444 client->m_downPartStatus.SetAllTrue(); 1445 } else if (partStatusTag->GetTagDataLen() == client->m_downPartStatus.SizeBuffer()) { 1446 client->m_downPartStatus.SetBuffer(partStatusTag->GetTagData()); 1447 } 1448 notified = false; 1449 } 1450 1451 if (!notified && client->m_reqfile && client->m_reqfile->ShowSources()) { 1452 SourceItemType type; 1453 switch (client->GetDownloadState()) { 1454 case DS_DOWNLOADING: 1455 case DS_ONQUEUE: 1456 // We will send A4AF, which will be checked. 1457 type = A4AF_SOURCE; 1458 break; 1459 default: 1460 type = UNAVAILABLE_SOURCE; 1461 break; 1462 } 1463 1464 Notify_SourceCtrlUpdateSource(client->ECID(), type); 1465 } 1466 1467 // Upload client 1468 notified = false; 1469 if (tag->UploadFile(fileID)) { 1470 if (client->m_uploadingfile) { 1471 client->m_uploadingfile->RemoveUploadingClient(client); // this notifies 1472 notified = true; 1473 client->m_uploadingfile = NULL; 1474 } 1475 CKnownFile * kf = theApp->knownfiles->GetByID(fileID); 1476 if (kf) { 1477 client->m_uploadingfile = kf; 1478 client->m_upPartStatus.setsize(kf->GetPartCount(), 0); 1479 client->m_uploadingfile->AddUploadingClient(client); // this notifies 1480 notified = true; 1481 } 1482 } 1483 1484 // Part status 1485 partStatusTag = tag->GetTagByName(EC_TAG_CLIENT_UPLOAD_PART_STATUS); 1486 if (partStatusTag) { 1487 if (partStatusTag->GetTagDataLen() == client->m_upPartStatus.SizeBuffer()) { 1488 client->m_upPartStatus.SetBuffer(partStatusTag->GetTagData()); 1489 } 1490 notified = false; 1491 } 1492 1493 if (!notified && client->m_uploadingfile 1494 && (client->m_uploadingfile->ShowPeers() || (client->m_nUploadState == US_UPLOADING))) { 1495 // notify if KnowFile is selected, or if it's uploading (in case clients are in show uploading mode) 1496 SourceItemType type; 1497 switch (client->GetUploadState()) { 1498 case US_UPLOADING: 1499 case US_ONUPLOADQUEUE: 1500 type = AVAILABLE_SOURCE; 1501 break; 1502 default: 1503 type = UNAVAILABLE_SOURCE; 1504 break; 1505 } 1506 Notify_SharedCtrlRefreshClient(client->ECID(), type); 1507 } 1508} 1509 1510 1511/* 1512 * Download queue container: hold PartFiles with progress status 1513 * 1514 */ 1515 1516 1517bool CDownQueueRem::AddLink(const wxString &link, uint8 cat) 1518{ 1519 CECPacket req(EC_OP_ADD_LINK); 1520 CECTag link_tag(EC_TAG_STRING, link); 1521 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat)); 1522 req.AddTag(link_tag); 1523 1524 m_conn->SendPacket(&req); 1525 return true; 1526} 1527 1528 1529void CDownQueueRem::ResetCatParts(int cat) 1530{ 1531 // Called when category is deleted. Command will be performed on the remote side, 1532 // but files still should be updated here right away, or drawing errors (colour not available) 1533 // will happen. 1534 for (iterator it = begin(); it != end(); it++) { 1535 CPartFile* file = it->second; 1536 file->RemoveCategory(cat); 1537 } 1538} 1539 1540 1541 1542void CKnownFilesRem::ProcessItemUpdatePartfile(CEC_PartFile_Tag *tag, CPartFile *file) 1543{ 1544 // 1545 // update status 1546 // 1547 tag->Speed(&file->m_kbpsDown); 1548 file->kBpsDown = file->m_kbpsDown / 1024.0; 1549 1550 tag->SizeXfer(&file->transferred); 1551 tag->SizeDone(&file->completedsize); 1552 tag->SourceXferCount(&file->transferingsrc); 1553 tag->SourceNotCurrCount(&file->m_notCurrentSources); 1554 tag->SourceCount(&file->m_source_count); 1555 tag->SourceCountA4AF(&file->m_a4af_source_count); 1556 tag->FileStatus(&file->status); 1557 tag->Stopped(&file->m_stopped); 1558 1559 tag->LastSeenComplete(&file->lastseencomplete); 1560 tag->LastDateChanged(&file->m_lastDateChanged); 1561 tag->DownloadActiveTime(&file->m_nDlActiveTime); 1562 tag->AvailablePartCount(&file->m_availablePartsCount); 1563 tag->Shared(&file->m_isShared); 1564 tag->A4AFAuto(file->m_is_A4AF_auto); 1565 1566 tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption); 1567 tag->GetGainDueToCompression(&file->m_iGainDueToCompression); 1568 tag->TotalPacketsSavedDueToICH(&file->m_iTotalPacketsSavedDueToICH); 1569 1570 tag->FileCat(&file->m_category); 1571 1572 tag->DownPrio(&file->m_iDownPriorityEC); 1573 if ( file->m_iDownPriorityEC >= 10 ) { 1574 file->m_iDownPriority = file->m_iDownPriorityEC - 10; 1575 file->m_bAutoDownPriority = true; 1576 } else { 1577 file->m_iDownPriority = file->m_iDownPriorityEC; 1578 file->m_bAutoDownPriority = false; 1579 } 1580 1581 file->percentcompleted = (100.0*file->GetCompletedSize()) / file->GetFileSize(); 1582 1583 // 1584 // Copy part/gap status 1585 // 1586 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS); 1587 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS); 1588 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS); 1589 if (gaptag || parttag || reqtag) { 1590 PartFileEncoderData &encoder = file->m_PartFileEncoderData; 1591 1592 if (gaptag) { 1593 ArrayOfUInts64 gaps; 1594 encoder.DecodeGaps(gaptag, gaps); 1595 int gap_size = gaps.size() / 2; 1596 // clear gaplist 1597 file->m_gaplist.Init(file->GetFileSize(), false); 1598 1599 // and refill it 1600 for (int j = 0; j < gap_size; j++) { 1601 file->m_gaplist.AddGap(gaps[2*j], gaps[2*j+1]); 1602 } 1603 } 1604 if (parttag) { 1605 encoder.DecodeParts(parttag, file->m_SrcpartFrequency); 1606 // sanity check 1607 wxASSERT (file->m_SrcpartFrequency.size() == file->GetPartCount()); 1608 } 1609 if (reqtag) { 1610 ArrayOfUInts64 reqs; 1611 encoder.DecodeReqs(reqtag, reqs); 1612 int req_size = reqs.size() / 2; 1613 // clear reqlist 1614 DeleteContents(file->m_requestedblocks_list); 1615 1616 // and refill it 1617 for (int j = 0; j < req_size; j++) { 1618 Requested_Block_Struct* block = new Requested_Block_Struct; 1619 block->StartOffset = reqs[2*j]; 1620 block->EndOffset = reqs[2*j+1]; 1621 file->m_requestedblocks_list.push_back(block); 1622 } 1623 } 1624 } 1625 1626 // Get source names and counts 1627 CECTag *srcnametag = tag->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES); 1628 if (srcnametag) { 1629 SourcenameItemMap &map = file->GetSourcenameItemMap(); 1630 for (CECTag::const_iterator it = srcnametag->begin(); it != srcnametag->end(); it++) { 1631 uint32 key = it->GetInt(); 1632 int count = it->GetTagByNameSafe(EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS)->GetInt(); 1633 if (count == 0) { 1634 map.erase(key); 1635 } else { 1636 SourcenameItem &item = map[key]; 1637 item.count = count; 1638 const CECTag *nametag = it->GetTagByName(EC_TAG_PARTFILE_SOURCE_NAMES); 1639 if (nametag) { 1640 item.name = nametag->GetStringData(); 1641 } 1642 } 1643 } 1644 } 1645 1646 // Get comments 1647 CECTag *commenttag = tag->GetTagByName(EC_TAG_PARTFILE_COMMENTS); 1648 if (commenttag) { 1649 file->ClearFileRatingList(); 1650 for (CECTag::const_iterator it = commenttag->begin(); it != commenttag->end(); ) { 1651 wxString u = (it++)->GetStringData(); 1652 wxString f = (it++)->GetStringData(); 1653 int r = (it++)->GetInt(); 1654 wxString c = (it++)->GetStringData(); 1655 file->AddFileRatingList(u, f, r, c); 1656 } 1657 file->UpdateFileRatingCommentAvail(); 1658 } 1659 1660 // Update A4AF sources 1661 ListOfUInts32 & clientIDs = file->GetA4AFClientIDs(); 1662 CECTag *a4aftag = tag->GetTagByName(EC_TAG_PARTFILE_A4AF_SOURCES); 1663 if (a4aftag) { 1664 file->ClearA4AFList(); 1665 clientIDs.clear(); 1666 for (CECTag::const_iterator it = a4aftag->begin(); it != a4aftag->end(); it++) { 1667 if (it->GetTagName() != EC_TAG_ECID) { // should always be this 1668 continue; 1669 } 1670 uint32 id = it->GetInt(); 1671 CClientRef * src = theApp->clientlist->GetByID(id); 1672 if (src) { 1673 file->AddA4AFSource(src->GetClient()); 1674 } else { 1675 // client wasn't transmitted yet, try it later 1676 clientIDs.push_back(id); 1677 } 1678 } 1679 } else if (!clientIDs.empty()) { 1680 // Process clients from the last pass whose ids were still unknown then 1681 for (ListOfUInts32::iterator it = clientIDs.begin(); it != clientIDs.end(); ) { 1682 ListOfUInts32::iterator it1 = it++; 1683 uint32 id = *it1; 1684 CClientRef * src = theApp->clientlist->GetByID(id); 1685 if (src) { 1686 file->AddA4AFSource(src->GetClient()); 1687 clientIDs.erase(it1); 1688 } 1689 } 1690 } 1691 1692 theApp->amuledlg->m_transferwnd->downloadlistctrl->UpdateItem(file); 1693 1694 // If file is shared check if it is already listed in shared files. 1695 // If not, add it and show it. 1696 if (file->IsShared() && !theApp->sharedfiles->count(file->ECID())) { 1697 (*theApp->sharedfiles)[file->ECID()] = file; 1698 theApp->amuledlg->m_sharedfileswnd->sharedfilesctrl->ShowFile(file); 1699 } 1700} 1701 1702 1703void CDownQueueRem::SendFileCommand(CPartFile *file, ec_tagname_t cmd) 1704{ 1705 CECPacket req(cmd); 1706 req.AddTag(CECTag(EC_TAG_PARTFILE, file->GetFileHash())); 1707 1708 m_conn->SendPacket(&req); 1709} 1710 1711 1712void CDownQueueRem::Prio(CPartFile *file, uint8 prio) 1713{ 1714 CECPacket req(EC_OP_PARTFILE_PRIO_SET); 1715 1716 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash()); 1717 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, prio)); 1718 req.AddTag(hashtag); 1719 1720 m_conn->SendPacket(&req); 1721} 1722 1723 1724void CDownQueueRem::AutoPrio(CPartFile *file, bool flag) 1725{ 1726 CECPacket req(EC_OP_PARTFILE_PRIO_SET); 1727 1728 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash()); 1729 1730 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, 1731 (uint8)(flag ? PR_AUTO : file->GetDownPriority()))); 1732 req.AddTag(hashtag); 1733 1734 m_conn->SendPacket(&req); 1735} 1736 1737 1738void CDownQueueRem::Category(CPartFile *file, uint8 cat) 1739{ 1740 CECPacket req(EC_OP_PARTFILE_SET_CAT); 1741 file->SetCategory(cat); 1742 1743 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash()); 1744 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat)); 1745 req.AddTag(hashtag); 1746 1747 m_conn->SendPacket(&req); 1748} 1749 1750 1751void CDownQueueRem::AddSearchToDownload(CSearchFile* file, uint8 category) 1752{ 1753 CECPacket req(EC_OP_DOWNLOAD_SEARCH_RESULT); 1754 CECTag hashtag(EC_TAG_PARTFILE, file->GetFileHash()); 1755 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, category)); 1756 req.AddTag(hashtag); 1757 1758 m_conn->SendPacket(&req); 1759} 1760 1761 1762void CDownQueueRem::ClearCompleted(const ListOfUInts32 & ecids) 1763{ 1764 CECPacket req(EC_OP_CLEAR_COMPLETED); 1765 for (ListOfUInts32::const_iterator it = ecids.begin(); it != ecids.end(); it++) { 1766 req.AddTag(CECTag(EC_TAG_ECID, *it)); 1767 } 1768 1769 m_conn->SendPacket(&req); 1770} 1771 1772 1773/* 1774 * List of friends. 1775 */ 1776CFriendListRem::CFriendListRem(CRemoteConnect *conn) 1777: 1778CRemoteContainer<CFriend, uint32, CEC_Friend_Tag>(conn, true) 1779{ 1780} 1781 1782 1783void CFriendListRem::HandlePacket(const CECPacket *) 1784{ 1785 wxFAIL; // not needed 1786} 1787 1788 1789CFriend * CFriendListRem::CreateItem(CEC_Friend_Tag * tag) 1790{ 1791 CFriend * Friend = new CFriend(tag->ID()); 1792 ProcessItemUpdate(tag, Friend); 1793 return Friend; 1794} 1795 1796 1797void CFriendListRem::DeleteItem(CFriend * Friend) 1798{ 1799 Friend->UnLinkClient(false); 1800 Notify_ChatRemoveFriend(Friend); 1801} 1802 1803 1804uint32 CFriendListRem::GetItemID(CFriend * Friend) 1805{ 1806 return Friend->ECID(); 1807} 1808 1809 1810void CFriendListRem::ProcessItemUpdate(CEC_Friend_Tag * tag, CFriend * Friend) 1811{ 1812 if (!tag->HasChildTags()) { 1813 return; 1814 } 1815 tag->Name(Friend->m_strName); 1816 tag->UserHash(Friend->m_UserHash); 1817 tag->IP(Friend->m_dwLastUsedIP); 1818 tag->Port(Friend->m_nLastUsedPort); 1819 uint32 clientID; 1820 bool notified = false; 1821 if (tag->Client(clientID)) { 1822 if (clientID) { 1823 CClientRef * client = theApp->clientlist->GetByID(clientID); 1824 if (client) { 1825 Friend->LinkClient(*client); // this notifies 1826 notified = true; 1827 } 1828 } else { 1829 // Unlink 1830 Friend->UnLinkClient(false); 1831 } 1832 } 1833 if (!notified) { 1834 Notify_ChatUpdateFriend(Friend); 1835 } 1836} 1837 1838 1839void CFriendListRem::AddFriend(const CClientRef& toadd) 1840{ 1841 CECPacket req(EC_OP_FRIEND); 1842 1843 CECEmptyTag addtag(EC_TAG_FRIEND_ADD); 1844 addtag.AddTag(CECTag(EC_TAG_CLIENT, toadd.ECID())); 1845 req.AddTag(addtag); 1846 1847 m_conn->SendPacket(&req); 1848} 1849 1850 1851void CFriendListRem::AddFriend(const CMD4Hash& userhash, uint32 lastUsedIP, uint32 lastUsedPort, const wxString& name) 1852{ 1853 CECPacket req(EC_OP_FRIEND); 1854 1855 CECEmptyTag addtag(EC_TAG_FRIEND_ADD); 1856 addtag.AddTag(CECTag(EC_TAG_FRIEND_HASH, userhash)); 1857 addtag.AddTag(CECTag(EC_TAG_FRIEND_IP, lastUsedIP)); 1858 addtag.AddTag(CECTag(EC_TAG_FRIEND_PORT, lastUsedPort)); 1859 addtag.AddTag(CECTag(EC_TAG_FRIEND_NAME, name)); 1860 req.AddTag(addtag); 1861 1862 m_conn->SendPacket(&req); 1863} 1864 1865 1866void CFriendListRem::RemoveFriend(CFriend* toremove) 1867{ 1868 CECPacket req(EC_OP_FRIEND); 1869 1870 CECEmptyTag removetag(EC_TAG_FRIEND_REMOVE); 1871 removetag.AddTag(CECTag(EC_TAG_FRIEND, toremove->ECID())); 1872 req.AddTag(removetag); 1873 1874 m_conn->SendPacket(&req); 1875} 1876 1877 1878void CFriendListRem::SetFriendSlot(CFriend* Friend, bool new_state) 1879{ 1880 CECPacket req(EC_OP_FRIEND); 1881 1882 CECTag slottag(EC_TAG_FRIEND_FRIENDSLOT, new_state); 1883 slottag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID())); 1884 req.AddTag(slottag); 1885 1886 m_conn->SendPacket(&req); 1887} 1888 1889 1890void CFriendListRem::RequestSharedFileList(CFriend* Friend) 1891{ 1892 CECPacket req(EC_OP_FRIEND); 1893 1894 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED); 1895 sharedtag.AddTag(CECTag(EC_TAG_FRIEND, Friend->ECID())); 1896 req.AddTag(sharedtag); 1897 1898 m_conn->SendPacket(&req); 1899} 1900 1901 1902void CFriendListRem::RequestSharedFileList(CClientRef& client) 1903{ 1904 CECPacket req(EC_OP_FRIEND); 1905 1906 CECEmptyTag sharedtag(EC_TAG_FRIEND_SHARED); 1907 sharedtag.AddTag(CECTag(EC_TAG_CLIENT, client.ECID())); 1908 req.AddTag(sharedtag); 1909 1910 m_conn->SendPacket(&req); 1911} 1912 1913 1914 1915/* 1916 * Search results 1917 */ 1918CSearchListRem::CSearchListRem(CRemoteConnect *conn) : CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>(conn, true) 1919{ 1920 m_curr_search = -1; 1921} 1922 1923 1924wxString CSearchListRem::StartNewSearch( 1925 uint32* nSearchID, SearchType search_type, 1926 const CSearchList::CSearchParams& params) 1927{ 1928 CECPacket search_req(EC_OP_SEARCH_START); 1929 EC_SEARCH_TYPE ec_search_type = EC_SEARCH_LOCAL; 1930 switch(search_type) { 1931 case LocalSearch: ec_search_type = EC_SEARCH_LOCAL; break; 1932 case GlobalSearch: ec_search_type = EC_SEARCH_GLOBAL; break; 1933 case KadSearch: ec_search_type = EC_SEARCH_KAD; break; 1934 } 1935 search_req.AddTag( 1936 CEC_Search_Tag(params.searchString, ec_search_type, 1937 params.typeText, params.extension, params.availability, 1938 params.minSize, params.maxSize)); 1939 1940 m_conn->SendPacket(&search_req); 1941 m_curr_search = *(nSearchID); // No kad remote search yet. 1942 1943 Flush(); 1944 1945 return wxEmptyString; // EC reply will have the error mesg is needed. 1946} 1947 1948 1949void CSearchListRem::StopSearch(bool) 1950{ 1951 if (m_curr_search != -1) { 1952 CECPacket search_req(EC_OP_SEARCH_STOP); 1953 m_conn->SendPacket(&search_req); 1954 } 1955} 1956 1957 1958void CSearchListRem::HandlePacket(const CECPacket *packet) 1959{ 1960 if ( packet->GetOpCode() == EC_OP_SEARCH_PROGRESS ) { 1961 CoreNotify_Search_Update_Progress(packet->GetFirstTagSafe()->GetInt()); 1962 } else { 1963 CRemoteContainer<CSearchFile, uint32, CEC_SearchFile_Tag>::HandlePacket(packet); 1964 } 1965} 1966 1967 1968CSearchFile::CSearchFile(CEC_SearchFile_Tag *tag) 1969: 1970CECID(tag->ID()), 1971m_parent(NULL), 1972m_showChildren(false), 1973m_sourceCount(0), 1974m_completeSourceCount(0), 1975m_kademlia(false), 1976m_downloadStatus(NEW), 1977m_clientID(0), 1978m_clientPort(0), 1979m_kadPublishInfo(0) 1980{ 1981 SetFileName(CPath(tag->FileName())); 1982 m_abyFileHash = tag->FileHash(); 1983 SetFileSize(tag->SizeFull()); 1984 1985 m_searchID = theApp->searchlist->m_curr_search; 1986 uint32 parentID = tag->ParentID(); 1987 if (parentID) { 1988 CSearchFile * parent = theApp->searchlist->GetByID(parentID); 1989 if (parent) { 1990 parent->AddChild(this); 1991 } 1992 } 1993} 1994 1995 1996void CSearchFile::AddChild(CSearchFile* file) 1997{ 1998 m_children.push_back(file); 1999 file->m_parent = this; 2000} 2001 2002 2003// dtor is virtual - must be implemented 2004CSearchFile::~CSearchFile() 2005{ 2006} 2007 2008 2009CSearchFile *CSearchListRem::CreateItem(CEC_SearchFile_Tag *tag) 2010{ 2011 CSearchFile *file = new CSearchFile(tag); 2012 ProcessItemUpdate(tag, file); 2013 2014 theApp->amuledlg->m_searchwnd->AddResult(file); 2015 2016 return file; 2017} 2018 2019 2020void CSearchListRem::DeleteItem(CSearchFile *file) 2021{ 2022 delete file; 2023} 2024 2025 2026uint32 CSearchListRem::GetItemID(CSearchFile *file) 2027{ 2028 return file->ECID(); 2029} 2030 2031 2032void CSearchListRem::ProcessItemUpdate(CEC_SearchFile_Tag *tag, CSearchFile *file) 2033{ 2034 uint32 sourceCount = file->m_sourceCount; 2035 uint32 completeSourceCount = file->m_completeSourceCount; 2036 CSearchFile::DownloadStatus status = file->m_downloadStatus; 2037 tag->SourceCount(&file->m_sourceCount); 2038 tag->CompleteSourceCount(&file->m_completeSourceCount); 2039 tag->DownloadStatus((uint32 *) &file->m_downloadStatus); 2040 2041 if (file->m_sourceCount != sourceCount 2042 || file->m_completeSourceCount != completeSourceCount 2043 || file->m_downloadStatus != status) { 2044 if (theApp->amuledlg && theApp->amuledlg->m_searchwnd) { 2045 theApp->amuledlg->m_searchwnd->UpdateResult(file); 2046 } 2047 } 2048} 2049 2050 2051bool CSearchListRem::Phase1Done(const CECPacket *WXUNUSED(reply)) 2052{ 2053 CECPacket progress_req(EC_OP_SEARCH_PROGRESS); 2054 m_conn->SendRequest(this, &progress_req); 2055 2056 return true; 2057} 2058 2059 2060void CSearchListRem::RemoveResults(long nSearchID) 2061{ 2062 ResultMap::iterator it = m_results.find(nSearchID); 2063 if (it != m_results.end()) { 2064 CSearchResultList& list = it->second; 2065 for (unsigned int i = 0; i < list.size(); ++i) { 2066 delete list[i]; 2067 } 2068 m_results.erase(it); 2069 } 2070} 2071 2072 2073const CSearchResultList& CSearchListRem::GetSearchResults(long nSearchID) 2074{ 2075 ResultMap::const_iterator it = m_results.find(nSearchID); 2076 if (it != m_results.end()) { 2077 return it->second; 2078 } 2079 2080 // TODO: Should we assert in this case? 2081 static CSearchResultList list; 2082 return list; 2083} 2084 2085 2086void CStatsUpdaterRem::HandlePacket(const CECPacket *packet) 2087{ 2088 theStats::UpdateStats(packet); 2089 theApp->amuledlg->ShowTransferRate(); 2090 theApp->ShowUserCount(); // maybe there should be a check if a usercount changed ? 2091 // handle the connstate tag which is included in the stats packet 2092 theApp->serverconnect->HandlePacket(packet); 2093} 2094 2095 2096void CUpDownClient::RequestSharedFileList() 2097{ 2098 CClientRef ref = CCLIENTREF(this, wxEmptyString); 2099 theApp->friendlist->RequestSharedFileList(ref); 2100} 2101 2102 2103bool CUpDownClient::SwapToAnotherFile( 2104 bool WXUNUSED(bIgnoreNoNeeded), 2105 bool WXUNUSED(ignoreSuspensions), 2106 bool WXUNUSED(bRemoveCompletely), 2107 CPartFile* toFile) 2108{ 2109 CECPacket req(EC_OP_CLIENT_SWAP_TO_ANOTHER_FILE); 2110 req.AddTag(CECTag(EC_TAG_CLIENT, ECID())); 2111 req.AddTag(CECTag(EC_TAG_PARTFILE, toFile->GetFileHash())); 2112 theApp->m_connect->SendPacket(&req); 2113 2114 return true; 2115} 2116 2117 2118wxString CAICHHash::GetString() const 2119{ 2120 return EncodeBase32(m_abyBuffer, HASHSIZE); 2121} 2122 2123 2124// 2125// Those functions are virtual. So even they don't get called they must 2126// be defined so linker will be happy 2127// 2128CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/) 2129{ 2130 wxFAIL; 2131 return 0; 2132} 2133 2134 2135bool CKnownFile::LoadFromFile(const class CFileDataIO*) 2136{ 2137 wxFAIL; 2138 return false; 2139} 2140 2141 2142void CKnownFile::UpdatePartsInfo() 2143{ 2144 wxFAIL; 2145} 2146 2147 2148CPacket* CPartFile::CreateSrcInfoPacket(CUpDownClient const *, uint8 /*byRequestedVersion*/, uint16 /*nRequestedOptions*/) 2149{ 2150 wxFAIL; 2151 return 0; 2152} 2153 2154 2155void CPartFile::UpdatePartsInfo() 2156{ 2157 wxFAIL; 2158} 2159 2160 2161 2162void CPartFile::UpdateFileRatingCommentAvail() 2163{ 2164 bool prevComment = m_hasComment; 2165 int prevRating = m_iUserRating; 2166 2167 m_hasComment = false; 2168 m_iUserRating = 0; 2169 int ratingCount = 0; 2170 2171 FileRatingList::iterator it = m_FileRatingList.begin(); 2172 for (; it != m_FileRatingList.end(); ++it) { 2173 SFileRating& cur_rat = *it; 2174 2175 if (!cur_rat.Comment.IsEmpty()) { 2176 m_hasComment = true; 2177 } 2178 2179 uint8 rating = cur_rat.Rating; 2180 if (rating) { 2181 wxASSERT(rating <= 5); 2182 2183 ratingCount++; 2184 m_iUserRating += rating; 2185 } 2186 } 2187 2188 if (ratingCount) { 2189 m_iUserRating /= ratingCount; 2190 wxASSERT(m_iUserRating > 0 && m_iUserRating <= 5); 2191 } 2192 2193 if ((prevComment != m_hasComment) || (prevRating != m_iUserRating)) { 2194 UpdateDisplayedInfo(); 2195 } 2196} 2197 2198 2199void CStatTreeRem::DoRequery() 2200{ 2201 CECPacket request(EC_OP_GET_STATSTREE); 2202 if (thePrefs::GetMaxClientVersions() != 0) { 2203 request.AddTag(CECTag(EC_TAG_STATTREE_CAPPING, (uint8)thePrefs::GetMaxClientVersions())); 2204 } 2205 m_conn->SendRequest(this, &request); 2206} 2207 2208void CStatTreeRem::HandlePacket(const CECPacket * p) 2209{ 2210 const CECTag* treeRoot = p->GetTagByName(EC_TAG_STATTREE_NODE); 2211 if (treeRoot) { 2212 theApp->amuledlg->m_statisticswnd->RebuildStatTreeRemote(treeRoot); 2213 theApp->amuledlg->m_statisticswnd->ShowStatistics(); 2214 } 2215} 2216 2217CamuleRemoteGuiApp *theApp; 2218 2219// 2220// since gui is not linked with amule.cpp - define events here 2221// 2222DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD) 2223DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE) 2224DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE) 2225DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE) 2226// File_checked_for_headers 2227