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