1 // 2 // This file is part of the aMule Project. 3 // 4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6 // 7 // Any parts of this program derived from the xMule, lMule or eMule project, 8 // or contributed by third-party developers are copyrighted by their 9 // respective authors. 10 // 11 // This program is free software; you can redistribute it and/or modify 12 // it under the terms of the GNU General Public License as published by 13 // the Free Software Foundation; either version 2 of the License, or 14 // (at your option) any later version. 15 // 16 // This program is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU General Public License for more details. 20 // 21 // You should have received a copy of the GNU General Public License 22 // along with this program; if not, write to the Free Software 23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24 // 25 26 27 #include "amule.h" // Interface declarations. 28 29 #include <csignal> 30 #include <cstring> 31 #include <wx/process.h> 32 #include <wx/sstream.h> 33 34 #ifdef HAVE_CONFIG_H 35 #include "config.h" // Needed for HAVE_GETRLIMIT, HAVE_SETRLIMIT, 36 // HAVE_SYS_RESOURCE_H, HAVE_SYS_STATVFS_H, VERSION 37 // and ENABLE_NLS 38 #endif 39 40 #include <common/ClientVersion.h> 41 42 #include <wx/cmdline.h> // Needed for wxCmdLineParser 43 #include <wx/config.h> // Do_not_auto_remove (win32) 44 #include <wx/fileconf.h> 45 #include <wx/socket.h> 46 #include <wx/tokenzr.h> 47 #include <wx/wfstream.h> 48 49 50 #include <common/Format.h> // Needed for CFormat 51 #include "kademlia/kademlia/Kademlia.h" 52 #include "kademlia/kademlia/Prefs.h" 53 #include "kademlia/kademlia/UDPFirewallTester.h" 54 #include "CanceledFileList.h" 55 #include "ClientCreditsList.h" // Needed for CClientCreditsList 56 #include "ClientList.h" // Needed for CClientList 57 #include "ClientUDPSocket.h" // Needed for CClientUDPSocket & CMuleUDPSocket 58 #include "ExternalConn.h" // Needed for ExternalConn & MuleConnection 59 #include <common/FileFunctions.h> // Needed for CDirIterator 60 #include "FriendList.h" // Needed for CFriendList 61 #include "HTTPDownload.h" // Needed for CHTTPDownloadThread 62 #include "InternalEvents.h" // Needed for CMuleInternalEvent 63 #include "IPFilter.h" // Needed for CIPFilter 64 #include "KnownFileList.h" // Needed for CKnownFileList 65 #include "ListenSocket.h" // Needed for CListenSocket 66 #include "Logger.h" // Needed for CLogger // Do_not_auto_remove 67 #include "MagnetURI.h" // Needed for CMagnetURI 68 #include "OtherFunctions.h" 69 #include "PartFile.h" // Needed for CPartFile 70 #include "PlatformSpecific.h" // Needed for PlatformSpecific::AllowSleepMode(); 71 #include "Preferences.h" // Needed for CPreferences 72 #include "SearchList.h" // Needed for CSearchList 73 #include "Server.h" // Needed for GetListName 74 #include "ServerList.h" // Needed for CServerList 75 #include "ServerConnect.h" // Needed for CServerConnect 76 #include "ServerUDPSocket.h" // Needed for CServerUDPSocket 77 #include "Statistics.h" // Needed for CStatistics 78 #include "TerminationProcessAmuleweb.h" // Needed for CTerminationProcessAmuleweb 79 #include "ThreadTasks.h" 80 #include "UploadQueue.h" // Needed for CUploadQueue 81 #include "UploadBandwidthThrottler.h" 82 #include "UserEvents.h" 83 #include "ScopedPtr.h" 84 85 #ifdef ENABLE_UPNP 86 #include "UPnPBase.h" // Needed for UPnP 87 #endif 88 89 #ifdef __WXMAC__ 90 #include <wx/sysopt.h> // Do_not_auto_remove 91 #endif 92 93 #ifndef AMULE_DAEMON 94 #ifdef __WXMAC__ 95 #include <CoreFoundation/CFBundle.h> // Do_not_auto_remove 96 #if wxCHECK_VERSION(2, 9, 0) 97 #include <wx/osx/core/cfstring.h> // Do_not_auto_remove 98 #else 99 #include <wx/mac/corefoundation/cfstring.h> // Do_not_auto_remove 100 #endif 101 #endif 102 #include <wx/msgdlg.h> 103 104 #include "amuleDlg.h" 105 #endif 106 107 108 #ifdef HAVE_SYS_RESOURCE_H 109 #include <sys/resource.h> 110 #endif 111 112 #ifdef HAVE_SYS_STATVFS_H 113 #include <sys/statvfs.h> // Do_not_auto_remove 114 #endif 115 116 117 #ifdef __GLIBC__ 118 # define RLIMIT_RESOURCE __rlimit_resource 119 #else 120 # define RLIMIT_RESOURCE int 121 #endif 122 123 #ifdef AMULE_DAEMON 124 CamuleDaemonApp *theApp; 125 #else 126 CamuleGuiApp *theApp; 127 #endif 128 129 static void UnlimitResource(RLIMIT_RESOURCE resType) 130 { 131 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) 132 struct rlimit rl; 133 getrlimit(resType, &rl); 134 rl.rlim_cur = rl.rlim_max; 135 setrlimit(resType, &rl); 136 #endif 137 } 138 139 140 static void SetResourceLimits() 141 { 142 #ifdef HAVE_SYS_RESOURCE_H 143 UnlimitResource(RLIMIT_DATA); 144 #ifndef __UCLIBC__ 145 UnlimitResource(RLIMIT_FSIZE); 146 #endif 147 UnlimitResource(RLIMIT_NOFILE); 148 #ifdef RLIMIT_RSS 149 UnlimitResource(RLIMIT_RSS); 150 #endif 151 #endif 152 } 153 154 // We store the received signal in order to avoid race-conditions 155 // in the signal handler. 156 bool g_shutdownSignal = false; 157 158 void OnShutdownSignal( int /* sig */ ) 159 { 160 signal(SIGINT, SIG_DFL); 161 signal(SIGTERM, SIG_DFL); 162 163 g_shutdownSignal = true; 164 165 #ifdef AMULE_DAEMON 166 theApp->ExitMainLoop(); 167 #endif 168 } 169 170 171 CamuleApp::CamuleApp() 172 { 173 // Madcat - Initialize timer as the VERY FIRST thing to avoid any issues later. 174 // Kry - I love to init the vars on init, even before timer. 175 StartTickTimer(); 176 177 // Initialization 178 m_app_state = APP_STATE_STARTING; 179 180 theApp = &wxGetApp(); 181 182 clientlist = NULL; 183 searchlist = NULL; 184 knownfiles = NULL; 185 canceledfiles = NULL; 186 serverlist = NULL; 187 serverconnect = NULL; 188 sharedfiles = NULL; 189 listensocket = NULL; 190 clientudp = NULL; 191 clientcredits = NULL; 192 friendlist = NULL; 193 downloadqueue = NULL; 194 uploadqueue = NULL; 195 ipfilter = NULL; 196 ECServerHandler = NULL; 197 glob_prefs = NULL; 198 m_statistics = NULL; 199 uploadBandwidthThrottler = NULL; 200 #ifdef ENABLE_UPNP 201 m_upnp = NULL; 202 m_upnpMappings.resize(4); 203 #endif 204 core_timer = NULL; 205 206 m_localip = 0; 207 m_dwPublicIP = 0; 208 webserver_pid = 0; 209 210 enable_daemon_fork = false; 211 212 // Apprently needed for *BSD 213 SetResourceLimits(); 214 215 #ifdef _MSC_VER 216 _CrtSetDbgFlag(0); // Disable useless memleak debugging 217 #endif 218 } 219 220 CamuleApp::~CamuleApp() 221 { 222 // Closing the log-file as the very last thing, since 223 // wxWidgets log-events are saved in it as well. 224 theLogger.CloseLogfile(); 225 } 226 227 int CamuleApp::OnExit() 228 { 229 if (m_app_state!=APP_STATE_STARTING) { 230 AddLogLineNS(_("Now, exiting main app...")); 231 } 232 233 // From wxWidgets docs, wxConfigBase: 234 // ... 235 // Note that you must delete this object (usually in wxApp::OnExit) 236 // in order to avoid memory leaks, wxWidgets won't do it automatically. 237 // 238 // As it happens, you may even further simplify the procedure described 239 // above: you may forget about calling Set(). When Get() is called and 240 // there is no current object, it will create one using Create() function. 241 // To disable this behaviour DontCreateOnDemand() is provided. 242 delete wxConfigBase::Set((wxConfigBase *)NULL); 243 244 // Save credits 245 clientcredits->SaveList(); 246 247 // Kill amuleweb if running 248 if (webserver_pid) { 249 AddLogLineNS(CFormat(_("Terminating amuleweb instance with pid '%ld' ... ")) % webserver_pid); 250 wxKillError rc; 251 if (wxKill(webserver_pid, wxSIGTERM, &rc) == -1) { 252 AddLogLineNS(CFormat(_("Killing amuleweb instance with pid '%ld' ... ")) % webserver_pid); 253 if (wxKill(webserver_pid, wxSIGKILL, &rc) == -1) { 254 AddLogLineNS(_("Failed")); 255 } 256 } 257 } 258 259 if (m_app_state!=APP_STATE_STARTING) { 260 AddLogLineNS(_("aMule OnExit: Terminating core.")); 261 } 262 263 delete serverlist; 264 serverlist = NULL; 265 266 delete searchlist; 267 searchlist = NULL; 268 269 delete clientcredits; 270 clientcredits = NULL; 271 272 delete friendlist; 273 friendlist = NULL; 274 275 // Destroying CDownloadQueue calls destructor for CPartFile 276 // calling CSharedFileList::SafeAddKFile occasionally. 277 delete sharedfiles; 278 sharedfiles = NULL; 279 280 delete serverconnect; 281 serverconnect = NULL; 282 283 delete listensocket; 284 listensocket = NULL; 285 286 delete clientudp; 287 clientudp = NULL; 288 289 delete knownfiles; 290 knownfiles = NULL; 291 292 delete canceledfiles; 293 canceledfiles = NULL; 294 295 delete clientlist; 296 clientlist = NULL; 297 298 delete uploadqueue; 299 uploadqueue = NULL; 300 301 delete downloadqueue; 302 downloadqueue = NULL; 303 304 delete ipfilter; 305 ipfilter = NULL; 306 307 #ifdef ENABLE_UPNP 308 delete m_upnp; 309 m_upnp = NULL; 310 #endif 311 312 delete ECServerHandler; 313 ECServerHandler = NULL; 314 315 delete m_statistics; 316 m_statistics = NULL; 317 318 delete glob_prefs; 319 glob_prefs = NULL; 320 CPreferences::EraseItemList(); 321 322 delete uploadBandwidthThrottler; 323 uploadBandwidthThrottler = NULL; 324 325 #ifdef ASIO_SOCKETS 326 delete m_AsioService; 327 m_AsioService = NULL; 328 #endif 329 330 wxSocketBase::Shutdown(); // needed because we also called Initialize() manually 331 332 if (m_app_state!=APP_STATE_STARTING) { 333 AddLogLineNS(_("aMule shutdown completed.")); 334 } 335 336 #if wxUSE_MEMORY_TRACING 337 AddLogLineNS(_("Memory debug results for aMule exit:")); 338 // Log mem debug mesages to wxLogStderr 339 wxLog* oldLog = wxLog::SetActiveTarget(new wxLogStderr); 340 //AddLogLineNS(wxT("**************Classes**************"); 341 //wxDebugContext::PrintClasses(); 342 //AddLogLineNS(wxT("***************Dump***************"); 343 //wxDebugContext::Dump(); 344 AddLogLineNS(wxT("***************Stats**************")); 345 wxDebugContext::PrintStatistics(true); 346 347 // Set back to wxLogGui 348 delete wxLog::SetActiveTarget(oldLog); 349 #endif 350 351 StopTickTimer(); 352 353 // Return 0 for succesful program termination 354 return AMULE_APP_BASE::OnExit(); 355 } 356 357 358 int CamuleApp::InitGui(bool, wxString &) 359 { 360 return 0; 361 } 362 363 364 // 365 // Application initialization 366 // 367 bool CamuleApp::OnInit() 368 { 369 #if wxUSE_MEMORY_TRACING 370 // any text before call of Localize_mule needs not to be translated. 371 AddLogLineNS(wxT("Checkpoint set on app init for memory debug")); // debug output 372 wxDebugContext::SetCheckpoint(); 373 #endif 374 375 // Forward wxLog events to CLogger 376 wxLog::SetActiveTarget(new CLoggerTarget); 377 378 m_localip = StringHosttoUint32(::wxGetFullHostName()); 379 380 #ifndef __WINDOWS__ 381 // get rid of sigpipe 382 signal(SIGPIPE, SIG_IGN); 383 #else 384 // Handle CTRL-Break 385 signal(SIGBREAK, OnShutdownSignal); 386 #endif 387 // Handle sigint and sigterm 388 signal(SIGINT, OnShutdownSignal); 389 signal(SIGTERM, OnShutdownSignal); 390 391 #ifdef __WXMAC__ 392 // For listctrl's to behave on Mac 393 wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1); 394 #endif 395 396 // Handle uncaught exceptions 397 InstallMuleExceptionHandler(); 398 399 if (!InitCommon(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv)) { 400 return false; 401 } 402 403 glob_prefs = new CPreferences(); 404 405 CPath outDir; 406 if (CheckMuleDirectory(wxT("temp"), thePrefs::GetTempDir(), thePrefs::GetConfigDir() + wxT("Temp"), outDir)) { 407 thePrefs::SetTempDir(outDir); 408 } else { 409 return false; 410 } 411 412 if (CheckMuleDirectory(wxT("incoming"), thePrefs::GetIncomingDir(), thePrefs::GetConfigDir() + wxT("Incoming"), outDir)) { 413 thePrefs::SetIncomingDir(outDir); 414 } else { 415 return false; 416 } 417 418 // Initialize wx sockets (needed for http download in background with Asio sockets) 419 wxSocketBase::Initialize(); 420 421 // Some sanity check 422 if (!thePrefs::UseTrayIcon()) { 423 thePrefs::SetMinToTray(false); 424 } 425 426 // Build the filenames for the two OS files 427 SetOSFiles(thePrefs::GetOSDir().GetRaw()); 428 429 // Check if we have the old style locale config 430 bool old_localedef = false; 431 wxString langId = thePrefs::GetLanguageID(); 432 if (!langId.IsEmpty() && (langId.GetChar(0) >= '0' && langId.GetChar(0) <= '9')) { 433 old_localedef = true; 434 thePrefs::SetLanguageID(wxLang2Str(wxLANGUAGE_DEFAULT)); 435 glob_prefs->Save(); 436 } 437 438 #ifdef ENABLE_NLS 439 // Load localization settings 440 Localize_mule(); 441 442 if (old_localedef) { 443 ShowAlert(_("Your locale has been changed to System Default due to a configuration change. Sorry."), _("Info"), wxCENTRE | wxOK | wxICON_ERROR); 444 } 445 #endif 446 447 // Configure EC for amuled when invoked with ec-config 448 if (ec_config) { 449 AddLogLineNS(_("\nEC configuration")); 450 thePrefs::SetECPass(GetPassword(false).Encode()); 451 thePrefs::EnableExternalConnections(true); 452 AddLogLineNS(_("Password set and external connections enabled.")); 453 } 454 455 #ifndef __WINDOWS__ 456 if (getuid() == 0) { 457 wxString msg = 458 wxT("Warning! You are running aMule as root.\n") 459 wxT("Doing so is not recommended for security reasons,\n") 460 wxT("and you are advised to run aMule as an normal\n") 461 wxT("user instead."); 462 463 ShowAlert(msg, _("WARNING"), wxCENTRE | wxOK | wxICON_ERROR); 464 465 fprintf(stderr, "\n--------------------------------------------------\n"); 466 fprintf(stderr, "%s", (const char*)unicode2UTF8(msg)); 467 fprintf(stderr, "\n--------------------------------------------------\n\n"); 468 } 469 #endif 470 471 // Display notification on new version or first run 472 wxTextFile vfile( thePrefs::GetConfigDir() + wxT("lastversion") ); 473 wxString newMule(wxT( VERSION )); 474 475 if ( !wxFileExists( vfile.GetName() ) ) { 476 vfile.Create(); 477 } 478 479 if ( vfile.Open() ) { 480 // Check if this version has been run before 481 bool found = false; 482 for ( size_t i = 0; i < vfile.GetLineCount(); i++ ) { 483 // Check if this version has been run before 484 if ( vfile.GetLine(i) == newMule ) { 485 found = true; 486 break; 487 } 488 } 489 490 // We havent run this version before? 491 if ( !found ) { 492 // Insert new at top to provide faster searches 493 vfile.InsertLine( newMule, 0 ); 494 495 Trigger_New_version( newMule ); 496 } 497 498 // Keep at most 10 entires 499 while ( vfile.GetLineCount() > 10 ) 500 vfile.RemoveLine( vfile.GetLineCount() - 1 ); 501 502 vfile.Write(); 503 vfile.Close(); 504 } 505 506 m_statistics = new CStatistics(); 507 508 clientlist = new CClientList(); 509 friendlist = new CFriendList(); 510 searchlist = new CSearchList(); 511 knownfiles = new CKnownFileList(); 512 canceledfiles = new CCanceledFileList; 513 serverlist = new CServerList(); 514 515 sharedfiles = new CSharedFileList(knownfiles); 516 clientcredits = new CClientCreditsList(); 517 518 // bugfix - do this before creating the uploadqueue 519 downloadqueue = new CDownloadQueue(); 520 uploadqueue = new CUploadQueue(); 521 ipfilter = new CIPFilter(); 522 523 // Creates all needed listening sockets 524 wxString msg; 525 if (!ReinitializeNetwork(&msg)) { 526 AddLogLineNS(wxT("\n")); 527 AddLogLineNS(msg); 528 } 529 530 // Test if there's any new version 531 if (thePrefs::GetCheckNewVersion()) { 532 // We use the thread base because I don't want a dialog to pop up. 533 CHTTPDownloadThread* version_check = 534 new CHTTPDownloadThread(wxT("http://amule.sourceforge.net/lastversion"), 535 thePrefs::GetConfigDir() + wxT("last_version_check"), thePrefs::GetConfigDir() + wxT("last_version"), HTTP_VersionCheck, false, false); 536 version_check->Create(); 537 version_check->Run(); 538 } 539 540 // Create main dialog, or fork to background (daemon). 541 InitGui(m_geometryEnabled, m_geometryString); 542 543 #ifdef AMULE_DAEMON 544 // Need to refresh wxSingleInstanceChecker after the daemon fork() ! 545 if (enable_daemon_fork) { 546 RefreshSingleInstanceChecker(); 547 // No need to check IsAnotherRunning() - we've done it before. 548 } 549 #endif 550 551 // Has to be created after the call to InitGui, as fork 552 // (when using posix threads) only replicates the mainthread, 553 // and the UBT constructor creates a thread. 554 uploadBandwidthThrottler = new UploadBandwidthThrottler(); 555 556 #ifdef ASIO_SOCKETS 557 m_AsioService = new CAsioService; 558 #endif 559 560 // Start performing background tasks 561 // This will start loading the IP filter. It will start right away. 562 // Log is confusing, because log entries from background will only be printed 563 // once foreground becomes idle, and that will only be after loading 564 // of the partfiles has finished. 565 CThreadScheduler::Start(); 566 567 // These must be initialized after the gui is loaded. 568 if (thePrefs::GetNetworkED2K()) { 569 serverlist->Init(); 570 } 571 downloadqueue->LoadMetFiles(thePrefs::GetTempDir()); 572 sharedfiles->Reload(); 573 574 // Ensure that the up/down ratio is used 575 CPreferences::CheckUlDlRatio(); 576 577 // Load saved friendlist (now, so it can update in GUI right away) 578 friendlist->LoadList(); 579 580 // The user can start pressing buttons like mad if he feels like it. 581 m_app_state = APP_STATE_RUNNING; 582 583 if (!serverlist->GetServerCount() && thePrefs::GetNetworkED2K()) { 584 // There are no servers and ED2K active -> ask for download. 585 // As we cannot ask in amuled, we just update there 586 #ifndef AMULE_DAEMON 587 if (wxYES == wxMessageBox( 588 wxString( 589 _("You don't have any server in the server list.\nDo you want aMule to download a new list now?")), 590 wxString(_("Server list download")), 591 wxYES_NO, 592 static_cast<wxWindow*>(theApp->amuledlg))) 593 #endif 594 { 595 serverlist->UpdateServerMetFromURL(thePrefs::GetEd2kServersUrl()); 596 } 597 } 598 599 600 // Autoconnect if that option is enabled 601 if (thePrefs::DoAutoConnect()) { 602 // IP filter is still loading and will be finished on event. 603 // Tell it to autoconnect. 604 if (thePrefs::GetNetworkED2K()) { 605 ipfilter->ConnectToAnyServerWhenReady(); 606 } 607 if (thePrefs::GetNetworkKademlia()) { 608 ipfilter->StartKADWhenReady(); 609 } 610 } 611 612 // Enable GeoIP 613 #ifdef ENABLE_IP2COUNTRY 614 theApp->amuledlg->EnableIP2Country(); 615 #endif 616 617 // Run webserver? 618 if (thePrefs::GetWSIsEnabled()) { 619 wxString aMuleConfigFile = thePrefs::GetConfigDir() + m_configFile; 620 wxString amulewebPath = thePrefs::GetWSPath(); 621 622 #if defined(__WXMAC__) && !defined(AMULE_DAEMON) 623 // For the Mac GUI application, look for amuleweb in the bundle 624 CFURLRef amulewebUrl = CFBundleCopyAuxiliaryExecutableURL( 625 CFBundleGetMainBundle(), CFSTR("amuleweb")); 626 627 if (amulewebUrl) { 628 CFURLRef absoluteUrl = CFURLCopyAbsoluteURL(amulewebUrl); 629 CFRelease(amulewebUrl); 630 631 if (absoluteUrl) { 632 CFStringRef amulewebCfstr = CFURLCopyFileSystemPath(absoluteUrl, kCFURLPOSIXPathStyle); 633 CFRelease(absoluteUrl); 634 #if wxCHECK_VERSION(2, 9, 0) 635 amulewebPath = wxCFStringRef(amulewebCfstr).AsString(wxLocale::GetSystemEncoding()); 636 #else 637 amulewebPath = wxMacCFStringHolder(amulewebCfstr).AsString(wxLocale::GetSystemEncoding()); 638 #endif 639 } 640 } 641 #endif 642 643 #ifdef __WINDOWS__ 644 # define QUOTE wxT("\"") 645 #else 646 # define QUOTE wxT("\'") 647 #endif 648 649 wxString cmd = 650 QUOTE + 651 amulewebPath + 652 QUOTE wxT(" ") QUOTE wxT("--amule-config-file=") + 653 aMuleConfigFile + 654 QUOTE; 655 CTerminationProcessAmuleweb *p = new CTerminationProcessAmuleweb(cmd, &webserver_pid); 656 webserver_pid = wxExecute(cmd, wxEXEC_ASYNC, p); 657 bool webserver_ok = webserver_pid > 0; 658 if (webserver_ok) { 659 AddLogLineC(CFormat(_("web server running on pid %d")) % webserver_pid); 660 } else { 661 delete p; 662 ShowAlert(_( 663 "You requested to run web server on startup, but the amuleweb binary cannot be run. Please install the package containing aMule web server, or compile aMule using --enable-webserver and run make install"), 664 _("ERROR"), wxOK | wxICON_ERROR); 665 } 666 } 667 668 return true; 669 } 670 671 bool CamuleApp::ReinitializeNetwork(wxString* msg) 672 { 673 bool ok = true; 674 static bool firstTime = true; 675 676 if (!firstTime) { 677 // TODO: Destroy previously created sockets 678 } 679 firstTime = false; 680 681 // Some sanity checks first 682 if (thePrefs::ECPort() == thePrefs::GetPort()) { 683 // Select a random usable port in the range 1025 ... 2^16 - 1 684 uint16 port = thePrefs::ECPort(); 685 while ( port < 1024 || port == thePrefs::GetPort() ) { 686 port = (uint16)rand(); 687 } 688 thePrefs::SetECPort( port ); 689 690 wxString err = 691 wxT("Network configuration failed! You cannot use the same port\n") 692 wxT("for the main TCP port and the External Connections port.\n") 693 wxT("The EC port has been changed to avoid conflict, see the\n") 694 wxT("preferences for the new value.\n"); 695 *msg << err; 696 697 AddLogLineN(wxEmptyString ); 698 AddLogLineC(err ); 699 AddLogLineN(wxEmptyString ); 700 701 ok = false; 702 } 703 704 if (thePrefs::GetUDPPort() == thePrefs::GetPort() + 3) { 705 // Select a random usable value in the range 1025 ... 2^16 - 1 706 uint16 port = thePrefs::GetUDPPort(); 707 while ( port < 1024 || port == thePrefs::GetPort() + 3 ) { 708 port = (uint16)rand(); 709 } 710 thePrefs::SetUDPPort( port ); 711 712 wxString err = 713 wxT("Network configuration failed! You set your UDP port to\n") 714 wxT("the value of the main TCP port plus 3.\n") 715 wxT("This port has been reserved for the Server-UDP port. The\n") 716 wxT("port value has been changed to avoid conflict, see the\n") 717 wxT("preferences for the new value\n"); 718 *msg << err; 719 720 AddLogLineN(wxEmptyString ); 721 AddLogLineC(err ); 722 AddLogLineN(wxEmptyString ); 723 724 ok = false; 725 } 726 727 // Create the address where we are going to listen 728 // TODO: read this from configuration file 729 amuleIPV4Address myaddr[4]; 730 731 // Create the External Connections Socket. 732 // Default is 4712. 733 // Get ready to handle connections from apps like amulecmd 734 if (thePrefs::GetECAddress().IsEmpty() || !myaddr[0].Hostname(thePrefs::GetECAddress())) { 735 myaddr[0].AnyAddress(); 736 } 737 myaddr[0].Service(thePrefs::ECPort()); 738 ECServerHandler = new ExternalConn(myaddr[0], msg); 739 740 // Create the UDP socket TCP+3. 741 // Used for source asking on servers. 742 if (thePrefs::GetAddress().IsEmpty()) { 743 myaddr[1].AnyAddress(); 744 } else if (!myaddr[1].Hostname(thePrefs::GetAddress())) { 745 myaddr[1].AnyAddress(); 746 AddLogLineC(CFormat(_("Could not bind ports to the specified address: %s")) 747 % thePrefs::GetAddress()); 748 } 749 750 wxString ip = myaddr[1].IPAddress(); 751 myaddr[1].Service(thePrefs::GetPort()+3); 752 serverconnect = new CServerConnect(serverlist, myaddr[1]); 753 *msg << CFormat( wxT("*** Server UDP socket (TCP+3) at %s:%u\n") ) 754 % ip % ((unsigned int)thePrefs::GetPort() + 3u); 755 756 // Create the ListenSocket (aMule TCP socket). 757 // Used for Client Port / Connections from other clients, 758 // Client to Client Source Exchange. 759 // Default is 4662. 760 myaddr[2] = myaddr[1]; 761 myaddr[2].Service(thePrefs::GetPort()); 762 listensocket = new CListenSocket(myaddr[2]); 763 *msg << CFormat( wxT("*** TCP socket (TCP) listening on %s:%u\n") ) 764 % ip % (unsigned int)(thePrefs::GetPort()); 765 // Notify(true) has already been called to the ListenSocket, so events may 766 // be already comming in. 767 if (!listensocket->IsOk()) { 768 // If we wern't able to start listening, we need to warn the user 769 wxString err; 770 err = CFormat(_("Port %u is not available. You will be LOWID\n")) % 771 (unsigned int)(thePrefs::GetPort()); 772 *msg << err; 773 AddLogLineC(err); 774 err.Clear(); 775 err = CFormat( 776 _("Port %u is not available!\n\nThis means that you will be LOWID.\n\nCheck your network to make sure the port is open for output and input.")) % 777 (unsigned int)(thePrefs::GetPort()); 778 ShowAlert(err, _("ERROR"), wxOK | wxICON_ERROR); 779 } 780 781 // Create the UDP socket. 782 // Used for extended eMule protocol, Queue Rating, File Reask Ping. 783 // Also used for Kademlia. 784 // Default is port 4672. 785 myaddr[3] = myaddr[1]; 786 myaddr[3].Service(thePrefs::GetUDPPort()); 787 clientudp = new CClientUDPSocket(myaddr[3], thePrefs::GetProxyData()); 788 if (!thePrefs::IsUDPDisabled()) { 789 *msg << CFormat( wxT("*** Client UDP socket (extended eMule) at %s:%u") ) 790 % ip % thePrefs::GetUDPPort(); 791 } else { 792 *msg << wxT("*** Client UDP socket (extended eMule) disabled on preferences"); 793 } 794 795 #ifdef ENABLE_UPNP 796 if (thePrefs::GetUPnPEnabled()) { 797 try { 798 m_upnpMappings[0] = CUPnPPortMapping( 799 myaddr[0].Service(), 800 "TCP", 801 thePrefs::GetUPnPECEnabled(), 802 "aMule TCP External Connections Socket"); 803 m_upnpMappings[1] = CUPnPPortMapping( 804 myaddr[1].Service(), 805 "UDP", 806 thePrefs::GetUPnPEnabled(), 807 "aMule UDP socket (TCP+3)"); 808 m_upnpMappings[2] = CUPnPPortMapping( 809 myaddr[2].Service(), 810 "TCP", 811 thePrefs::GetUPnPEnabled(), 812 "aMule TCP Listen Socket"); 813 m_upnpMappings[3] = CUPnPPortMapping( 814 myaddr[3].Service(), 815 "UDP", 816 thePrefs::GetUPnPEnabled(), 817 "aMule UDP Extended eMule Socket"); 818 m_upnp = new CUPnPControlPoint(thePrefs::GetUPnPTCPPort()); 819 m_upnp->AddPortMappings(m_upnpMappings); 820 } catch(CUPnPException &e) { 821 wxString error_msg; 822 error_msg << e.what(); 823 AddLogLineC(error_msg); 824 fprintf(stderr, "%s\n", (const char *)unicode2char(error_msg)); 825 } 826 } 827 #endif 828 829 return ok; 830 } 831 832 /* Original implementation by Bouc7 of the eMule Project. 833 aMule Signature idea was designed by BigBob and implemented 834 by Un-Thesis, with design inputs and suggestions from bothie. 835 */ 836 void CamuleApp::OnlineSig(bool zero /* reset stats (used on shutdown) */) 837 { 838 // Do not do anything if online signature is disabled in Preferences 839 if (!thePrefs::IsOnlineSignatureEnabled() || m_emulesig_path.IsEmpty()) { 840 // We do not need to check m_amulesig_path because if m_emulesig_path is empty, 841 // that means m_amulesig_path is empty too. 842 return; 843 } 844 845 // Remove old signature files 846 if ( wxFileExists( m_emulesig_path ) ) { wxRemoveFile( m_emulesig_path ); } 847 if ( wxFileExists( m_amulesig_path ) ) { wxRemoveFile( m_amulesig_path ); } 848 849 850 wxTextFile amulesig_out; 851 wxTextFile emulesig_out; 852 853 // Open both files if needed 854 if ( !emulesig_out.Create( m_emulesig_path) ) { 855 AddLogLineC(_("Failed to create OnlineSig File")); 856 // Will never try again. 857 m_amulesig_path.Clear(); 858 m_emulesig_path.Clear(); 859 return; 860 } 861 862 if ( !amulesig_out.Create(m_amulesig_path) ) { 863 AddLogLineC(_("Failed to create aMule OnlineSig File")); 864 // Will never try again. 865 m_amulesig_path.Clear(); 866 m_emulesig_path.Clear(); 867 return; 868 } 869 870 wxString emulesig_string; 871 wxString temp; 872 873 if (zero) { 874 emulesig_string = wxT("0\xA0.0|0.0|0"); 875 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0\n0\n0.0\n0.0\n0\n0")); 876 } else { 877 if (IsConnectedED2K()) { 878 879 temp = CFormat(wxT("%d")) % serverconnect->GetCurrentServer()->GetPort(); 880 881 // We are online 882 emulesig_string = 883 // Connected 884 wxT("1|") 885 //Server name 886 + serverconnect->GetCurrentServer()->GetListName() 887 + wxT("|") 888 // IP and port of the server 889 + serverconnect->GetCurrentServer()->GetFullIP() 890 + wxT("|") 891 + temp; 892 893 894 // Now for amule sig 895 896 // Connected. State 1, full info 897 amulesig_out.AddLine(wxT("1")); 898 // Server Name 899 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetListName()); 900 // Server IP 901 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetFullIP()); 902 // Server Port 903 amulesig_out.AddLine(temp); 904 905 if (serverconnect->IsLowID()) { 906 amulesig_out.AddLine(wxT("L")); 907 } else { 908 amulesig_out.AddLine(wxT("H")); 909 } 910 911 } else if (serverconnect->IsConnecting()) { 912 emulesig_string = wxT("0"); 913 914 // Connecting. State 2, No info. 915 amulesig_out.AddLine(wxT("2\n0\n0\n0\n0")); 916 } else { 917 // Not connected to a server 918 emulesig_string = wxT("0"); 919 920 // Not connected, state 0, no info 921 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0")); 922 } 923 if (IsConnectedKad()) { 924 if(Kademlia::CKademlia::IsFirewalled()) { 925 // Connected. Firewalled. State 1. 926 amulesig_out.AddLine(wxT("1")); 927 } else { 928 // Connected. State 2. 929 amulesig_out.AddLine(wxT("2")); 930 } 931 } else { 932 // Not connected.State 0. 933 amulesig_out.AddLine(wxT("0")); 934 } 935 emulesig_string += wxT("\xA"); 936 937 // Datarate for downloads 938 temp = CFormat(wxT("%.1f")) % (theStats::GetDownloadRate() / 1024.0); 939 940 emulesig_string += temp + wxT("|"); 941 amulesig_out.AddLine(temp); 942 943 // Datarate for uploads 944 temp = CFormat(wxT("%.1f")) % (theStats::GetUploadRate() / 1024.0); 945 946 emulesig_string += temp + wxT("|"); 947 amulesig_out.AddLine(temp); 948 949 // Number of users waiting for upload 950 temp = CFormat(wxT("%d")) % theStats::GetWaitingUserCount(); 951 952 emulesig_string += temp; 953 amulesig_out.AddLine(temp); 954 955 // Number of shared files (not on eMule) 956 amulesig_out.AddLine(CFormat(wxT("%d")) % theStats::GetSharedFileCount()); 957 } 958 959 // eMule signature finished here. Write the line to the wxTextFile. 960 emulesig_out.AddLine(emulesig_string); 961 962 // Now for aMule signature extras 963 964 // Nick on the network 965 amulesig_out.AddLine(thePrefs::GetUserNick()); 966 967 // Total received in bytes 968 amulesig_out.AddLine(CFormat(wxT("%llu")) % theStats::GetTotalReceivedBytes()); 969 970 // Total sent in bytes 971 amulesig_out.AddLine(CFormat(wxT("%llu")) % theStats::GetTotalSentBytes()); 972 973 // amule version 974 #ifdef SVNDATE 975 amulesig_out.AddLine(wxT(VERSION) wxT(" ") wxT(SVNDATE)); 976 #else 977 amulesig_out.AddLine(wxT(VERSION)); 978 #endif 979 980 if (zero) { 981 amulesig_out.AddLine(wxT("0")); 982 amulesig_out.AddLine(wxT("0")); 983 amulesig_out.AddLine(wxT("0")); 984 } else { 985 // Total received bytes in session 986 amulesig_out.AddLine( CFormat( wxT("%llu") ) % 987 theStats::GetSessionReceivedBytes() ); 988 989 // Total sent bytes in session 990 amulesig_out.AddLine( CFormat( wxT("%llu") ) % 991 theStats::GetSessionSentBytes() ); 992 993 // Uptime 994 amulesig_out.AddLine(CFormat(wxT("%llu")) % theStats::GetUptimeSeconds()); 995 } 996 997 // Flush the files 998 emulesig_out.Write(); 999 amulesig_out.Write(); 1000 } //End Added By Bouc7 1001 1002 1003 #if wxUSE_ON_FATAL_EXCEPTION 1004 // Gracefully handle fatal exceptions and print backtrace if possible 1005 void CamuleApp::OnFatalException() 1006 { 1007 /* Print the backtrace */ 1008 wxString msg; 1009 msg << wxT("\n--------------------------------------------------------------------------------\n") 1010 << wxT("A fatal error has occurred and aMule has crashed.\n") 1011 << wxT("Please assist us in fixing this problem by posting the backtrace below in our\n") 1012 << wxT("'aMule Crashes' forum and include as much information as possible regarding the\n") 1013 << wxT("circumstances of this crash. The forum is located here:\n") 1014 << wxT(" http://forum.amule.org/index.php?board=67.0\n") 1015 << wxT("If possible, please try to generate a real backtrace of this crash:\n") 1016 << wxT(" http://wiki.amule.org/wiki/Backtraces\n\n") 1017 << wxT("----------------------------=| BACKTRACE FOLLOWS: |=----------------------------\n") 1018 << wxT("Current version is: ") << FullMuleVersion 1019 << wxT("\nRunning on: ") << OSDescription 1020 << wxT("\n\n") 1021 << get_backtrace(1) // 1 == skip this function. 1022 << wxT("\n--------------------------------------------------------------------------------\n"); 1023 1024 theLogger.EmergencyLog(msg, true); 1025 } 1026 #endif 1027 1028 1029 // Sets the localization of aMule 1030 void CamuleApp::Localize_mule() 1031 { 1032 InitCustomLanguages(); 1033 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID())); 1034 if (!m_locale.IsOk()) { 1035 AddLogLineN(_("The selected locale seems not to be installed on your box. (Note: I'll try to set it anyway)")); 1036 } 1037 } 1038 1039 1040 // Displays information related to important changes in aMule. 1041 // Is called when the user runs a new version of aMule 1042 void CamuleApp::Trigger_New_version(wxString new_version) 1043 { 1044 wxString info = wxT(" --- ") + CFormat(_("This is the first time you run aMule %s")) % new_version + wxT(" ---\n\n"); 1045 if (new_version == wxT("SVN")) { 1046 info += _("This version is a testing version, updated daily, and\n"); 1047 info += _("we give no warranty it won't break anything, burn your house,\n"); 1048 info += _("or kill your dog. But it *should* be safe to use anyway.\n"); 1049 } 1050 1051 // General info 1052 info += wxT("\n"); 1053 info += _("More information, support and new releases can found at our homepage,\n"); 1054 info += _("at www.aMule.org, or in our IRC channel #aMule at irc.freenode.net.\n"); 1055 info += wxT("\n"); 1056 info += _("Feel free to report any bugs to http://forum.amule.org"); 1057 1058 ShowAlert(info, _("Info"), wxCENTRE | wxOK | wxICON_ERROR); 1059 } 1060 1061 1062 void CamuleApp::SetOSFiles(const wxString& new_path) 1063 { 1064 if ( thePrefs::IsOnlineSignatureEnabled() ) { 1065 if ( ::wxDirExists(new_path) ) { 1066 m_emulesig_path = JoinPaths(new_path, wxT("onlinesig.dat")); 1067 m_amulesig_path = JoinPaths(new_path, wxT("amulesig.dat")); 1068 } else { 1069 ShowAlert(_("The folder for Online Signature files you specified is INVALID!\n OnlineSignature will be DISABLED until you fix it on preferences."), _("ERROR"), wxOK | wxICON_ERROR); 1070 m_emulesig_path.Clear(); 1071 m_amulesig_path.Clear(); 1072 } 1073 } else { 1074 m_emulesig_path.Clear(); 1075 m_amulesig_path.Clear(); 1076 } 1077 } 1078 1079 1080 #ifdef __WXDEBUG__ 1081 #ifndef wxUSE_STACKWALKER 1082 #define wxUSE_STACKWALKER 0 1083 #endif 1084 void CamuleApp::OnAssertFailure(const wxChar* file, int line, 1085 const wxChar* func, const wxChar* cond, const wxChar* msg) 1086 { 1087 wxString errmsg = CFormat( wxT("Assertion failed: %s:%s:%d: Assertion '%s' failed. %s\nBacktrace follows:\n%s\n") ) 1088 % file % func % line % cond % ( msg ? msg : wxT("") ) 1089 % get_backtrace(2); // Skip the function-calls directly related to the assert call. 1090 theLogger.EmergencyLog(errmsg, false); 1091 1092 if (wxThread::IsMain() && IsRunning()) { 1093 AMULE_APP_BASE::OnAssertFailure(file, line, func, cond, msg); 1094 } else { 1095 #ifdef _MSC_VER 1096 wxString s = CFormat(wxT("%s in %s")) % cond % func; 1097 if (msg) { 1098 s << wxT(" : ") << msg; 1099 } 1100 _wassert(s.wc_str(), file, line); 1101 #else 1102 // Abort, allows gdb to catch the assertion 1103 raise( SIGABRT ); 1104 #endif 1105 } 1106 } 1107 #endif 1108 1109 1110 void CamuleApp::OnUDPDnsDone(CMuleInternalEvent& evt) 1111 { 1112 CServerUDPSocket* socket =reinterpret_cast<CServerUDPSocket*>(evt.GetClientData()); 1113 socket->OnHostnameResolved(evt.GetExtraLong()); 1114 } 1115 1116 1117 void CamuleApp::OnSourceDnsDone(CMuleInternalEvent& evt) 1118 { 1119 downloadqueue->OnHostnameResolved(evt.GetExtraLong()); 1120 } 1121 1122 1123 void CamuleApp::OnServerDnsDone(CMuleInternalEvent& evt) 1124 { 1125 AddLogLineNS(_("Server hostname notified")); 1126 serverconnect->OnServerHostnameResolved(evt.GetClientData(), evt.GetExtraLong()); 1127 } 1128 1129 1130 void CamuleApp::OnTCPTimer(CTimerEvent& WXUNUSED(evt)) 1131 { 1132 if(!IsRunning()) { 1133 return; 1134 } 1135 serverconnect->StopConnectionTry(); 1136 if (IsConnectedED2K() ) { 1137 return; 1138 } 1139 serverconnect->ConnectToAnyServer(); 1140 } 1141 1142 1143 void CamuleApp::OnCoreTimer(CTimerEvent& WXUNUSED(evt)) 1144 { 1145 // Former TimerProc section 1146 static uint64 msPrev1, msPrev5, msPrevSave, msPrevHist, msPrevOS, msPrevKnownMet; 1147 uint64 msCur = theStats::GetUptimeMillis(); 1148 TheTime = msCur / 1000; 1149 1150 if (!IsRunning()) { 1151 return; 1152 } 1153 1154 #ifndef AMULE_DAEMON 1155 // Check if we should terminate the app 1156 if ( g_shutdownSignal ) { 1157 wxWindow* top = GetTopWindow(); 1158 1159 if ( top ) { 1160 top->Close(true); 1161 } else { 1162 // No top-window, have to force termination. 1163 wxExit(); 1164 } 1165 } 1166 #endif 1167 1168 // There is a theoretical chance that the core time function can recurse: 1169 // if an event function gets blocked on a mutex (communicating with the 1170 // UploadBandwidthThrottler) wx spawns a new event loop and processes more events. 1171 // If CPU load gets high a new core timer event could be generated before the last 1172 // one was finished and so recursion could occur, which would be bad. 1173 // Detect this and do an early return then. 1174 static bool recurse = false; 1175 if (recurse) { 1176 return; 1177 } 1178 recurse = true; 1179 1180 uploadqueue->Process(); 1181 downloadqueue->Process(); 1182 //theApp->clientcredits->Process(); 1183 theStats::CalculateRates(); 1184 1185 if (msCur-msPrevHist > 1000) { 1186 // unlike the other loop counters in this function this one will sometimes 1187 // produce two calls in quick succession (if there was a gap of more than one 1188 // second between calls to TimerProc) - this is intentional! This way the 1189 // history list keeps an average of one node per second and gets thinned out 1190 // correctly as time progresses. 1191 msPrevHist += 1000; 1192 1193 m_statistics->RecordHistory(); 1194 1195 } 1196 1197 1198 if (msCur-msPrev1 > 1000) { // approximately every second 1199 msPrev1 = msCur; 1200 clientcredits->Process(); 1201 clientlist->Process(); 1202 1203 // Publish files to server if needed. 1204 sharedfiles->Process(); 1205 1206 if( Kademlia::CKademlia::IsRunning() ) { 1207 Kademlia::CKademlia::Process(); 1208 if(Kademlia::CKademlia::GetPrefs()->HasLostConnection()) { 1209 StopKad(); 1210 clientudp->Close(); 1211 clientudp->Open(); 1212 if (thePrefs::Reconnect()) { 1213 StartKad(); 1214 } 1215 } 1216 } 1217 1218 if( serverconnect->IsConnecting() && !serverconnect->IsSingleConnect() ) { 1219 serverconnect->TryAnotherConnectionrequest(); 1220 } 1221 if (serverconnect->IsConnecting()) { 1222 serverconnect->CheckForTimeout(); 1223 } 1224 listensocket->UpdateConnectionsStatus(); 1225 1226 } 1227 1228 1229 if (msCur-msPrev5 > 5000) { // every 5 seconds 1230 msPrev5 = msCur; 1231 listensocket->Process(); 1232 } 1233 1234 if (msCur-msPrevSave >= 60000) { 1235 msPrevSave = msCur; 1236 theStats::Save(); 1237 } 1238 1239 // Special 1240 if (msCur - msPrevOS >= thePrefs::GetOSUpdate() * 1000ull) { 1241 OnlineSig(); // Added By Bouc7 1242 msPrevOS = msCur; 1243 } 1244 1245 if (msCur - msPrevKnownMet >= 30*60*1000/*There must be a prefs option for this*/) { 1246 // Save Shared Files data 1247 knownfiles->Save(); 1248 msPrevKnownMet = msCur; 1249 } 1250 1251 1252 // Recomended by lugdunummaster himself - from emule 0.30c 1253 serverconnect->KeepConnectionAlive(); 1254 1255 // Disarm recursion protection 1256 recurse = false; 1257 } 1258 1259 1260 void CamuleApp::OnFinishedHashing(CHashingEvent& evt) 1261 { 1262 wxCHECK_RET(evt.GetResult(), wxT("No result of hashing")); 1263 1264 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner()); 1265 CKnownFile* result = evt.GetResult(); 1266 1267 if (owner) { 1268 // Check if the partfile still exists, as it might have 1269 // been deleted in the mean time. 1270 if (downloadqueue->IsPartFile(owner)) { 1271 // This cast must not be done before the IsPartFile 1272 // call, as dynamic_cast will barf on dangling pointers. 1273 dynamic_cast<CPartFile*>(owner)->PartFileHashFinished(result); 1274 } 1275 } else { 1276 static uint64 bytecount = 0; 1277 1278 if (knownfiles->SafeAddKFile(result, true)) { 1279 AddDebugLogLineN(logKnownFiles, 1280 CFormat(wxT("Safe adding file to sharedlist: %s")) % result->GetFileName()); 1281 sharedfiles->SafeAddKFile(result); 1282 1283 bytecount += result->GetFileSize(); 1284 // If we have added files with a total size of ~3000mb 1285 if (bytecount >= wxULL(3145728000)) { 1286 AddDebugLogLineN(logKnownFiles, wxT("Failsafe for crash on file hashing creation")); 1287 if ( m_app_state != APP_STATE_SHUTTINGDOWN ) { 1288 knownfiles->Save(); 1289 bytecount = 0; 1290 } 1291 } 1292 } else { 1293 AddDebugLogLineN(logKnownFiles, 1294 CFormat(wxT("File not added to sharedlist: %s")) % result->GetFileName()); 1295 delete result; 1296 } 1297 } 1298 } 1299 1300 1301 void CamuleApp::OnFinishedAICHHashing(CHashingEvent& evt) 1302 { 1303 wxCHECK_RET(evt.GetResult(), wxT("No result of AICH-hashing")); 1304 1305 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner()); 1306 CScopedPtr<CKnownFile> result(evt.GetResult()); 1307 1308 if (result->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE) { 1309 CAICHHashSet* oldSet = owner->GetAICHHashset(); 1310 CAICHHashSet* newSet = result->GetAICHHashset(); 1311 1312 owner->SetAICHHashset(newSet); 1313 newSet->SetOwner(owner); 1314 1315 result->SetAICHHashset(oldSet); 1316 oldSet->SetOwner(result.get()); 1317 } 1318 } 1319 1320 1321 void CamuleApp::OnFinishedCompletion(CCompletionEvent& evt) 1322 { 1323 CPartFile* completed = const_cast<CPartFile*>(evt.GetOwner()); 1324 wxCHECK_RET(completed, wxT("Completion event sent for unspecified file")); 1325 wxASSERT_MSG(downloadqueue->IsPartFile(completed), wxT("CCompletionEvent for unknown partfile.")); 1326 1327 completed->CompleteFileEnded(evt.ErrorOccured(), evt.GetFullPath()); 1328 if (evt.ErrorOccured()) { 1329 CUserEvents::ProcessEvent(CUserEvents::ErrorOnCompletion, completed); 1330 } 1331 1332 // Check if we should execute an script/app/whatever. 1333 CUserEvents::ProcessEvent(CUserEvents::DownloadCompleted, completed); 1334 } 1335 1336 void CamuleApp::OnFinishedAllocation(CAllocFinishedEvent& evt) 1337 { 1338 CPartFile *file = evt.GetFile(); 1339 wxCHECK_RET(file, wxT("Allocation finished event sent for unspecified file")); 1340 wxASSERT_MSG(downloadqueue->IsPartFile(file), wxT("CAllocFinishedEvent for unknown partfile")); 1341 1342 file->SetStatus(PS_EMPTY); 1343 1344 if (evt.Succeeded()) { 1345 if (evt.IsPaused()) { 1346 file->StopFile(); 1347 } else { 1348 file->ResumeFile(); 1349 } 1350 } else { 1351 AddLogLineN(CFormat(_("Disk space preallocation for file '%s' failed: %s")) % file->GetFileName() % wxString(UTF82unicode(std::strerror(evt.GetResult())))); 1352 file->StopFile(); 1353 } 1354 1355 file->AllocationFinished(); 1356 }; 1357 1358 void CamuleApp::OnNotifyEvent(CMuleGUIEvent& evt) 1359 { 1360 #ifdef AMULE_DAEMON 1361 evt.Notify(); 1362 #else 1363 if (theApp->amuledlg) { 1364 evt.Notify(); 1365 } 1366 #endif 1367 } 1368 1369 1370 void CamuleApp::ShutDown() 1371 { 1372 // Just in case 1373 PlatformSpecific::AllowSleepMode(); 1374 1375 // Log 1376 AddDebugLogLineN(logGeneral, wxT("CamuleApp::ShutDown() has started.")); 1377 1378 // Signal the hashing thread to terminate 1379 m_app_state = APP_STATE_SHUTTINGDOWN; 1380 1381 // Stop ASIO thread 1382 #ifdef ASIO_SOCKETS // only needed to suppress the log message in non-Asio build 1383 AddDebugLogLineN(logGeneral, wxT("Terminate ASIO thread.")); 1384 m_AsioService->Stop(); 1385 #endif 1386 1387 StopKad(); 1388 1389 // Kry - Save the sources seeds on app exit 1390 if (thePrefs::GetSrcSeedsOn()) { 1391 downloadqueue->SaveSourceSeeds(); 1392 } 1393 1394 OnlineSig(true); // Added By Bouc7 1395 1396 // Exit HTTP downloads 1397 CHTTPDownloadThread::StopAll(); 1398 1399 // Exit thread scheduler and upload thread 1400 CThreadScheduler::Terminate(); 1401 1402 AddDebugLogLineN(logGeneral, wxT("Terminate upload thread.")); 1403 uploadBandwidthThrottler->EndThread(); 1404 1405 // Close sockets to avoid new clients coming in 1406 if (listensocket) { 1407 listensocket->Close(); 1408 listensocket->KillAllSockets(); 1409 } 1410 1411 if (serverconnect) { 1412 serverconnect->Disconnect(); 1413 } 1414 1415 ECServerHandler->KillAllSockets(); 1416 1417 #ifdef ENABLE_UPNP 1418 if (thePrefs::GetUPnPEnabled()) { 1419 if (m_upnp) { 1420 m_upnp->DeletePortMappings(m_upnpMappings); 1421 } 1422 } 1423 #endif 1424 1425 // saving data & stuff 1426 if (knownfiles) { 1427 knownfiles->Save(); 1428 } 1429 1430 theStats::Save(); 1431 1432 CPath configFileName = CPath(thePrefs::GetConfigDir() + m_configFile); 1433 CPath::BackupFile(configFileName, wxT(".bak")); 1434 1435 if (clientlist) { 1436 clientlist->DeleteAll(); 1437 } 1438 1439 // Log 1440 AddDebugLogLineN(logGeneral, wxT("CamuleApp::ShutDown() has ended.")); 1441 } 1442 1443 1444 bool CamuleApp::AddServer(CServer *srv, bool fromUser) 1445 { 1446 if ( serverlist->AddServer(srv, fromUser) ) { 1447 Notify_ServerAdd(srv); 1448 return true; 1449 } 1450 return false; 1451 } 1452 1453 1454 uint32 CamuleApp::GetPublicIP(bool ignorelocal) const 1455 { 1456 if (m_dwPublicIP == 0) { 1457 if (Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::GetIPAddress() ) { 1458 return wxUINT32_SWAP_ALWAYS(Kademlia::CKademlia::GetIPAddress()); 1459 } else { 1460 return ignorelocal ? 0 : m_localip; 1461 } 1462 } 1463 1464 return m_dwPublicIP; 1465 } 1466 1467 1468 void CamuleApp::SetPublicIP(const uint32 dwIP) 1469 { 1470 wxASSERT((dwIP == 0) || !IsLowID(dwIP)); 1471 1472 if (dwIP != 0 && dwIP != m_dwPublicIP && serverlist != NULL) { 1473 m_dwPublicIP = dwIP; 1474 serverlist->CheckForExpiredUDPKeys(); 1475 } else { 1476 m_dwPublicIP = dwIP; 1477 } 1478 } 1479 1480 1481 wxString CamuleApp::GetLog(bool reset) 1482 { 1483 wxFile logfile; 1484 logfile.Open(thePrefs::GetConfigDir() + wxT("logfile")); 1485 if ( !logfile.IsOpened() ) { 1486 return _("ERROR: can't open logfile"); 1487 } 1488 int len = logfile.Length(); 1489 if ( len == 0 ) { 1490 return _("WARNING: logfile is empty. Something is wrong."); 1491 } 1492 char *tmp_buffer = new char[len + sizeof(wxChar)]; 1493 logfile.Read(tmp_buffer, len); 1494 memset(tmp_buffer + len, 0, sizeof(wxChar)); 1495 1496 // try to guess file format 1497 wxString str; 1498 if (tmp_buffer[0] && tmp_buffer[1]) { 1499 str = wxString(UTF82unicode(tmp_buffer)); 1500 } else { 1501 str = wxWCharBuffer((wchar_t *)tmp_buffer); 1502 } 1503 1504 delete [] tmp_buffer; 1505 if ( reset ) { 1506 theLogger.CloseLogfile(); 1507 if (theLogger.OpenLogfile(thePrefs::GetConfigDir() + wxT("logfile"))) { 1508 AddLogLineN(_("Log has been reset")); 1509 } 1510 ECServerHandler->ResetAllLogs(); 1511 } 1512 return str; 1513 } 1514 1515 1516 wxString CamuleApp::GetServerLog(bool reset) 1517 { 1518 wxString ret = server_msg; 1519 if ( reset ) { 1520 server_msg.Clear(); 1521 } 1522 return ret; 1523 } 1524 1525 wxString CamuleApp::GetDebugLog(bool reset) 1526 { 1527 return GetLog(reset); 1528 } 1529 1530 1531 void CamuleApp::AddServerMessageLine(wxString &msg) 1532 { 1533 server_msg += msg + wxT("\n"); 1534 AddLogLineN(CFormat(_("ServerMessage: %s")) % msg); 1535 } 1536 1537 1538 1539 void CamuleApp::OnFinishedHTTPDownload(CMuleInternalEvent& event) 1540 { 1541 switch (event.GetInt()) { 1542 case HTTP_IPFilter: 1543 ipfilter->DownloadFinished(event.GetExtraLong()); 1544 break; 1545 case HTTP_ServerMet: 1546 if (serverlist->DownloadFinished(event.GetExtraLong()) && !IsConnectedED2K()) { 1547 // If successfully downloaded a server list, and are not connected at the moment, try to connect. 1548 // This happens when no server met is available on startup. 1549 serverconnect->ConnectToAnyServer(); 1550 } 1551 break; 1552 case HTTP_ServerMetAuto: 1553 serverlist->AutoDownloadFinished(event.GetExtraLong()); 1554 break; 1555 case HTTP_VersionCheck: 1556 CheckNewVersion(event.GetExtraLong()); 1557 break; 1558 case HTTP_NodesDat: 1559 if (event.GetExtraLong() == HTTP_Success) { 1560 1561 wxString file = thePrefs::GetConfigDir() + wxT("nodes.dat"); 1562 if (wxFileExists(file)) { 1563 wxRemoveFile(file); 1564 } 1565 1566 if ( Kademlia::CKademlia::IsRunning() ) { 1567 Kademlia::CKademlia::Stop(); 1568 } 1569 1570 wxRenameFile(file + wxT(".download"),file); 1571 1572 Kademlia::CKademlia::Start(); 1573 theApp->ShowConnectionState(); 1574 // cppcheck-suppress duplicateBranch 1575 } else if (event.GetExtraLong() == HTTP_Skipped) { 1576 AddLogLineN(CFormat(_("Skipped download of %s, because requested file is not newer.")) % wxT("nodes.dat")); 1577 } else { 1578 AddLogLineC(_("Failed to download the nodes list.")); 1579 } 1580 break; 1581 #ifdef ENABLE_IP2COUNTRY 1582 case HTTP_GeoIP: 1583 theApp->amuledlg->IP2CountryDownloadFinished(event.GetExtraLong()); 1584 // If we updated, the dialog is already up. Redraw it to show the flags. 1585 theApp->amuledlg->Refresh(); 1586 break; 1587 #endif 1588 } 1589 } 1590 1591 void CamuleApp::CheckNewVersion(uint32 result) 1592 { 1593 if (result == HTTP_Success) { 1594 wxString filename = thePrefs::GetConfigDir() + wxT("last_version_check"); 1595 wxTextFile file; 1596 1597 if (!file.Open(filename)) { 1598 AddLogLineC(_("Failed to open the downloaded version check file") ); 1599 return; 1600 } else if (!file.GetLineCount()) { 1601 AddLogLineC(_("Corrupted version check file")); 1602 } else { 1603 wxString versionLine = file.GetFirstLine(); 1604 wxStringTokenizer tkz(versionLine, wxT(".")); 1605 1606 AddDebugLogLineN(logGeneral, wxString(wxT("Running: ")) + wxT(VERSION) + wxT(", Version check: ") + versionLine); 1607 1608 long fields[] = {0, 0, 0}; 1609 for (int i = 0; i < 3; ++i) { 1610 if (!tkz.HasMoreTokens()) { 1611 AddLogLineC(_("Corrupted version check file")); 1612 return; 1613 } else { 1614 wxString token = tkz.GetNextToken(); 1615 1616 if (!token.ToLong(&fields[i])) { 1617 AddLogLineC(_("Corrupted version check file")); 1618 return; 1619 } 1620 } 1621 } 1622 1623 long curVer = make_full_ed2k_version(VERSION_MJR, VERSION_MIN, VERSION_UPDATE); 1624 long newVer = make_full_ed2k_version(fields[0], fields[1], fields[2]); 1625 1626 if (curVer < newVer) { 1627 AddLogLineC(_("You are using an outdated version of aMule!")); 1628 // cppcheck-suppress zerodiv 1629 AddLogLineN(CFormat(_("Your aMule version is %i.%i.%i and the latest version is %li.%li.%li")) % VERSION_MJR % VERSION_MIN % VERSION_UPDATE % fields[0] % fields[1] % fields[2]); 1630 AddLogLineN(_("The latest version can always be found at http://www.amule.org")); 1631 #ifdef AMULE_DAEMON 1632 AddLogLineCS(CFormat(_("WARNING: Your aMuled version is outdated: %i.%i.%i < %li.%li.%li")) 1633 % VERSION_MJR % VERSION_MIN % VERSION_UPDATE % fields[0] % fields[1] % fields[2]); 1634 #endif 1635 } else { 1636 AddLogLineN(_("Your copy of aMule is up to date.")); 1637 } 1638 } 1639 1640 file.Close(); 1641 wxRemoveFile(filename); 1642 } else { 1643 AddLogLineC(_("Failed to download the version check file")); 1644 } 1645 1646 } 1647 1648 1649 bool CamuleApp::IsConnected() const 1650 { 1651 return (IsConnectedED2K() || IsConnectedKad()); 1652 } 1653 1654 1655 bool CamuleApp::IsConnectedED2K() const 1656 { 1657 return serverconnect && serverconnect->IsConnected(); 1658 } 1659 1660 1661 bool CamuleApp::IsConnectedKad() const 1662 { 1663 return Kademlia::CKademlia::IsConnected(); 1664 } 1665 1666 1667 bool CamuleApp::IsFirewalled() const 1668 { 1669 if (theApp->IsConnectedED2K() && !theApp->serverconnect->IsLowID()) { 1670 return false; // we have an eD2K HighID -> not firewalled 1671 } 1672 1673 return IsFirewalledKad(); // If kad says ok, it's ok. 1674 } 1675 1676 bool CamuleApp::IsFirewalledKad() const 1677 { 1678 return !Kademlia::CKademlia::IsConnected() // not connected counts as firewalled 1679 || Kademlia::CKademlia::IsFirewalled(); 1680 } 1681 1682 bool CamuleApp::IsFirewalledKadUDP() const 1683 { 1684 return !Kademlia::CKademlia::IsConnected() // not connected counts as firewalled 1685 || Kademlia::CUDPFirewallTester::IsFirewalledUDP(true); 1686 } 1687 1688 bool CamuleApp::IsKadRunning() const 1689 { 1690 return Kademlia::CKademlia::IsRunning(); 1691 } 1692 1693 bool CamuleApp::IsKadRunningInLanMode() const 1694 { 1695 return Kademlia::CKademlia::IsRunningInLANMode(); 1696 } 1697 1698 // Kad stats 1699 uint32 CamuleApp::GetKadUsers() const 1700 { 1701 return Kademlia::CKademlia::GetKademliaUsers(); 1702 } 1703 1704 uint32 CamuleApp::GetKadFiles() const 1705 { 1706 return Kademlia::CKademlia::GetKademliaFiles(); 1707 } 1708 1709 uint32 CamuleApp::GetKadIndexedSources() const 1710 { 1711 return Kademlia::CKademlia::GetIndexed()->m_totalIndexSource; 1712 } 1713 1714 uint32 CamuleApp::GetKadIndexedKeywords() const 1715 { 1716 return Kademlia::CKademlia::GetIndexed()->m_totalIndexKeyword; 1717 } 1718 1719 uint32 CamuleApp::GetKadIndexedNotes() const 1720 { 1721 return Kademlia::CKademlia::GetIndexed()->m_totalIndexNotes; 1722 } 1723 1724 uint32 CamuleApp::GetKadIndexedLoad() const 1725 { 1726 return Kademlia::CKademlia::GetIndexed()->m_totalIndexLoad; 1727 } 1728 1729 1730 // True IP of machine 1731 uint32 CamuleApp::GetKadIPAdress() const 1732 { 1733 return wxUINT32_SWAP_ALWAYS(Kademlia::CKademlia::GetPrefs()->GetIPAddress()); 1734 } 1735 1736 // Buddy status 1737 uint8 CamuleApp::GetBuddyStatus() const 1738 { 1739 return clientlist->GetBuddyStatus(); 1740 } 1741 1742 uint32 CamuleApp::GetBuddyIP() const 1743 { 1744 return clientlist->GetBuddyIP(); 1745 } 1746 1747 uint32 CamuleApp::GetBuddyPort() const 1748 { 1749 return clientlist->GetBuddyPort(); 1750 } 1751 1752 const Kademlia::CUInt128& CamuleApp::GetKadID() const 1753 { 1754 return Kademlia::CKademlia::GetKadID(); 1755 } 1756 1757 bool CamuleApp::CanDoCallback(uint32 clientServerIP, uint16 clientServerPort) 1758 { 1759 if (Kademlia::CKademlia::IsConnected()) { 1760 if (IsConnectedED2K()) { 1761 if (serverconnect->IsLowID()) { 1762 if (Kademlia::CKademlia::IsFirewalled()) { 1763 //Both Connected - Both Firewalled 1764 return false; 1765 } else { 1766 if (clientServerIP == theApp->serverconnect->GetCurrentServer()->GetIP() && 1767 clientServerPort == theApp->serverconnect->GetCurrentServer()->GetPort()) { 1768 // Both Connected - Server lowID, Kad Open - Client on same server 1769 // We prevent a callback to the server as this breaks the protocol 1770 // and will get you banned. 1771 return false; 1772 } else { 1773 // Both Connected - Server lowID, Kad Open - Client on remote server 1774 return true; 1775 } 1776 } 1777 } else { 1778 //Both Connected - Server HighID, Kad don't care 1779 return true; 1780 } 1781 } else { 1782 if (Kademlia::CKademlia::IsFirewalled()) { 1783 //Only Kad Connected - Kad Firewalled 1784 return false; 1785 } else { 1786 //Only Kad Conected - Kad Open 1787 return true; 1788 } 1789 } 1790 } else { 1791 if (IsConnectedED2K()) { 1792 if (serverconnect->IsLowID()) { 1793 //Only Server Connected - Server LowID 1794 return false; 1795 } else { 1796 //Only Server Connected - Server HighID 1797 return true; 1798 } 1799 } else { 1800 //We are not connected at all! 1801 return false; 1802 } 1803 } 1804 } 1805 1806 void CamuleApp::ShowUserCount() { 1807 uint32 totaluser = 0, totalfile = 0; 1808 1809 theApp->serverlist->GetUserFileStatus( totaluser, totalfile ); 1810 1811 wxString buffer; 1812 1813 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s"); 1814 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s"); 1815 1816 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) { 1817 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(totaluser) % CastItoIShort(Kademlia::CKademlia::GetKademliaUsers()) % CastItoIShort(totalfile) % CastItoIShort(Kademlia::CKademlia::GetKademliaFiles()); 1818 } else if (thePrefs::GetNetworkED2K()) { 1819 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(totaluser) % CastItoIShort(totalfile); 1820 } else if (thePrefs::GetNetworkKademlia()) { 1821 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(Kademlia::CKademlia::GetKademliaUsers()) % CastItoIShort(Kademlia::CKademlia::GetKademliaFiles()); 1822 } else { 1823 buffer = _("No networks selected"); 1824 } 1825 1826 Notify_ShowUserCount(buffer); 1827 } 1828 1829 1830 #ifndef ASIO_SOCKETS 1831 void CamuleApp::ListenSocketHandler(wxSocketEvent& event) 1832 { 1833 { wxCHECK_RET(listensocket, wxT("Connection-event for NULL'd listen-socket")); } 1834 { wxCHECK_RET(event.GetSocketEvent() == wxSOCKET_CONNECTION, 1835 wxT("Invalid event received for listen-socket")); } 1836 1837 if (m_app_state == APP_STATE_RUNNING) { 1838 listensocket->OnAccept(); 1839 } else if (m_app_state == APP_STATE_STARTING) { 1840 // When starting up, connection may be made before we are able 1841 // to handle them. However, if these are ignored, no futher 1842 // connection-events will be triggered, so we have to accept it. 1843 CLibSocket* socket = listensocket->Accept(false); 1844 1845 wxCHECK_RET(socket, wxT("NULL returned by Accept() during startup")); 1846 1847 socket->Destroy(); 1848 } 1849 } 1850 #endif 1851 1852 1853 void CamuleApp::ShowConnectionState(bool forceUpdate) 1854 { 1855 static uint8 old_state = (1<<7); // This flag doesn't exist 1856 1857 uint8 state = 0; 1858 1859 if (theApp->serverconnect->IsConnected()) { 1860 state |= CONNECTED_ED2K; 1861 } 1862 1863 if (Kademlia::CKademlia::IsRunning()) { 1864 if (Kademlia::CKademlia::IsConnected()) { 1865 if (!Kademlia::CKademlia::IsFirewalled()) { 1866 state |= CONNECTED_KAD_OK; 1867 } else { 1868 state |= CONNECTED_KAD_FIREWALLED; 1869 } 1870 } else { 1871 state |= CONNECTED_KAD_NOT; 1872 } 1873 } 1874 1875 if (old_state != state) { 1876 // Get the changed value 1877 int changed_flags = old_state ^ state; 1878 1879 if (changed_flags & CONNECTED_ED2K) { 1880 // ED2K status changed 1881 wxString connected_server; 1882 CServer* ed2k_server = theApp->serverconnect->GetCurrentServer(); 1883 if (ed2k_server) { 1884 connected_server = ed2k_server->GetListName(); 1885 } 1886 if (state & CONNECTED_ED2K) { 1887 // We connected to some server 1888 const wxString id = theApp->serverconnect->IsLowID() ? _("with LowID") : _("with HighID"); 1889 1890 AddLogLineC(CFormat(_("Connected to %s %s")) % connected_server % id); 1891 } else { 1892 // cppcheck-suppress duplicateBranch 1893 if ( theApp->serverconnect->IsConnecting() ) { 1894 AddLogLineC(CFormat(_("Connecting to %s")) % connected_server); 1895 } else { 1896 AddLogLineC(_("Disconnected from eD2k")); 1897 } 1898 } 1899 } 1900 1901 if (changed_flags & CONNECTED_KAD_NOT) { 1902 // cppcheck-suppress duplicateBranch 1903 if (state & CONNECTED_KAD_NOT) { 1904 AddLogLineC(_("Kad started.")); 1905 } else { 1906 AddLogLineC(_("Kad stopped.")); 1907 } 1908 } 1909 1910 if (changed_flags & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) { 1911 if (state & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) { 1912 // cppcheck-suppress duplicateBranch 1913 if (state & CONNECTED_KAD_OK) { 1914 AddLogLineC(_("Connected to Kad (ok)")); 1915 } else { 1916 AddLogLineC(_("Connected to Kad (firewalled)")); 1917 } 1918 } else { 1919 AddLogLineC(_("Disconnected from Kad")); 1920 } 1921 } 1922 1923 old_state = state; 1924 1925 theApp->downloadqueue->OnConnectionState(IsConnected()); 1926 } 1927 1928 ShowUserCount(); 1929 Notify_ShowConnState(forceUpdate); 1930 } 1931 1932 1933 #ifndef ASIO_SOCKETS 1934 void CamuleApp::UDPSocketHandler(wxSocketEvent& event) 1935 { 1936 CMuleUDPSocket* socket = reinterpret_cast<CMuleUDPSocket*>(event.GetClientData()); 1937 wxCHECK_RET(socket, wxT("No socket owner specified.")); 1938 1939 if (IsOnShutDown() || thePrefs::IsUDPDisabled()) return; 1940 1941 if (!IsRunning()) { 1942 if (event.GetSocketEvent() == wxSOCKET_INPUT) { 1943 // Back to the queue! 1944 theApp->AddPendingEvent(event); 1945 return; 1946 } 1947 } 1948 1949 switch (event.GetSocketEvent()) { 1950 case wxSOCKET_INPUT: 1951 socket->OnReceive(0); 1952 break; 1953 1954 case wxSOCKET_OUTPUT: 1955 socket->OnSend(0); 1956 break; 1957 1958 case wxSOCKET_LOST: 1959 socket->OnDisconnected(0); 1960 break; 1961 1962 default: 1963 wxFAIL; 1964 break; 1965 } 1966 } 1967 #endif 1968 1969 1970 void CamuleApp::OnUnhandledException() 1971 { 1972 // Call the generic exception-handler. 1973 fprintf(stderr, "\taMule Version: %s\n", (const char*)unicode2char(GetFullMuleVersion())); 1974 ::OnUnhandledException(); 1975 } 1976 1977 void CamuleApp::StartKad() 1978 { 1979 if (!Kademlia::CKademlia::IsRunning() && thePrefs::GetNetworkKademlia()) { 1980 // Kad makes no sense without the Client-UDP socket. 1981 if (!thePrefs::IsUDPDisabled()) { 1982 if (ipfilter->IsReady()) { 1983 Kademlia::CKademlia::Start(); 1984 } else { 1985 ipfilter->StartKADWhenReady(); 1986 } 1987 } else { 1988 AddLogLineC(_("Kad network cannot be used if UDP port is disabled on preferences, not starting.")); 1989 } 1990 } else if (!thePrefs::GetNetworkKademlia()) { 1991 AddLogLineC(_("Kad network disabled on preferences, not connecting.")); 1992 } 1993 } 1994 1995 void CamuleApp::StopKad() 1996 { 1997 // Stop Kad if it's running 1998 if (Kademlia::CKademlia::IsRunning()) { 1999 Kademlia::CKademlia::Stop(); 2000 } 2001 } 2002 2003 2004 void CamuleApp::BootstrapKad(uint32 ip, uint16 port) 2005 { 2006 if (!Kademlia::CKademlia::IsRunning()) { 2007 Kademlia::CKademlia::Start(); 2008 theApp->ShowConnectionState(); 2009 } 2010 2011 Kademlia::CKademlia::Bootstrap(ip, port); 2012 } 2013 2014 2015 void CamuleApp::UpdateNotesDat(const wxString& url) 2016 { 2017 wxString strTempFilename(thePrefs::GetConfigDir() + wxT("nodes.dat.download")); 2018 2019 CHTTPDownloadThread *downloader = new CHTTPDownloadThread(url, strTempFilename, thePrefs::GetConfigDir() + wxT("nodes.dat"), HTTP_NodesDat, true, false); 2020 downloader->Create(); 2021 downloader->Run(); 2022 } 2023 2024 2025 void CamuleApp::DisconnectED2K() 2026 { 2027 // Stop ED2K if it's running 2028 if (IsConnectedED2K()) { 2029 serverconnect->Disconnect(); 2030 } 2031 } 2032 2033 bool CamuleApp::CryptoAvailable() const 2034 { 2035 return clientcredits && clientcredits->CryptoAvailable(); 2036 } 2037 2038 uint32 CamuleApp::GetED2KID() const { 2039 return serverconnect ? serverconnect->GetClientID() : 0; 2040 } 2041 2042 uint32 CamuleApp::GetID() const { 2043 uint32 ID; 2044 2045 if( Kademlia::CKademlia::IsConnected() && !Kademlia::CKademlia::IsFirewalled() ) { 2046 // We trust Kad above ED2K 2047 ID = ENDIAN_NTOHL(Kademlia::CKademlia::GetIPAddress()); 2048 } else if( theApp->serverconnect->IsConnected() ) { 2049 ID = theApp->serverconnect->GetClientID(); 2050 } else if ( Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::IsFirewalled() ) { 2051 // A firewalled Kad client get's a "1" 2052 ID = 1; 2053 } else { 2054 ID = 0; 2055 } 2056 2057 return ID; 2058 } 2059 2060 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD) 2061 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE) 2062 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE) 2063 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE) 2064 // File_checked_for_headers 2065