Upstream tarball 20080512
[amule.git] / src / amule.cpp
blobcf34e190e7ca6f4c6c4433d92785b66ddbb73a8f
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002 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.
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.
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
27 #define AMULE_CPP
30 #include "amule.h" // Interface declarations.
32 #include <csignal>
33 #include <wx/process.h>
34 #include <wx/sstream.h>
36 #ifdef HAVE_CONFIG_H
37 #include "config.h" // Needed for HAVE_GETRLIMIT, HAVE_SETRLIMIT,
38 // HAVE_SYS_RESOURCE_H, HAVE_SYS_STATVFS_H, VERSION
39 // and ENABLE_NLS
40 #endif
42 #include <common/ClientVersion.h>
44 #include <wx/cmdline.h> // Needed for wxCmdLineParser
45 #include <wx/config.h> // Do_not_auto_remove (win32)
46 #include <wx/fileconf.h>
47 #include <wx/snglinst.h>
48 #include <wx/tokenzr.h>
49 #include <wx/wfstream.h>
52 #include <common/Format.h> // Needed for CFormat
53 #include "kademlia/kademlia/Kademlia.h"
54 #include "kademlia/kademlia/Prefs.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 "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 "updownclient.h" // Needed for CUpDownClient
80 #include "UploadQueue.h" // Needed for CUploadQueue
81 #include "UploadBandwidthThrottler.h"
82 #include "UserEvents.h"
84 #ifdef ENABLE_UPNP
85 #include "UPnP.h" // Needed for UPnP
86 #endif
88 #ifdef __WXMAC__
89 #include <wx/sysopt.h> // Do_not_auto_remove
90 #endif
92 #ifndef AMULE_DAEMON
93 #ifdef __WXMAC__
94 #include <CoreFoundation/CFBundle.h> // Do_not_auto_remove
95 #include <wx/mac/corefoundation/cfstring.h> // Do_not_auto_remove
96 #endif
97 #include <wx/msgdlg.h>
99 #include "amuleDlg.h"
100 #endif
103 #ifdef HAVE_SYS_RESOURCE_H
104 #include <sys/resource.h>
105 #endif
107 #ifdef HAVE_SYS_STATVFS_H
108 #include <sys/statvfs.h> // Do_not_auto_remove
109 #endif
112 #ifdef __GLIBC__
113 # define RLIMIT_RESOURCE __rlimit_resource
114 #else
115 # define RLIMIT_RESOURCE int
116 #endif
118 static void UnlimitResource(RLIMIT_RESOURCE resType)
120 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
121 struct rlimit rl;
122 getrlimit(resType, &rl);
123 rl.rlim_cur = rl.rlim_max;
124 setrlimit(resType, &rl);
125 #endif
129 static void SetResourceLimits()
131 #ifdef HAVE_SYS_RESOURCE_H
132 UnlimitResource(RLIMIT_DATA);
133 UnlimitResource(RLIMIT_FSIZE);
134 UnlimitResource(RLIMIT_NOFILE);
135 #ifdef RLIMIT_RSS
136 UnlimitResource(RLIMIT_RSS);
137 #endif
138 #endif
141 // We store the received signal in order to avoid race-conditions
142 // in the signal handler.
143 bool g_shutdownSignal = false;
145 void OnShutdownSignal( int /* sig */ )
147 signal(SIGINT, SIG_DFL);
148 signal(SIGTERM, SIG_DFL);
150 g_shutdownSignal = true;
152 #ifdef AMULE_DAEMON
153 theApp->ExitMainLoop();
154 #endif
158 CamuleApp::CamuleApp()
160 // Madcat - Initialize timer as the VERY FIRST thing to avoid any issues later.
161 // Kry - I love to init the vars on init, even before timer.
162 StartTickTimer();
164 // Initialization
165 m_app_state = APP_STATE_STARTING;
167 theApp = &wxGetApp();
169 clientlist = NULL;
170 searchlist = NULL;
171 knownfiles = NULL;
172 serverlist = NULL;
173 serverconnect = NULL;
174 sharedfiles = NULL;
175 listensocket = NULL;
176 clientudp = NULL;
177 clientcredits = NULL;
178 friendlist = NULL;
179 downloadqueue = NULL;
180 uploadqueue = NULL;
181 ipfilter = NULL;
182 ECServerHandler = NULL;
183 m_singleInstance= NULL;
184 glob_prefs = NULL;
185 m_statistics = NULL;
186 uploadBandwidthThrottler = NULL;
187 #ifdef ENABLE_UPNP
188 m_upnp = NULL;
189 m_upnpMappings.resize(4);
190 #endif
191 core_timer = NULL;
192 applog = NULL;
194 m_localip = 0;
195 m_dwPublicIP = 0;
196 webserver_pid = 0;
198 enable_stdout_log = false;
199 enable_daemon_fork = false;
201 strFullMuleVersion = NULL;
202 strOSDescription = NULL;
204 // Apprently needed for *BSD
205 SetResourceLimits();
208 CamuleApp::~CamuleApp()
210 // Closing the log-file as the very last thing, since
211 // wxWidgets log-events are saved in it as well.
212 delete applog;
213 applog = NULL;
216 int CamuleApp::OnExit()
218 if (m_app_state!=APP_STATE_STARTING) {
219 printf("Now, exiting main app...\n");
222 // From wxWidgets docs, wxConfigBase:
223 // ...
224 // Note that you must delete this object (usually in wxApp::OnExit)
225 // in order to avoid memory leaks, wxWidgets won't do it automatically.
227 // As it happens, you may even further simplify the procedure described
228 // above: you may forget about calling Set(). When Get() is called and
229 // there is no current object, it will create one using Create() function.
230 // To disable this behaviour DontCreateOnDemand() is provided.
231 delete wxConfigBase::Set((wxConfigBase *)NULL);
233 // Save credits
234 clientcredits->SaveList();
236 // Kill amuleweb if running
237 if (webserver_pid) {
238 printf("Killing amuleweb instance with pid `%ld' ... ", webserver_pid);
239 wxKillError rc;
240 wxKill(webserver_pid, wxSIGTERM, &rc);
241 printf("Killed!\n");
244 if (m_app_state!=APP_STATE_STARTING) {
245 printf("aMule OnExit: Terminating core.\n");
248 delete serverlist;
249 serverlist = NULL;
251 delete searchlist;
252 searchlist = NULL;
254 delete clientcredits;
255 clientcredits = NULL;
257 delete friendlist;
258 friendlist = NULL;
260 // Destroying CDownloadQueue calls destructor for CPartFile
261 // calling CSharedFileList::SafeAddKFile occasionally.
262 delete sharedfiles;
263 sharedfiles = NULL;
265 delete serverconnect;
266 serverconnect = NULL;
268 delete listensocket;
269 listensocket = NULL;
271 delete clientudp;
272 clientudp = NULL;
274 delete knownfiles;
275 knownfiles = NULL;
277 delete clientlist;
278 clientlist = NULL;
280 delete uploadqueue;
281 uploadqueue = NULL;
283 delete downloadqueue;
284 downloadqueue = NULL;
286 delete ipfilter;
287 ipfilter = NULL;
289 #ifdef ENABLE_UPNP
290 delete m_upnp;
291 m_upnp = NULL;
292 #endif
294 delete ECServerHandler;
295 ECServerHandler = NULL;
297 delete m_statistics;
298 m_statistics = NULL;
300 delete glob_prefs;
301 glob_prefs = NULL;
302 CPreferences::EraseItemList();
304 #if defined(__WXMAC__) && defined(AMULE_DAEMON)
305 //#warning TODO: fix wxSingleInstanceChecker for amuled on Mac (wx link problems)
306 #else
307 delete m_singleInstance;
308 #endif
309 m_singleInstance = NULL;
311 delete uploadBandwidthThrottler;
312 uploadBandwidthThrottler = NULL;
314 if (m_app_state!=APP_STATE_STARTING) {
315 printf("aMule shutdown completed.\n");
318 #if wxUSE_MEMORY_TRACING
319 printf("Memory debug results for aMule exit:\n");
320 // Log mem debug mesages to wxLogStderr
321 wxLog* oldLog = wxLog::SetActiveTarget(new wxLogStderr);
323 printf("**************Classes**************\n");
324 wxDebugContext::PrintClasses();
326 //printf("***************Dump***************\n");
327 //wxDebugContext::Dump();
328 printf("***************Stats**************\n");
329 wxDebugContext::PrintStatistics(true);
331 // Set back to wxLogGui
332 delete wxLog::SetActiveTarget(oldLog);
333 #endif
335 StopTickTimer();
337 // Return 0 for succesful program termination
338 return AMULE_APP_BASE::OnExit();
342 int CamuleApp::InitGui(bool, wxString &)
344 return 0;
349 * Checks permissions on a aMule directory, creating if needed.
351 * @param desc A description of the directory in question, used for error messages.
352 * @param directory The directory in question.
353 * @param fallback If the dir specified with 'directory' could not be created, try this instead.
354 * @return The bool is false on error. The wxString contains the used path.
356 std::pair<bool, CPath> CheckMuleDirectory(const wxString& desc, const CPath& directory, const wxString& alternative)
358 wxString msg;
360 if (directory.IsDir(CPath::readwritable)) {
361 return std::pair<bool, CPath>(true, directory);
362 } else if (directory.DirExists()) {
363 msg = CFormat(wxT("Permissions on the %s directory too strict!\n")
364 wxT("aMule cannot proceed. To fix this, you must set read/write/exec\n")
365 wxT("permissions for the folder '%s'"))
366 % desc % directory;
367 } else if (CPath::MakeDir(directory)) {
368 return std::pair<bool, CPath>(true, directory);
369 } else {
370 msg << CFormat(wxT("Could not create the %s directory at '%s'."))
371 % desc % directory;
374 // Attempt to use fallback directory.
375 const CPath fallback = CPath(alternative);
376 if (fallback.IsOk() && (directory != fallback)) {
377 msg << wxT("\nAttempting to use default directory at location \n'")
378 << alternative << wxT("'.");
379 theApp->ShowAlert(msg, wxT("Error accessing directory."), wxICON_ERROR | wxOK);
381 return CheckMuleDirectory(desc, fallback, wxEmptyString);
384 theApp->ShowAlert(msg, wxT("Fatal error."), wxICON_ERROR | wxOK);
385 return std::pair<bool, wxString>(false, wxEmptyString);
390 // Application initialization
392 bool CamuleApp::OnInit()
394 #if wxUSE_MEMORY_TRACING
395 printf("Checkpoint set on app init for memory debug\n");
396 wxDebugContext::SetCheckpoint();
397 #endif
399 // Forward wxLog events to CLogger
400 wxLog::SetActiveTarget(new CLoggerTarget);
402 m_localip = StringHosttoUint32(::wxGetFullHostName());
404 #ifndef __WXMSW__
405 // get rid of sigpipe
406 signal(SIGPIPE, SIG_IGN);
407 // Handle sigint and sigterm
408 signal(SIGINT, OnShutdownSignal);
409 signal(SIGTERM, OnShutdownSignal);
410 #endif
412 #ifdef __WXMAC__
413 // For listctrl's to behave on Mac
414 wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1);
415 #endif
417 // This can't be on constructor or wx2.4.2 doesn't set it.
418 #if !wxCHECK_VERSION(2, 9, 0)
419 SetVendorName(wxT("TikuWarez"));
420 #endif
421 SetAppName(wxT("aMule"));
423 wxString FullMuleVersion = GetFullMuleVersion();
424 wxString OSDescription = wxGetOsDescription();
425 strFullMuleVersion = strdup((const char *)unicode2char(FullMuleVersion));
426 strOSDescription = strdup((const char *)unicode2char(OSDescription));
427 OSType = OSDescription.BeforeFirst( wxT(' ') );
428 if ( OSType.IsEmpty() ) {
429 OSType = wxT("Unknown");
432 // Handle uncaught exceptions
433 InstallMuleExceptionHandler();
435 // Parse cmdline arguments.
436 wxCmdLineParser cmdline(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv);
438 // Handle these arguments.
439 cmdline.AddSwitch(wxT("v"), wxT("version"), wxT("Displays the current version number."));
440 cmdline.AddSwitch(wxT("h"), wxT("help"), wxT("Displays this information."));
441 cmdline.AddSwitch(wxT("i"), wxT("enable-stdin"), wxT("Does not disable stdin."));
442 #ifdef AMULE_DAEMON
443 cmdline.AddSwitch(wxT("f"), wxT("full-daemon"), wxT("Fork to background."));
444 cmdline.AddOption(wxT("c"), wxT("config-dir"), wxT("read config from <dir> instead of home"));
445 cmdline.AddSwitch(wxT("e"), wxT("ec-config"), wxT("Configure EC (External Connections)."));
446 #else
447 cmdline.AddOption(wxT("geometry"), wxEmptyString,
448 wxT("Sets the geometry of the app.\n")
449 wxT("\t\t\t<str> uses the same format as standard X11 apps:\n")
450 wxT("\t\t\t[=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]"));
451 #endif
452 cmdline.AddSwitch(wxT("d"), wxT("disable-fatal"), wxT("Does not handle fatal exception."));
453 cmdline.AddSwitch(wxT("o"), wxT("log-stdout"), wxT("Print log messages to stdout."));
454 cmdline.AddSwitch(wxT("r"), wxT("reset-config"), wxT("Resets config to default values."));
456 // Show help on --help or invalid commands
457 if ( cmdline.Parse() ) {
458 return false;
459 } else if ( cmdline.Found(wxT("help")) ) {
460 cmdline.Usage();
461 return false;
464 bool ec_config = false;
466 #ifdef AMULE_DAEMON
467 ec_config = cmdline.Found(wxT("ec-config"));
468 if ( cmdline.Found(wxT("config-dir"), &ConfigDir) ) {
469 if (ConfigDir.Last() != wxFileName::GetPathSeparator()) {
470 ConfigDir += wxFileName::GetPathSeparator();
472 } else {
473 ConfigDir = GetConfigDir();
475 #else
476 ConfigDir = GetConfigDir();
477 #endif
479 if ( !cmdline.Found(wxT("disable-fatal")) ) {
480 #ifndef __WXMSW__
481 // catch fatal exceptions
482 wxHandleFatalExceptions(true);
483 #endif
486 bool reset_config = cmdline.Found(wxT("reset-config"));
488 enable_stdout_log = cmdline.Found(wxT("log-stdout"));
489 #ifdef AMULE_DAEMON
490 enable_daemon_fork = cmdline.Found(wxT("full-daemon"));
491 #else
492 enable_daemon_fork = false;
493 #endif
495 if ( enable_stdout_log ) {
496 if ( enable_daemon_fork ) {
497 printf("Daemon will fork to background - log to stdout disabled\n");
498 enable_stdout_log = false;
499 } else {
500 printf("Logging to stdout enabled\n");
504 if ( cmdline.Found(wxT("version")) ) {
505 printf("%s (OS: %s)\n",
506 (const char*)unicode2char(GetFullMuleVersion()),
507 (const char*)unicode2char(OSType));
509 return false;
512 // Default geometry of the GUI. Can be changed with a cmdline argument...
513 bool geometry_enabled = false;
514 wxString geom_string;
515 #ifndef AMULE_DAEMON
516 if ( cmdline.Found(wxT("geometry"), &geom_string) ) {
517 geometry_enabled = true;
519 #endif
522 printf("Initialising aMule\n");
524 // Ensure that "~/.aMule/" is accessible.
525 if (!CheckMuleDirectory(wxT("configuration"), CPath(ConfigDir), wxEmptyString).first) {
526 return false;
529 if (reset_config) {
530 // Make a backup first.
531 wxRemoveFile(ConfigDir + wxT("amule.conf.backup"));
532 wxRenameFile(ConfigDir + wxT("amule.conf"), ConfigDir + wxT("amule.conf.backup"));
533 printf("Your settings have ben resetted to default values.\nOld config file has been saved as amule.conf.backup\n");
536 #if defined(__WXMAC__) && defined(AMULE_DAEMON)
537 //#warning TODO: fix wxSingleInstanceChecker for amuled on Mac (wx link problems)
538 printf("WARNING: The check for other instances is currently disabled in amuled.\n"
539 "Please make sure that no other instance of aMule is running or your files might be corrupted.\n");
540 #else
541 printf("Checking if there is an instance already running...\n");
543 m_singleInstance = new wxSingleInstanceChecker(wxT("muleLock"), ConfigDir);
544 if (m_singleInstance->IsAnotherRunning()) {
545 printf("There is an instance of aMule already running\n");
547 // This is very tricky. The most secure way to communicate is via ED2K links file
548 wxTextFile ed2kFile(ConfigDir + wxT("ED2KLinks"));
549 if (!ed2kFile.Exists()) {
550 ed2kFile.Create();
553 if (ed2kFile.Open()) {
554 ed2kFile.AddLine(wxT("RAISE_DIALOG"));
555 ed2kFile.Write();
557 printf("Raising current running instance.\n");
558 } else {
559 printf("Failed to open 'ED2KFile', cannot signal running instance.\n");
562 return false;
563 } else {
564 printf("No other instances are running.\n");
566 #endif
568 // Close standard-input
569 if ( !cmdline.Found(wxT("enable-stdin")) ) {
570 // The full daemon will close all std file-descriptors by itself,
571 // so closing it here would lead to the closing on the first open
572 // file, which is the logfile opened below
573 if (!enable_daemon_fork) {
574 close(0);
578 // This creates the CFG file we shall use
579 wxConfigBase* cfg = new wxFileConfig( wxEmptyString, wxEmptyString, ConfigDir + wxT("amule.conf") );
581 // Set the config object as the global cfg file
582 wxConfig::Set( cfg );
584 // Make a backup of the log file
585 CPath logfileName = CPath(ConfigDir + wxT("logfile"));
586 if (logfileName.FileExists()) {
587 CPath::BackupFile(logfileName, wxT(".bak"));
590 // Open the log file
591 applog = new wxFFileOutputStream(logfileName.GetRaw());
592 if (!applog->Ok()) {
593 // use std err as last resolt to indicate problem
594 fputs("ERROR: unable to open log file\n", stderr);
595 delete applog;
596 applog = NULL;
597 // failure to open log is serious problem
598 return false;
601 // Load Preferences
602 CPreferences::BuildItemList(ConfigDir);
603 CPreferences::LoadAllItems( wxConfigBase::Get() );
605 glob_prefs = new CPreferences();
607 std::pair<bool, CPath> checkResult;
608 checkResult = CheckMuleDirectory(wxT("temp"), thePrefs::GetTempDir(), ConfigDir + wxT("Temp"));
609 if (checkResult.first) {
610 thePrefs::SetTempDir(checkResult.second);
611 } else {
612 return false;
615 checkResult = CheckMuleDirectory(wxT("incoming"), thePrefs::GetIncomingDir(), ConfigDir + wxT("Incoming"));
616 if (checkResult.first) {
617 thePrefs::SetIncomingDir(checkResult.second);
618 } else {
619 return false;
622 // Some sanity check
623 if (!thePrefs::UseTrayIcon()) {
624 thePrefs::SetMinToTray(false);
627 // Build the filenames for the two OS files
628 SetOSFiles(thePrefs::GetOSDir().GetRaw());
630 #ifdef ENABLE_NLS
631 // Load localization settings
632 Localize_mule();
633 #endif
635 // Configure EC for amuled when invoked with ec-config
636 if (ec_config) {
637 printf("\nEC configuration\n");
638 thePrefs::SetECPass(GetPassword());
639 thePrefs::EnableExternalConnections(true);
640 printf("Password set and external connections enabled.\n");
643 // Display notification on new version or first run
644 wxTextFile vfile( ConfigDir + wxT("lastversion") );
645 wxString newMule(wxT( VERSION ));
647 // Test if there's any new version
648 if (thePrefs::CheckNewVersion()) {
649 // We use the thread base because I don't want a dialog to pop up.
650 CHTTPDownloadThread* version_check =
651 new CHTTPDownloadThread(wxT("http://amule.sourceforge.net/lastversion"),
652 theApp->ConfigDir + wxT("last_version_check"), HTTP_VersionCheck, false);
653 version_check->Create();
654 version_check->Run();
657 if ( !wxFileExists( vfile.GetName() ) ) {
658 vfile.Create();
661 #ifndef __WXMSW__
662 if (getuid() == 0) {
663 wxString msg =
664 wxT("Warning! You are running aMule as root.\n")
665 wxT("Doing so is not recommended for security reasons,\n")
666 wxT("and you are advised to run aMule as an normal\n")
667 wxT("user instead.");
669 ShowAlert(msg, _("Warning"), wxCENTRE | wxOK | wxICON_ERROR);
671 fprintf(stderr, "\n--------------------------------------------------\n");
672 fprintf(stderr, "%s", (const char*)unicode2UTF8(msg));
673 fprintf(stderr, "\n--------------------------------------------------\n\n");
675 #endif
677 if ( vfile.Open() ) {
678 // Check if this version has been run before
679 bool found = false;
680 for ( size_t i = 0; i < vfile.GetLineCount(); i++ ) {
681 // Check if this version has been run before
682 if ( vfile.GetLine(i) == newMule ) {
683 found = true;
684 break;
688 // We havent run this version before?
689 if ( !found ) {
690 // Insert new at top to provide faster searches
691 vfile.InsertLine( newMule, 0 );
693 Trigger_New_version( newMule );
696 // Keep at most 10 entires
697 while ( vfile.GetLineCount() > 10 )
698 vfile.RemoveLine( vfile.GetLineCount() - 1 );
700 vfile.Write();
701 vfile.Close();
704 // Check if we have the old style locale config
705 wxString langId = thePrefs::GetLanguageID();
706 if (!langId.IsEmpty() && (langId.GetChar(0) >= '0' && langId.GetChar(0) <= '9')) {
707 wxString info(_("Your locale has been changed to System Default due to a configuration change. Sorry."));
708 thePrefs::SetLanguageID(wxLang2Str(wxLANGUAGE_DEFAULT));
709 ShowAlert(info, _("Info"), wxCENTRE | wxOK | wxICON_ERROR);
712 m_statistics = new CStatistics();
714 clientlist = new CClientList();
715 friendlist = new CFriendList();
716 searchlist = new CSearchList();
717 knownfiles = new CKnownFileList();
718 serverlist = new CServerList();
720 sharedfiles = new CSharedFileList(knownfiles);
721 clientcredits = new CClientCreditsList();
723 // bugfix - do this before creating the uploadqueue
724 downloadqueue = new CDownloadQueue();
725 uploadqueue = new CUploadQueue();
726 ipfilter = new CIPFilter();
728 // Creates all needed listening sockets
729 wxString msg;
730 if (!ReinitializeNetwork(&msg)) {
731 printf("\n%s\n", (const char *)unicode2char(msg));
734 // Create main dialog, or fork to background (daemon).
735 InitGui(geometry_enabled, geom_string);
737 // Has to be created after the call to InitGui, as fork
738 // (when using posix threads) only replicates the mainthread,
739 // and the UBT constructor creates a thread.
740 uploadBandwidthThrottler = new UploadBandwidthThrottler();
742 // These must be initialized after the gui is loaded.
743 serverlist->Init();
744 downloadqueue->LoadMetFiles(thePrefs::GetTempDir());
745 sharedfiles->Reload();
747 if (thePrefs::IPFilterAutoLoad()) {
748 ipfilter->Update(thePrefs::IPFilterURL());
752 // Ensure that the up/down ratio is used
753 CPreferences::CheckUlDlRatio();
755 // The user can start pressing buttons like mad if he feels like it.
756 m_app_state = APP_STATE_RUNNING;
758 // Kry - Load the sources seeds on app init
759 if (thePrefs::GetSrcSeedsOn()) {
760 downloadqueue->LoadSourceSeeds();
763 if (!serverlist->GetServerCount() && thePrefs::GetNetworkED2K()) {
764 // There are no servers and ED2K active -> ask for download.
765 // As we cannot ask in amuled, we just update there
766 // Kry TODO: Store server.met URL on preferences and use it here and in GUI.
767 #ifndef AMULE_DAEMON
768 if (wxYES == wxMessageBox(
769 wxString(
770 _("You don't have any server in the server list.\nDo you want aMule to download a new list now?")),
771 wxString(_("Server list download")),
772 wxYES_NO,
773 static_cast<wxWindow*>(theApp->amuledlg)))
774 #endif
776 // workaround amuled crash
777 #ifndef AMULE_DAEMON
778 serverlist->UpdateServerMetFromURL(
779 wxT("http://gruk.org/server.met.gz"));
780 #endif
785 // Autoconnect if that option is enabled
786 if (thePrefs::DoAutoConnect() && (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia())) {
787 AddLogLineM(true, _("Connecting"));
788 if (thePrefs::GetNetworkED2K()) {
789 theApp->serverconnect->ConnectToAnyServer();
792 StartKad();
796 // No webserver on Win at all (yet)
797 #ifndef __WXMSW__
798 // Run webserver?
799 if (thePrefs::GetWSIsEnabled()) {
800 wxString aMuleConfigFile = ConfigDir + wxT("amule.conf");
801 wxString amulewebPath = wxT("amuleweb");
803 #if defined(__WXMAC__) && !defined(AMULE_DAEMON)
804 // For the Mac GUI application, look for amuleweb in the bundle
805 CFURLRef amulewebUrl = CFBundleCopyAuxiliaryExecutableURL(
806 CFBundleGetMainBundle(), CFSTR("amuleweb"));
808 if (amulewebUrl) {
809 CFURLRef absoluteUrl = CFURLCopyAbsoluteURL(amulewebUrl);
810 CFRelease(amulewebUrl);
812 if (absoluteUrl) {
813 CFStringRef amulewebCfstr = CFURLCopyFileSystemPath(absoluteUrl, kCFURLPOSIXPathStyle);
814 CFRelease(absoluteUrl);
815 amulewebPath = wxMacCFStringHolder(amulewebCfstr).AsString(wxLocale::GetSystemEncoding());
818 #endif
820 wxString cmd =
821 wxT("'") +
822 amulewebPath +
823 wxT("' '--amule-config-file=") +
824 aMuleConfigFile +
825 wxT("'");
826 CTerminationProcessAmuleweb *p = new CTerminationProcessAmuleweb(cmd, &webserver_pid);
827 webserver_pid = wxExecute(cmd, wxEXEC_ASYNC, p);
828 bool webserver_ok = webserver_pid > 0;
829 if (webserver_ok) {
830 AddLogLineM(true, CFormat(_("webserver running on pid %d")) % webserver_pid);
831 } else {
832 delete p;
833 ShowAlert(_(
834 "You requested to run webserver from startup, "
835 "but the amuleweb binary cannot be run. "
836 "Please install the package containing aMule webserver, "
837 "or compile aMule using --enable-webserver and run make install"),
838 _("Error"), wxOK | wxICON_ERROR);
841 #endif /* ! __WXMSW__ */
843 // Start performing background tasks
844 CThreadScheduler::Start();
846 return true;
849 bool CamuleApp::ReinitializeNetwork(wxString* msg)
851 bool ok = true;
852 static bool firstTime = true;
854 if (!firstTime) {
855 // TODO: Destroy previously created sockets
857 firstTime = false;
859 // Some sanity checks first
860 if (thePrefs::ECPort() == thePrefs::GetPort()) {
861 // Select a random usable port in the range 1025 ... 2^16 - 1
862 uint16 port = thePrefs::ECPort();
863 while ( port < 1024 || port == thePrefs::GetPort() ) {
864 port = (uint16)rand();
866 thePrefs::SetECPort( port );
868 wxString err =
869 wxT("Network configuration failed! You cannot use the same port\n")
870 wxT("for the main TCP port and the External Connections port.\n")
871 wxT("The EC port has been changed to avoid conflict, see the\n")
872 wxT("preferences for the new value.\n");
873 *msg << err;
875 AddLogLineM( false, wxEmptyString );
876 AddLogLineM( true, err );
877 AddLogLineM( false, wxEmptyString );
879 ok = false;
882 if (thePrefs::GetUDPPort() == thePrefs::GetPort() + 3) {
883 // Select a random usable value in the range 1025 ... 2^16 - 1
884 uint16 port = thePrefs::GetUDPPort();
885 while ( port < 1024 || port == thePrefs::GetPort() + 3 ) {
886 port = (uint16)rand();
888 thePrefs::SetUDPPort( port );
890 wxString err =
891 wxT("Network configuration failed! You set your UDP port to\n")
892 wxT("the value of the main TCP port plus 3.\n")
893 wxT("This port has been reserved for the Server-UDP port. The\n")
894 wxT("port value has been changed to avoid conflict, see the\n")
895 wxT("preferences for the new value\n");
896 *msg << err;
898 AddLogLineM( false, wxEmptyString );
899 AddLogLineM( true, err );
900 AddLogLineM( false, wxEmptyString );
902 ok = false;
905 // Create the address where we are going to listen
906 // TODO: read this from configuration file
907 amuleIPV4Address myaddr[4];
909 // Create the External Connections Socket.
910 // Default is 4712.
911 // Get ready to handle connections from apps like amulecmd
912 if (thePrefs::GetECAddress().IsEmpty() || !myaddr[0].Hostname(thePrefs::GetECAddress())) {
913 myaddr[0].AnyAddress();
915 myaddr[0].Service(thePrefs::ECPort());
916 ECServerHandler = new ExternalConn(myaddr[0], msg);
918 // Create the UDP socket TCP+3.
919 // Used for source asking on servers.
920 if (thePrefs::GetAddress().IsEmpty()) {
921 myaddr[1].AnyAddress();
922 } else if (!myaddr[1].Hostname(thePrefs::GetAddress())) {
923 myaddr[1].AnyAddress();
924 AddLogLineM(true, CFormat(_("Could not bind ports to the specified address: %s"))
925 % thePrefs::GetAddress());
928 wxString ip = myaddr[1].IPAddress();
929 myaddr[1].Service(thePrefs::GetPort()+3);
930 serverconnect = new CServerConnect(serverlist, myaddr[1]);
931 *msg << CFormat( wxT("*** Server UDP socket (TCP+3) at %s:%u\n") )
932 % ip % ((unsigned int)thePrefs::GetPort() + 3u);
934 // Create the ListenSocket (aMule TCP socket).
935 // Used for Client Port / Connections from other clients,
936 // Client to Client Source Exchange.
937 // Default is 4662.
938 myaddr[2] = myaddr[1];
939 myaddr[2].Service(thePrefs::GetPort());
940 listensocket = new CListenSocket(myaddr[2]);
941 *msg << CFormat( wxT("*** TCP socket (TCP) listening on %s:%u\n") )
942 % ip % (unsigned int)(thePrefs::GetPort());
943 // This command just sets a flag to control maximum number of connections.
944 // Notify(true) has already been called to the ListenSocket, so events may
945 // be already comming in.
946 if (listensocket->Ok()) {
947 listensocket->StartListening();
948 } else {
949 // If we wern't able to start listening, we need to warn the user
950 wxString err;
951 err = CFormat(_("Port %u is not available. You will be LOWID\n")) %
952 (unsigned int)(thePrefs::GetPort());
953 *msg << err;
954 AddLogLineM(true, err);
955 err.Clear();
956 err = CFormat(
957 _("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.")) %
958 (unsigned int)(thePrefs::GetPort());
959 ShowAlert(err, _("Error"), wxOK | wxICON_ERROR);
962 // Create the UDP socket.
963 // Used for extended eMule protocol, Queue Rating, File Reask Ping.
964 // Also used for Kademlia.
965 // Default is port 4672.
966 myaddr[3] = myaddr[1];
967 myaddr[3].Service(thePrefs::GetUDPPort());
968 clientudp = new CClientUDPSocket(myaddr[3], thePrefs::GetProxyData());
969 if (!thePrefs::IsUDPDisabled()) {
970 *msg << CFormat( wxT("*** Client UDP socket (extended eMule) at %s:%u") )
971 % ip % thePrefs::GetUDPPort();
972 } else {
973 *msg << wxT("*** Client UDP socket (extended eMule) disabled on preferences");
976 #ifdef ENABLE_UPNP
977 if (thePrefs::GetUPnPEnabled()) {
978 try {
979 m_upnpMappings[0] = CUPnPPortMapping(
980 myaddr[0].Service(),
981 "TCP",
982 thePrefs::GetUPnPECEnabled(),
983 "aMule TCP External Connections Socket");
984 m_upnpMappings[1] = CUPnPPortMapping(
985 myaddr[1].Service(),
986 "UDP",
987 thePrefs::GetUPnPEnabled(),
988 "aMule UDP socket (TCP+3)");
989 m_upnpMappings[2] = CUPnPPortMapping(
990 myaddr[2].Service(),
991 "TCP",
992 thePrefs::GetUPnPEnabled(),
993 "aMule TCP Listen Socket");
994 m_upnpMappings[3] = CUPnPPortMapping(
995 myaddr[3].Service(),
996 "UDP",
997 thePrefs::GetUPnPEnabled(),
998 "aMule UDP Extended eMule Socket");
999 m_upnp = new CUPnPControlPoint(thePrefs::GetUPnPTCPPort());
1000 m_upnp->AddPortMappings(m_upnpMappings);
1001 } catch(CUPnPException &e) {
1002 wxString error_msg;
1003 error_msg << e.what();
1004 AddLogLineM(true, error_msg);
1005 fprintf(stderr, "%s\n", (const char *)unicode2char(error_msg));
1008 #endif
1010 return ok;
1013 // Returns a magnet ed2k URI
1014 wxString CamuleApp::CreateMagnetLink(const CAbstractFile *f)
1016 CMagnetURI uri;
1018 uri.AddField(wxT("dn"), f->GetFileName().Cleanup(false).GetPrintable());
1019 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2k:")) + f->GetFileHash().Encode().Lower());
1020 uri.AddField(wxT("xl"), wxString::Format(wxT("%") wxLongLongFmtSpec wxT("u"), f->GetFileSize()));
1022 return uri.GetLink();
1025 // Returns a ed2k file URL
1026 wxString CamuleApp::CreateED2kLink(const CAbstractFile *f, bool add_source, bool use_hostname, bool addcryptoptions)
1028 wxASSERT(!(!add_source && (use_hostname || addcryptoptions)));
1029 // Construct URL like this: ed2k://|file|<filename>|<size>|<hash>|/
1030 wxString strURL = CFormat(wxT("ed2k://|file|%s|%i|%s|/"))
1031 % f->GetFileName().Cleanup(false)
1032 % f->GetFileSize() % f->GetFileHash().Encode();
1034 if (add_source && IsConnected() && !IsFirewalled()) {
1035 // Create the first part of the URL
1036 strURL << wxT("|sources,");
1037 if (use_hostname) {
1038 strURL << thePrefs::GetYourHostname();
1039 } else {
1040 uint32 clientID = GetID();
1041 strURL << (uint8) clientID << wxT(".") <<
1042 (uint8)(clientID >> 8) << wxT(".") <<
1043 (uint8)(clientID >> 16) << wxT(".") <<
1044 (uint8)(clientID >> 24);
1047 strURL << wxT(":") <<
1048 thePrefs::GetPort();
1050 if (addcryptoptions) {
1051 const uint8 uSupportsCryptLayer = thePrefs::IsClientCryptLayerSupported() ? 1 : 0;
1052 const uint8 uRequestsCryptLayer = thePrefs::IsClientCryptLayerRequested() ? 1 : 0;
1053 const uint8 uRequiresCryptLayer = thePrefs::IsClientCryptLayerRequired() ? 1 : 0;
1054 const uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0) | (uSupportsCryptLayer ? 0x80 : 0x00);
1056 strURL << wxT(":") << byCryptOptions;
1058 if (byCryptOptions & 0x80) {
1059 strURL << wxT(":") << thePrefs::GetUserHash().Encode();
1062 strURL << wxT("|/");
1063 } else if (add_source) {
1064 AddLogLineM(true, _("WARNING: You can't add yourself as a source for a ed2k link while being lowid."));
1067 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|sources,[(<ip>|<hostname>):<port>[:cryptoptions[:hash]]]|/"
1068 return strURL;
1071 // Returns a ed2k link with AICH info if available
1072 wxString CamuleApp::CreateED2kAICHLink(const CKnownFile* f)
1074 // Create the first part of the URL
1075 wxString strURL = CreateED2kLink(f);
1076 // Append the AICH info
1077 if (f->HasProperAICHHashSet()) {
1078 strURL << wxT("|h=") << f->GetAICHMasterHash() << wxT("|/");
1081 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|h=<AICH master hash>|/"
1082 return strURL;
1085 /* Original implementation by Bouc7 of the eMule Project.
1086 aMule Signature idea was designed by BigBob and implemented
1087 by Un-Thesis, with design inputs and suggestions from bothie.
1089 void CamuleApp::OnlineSig(bool zero /* reset stats (used on shutdown) */)
1091 // Do not do anything if online signature is disabled in Preferences
1092 if (!thePrefs::IsOnlineSignatureEnabled() || m_emulesig_path.IsEmpty()) {
1093 // We do not need to check m_amulesig_path because if m_emulesig_path is empty,
1094 // that means m_amulesig_path is empty too.
1095 return;
1098 // Remove old signature files
1099 if ( wxFileExists( m_emulesig_path ) ) { wxRemoveFile( m_emulesig_path ); }
1100 if ( wxFileExists( m_amulesig_path ) ) { wxRemoveFile( m_amulesig_path ); }
1103 wxTextFile amulesig_out;
1104 wxTextFile emulesig_out;
1106 // Open both files if needed
1107 if ( !emulesig_out.Create( m_emulesig_path) ) {
1108 AddLogLineM(true, _("Failed to create OnlineSig File"));
1109 // Will never try again.
1110 m_amulesig_path.Clear();
1111 m_emulesig_path.Clear();
1112 return;
1115 if ( !amulesig_out.Create(m_amulesig_path) ) {
1116 AddLogLineM(true, _("Failed to create aMule OnlineSig File"));
1117 // Will never try again.
1118 m_amulesig_path.Clear();
1119 m_emulesig_path.Clear();
1120 return;
1123 wxString emulesig_string;
1124 wxString temp;
1126 if (zero) {
1127 emulesig_string = wxT("0\xA0.0|0.0|0");
1128 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0\n0\n0.0\n0.0\n0\n0"));
1129 } else {
1130 if (IsConnectedED2K()) {
1132 temp = wxString::Format(wxT("%d"),serverconnect->GetCurrentServer()->GetPort());
1134 // We are online
1135 emulesig_string =
1136 // Connected
1137 wxT("1|")
1138 //Server name
1139 + serverconnect->GetCurrentServer()->GetListName()
1140 + wxT("|")
1141 // IP and port of the server
1142 + serverconnect->GetCurrentServer()->GetFullIP()
1143 + wxT("|")
1144 + temp;
1147 // Now for amule sig
1149 // Connected. State 1, full info
1150 amulesig_out.AddLine(wxT("1"));
1151 // Server Name
1152 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetListName());
1153 // Server IP
1154 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetFullIP());
1155 // Server Port
1156 amulesig_out.AddLine(temp);
1158 if (serverconnect->IsLowID()) {
1159 amulesig_out.AddLine(wxT("L"));
1160 } else {
1161 amulesig_out.AddLine(wxT("H"));
1164 } else if (serverconnect->IsConnecting()) {
1165 emulesig_string = wxT("0");
1167 // Connecting. State 2, No info.
1168 amulesig_out.AddLine(wxT("2\n0\n0\n0\n0"));
1169 } else {
1170 // Not connected to a server
1171 emulesig_string = wxT("0");
1173 // Not connected, state 0, no info
1174 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0"));
1176 if (IsConnectedKad()) {
1177 if(Kademlia::CKademlia::IsFirewalled()) {
1178 // Connected. Firewalled. State 1.
1179 amulesig_out.AddLine(wxT("1"));
1180 } else {
1181 // Connected. State 2.
1182 amulesig_out.AddLine(wxT("2"));
1184 } else {
1185 // Not connected.State 0.
1186 amulesig_out.AddLine(wxT("0"));
1188 emulesig_string += wxT("\xA");
1190 // Datarate for downloads
1191 temp = wxString::Format(wxT("%.1f"), theStats::GetDownloadRate() / 1024.0);
1193 emulesig_string += temp + wxT("|");
1194 amulesig_out.AddLine(temp);
1196 // Datarate for uploads
1197 temp = wxString::Format(wxT("%.1f"), theStats::GetUploadRate() / 1024.0);
1199 emulesig_string += temp + wxT("|");
1200 amulesig_out.AddLine(temp);
1202 // Number of users waiting for upload
1203 temp = wxString::Format(wxT("%d"), theStats::GetWaitingUserCount());
1205 emulesig_string += temp;
1206 amulesig_out.AddLine(temp);
1208 // Number of shared files (not on eMule)
1209 amulesig_out.AddLine(wxString::Format(wxT("%d"), theStats::GetSharedFileCount()));
1212 // eMule signature finished here. Write the line to the wxTextFile.
1213 emulesig_out.AddLine(emulesig_string);
1215 // Now for aMule signature extras
1217 // Nick on the network
1218 amulesig_out.AddLine(thePrefs::GetUserNick());
1220 // Total received in bytes
1221 amulesig_out.AddLine( CFormat( wxT("%llu") ) % (theStats::GetSessionReceivedBytes() + thePrefs::GetTotalDownloaded()) );
1223 // Total sent in bytes
1224 amulesig_out.AddLine( CFormat( wxT("%llu") ) % (theStats::GetSessionSentBytes() + thePrefs::GetTotalUploaded()) );
1226 // amule version
1227 #ifdef SVNDATE
1228 amulesig_out.AddLine(wxT(VERSION " " SVNDATE));
1229 #else
1230 amulesig_out.AddLine(wxT(VERSION));
1231 #endif
1233 if (zero) {
1234 amulesig_out.AddLine(wxT("0"));
1235 amulesig_out.AddLine(wxT("0"));
1236 amulesig_out.AddLine(wxT("0"));
1237 } else {
1238 // Total received bytes in session
1239 amulesig_out.AddLine( CFormat( wxT("%llu") ) %
1240 theStats::GetSessionReceivedBytes() );
1242 // Total sent bytes in session
1243 amulesig_out.AddLine( CFormat( wxT("%llu") ) %
1244 theStats::GetSessionSentBytes() );
1246 // Uptime
1247 amulesig_out.AddLine(CFormat(wxT("%llu")) % theStats::GetUptimeSeconds());
1250 // Flush the files
1251 emulesig_out.Write();
1252 amulesig_out.Write();
1253 } //End Added By Bouc7
1256 // Gracefully handle fatal exceptions and print backtrace if possible
1257 void CamuleApp::OnFatalException()
1259 /* Print the backtrace */
1260 fprintf(stderr, "\n--------------------------------------------------------------------------------\n");
1261 fprintf(stderr, "A fatal error has occurred and aMule has crashed.\n");
1262 fprintf(stderr, "Please assist us in fixing this problem by posting the backtrace below in our\n");
1263 fprintf(stderr, "'aMule Crashes' forum and include as much information as possible regarding the\n");
1264 fprintf(stderr, "circumstances of this crash. The forum is located here:\n");
1265 fprintf(stderr, " http://forum.amule.org/index.php?board=67.0\n");
1266 fprintf(stderr, "If possible, please try to generate a real backtrace of this crash:\n");
1267 fprintf(stderr, " http://www.amule.org/wiki/index.php/Backtraces\n\n");
1268 fprintf(stderr, "----------------------------=| BACKTRACE FOLLOWS: |=----------------------------\n");
1269 fprintf(stderr, "Current version is: %s\n", strFullMuleVersion);
1270 fprintf(stderr, "Running on: %s\n\n", strOSDescription);
1272 print_backtrace(1); // 1 == skip this function.
1274 fprintf(stderr, "\n--------------------------------------------------------------------------------\n");
1278 // Sets the localization of aMule
1279 void CamuleApp::Localize_mule()
1281 InitCustomLanguages();
1282 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
1283 if (!m_locale.IsOk()) {
1284 AddLogLineM(false,_("The selected locale seems not to be installed on your box. (Note: I'll try to set it anyway)"));
1289 // Displays information related to important changes in aMule.
1290 // Is called when the user runs a new version of aMule
1291 void CamuleApp::Trigger_New_version(wxString new_version)
1293 wxString info = wxT(" --- ") + CFormat(_("This is the first time you run aMule %s")) % new_version + wxT(" ---\n\n");
1294 if (new_version == wxT("SVN")) {
1295 info += _("This version is a testing version, updated daily, and\n");
1296 info += _("we give no warranty it won't break anything, burn your house,\n");
1297 info += _("or kill your dog. But it *should* be safe to use anyway.\n");
1298 } else if (new_version == wxT("2.2.0")) {
1299 thePrefs::SetAddServersFromServer(false);
1300 thePrefs::SetAddServersFromClient(false);
1301 info += _("The following options have been changed in this release for security reasons:\n");
1302 info += _("\n* Enabled Protocol Obfuscation support for incoming and outgoing connections.\n");
1303 info += _("\n* Disabled updating the server list from other server and clients.\n");
1304 info += _("\nFor more information on the reason for this changes, seach\nthe aMule wiki at http://wiki.amule.org for \"fake servers\" info.\nIt's important that you clear any fake server from your server list for aMule to work properly.");
1307 // General info
1308 info += wxT("\n");
1309 info += _("More information, support and new releases can found at our homepage,\n");
1310 info += _("at www.aMule.org, or in our IRC channel #aMule at irc.freenode.net.\n");
1311 info += wxT("\n");
1312 info += _("Feel free to report any bugs to http://forum.amule.org");
1314 ShowAlert(info, _("Info"), wxCENTRE | wxOK | wxICON_ERROR);
1318 void CamuleApp::SetOSFiles(const wxString new_path)
1320 if ( thePrefs::IsOnlineSignatureEnabled() ) {
1321 if ( ::wxDirExists(new_path) ) {
1322 m_emulesig_path = JoinPaths(new_path, wxT("onlinesig.dat"));
1323 m_amulesig_path = JoinPaths(new_path, wxT("amulesig.dat"));
1324 } else {
1325 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);
1326 m_emulesig_path.Clear();
1327 m_amulesig_path.Clear();
1329 } else {
1330 m_emulesig_path.Clear();
1331 m_amulesig_path.Clear();
1336 #ifdef __WXDEBUG__
1337 #ifndef wxUSE_STACKWALKER
1338 #define wxUSE_STACKWALKER 0
1339 #endif
1340 void CamuleApp::OnAssertFailure(const wxChar* file, int line,
1341 const wxChar* func, const wxChar* cond, const wxChar* msg)
1343 if (!wxUSE_STACKWALKER || !wxThread::IsMain() || !IsRunning()) {
1344 wxString errmsg = CFormat( wxT("%s:%s:%d: Assertion '%s' failed. %s") )
1345 % file % func % line % cond % ( msg ? msg : wxT("") );
1347 fprintf(stderr, "Assertion failed: %s\n", (const char*)unicode2char(errmsg));
1349 // Skip the function-calls directly related to the assert call.
1350 fprintf(stderr, "\nBacktrace follows:\n");
1351 print_backtrace(3);
1352 fprintf(stderr, "\n");
1355 if (wxThread::IsMain() && IsRunning()) {
1356 AMULE_APP_BASE::OnAssertFailure(file, line, func, cond, msg);
1357 } else {
1358 // Abort, allows gdb to catch the assertion
1359 raise( SIGABRT );
1362 #endif
1365 void CamuleApp::OnUDPDnsDone(CMuleInternalEvent& evt)
1367 CServerUDPSocket* socket =(CServerUDPSocket*)evt.GetClientData();
1368 socket->OnHostnameResolved(evt.GetExtraLong());
1372 void CamuleApp::OnSourceDnsDone(CMuleInternalEvent& evt)
1374 downloadqueue->OnHostnameResolved(evt.GetExtraLong());
1378 void CamuleApp::OnServerDnsDone(CMuleInternalEvent& evt)
1380 printf("Server hostname notified\n");
1381 serverconnect->OnServerHostnameResolved(evt.GetClientData(), evt.GetExtraLong());
1385 void CamuleApp::OnTCPTimer(CTimerEvent& WXUNUSED(evt))
1387 if(!IsRunning()) {
1388 return;
1390 serverconnect->StopConnectionTry();
1391 if (IsConnectedED2K() ) {
1392 return;
1394 serverconnect->ConnectToAnyServer();
1398 void CamuleApp::OnCoreTimer(CTimerEvent& WXUNUSED(evt))
1400 // Former TimerProc section
1401 static uint64 msPrev1, msPrev5, msPrevSave, msPrevHist, msPrevOS, msPrevKnownMet;
1402 uint64 msCur = theStats::GetUptimeMillis();
1404 if (!IsRunning()) {
1405 return;
1408 #ifndef AMULE_DAEMON
1409 // Check if we should terminate the app
1410 if ( g_shutdownSignal ) {
1411 wxWindow* top = GetTopWindow();
1413 if ( top ) {
1414 top->Close(true);
1415 } else {
1416 // No top-window, have to force termination.
1417 wxExit();
1420 #endif
1422 CLogger::FlushPendingEntries();
1424 uploadqueue->Process();
1425 downloadqueue->Process();
1426 //theApp->clientcredits->Process();
1427 theStats::CalculateRates();
1429 if (msCur-msPrevHist > 1000) {
1430 // unlike the other loop counters in this function this one will sometimes
1431 // produce two calls in quick succession (if there was a gap of more than one
1432 // second between calls to TimerProc) - this is intentional! This way the
1433 // history list keeps an average of one node per second and gets thinned out
1434 // correctly as time progresses.
1435 msPrevHist += 1000;
1437 m_statistics->RecordHistory();
1442 if (msCur-msPrev1 > 1000) { // approximately every second
1443 msPrev1 = msCur;
1444 clientcredits->Process();
1445 clientlist->Process();
1447 // Publish files to server if needed.
1448 sharedfiles->Process();
1450 if( Kademlia::CKademlia::IsRunning() ) {
1451 Kademlia::CKademlia::Process();
1452 if(Kademlia::CKademlia::GetPrefs()->HasLostConnection()) {
1453 StopKad();
1454 clientudp->Close();
1455 clientudp->Open();
1456 if (thePrefs::Reconnect()) {
1457 StartKad();
1462 if( serverconnect->IsConnecting() && !serverconnect->IsSingleConnect() ) {
1463 serverconnect->TryAnotherConnectionrequest();
1465 if (serverconnect->IsConnecting()) {
1466 serverconnect->CheckForTimeout();
1468 listensocket->UpdateConnectionsStatus();
1473 if (msCur-msPrev5 > 5000) { // every 5 seconds
1474 msPrev5 = msCur;
1475 listensocket->Process();
1478 if (msCur-msPrevSave >= 60000) {
1479 msPrevSave = msCur;
1480 wxString buffer;
1482 // Save total upload/download to preferences
1483 wxConfigBase* cfg = wxConfigBase::Get();
1484 buffer = CFormat(wxT("%llu")) % (theStats::GetSessionReceivedBytes() + thePrefs::GetTotalDownloaded());
1485 cfg->Write(wxT("/Statistics/TotalDownloadedBytes"), buffer);
1487 buffer = CFormat(wxT("%llu")) % (theStats::GetSessionSentBytes() + thePrefs::GetTotalUploaded());
1488 cfg->Write(wxT("/Statistics/TotalUploadedBytes"), buffer);
1490 // Write changes to file
1491 cfg->Flush();
1495 // Special
1496 if (msCur - msPrevOS >= thePrefs::GetOSUpdate() * 1000ull) {
1497 OnlineSig(); // Added By Bouc7
1498 msPrevOS = msCur;
1501 if (msCur - msPrevKnownMet >= 30*60*1000/*There must be a prefs option for this*/) {
1502 // Save Shared Files data
1503 knownfiles->Save();
1504 msPrevKnownMet = msCur;
1508 // Recomended by lugdunummaster himself - from emule 0.30c
1509 serverconnect->KeepConnectionAlive();
1514 void CamuleApp::OnFinishedHashing(CHashingEvent& evt)
1516 wxCHECK_RET(evt.GetResult(), wxT("No result of hashing"));
1518 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner());
1519 CKnownFile* result = evt.GetResult();
1521 if (owner) {
1522 // Check if the partfile still exists, as it might have
1523 // been deleted in the mean time.
1524 if (downloadqueue->IsPartFile(owner)) {
1525 // This cast must not be done before the IsPartFile
1526 // call, as dynamic_cast will barf on dangling pointers.
1527 dynamic_cast<CPartFile*>(owner)->PartFileHashFinished(result);
1529 } else {
1530 static int filecount;
1531 static uint64 bytecount;
1533 if (knownfiles->SafeAddKFile(result)) {
1534 AddDebugLogLineM(false, logKnownFiles,
1535 CFormat(wxT("Safe adding file to sharedlist: %s")) % result->GetFileName());
1536 sharedfiles->SafeAddKFile(result);
1538 filecount++;
1539 bytecount += result->GetFileSize();
1540 // If we have added 30 files or files with a total size of ~300mb
1541 if ( ( filecount == 30 ) || ( bytecount >= 314572800 ) ) {
1542 AddDebugLogLineM(false, logKnownFiles, wxT("Failsafe for crash on file hashing creation"));
1543 if ( m_app_state != APP_STATE_SHUTTINGDOWN ) {
1544 knownfiles->Save();
1545 filecount = 0;
1546 bytecount = 0;
1549 } else {
1550 AddDebugLogLineM(false, logKnownFiles,
1551 CFormat(wxT("File not added to sharedlist: %s")) % result->GetFileName());
1552 delete result;
1558 void CamuleApp::OnFinishedAICHHashing(CHashingEvent& evt)
1560 wxCHECK_RET(evt.GetResult(), wxT("No result of AICH-hashing"));
1562 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner());
1563 std::auto_ptr<CKnownFile> result(evt.GetResult());
1565 // Check that the owner is still valid
1566 if (knownfiles->IsKnownFile(owner)) {
1567 if (result->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE) {
1568 CAICHHashSet* oldSet = owner->GetAICHHashset();
1569 CAICHHashSet* newSet = result->GetAICHHashset();
1571 owner->SetAICHHashset(newSet);
1572 newSet->SetOwner(owner);
1574 result->SetAICHHashset(oldSet);
1575 oldSet->SetOwner(result.get());
1581 void CamuleApp::OnFinishedCompletion(CCompletionEvent& evt)
1583 CPartFile* completed = const_cast<CPartFile*>(evt.GetOwner());
1584 wxCHECK_RET(completed, wxT("Completion event sent for unspecified file"));
1585 wxASSERT_MSG(downloadqueue->IsPartFile(completed), wxT("CCompletionEvent for unknown partfile."));
1587 completed->CompleteFileEnded(evt.ErrorOccured(), evt.GetFullPath());
1588 if (evt.ErrorOccured()) {
1589 CUserEvents::ProcessEvent(CUserEvents::ErrorOnCompletion, completed);
1592 // Check if we should execute an script/app/whatever.
1593 CUserEvents::ProcessEvent(CUserEvents::DownloadCompleted, completed);
1597 void CamuleApp::OnNotifyEvent(CMuleGUIEvent& evt)
1599 #if defined(AMULE_DAEMON)
1600 evt.Notify();
1601 #else
1602 if (theApp->amuledlg) {
1603 evt.Notify();
1605 #endif
1609 void CamuleApp::ShutDown()
1611 // Log
1612 AddDebugLogLineM(false, logGeneral, wxT("CamuleApp::ShutDown() has started."));
1614 // Signal the hashing thread to terminate
1615 m_app_state = APP_STATE_SHUTTINGDOWN;
1617 StopKad();
1619 // Kry - Save the sources seeds on app exit
1620 if (thePrefs::GetSrcSeedsOn()) {
1621 downloadqueue->SaveSourceSeeds();
1624 OnlineSig(true); // Added By Bouc7
1626 // Close sockets to avoid new clients coming in
1627 if (listensocket) {
1628 listensocket->Close();
1629 listensocket->KillAllSockets();
1632 if (serverconnect) {
1633 serverconnect->Disconnect();
1636 ECServerHandler->KillAllSockets();
1638 #ifdef ENABLE_UPNP
1639 if (thePrefs::GetUPnPEnabled()) {
1640 if (m_upnp) {
1641 m_upnp->DeletePortMappings(m_upnpMappings);
1644 #endif
1646 // saving data & stuff
1647 if (knownfiles) {
1648 knownfiles->Save();
1651 thePrefs::Add2TotalDownloaded(theStats::GetSessionReceivedBytes());
1652 thePrefs::Add2TotalUploaded(theStats::GetSessionSentBytes());
1654 if (glob_prefs) {
1655 glob_prefs->Save();
1658 if (clientlist) {
1659 clientlist->DeleteAll();
1662 CThreadScheduler::Terminate();
1664 theApp->uploadBandwidthThrottler->EndThread();
1666 // Log
1667 AddDebugLogLineM(false, logGeneral, wxT("CamuleApp::ShutDown() has ended."));
1671 bool CamuleApp::AddServer(CServer *srv, bool fromUser)
1673 if ( serverlist->AddServer(srv, fromUser) ) {
1674 Notify_ServerAdd(srv);
1675 return true;
1677 return false;
1681 void CamuleApp::AddLogLine(const wxString &msg)
1683 // At most one trailing new-line, which we add
1684 wxString message = msg;
1685 while ( !message.IsEmpty() && message.Last() == wxT('\n') ) {
1686 message.RemoveLast();
1689 wxString full_line = wxDateTime::Now().FormatISODate() + wxT(" ") +
1690 wxDateTime::Now().FormatISOTime() + wxT(": ") + message + wxT("\n");
1692 wxStringInputStream stream(full_line);
1694 if (applog) { // This check is needed, because if we assert before the logger is created, it will crash.
1695 (*applog) << stream;
1696 applog->Sync();
1699 if (enable_stdout_log) {
1700 printf("%s", (const char*)unicode2char(full_line));
1705 uint32 CamuleApp::GetPublicIP(bool ignorelocal) const
1707 if (m_dwPublicIP == 0) {
1708 if (Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::GetIPAddress() ) {
1709 return wxUINT32_SWAP_ALWAYS(Kademlia::CKademlia::GetIPAddress());
1710 } else {
1711 return ignorelocal ? 0 : m_localip;
1715 return m_dwPublicIP;
1719 void CamuleApp::SetPublicIP(const uint32 dwIP)
1721 wxASSERT((dwIP == 0) || !IsLowID(dwIP));
1723 if (dwIP != 0 && dwIP != m_dwPublicIP && serverlist != NULL) {
1724 m_dwPublicIP = dwIP;
1725 serverlist->CheckForExpiredUDPKeys();
1726 } else {
1727 m_dwPublicIP = dwIP;
1732 wxString CamuleApp::GetLog(bool reset)
1734 ConfigDir = GetConfigDir();
1735 wxFile logfile;
1736 logfile.Open(ConfigDir + wxT("logfile"));
1737 if ( !logfile.IsOpened() ) {
1738 return wxTRANSLATE("ERROR: can't open logfile");
1740 int len = logfile.Length();
1741 if ( len == 0 ) {
1742 return wxTRANSLATE("WARNING: logfile is empty. Something is wrong.");
1744 char *tmp_buffer = new char[len + sizeof(wxChar)];
1745 logfile.Read(tmp_buffer, len);
1746 memset(tmp_buffer + len, 0, sizeof(wxChar));
1748 // try to guess file format
1749 wxString str;
1750 if (tmp_buffer[0] && tmp_buffer[1]) {
1751 str = wxString(UTF82unicode(tmp_buffer));
1752 } else {
1753 str = wxString((wxWCharBuffer&)tmp_buffer);
1756 delete [] tmp_buffer;
1757 if ( reset ) {
1758 delete applog;
1759 applog = new wxFFileOutputStream(ConfigDir + wxT("logfile"));
1760 if ( applog->Ok() ) {
1761 AddLogLine(_("Log has been reset"));
1762 } else {
1763 delete applog;
1764 applog = 0;
1767 return str;
1771 wxString CamuleApp::GetServerLog(bool reset)
1773 wxString ret = server_msg;
1774 if ( reset ) {
1775 server_msg.Clear();
1777 return ret;
1780 wxString CamuleApp::GetDebugLog(bool reset)
1782 return GetLog(reset);
1786 void CamuleApp::AddServerMessageLine(wxString &msg)
1788 server_msg += msg + wxT("\n");
1789 AddLogLine(CFormat(_("ServerMessage: %s")) % msg);
1794 void CamuleApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
1796 switch (event.GetInt()) {
1797 case HTTP_IPFilter:
1798 ipfilter->DownloadFinished(event.GetExtraLong());
1799 break;
1800 case HTTP_ServerMet:
1801 serverlist->DownloadFinished(event.GetExtraLong());
1802 break;
1803 case HTTP_ServerMetAuto:
1804 serverlist->AutoDownloadFinished(event.GetExtraLong());
1805 break;
1806 case HTTP_VersionCheck:
1807 CheckNewVersion(event.GetExtraLong());
1808 break;
1809 case HTTP_NodesDat:
1810 if (event.GetExtraLong() != -1) {
1812 wxString file = ConfigDir + wxT("nodes.dat");
1813 if (wxFileExists(file)) {
1814 wxRemoveFile(file);
1817 if ( Kademlia::CKademlia::IsRunning() ) {
1818 Kademlia::CKademlia::Stop();
1821 wxRenameFile(file + wxT(".download"),file);
1823 Kademlia::CKademlia::Start();
1824 theApp->ShowConnectionState();
1826 } else {
1827 AddLogLineM(true, _("Failed to download the nodes list."));
1829 break;
1833 void CamuleApp::CheckNewVersion(uint32 result)
1835 if (result == 1) {
1836 wxString filename = ConfigDir + wxT("last_version_check");
1837 wxTextFile file;
1839 if (!file.Open(filename)) {
1840 AddLogLineM(true, _("Failed to open the downloaded version check file") );
1841 return;
1842 } else if (!file.GetLineCount()) {
1843 AddLogLineM(true, _("Corrupted version check file"));
1844 } else {
1845 wxString versionLine = file.GetFirstLine();
1846 wxStringTokenizer tkz(versionLine, wxT("."));
1848 AddDebugLogLineM(false, logGeneral, wxString(wxT("Running: ")) + wxT(VERSION) + wxT(", Version check: ") + versionLine);
1850 long fields[] = {0, 0, 0};
1851 for (int i = 0; i < 3; ++i) {
1852 if (!tkz.HasMoreTokens()) {
1853 AddLogLineM(true, _("Corrupted version check file"));
1854 return;
1855 } else {
1856 wxString token = tkz.GetNextToken();
1858 if (!token.ToLong(&fields[i])) {
1859 AddLogLineM(true, _("Corrupted version check file"));
1860 return;
1865 long curVer = make_full_ed2k_version(VERSION_MJR, VERSION_MIN, VERSION_UPDATE);
1866 long newVer = make_full_ed2k_version(fields[0], fields[1], fields[2]);
1868 if (curVer < newVer) {
1869 AddLogLineM(true, _("You are using an outdated version of aMule!"));
1870 AddLogLineM(false, wxString::Format(_("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]));
1871 AddLogLineM(false, _("The latest version can always be found at http://www.amule.org"));
1872 #ifdef AMULE_DAEMON
1873 printf("%s\n", (const char*)unicode2UTF8(wxString::Format(
1874 _("WARNING: Your aMuled version is outdated: %i.%i.%i < %li.%li.%li"),
1875 VERSION_MJR, VERSION_MIN, VERSION_UPDATE, fields[0], fields[1], fields[2])));
1876 #endif
1877 } else {
1878 AddLogLineM(false, _("Your copy of aMule is up to date."));
1882 file.Close();
1883 wxRemoveFile(filename);
1884 } else {
1885 AddLogLineM(true, _("Failed to download the version check file") );
1891 bool CamuleApp::IsConnected()
1893 return (IsConnectedED2K() || IsConnectedKad());
1897 bool CamuleApp::IsConnectedED2K()
1899 return serverconnect && serverconnect->IsConnected();
1903 bool CamuleApp::IsConnectedKad()
1905 return Kademlia::CKademlia::IsConnected();
1909 bool CamuleApp::IsFirewalled()
1911 if (theApp->IsConnectedED2K() && !theApp->serverconnect->IsLowID()) {
1912 return false; // we have an eD2K HighID -> not firewalled
1915 return IsFirewalledKad(); // If kad says ok, it's ok.
1918 bool CamuleApp::IsFirewalledKad()
1920 if (Kademlia::CKademlia::IsConnected() && !Kademlia::CKademlia::IsFirewalled()) {
1921 return false; // we have an Kad HighID -> not firewalled
1924 return true; // firewalled
1927 bool CamuleApp::IsKadRunning()
1929 return Kademlia::CKademlia::IsRunning();
1932 bool CamuleApp::DoCallback( CUpDownClient *client )
1934 if(Kademlia::CKademlia::IsConnected()) {
1935 if(IsConnectedED2K()) {
1936 if(serverconnect->IsLowID()) {
1937 if(Kademlia::CKademlia::IsFirewalled()) {
1938 //Both Connected - Both Firewalled
1939 return false;
1940 } else {
1941 if(client->GetServerIP() == theApp->serverconnect->GetCurrentServer()->GetIP() &&
1942 client->GetServerPort() == theApp->serverconnect->GetCurrentServer()->GetPort()) {
1943 // Both Connected - Server lowID, Kad Open - Client on same server
1944 // We prevent a callback to the server as this breaks the protocol
1945 // and will get you banned.
1946 return false;
1947 } else {
1948 // Both Connected - Server lowID, Kad Open - Client on remote server
1949 return true;
1952 } else {
1953 //Both Connected - Server HighID, Kad don't care
1954 return true;
1956 } else {
1957 if(Kademlia::CKademlia::IsFirewalled()) {
1958 //Only Kad Connected - Kad Firewalled
1959 return false;
1960 } else {
1961 //Only Kad Conected - Kad Open
1962 return true;
1965 } else {
1966 if( IsConnectedED2K() ) {
1967 if( serverconnect->IsLowID() ) {
1968 //Only Server Connected - Server LowID
1969 return false;
1970 } else {
1971 //Only Server Connected - Server HighID
1972 return true;
1974 } else {
1975 //We are not connected at all!
1976 return false;
1981 void CamuleApp::ShowUserCount() {
1982 uint32 totaluser = 0, totalfile = 0;
1984 theApp->serverlist->GetUserFileStatus( totaluser, totalfile );
1986 wxString buffer;
1988 static const wxString s_singlenetstatusformat = _("Users: %s | Files: %s");
1989 static const wxString s_bothnetstatusformat = _("Users: E: %s K: %s | Files: E: %s K: %s");
1991 if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
1992 buffer = CFormat(s_bothnetstatusformat) % CastItoIShort(totaluser) % CastItoIShort(Kademlia::CKademlia::GetKademliaUsers()) % CastItoIShort(totalfile) % CastItoIShort(Kademlia::CKademlia::GetKademliaFiles());
1993 } else if (thePrefs::GetNetworkED2K()) {
1994 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(totaluser) % CastItoIShort(totalfile);
1995 } else if (thePrefs::GetNetworkKademlia()) {
1996 buffer = CFormat(s_singlenetstatusformat) % CastItoIShort(Kademlia::CKademlia::GetKademliaUsers()) % CastItoIShort(Kademlia::CKademlia::GetKademliaFiles());
1997 } else {
1998 buffer = _("No networks selected");
2001 Notify_ShowUserCount(buffer);
2005 void CamuleApp::ListenSocketHandler(wxSocketEvent& event)
2007 wxCHECK_RET(listensocket, wxT("Connection-event for NULL'd listen-socket"));
2008 wxCHECK_RET(event.GetSocketEvent() == wxSOCKET_CONNECTION,
2009 wxT("Invalid event received for listen-socket"));
2011 if (m_app_state == APP_STATE_RUNNING) {
2012 listensocket->OnAccept(0);
2013 } else if (m_app_state == APP_STATE_STARTING) {
2014 // When starting up, connection may be made before we are able
2015 // to handle them. However, if these are ignored, no futher
2016 // connection-events will be triggered, so we have to accept it.
2017 wxSocketBase* socket = listensocket->Accept(false);
2019 wxCHECK_RET(socket, wxT("NULL returned by Accept() during startup"));
2021 socket->Destroy();
2026 void CamuleApp::ShowConnectionState()
2028 static uint8 old_state = (1<<7); // This flag doesn't exist
2030 uint8 state = 0;
2032 if (theApp->serverconnect->IsConnected()) {
2033 state |= CONNECTED_ED2K;
2036 if (Kademlia::CKademlia::IsRunning()) {
2037 if (Kademlia::CKademlia::IsConnected()) {
2038 if (!Kademlia::CKademlia::IsFirewalled()) {
2039 state |= CONNECTED_KAD_OK;
2040 } else {
2041 state |= CONNECTED_KAD_FIREWALLED;
2043 } else {
2044 state |= CONNECTED_KAD_NOT;
2048 Notify_ShowConnState(state);
2050 if (old_state != state) {
2051 // Get the changed value
2052 int changed_flags = old_state ^ state;
2054 if (changed_flags & CONNECTED_ED2K) {
2055 // ED2K status changed
2056 wxString connected_server;
2057 CServer* ed2k_server = theApp->serverconnect->GetCurrentServer();
2058 if (ed2k_server) {
2059 connected_server = ed2k_server->GetListName();
2061 if (state & CONNECTED_ED2K) {
2062 // We connected to some server
2063 const wxString id = theApp->serverconnect->IsLowID() ? _("with LowID") : _("with HighID");
2065 AddLogLine(CFormat(_("Connected to %s %s")) % connected_server % id);
2066 } else {
2067 if ( theApp->serverconnect->IsConnecting() ) {
2068 AddLogLine(CFormat(_("Connecting to %s")) % connected_server);
2069 } else {
2070 AddLogLine(_("Disconnected from ED2K"));
2075 if (changed_flags & CONNECTED_KAD_NOT) {
2076 if (state & CONNECTED_KAD_NOT) {
2077 AddLogLine(_("Kad started."));
2078 } else {
2079 AddLogLine(_("Kad stopped."));
2083 if (changed_flags & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) {
2084 if (state & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) {
2085 if (state & CONNECTED_KAD_OK) {
2086 AddLogLine(_("Connected to Kad (ok)"));
2087 } else {
2088 AddLogLine(_("Connected to Kad (firewalled)"));
2090 } else {
2091 AddLogLine(_("Disconnected from Kad"));
2095 old_state = state;
2097 theApp->downloadqueue->OnConnectionState(IsConnected());
2100 ShowUserCount();
2101 Notify_ShowConnState(state);
2105 void CamuleApp::UDPSocketHandler(wxSocketEvent& event)
2107 CMuleUDPSocket* socket = (CMuleUDPSocket*)(event.GetClientData());
2108 wxCHECK_RET(socket, wxT("No socket owner specified."));
2110 if (IsOnShutDown() || thePrefs::IsUDPDisabled()) return;
2112 if (!IsRunning()) {
2113 if (event.GetSocketEvent() == wxSOCKET_INPUT) {
2114 // Back to the queue!
2115 theApp->AddPendingEvent(event);
2116 return;
2120 switch (event.GetSocketEvent()) {
2121 case wxSOCKET_INPUT:
2122 socket->OnReceive(0);
2123 break;
2125 case wxSOCKET_OUTPUT:
2126 socket->OnSend(0);
2127 break;
2129 case wxSOCKET_LOST:
2130 socket->OnDisconnected(0);
2131 break;
2133 default:
2134 wxASSERT(0);
2135 break;
2140 void CamuleApp::OnUnhandledException()
2142 // Call the generic exception-handler.
2143 fprintf(stderr, "\taMule Version: %s\n", (const char*)unicode2char(GetFullMuleVersion()));
2144 ::OnUnhandledException();
2147 void CamuleApp::StartKad()
2149 if (!Kademlia::CKademlia::IsRunning() && thePrefs::GetNetworkKademlia()) {
2150 // Kad makes no sense without the Client-UDP socket.
2151 if (!thePrefs::IsUDPDisabled()) {
2152 Kademlia::CKademlia::Start();
2153 } else {
2154 AddLogLineM(true,_("Kad network cannot be used if UDP port is disabled on preferences, not starting."));
2156 } else if (!thePrefs::GetNetworkKademlia()) {
2157 AddLogLineM(true,_("Kad network disabled on preferences, not connecting."));
2161 void CamuleApp::StopKad()
2163 // Stop Kad if it's running
2164 if (Kademlia::CKademlia::IsRunning()) {
2165 Kademlia::CKademlia::Stop();
2170 void CamuleApp::BootstrapKad(uint32 ip, uint16 port)
2172 if (!Kademlia::CKademlia::IsRunning()) {
2173 Kademlia::CKademlia::Start();
2174 theApp->ShowConnectionState();
2177 Kademlia::CKademlia::Bootstrap(ip, port, true);
2181 void CamuleApp::UpdateNotesDat(const wxString& url)
2183 wxString strTempFilename(theApp->ConfigDir + wxT("nodes.dat.download"));
2185 CHTTPDownloadThread *downloader = new CHTTPDownloadThread(url, strTempFilename, HTTP_NodesDat);
2186 downloader->Create();
2187 downloader->Run();
2191 void CamuleApp::DisconnectED2K()
2193 // Stop ED2K if it's running
2194 if (IsConnectedED2K()) {
2195 serverconnect->Disconnect();
2199 bool CamuleApp::CryptoAvailable() const
2201 return clientcredits && clientcredits->CryptoAvailable();
2204 uint32 CamuleApp::GetED2KID() const {
2205 return serverconnect ? serverconnect->GetClientID() : 0;
2208 uint32 CamuleApp::GetID() const {
2209 uint32 ID;
2211 if( Kademlia::CKademlia::IsConnected() && !Kademlia::CKademlia::IsFirewalled() ) {
2212 // We trust Kad above ED2K
2213 ID = ENDIAN_NTOHL(Kademlia::CKademlia::GetIPAddress());
2214 } else if( theApp->serverconnect->IsConnected() ) {
2215 ID = theApp->serverconnect->GetClientID();
2216 } else if ( Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::IsFirewalled() ) {
2217 // A firewalled Kad client get's a "1"
2218 ID = 1;
2219 } else {
2220 ID = 0;
2223 return ID;
2226 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2227 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2228 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2229 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2230 // File_checked_for_headers