Upstream tarball 20080304
[amule.git] / src / amule.cpp
blob2376408361e58d1febb90a1459a5db828277186d
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 and VERSION
39 #endif
41 #include <common/ClientVersion.h>
43 #include <wx/cmdline.h> // Needed for wxCmdLineParser
44 #include <wx/config.h> // Do_not_auto_remove (win32)
45 #include <wx/fileconf.h>
46 #include <wx/snglinst.h>
47 #include <wx/tokenzr.h>
48 #include <wx/wfstream.h>
51 #include <common/Format.h> // Needed for CFormat
52 #include "kademlia/kademlia/Kademlia.h"
53 #include "kademlia/kademlia/Prefs.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 "Preferences.h" // Needed for CPreferences
70 #include "SearchList.h" // Needed for CSearchList
71 #include "Server.h" // Needed for GetListName
72 #include "ServerList.h" // Needed for CServerList
73 #include "ServerConnect.h" // Needed for CServerConnect
74 #include "ServerUDPSocket.h" // Needed for CServerUDPSocket
75 #include "Statistics.h" // Needed for CStatistics
76 #include "TerminationProcessAmuleweb.h" // Needed for CTerminationProcessAmuleweb
77 #include "ThreadTasks.h"
78 #include "updownclient.h" // Needed for CUpDownClient
79 #include "UploadQueue.h" // Needed for CUploadQueue
80 #include "UploadBandwidthThrottler.h"
81 #include "UserEvents.h"
83 #ifdef ENABLE_UPNP
84 #include "UPnP.h" // Needed for UPnP
85 #endif
87 #ifdef __WXMAC__
88 #include <wx/sysopt.h> // Do_not_auto_remove
89 #endif
91 #ifndef AMULE_DAEMON
92 #ifdef __WXMAC__
93 #include <CoreFoundation/CFBundle.h> // Do_not_auto_remove
94 #include <wx/mac/corefoundation/cfstring.h> // Do_not_auto_remove
95 #endif
96 #include <wx/msgdlg.h>
98 #include "amuleDlg.h"
99 #endif
102 #ifdef HAVE_SYS_RESOURCE_H
103 #include <sys/resource.h>
104 #endif
106 #ifdef HAVE_SYS_STATVFS_H
107 #include <sys/statvfs.h> // Do_not_auto_remove
108 #endif
111 #ifdef __GLIBC__
112 # define RLIMIT_RESOURCE __rlimit_resource
113 #else
114 # define RLIMIT_RESOURCE int
115 #endif
117 static void UnlimitResource(RLIMIT_RESOURCE resType)
119 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT)
120 struct rlimit rl;
121 getrlimit(resType, &rl);
122 rl.rlim_cur = rl.rlim_max;
123 setrlimit(resType, &rl);
124 #endif
128 static void SetResourceLimits()
130 #ifdef HAVE_SYS_RESOURCE_H
131 UnlimitResource(RLIMIT_DATA);
132 UnlimitResource(RLIMIT_FSIZE);
133 UnlimitResource(RLIMIT_NOFILE);
134 #ifdef RLIMIT_RSS
135 UnlimitResource(RLIMIT_RSS);
136 #endif
137 #endif
140 // We store the received signal in order to avoid race-conditions
141 // in the signal handler.
142 bool g_shutdownSignal = false;
144 void OnShutdownSignal( int /* sig */ )
146 signal(SIGINT, SIG_DFL);
147 signal(SIGTERM, SIG_DFL);
149 g_shutdownSignal = true;
151 #ifdef AMULE_DAEMON
152 theApp->ExitMainLoop();
153 #endif
157 CamuleApp::CamuleApp()
159 // Madcat - Initialize timer as the VERY FIRST thing to avoid any issues later.
160 // Kry - I love to init the vars on init, even before timer.
161 StartTickTimer();
163 // Initialization
164 m_app_state = APP_STATE_STARTING;
166 theApp = &wxGetApp();
168 clientlist = NULL;
169 searchlist = NULL;
170 knownfiles = NULL;
171 serverlist = NULL;
172 serverconnect = NULL;
173 sharedfiles = NULL;
174 listensocket = NULL;
175 clientudp = NULL;
176 clientcredits = NULL;
177 friendlist = NULL;
178 downloadqueue = NULL;
179 uploadqueue = NULL;
180 ipfilter = NULL;
181 ECServerHandler = NULL;
182 m_singleInstance= NULL;
183 glob_prefs = NULL;
184 m_statistics = NULL;
185 uploadBandwidthThrottler = NULL;
186 #ifdef ENABLE_UPNP
187 m_upnp = NULL;
188 m_upnpMappings.resize(4);
189 #endif
190 core_timer = NULL;
191 applog = NULL;
193 m_localip = 0;
194 m_dwPublicIP = 0;
195 webserver_pid = 0;
197 enable_stdout_log = false;
198 enable_daemon_fork = false;
200 strFullMuleVersion = NULL;
201 strOSDescription = NULL;
203 // Apprently needed for *BSD
204 SetResourceLimits();
207 CamuleApp::~CamuleApp()
209 // Closing the log-file as the very last thing, since
210 // wxWidgets log-events are saved in it as well.
211 delete applog;
212 applog = NULL;
215 int CamuleApp::OnExit()
217 if (m_app_state!=APP_STATE_STARTING) {
218 printf("Now, exiting main app...\n");
221 // From wxWidgets docs, wxConfigBase:
222 // ...
223 // Note that you must delete this object (usually in wxApp::OnExit)
224 // in order to avoid memory leaks, wxWidgets won't do it automatically.
226 // As it happens, you may even further simplify the procedure described
227 // above: you may forget about calling Set(). When Get() is called and
228 // there is no current object, it will create one using Create() function.
229 // To disable this behaviour DontCreateOnDemand() is provided.
230 delete wxConfigBase::Set((wxConfigBase *)NULL);
232 // Save credits
233 clientcredits->SaveList();
235 // Kill amuleweb if running
236 if (webserver_pid) {
237 printf("Killing amuleweb instance with pid `%ld' ... ", webserver_pid);
238 wxKillError rc;
239 wxKill(webserver_pid, wxSIGTERM, &rc);
240 printf("Killed!\n");
243 if (m_app_state!=APP_STATE_STARTING) {
244 printf("aMule OnExit: Terminating core.\n");
247 delete serverlist;
248 serverlist = NULL;
250 delete searchlist;
251 searchlist = NULL;
253 delete clientcredits;
254 clientcredits = NULL;
256 delete friendlist;
257 friendlist = NULL;
259 // Destroying CDownloadQueue calls destructor for CPartFile
260 // calling CSharedFileList::SafeAddKFile occasionally.
261 delete sharedfiles;
262 sharedfiles = NULL;
264 delete serverconnect;
265 serverconnect = NULL;
267 delete listensocket;
268 listensocket = NULL;
270 delete clientudp;
271 clientudp = NULL;
273 delete knownfiles;
274 knownfiles = NULL;
276 delete clientlist;
277 clientlist = NULL;
279 delete uploadqueue;
280 uploadqueue = NULL;
282 delete downloadqueue;
283 downloadqueue = NULL;
285 delete ipfilter;
286 ipfilter = NULL;
288 #ifdef ENABLE_UPNP
289 delete m_upnp;
290 m_upnp = NULL;
291 #endif
293 delete ECServerHandler;
294 ECServerHandler = NULL;
296 delete m_statistics;
297 m_statistics = NULL;
299 delete glob_prefs;
300 glob_prefs = NULL;
301 CPreferences::EraseItemList();
303 #if defined(__WXMAC__) && defined(AMULE_DAEMON)
304 //#warning TODO: fix wxSingleInstanceChecker for amuled on Mac (wx link problems)
305 #else
306 delete m_singleInstance;
307 #endif
308 m_singleInstance = NULL;
310 delete uploadBandwidthThrottler;
311 uploadBandwidthThrottler = NULL;
313 if (m_app_state!=APP_STATE_STARTING) {
314 printf("aMule shutdown completed.\n");
317 #if wxUSE_MEMORY_TRACING
318 printf("Memory debug results for aMule exit:\n");
319 // Log mem debug mesages to wxLogStderr
320 wxLog* oldLog = wxLog::SetActiveTarget(new wxLogStderr);
322 printf("**************Classes**************\n");
323 wxDebugContext::PrintClasses();
325 //printf("***************Dump***************\n");
326 //wxDebugContext::Dump();
327 printf("***************Stats**************\n");
328 wxDebugContext::PrintStatistics(true);
330 // Set back to wxLogGui
331 delete wxLog::SetActiveTarget(oldLog);
332 #endif
334 StopTickTimer();
336 // Return 0 for succesful program termination
337 return AMULE_APP_BASE::OnExit();
341 int CamuleApp::InitGui(bool, wxString &)
343 return 0;
348 * Checks permissions on a aMule directory, creating if needed.
350 * @param desc A description of the directory in question, used for error messages.
351 * @param directory The directory in question.
352 * @param fallback If the dir specified with 'directory' could not be created, try this instead.
353 * @return The bool is false on error. The wxString contains the used path.
355 std::pair<bool, CPath> CheckMuleDirectory(const wxString& desc, const CPath& directory, const wxString& alternative)
357 wxString msg;
359 if (directory.IsDir(CPath::readwritable)) {
360 return std::pair<bool, CPath>(true, directory);
361 } else if (directory.DirExists()) {
362 msg = CFormat(wxT("Permissions on the %s directory too strict!\n")
363 wxT("aMule cannot proceed. To fix this, you must set read/write/exec\n")
364 wxT("permissions for the folder '%s'"))
365 % desc % directory;
366 } else if (CPath::MakeDir(directory)) {
367 return std::pair<bool, CPath>(true, directory);
368 } else {
369 msg << CFormat(wxT("Could not create the %s directory at '%s'."))
370 % desc % directory;
373 // Attempt to use fallback directory.
374 const CPath fallback = CPath(alternative);
375 if (fallback.IsOk() && (directory != fallback)) {
376 msg << wxT("\nAttempting to use default directory at location \n'")
377 << alternative << wxT("'.");
378 theApp->ShowAlert(msg, wxT("Error accessing directory."), wxICON_ERROR | wxOK);
380 return CheckMuleDirectory(desc, fallback, wxEmptyString);
383 theApp->ShowAlert(msg, wxT("Fatal error."), wxICON_ERROR | wxOK);
384 return std::pair<bool, wxString>(false, wxEmptyString);
389 // Application initialization
391 bool CamuleApp::OnInit()
393 #if wxUSE_MEMORY_TRACING
394 printf("Checkpoint set on app init for memory debug\n");
395 wxDebugContext::SetCheckpoint();
396 #endif
398 // Forward wxLog events to CLogger
399 wxLog::SetActiveTarget(new CLoggerTarget);
401 m_localip = StringHosttoUint32(::wxGetFullHostName());
403 #ifndef __WXMSW__
404 // get rid of sigpipe
405 signal(SIGPIPE, SIG_IGN);
406 // Handle sigint and sigterm
407 signal(SIGINT, OnShutdownSignal);
408 signal(SIGTERM, OnShutdownSignal);
409 #endif
411 #ifdef __WXMAC__
412 // For listctrl's to behave on Mac
413 wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1);
414 #endif
416 // This can't be on constructor or wx2.4.2 doesn't set it.
417 SetVendorName(wxT("TikuWarez"));
418 SetAppName(wxT("aMule"));
420 wxString FullMuleVersion = GetFullMuleVersion();
421 wxString OSDescription = wxGetOsDescription();
422 strFullMuleVersion = strdup((const char *)unicode2char(FullMuleVersion));
423 strOSDescription = strdup((const char *)unicode2char(OSDescription));
424 OSType = OSDescription.BeforeFirst( wxT(' ') );
425 if ( OSType.IsEmpty() ) {
426 OSType = wxT("Unknown");
429 // Handle uncaught exceptions
430 InstallMuleExceptionHandler();
432 // Parse cmdline arguments.
433 wxCmdLineParser cmdline(AMULE_APP_BASE::argc, AMULE_APP_BASE::argv);
435 // Handle these arguments.
436 cmdline.AddSwitch(wxT("v"), wxT("version"), wxT("Displays the current version number."));
437 cmdline.AddSwitch(wxT("h"), wxT("help"), wxT("Displays this information."));
438 cmdline.AddSwitch(wxT("i"), wxT("enable-stdin"), wxT("Does not disable stdin."));
439 #ifdef AMULE_DAEMON
440 cmdline.AddSwitch(wxT("f"), wxT("full-daemon"), wxT("Fork to background."));
441 cmdline.AddOption(wxT("c"), wxT("config-dir"), wxT("read config from <dir> instead of home"));
442 cmdline.AddSwitch(wxT("e"), wxT("ec-config"), wxT("Configure EC (External Connections)."));
443 #else
444 cmdline.AddOption(wxT("geometry"), wxEmptyString,
445 wxT("Sets the geometry of the app.\n")
446 wxT("\t\t\t<str> uses the same format as standard X11 apps:\n")
447 wxT("\t\t\t[=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]"));
448 #endif
449 cmdline.AddSwitch(wxT("d"), wxT("disable-fatal"), wxT("Does not handle fatal exception."));
450 cmdline.AddSwitch(wxT("o"), wxT("log-stdout"), wxT("Print log messages to stdout."));
451 cmdline.AddSwitch(wxT("r"), wxT("reset-config"), wxT("Resets config to default values."));
453 // Show help on --help or invalid commands
454 if ( cmdline.Parse() ) {
455 return false;
456 } else if ( cmdline.Found(wxT("help")) ) {
457 cmdline.Usage();
458 return false;
461 bool ec_config = false;
463 #ifdef AMULE_DAEMON
464 ec_config = cmdline.Found(wxT("ec-config"));
465 if ( cmdline.Found(wxT("config-dir"), &ConfigDir) ) {
466 if (ConfigDir.Last() != wxFileName::GetPathSeparator()) {
467 ConfigDir += wxFileName::GetPathSeparator();
469 } else {
470 ConfigDir = GetConfigDir();
472 #else
473 ConfigDir = GetConfigDir();
474 #endif
476 if ( !cmdline.Found(wxT("disable-fatal")) ) {
477 #ifndef __WXMSW__
478 // catch fatal exceptions
479 wxHandleFatalExceptions(true);
480 #endif
483 bool reset_config = cmdline.Found(wxT("reset-config"));
485 enable_stdout_log = cmdline.Found(wxT("log-stdout"));
486 #ifdef AMULE_DAEMON
487 enable_daemon_fork = cmdline.Found(wxT("full-daemon"));
488 #else
489 enable_daemon_fork = false;
490 #endif
492 if ( enable_stdout_log ) {
493 if ( enable_daemon_fork ) {
494 printf("Daemon will fork to background - log to stdout disabled\n");
495 enable_stdout_log = false;
496 } else {
497 printf("Logging to stdout enabled\n");
501 if ( cmdline.Found(wxT("version")) ) {
502 printf("%s (OS: %s)\n",
503 (const char*)unicode2char(GetFullMuleVersion()),
504 (const char*)unicode2char(OSType));
506 return false;
509 // Default geometry of the GUI. Can be changed with a cmdline argument...
510 bool geometry_enabled = false;
511 wxString geom_string;
512 #ifndef AMULE_DAEMON
513 if ( cmdline.Found(wxT("geometry"), &geom_string) ) {
514 geometry_enabled = true;
516 #endif
519 printf("Initialising aMule\n");
521 // Ensure that "~/.aMule/" is accessible.
522 if (!CheckMuleDirectory(wxT("configuration"), CPath(ConfigDir), wxEmptyString).first) {
523 return false;
526 if (reset_config) {
527 // Make a backup first.
528 wxRemoveFile(ConfigDir + wxT("amule.conf.backup"));
529 wxRenameFile(ConfigDir + wxT("amule.conf"), ConfigDir + wxT("amule.conf.backup"));
530 printf("Your settings have ben resetted to default values.\nOld config file has been saved as amule.conf.backup\n");
533 #if defined(__WXMAC__) && defined(AMULE_DAEMON)
534 //#warning TODO: fix wxSingleInstanceChecker for amuled on Mac (wx link problems)
535 printf("WARNING: The check for other instances is currently disabled in amuled.\n"
536 "Please make sure that no other instance of aMule is running or your files might be corrupted.\n");
537 #else
538 printf("Checking if there is an instance already running...\n");
540 m_singleInstance = new wxSingleInstanceChecker(wxT("muleLock"), ConfigDir);
541 if (m_singleInstance->IsAnotherRunning()) {
542 printf("There is an instance of aMule already running\n");
544 // This is very tricky. The most secure way to communicate is via ED2K links file
545 wxTextFile ed2kFile(ConfigDir + wxT("ED2KLinks"));
546 if (!ed2kFile.Exists()) {
547 ed2kFile.Create();
550 if (ed2kFile.Open()) {
551 ed2kFile.AddLine(wxT("RAISE_DIALOG"));
552 ed2kFile.Write();
554 printf("Raising current running instance.\n");
555 } else {
556 printf("Failed to open 'ED2KFile', cannot signal running instance.\n");
559 return false;
560 } else {
561 printf("No other instances are running.\n");
563 #endif
565 // Close standard-input
566 if ( !cmdline.Found(wxT("enable-stdin")) ) {
567 // The full daemon will close all std file-descriptors by itself,
568 // so closing it here would lead to the closing on the first open
569 // file, which is the logfile opened below
570 if (!enable_daemon_fork) {
571 close(0);
575 // This creates the CFG file we shall use
576 wxConfigBase* cfg = new wxFileConfig( wxEmptyString, wxEmptyString, ConfigDir + wxT("amule.conf") );
578 // Set the config object as the global cfg file
579 wxConfig::Set( cfg );
581 // Make a backup of the log file
582 CPath logfileName = CPath(ConfigDir + wxT("logfile"));
583 if (logfileName.FileExists()) {
584 CPath::BackupFile(logfileName, wxT(".bak"));
587 // Open the log file
588 applog = new wxFFileOutputStream(logfileName.GetRaw());
589 if (!applog->Ok()) {
590 // use std err as last resolt to indicate problem
591 fputs("ERROR: unable to open log file\n", stderr);
592 delete applog;
593 applog = NULL;
594 // failure to open log is serious problem
595 return false;
598 // Load Preferences
599 CPreferences::BuildItemList(ConfigDir);
600 CPreferences::LoadAllItems( wxConfigBase::Get() );
602 glob_prefs = new CPreferences();
604 std::pair<bool, CPath> checkResult;
605 checkResult = CheckMuleDirectory(wxT("temp"), thePrefs::GetTempDir(), ConfigDir + wxT("Temp"));
606 if (checkResult.first) {
607 thePrefs::SetTempDir(checkResult.second);
608 } else {
609 return false;
612 checkResult = CheckMuleDirectory(wxT("incoming"), thePrefs::GetIncomingDir(), ConfigDir + wxT("Incoming"));
613 if (checkResult.first) {
614 thePrefs::SetIncomingDir(checkResult.second);
615 } else {
616 return false;
619 // Some sanity check
620 if (!thePrefs::UseTrayIcon()) {
621 thePrefs::SetMinToTray(false);
624 // Build the filenames for the two OS files
625 SetOSFiles(thePrefs::GetOSDir().GetRaw());
627 // Load localization settings
628 Localize_mule();
630 // Configure EC for amuled when invoked with ec-config
631 if (ec_config) {
632 printf("\nEC configuration\n");
633 thePrefs::SetECPass(GetPassword());
634 thePrefs::EnableExternalConnections(true);
635 printf("Password set and external connections enabled.\n");
638 // Display notification on new version or first run
639 wxTextFile vfile( ConfigDir + wxT("lastversion") );
640 wxString newMule(wxT( VERSION ));
642 // Test if there's any new version
643 if (thePrefs::CheckNewVersion()) {
644 // We use the thread base because I don't want a dialog to pop up.
645 CHTTPDownloadThread* version_check =
646 new CHTTPDownloadThread(wxT("http://amule.sourceforge.net/lastversion"),
647 theApp->ConfigDir + wxT("last_version_check"), HTTP_VersionCheck, false);
648 version_check->Create();
649 version_check->Run();
652 if ( !wxFileExists( vfile.GetName() ) ) {
653 vfile.Create();
656 #ifndef __WXMSW__
657 if (getuid() == 0) {
658 wxString msg =
659 wxT("Warning! You are running aMule as root.\n")
660 wxT("Doing so is not recommended for security reasons,\n")
661 wxT("and you are advised to run aMule as an normal\n")
662 wxT("user instead.");
664 ShowAlert(msg, _("Warning"), wxCENTRE | wxOK | wxICON_ERROR);
666 fprintf(stderr, "\n--------------------------------------------------\n");
667 fprintf(stderr, "%s", (const char*)unicode2UTF8(msg));
668 fprintf(stderr, "\n--------------------------------------------------\n\n");
670 #endif
672 if ( vfile.Open() ) {
673 // Check if this version has been run before
674 bool found = false;
675 for ( size_t i = 0; i < vfile.GetLineCount(); i++ ) {
676 // Check if this version has been run before
677 if ( vfile.GetLine(i) == newMule ) {
678 found = true;
679 break;
683 // We havent run this version before?
684 if ( !found ) {
685 // Insert new at top to provide faster searches
686 vfile.InsertLine( newMule, 0 );
688 Trigger_New_version( newMule );
691 // Keep at most 10 entires
692 while ( vfile.GetLineCount() > 10 )
693 vfile.RemoveLine( vfile.GetLineCount() - 1 );
695 vfile.Write();
696 vfile.Close();
699 // Check if we have the old style locale config
700 wxString langId = thePrefs::GetLanguageID();
701 if (!langId.IsEmpty() && (langId.GetChar(0) >= '0' && langId.GetChar(0) <= '9')) {
702 wxString info(_("Your locale has been changed to System Default due to a configuration change. Sorry."));
703 thePrefs::SetLanguageID(wxLang2Str(wxLANGUAGE_DEFAULT));
704 ShowAlert(info, _("Info"), wxCENTRE | wxOK | wxICON_ERROR);
707 m_statistics = new CStatistics();
709 clientlist = new CClientList();
710 friendlist = new CFriendList();
711 searchlist = new CSearchList();
712 knownfiles = new CKnownFileList();
713 serverlist = new CServerList();
715 sharedfiles = new CSharedFileList(knownfiles);
716 clientcredits = new CClientCreditsList();
718 // bugfix - do this before creating the uploadqueue
719 downloadqueue = new CDownloadQueue();
720 uploadqueue = new CUploadQueue();
721 ipfilter = new CIPFilter();
723 // Creates all needed listening sockets
724 wxString msg;
725 if (!ReinitializeNetwork(&msg)) {
726 printf("\n%s\n", (const char *)unicode2char(msg));
729 // Create main dialog, or fork to background (daemon).
730 InitGui(geometry_enabled, geom_string);
732 // Has to be created after the call to InitGui, as fork
733 // (when using posix threads) only replicates the mainthread,
734 // and the UBT constructor creates a thread.
735 uploadBandwidthThrottler = new UploadBandwidthThrottler();
737 // These must be initialized after the gui is loaded.
738 serverlist->Init();
739 downloadqueue->LoadMetFiles(thePrefs::GetTempDir());
740 sharedfiles->Reload();
742 if (thePrefs::IPFilterAutoLoad()) {
743 ipfilter->Update(thePrefs::IPFilterURL());
747 // Ensure that the up/down ratio is used
748 CPreferences::CheckUlDlRatio();
750 // The user can start pressing buttons like mad if he feels like it.
751 m_app_state = APP_STATE_RUNNING;
753 // Kry - Load the sources seeds on app init
754 if (thePrefs::GetSrcSeedsOn()) {
755 downloadqueue->LoadSourceSeeds();
758 if (!serverlist->GetServerCount() && thePrefs::GetNetworkED2K()) {
759 // There are no servers and ED2K active -> ask for download.
760 // As we cannot ask in amuled, we just update there
761 // Kry TODO: Store server.met URL on preferences and use it here and in GUI.
762 #ifndef AMULE_DAEMON
763 if (wxYES == wxMessageBox(
764 wxString(
765 _("You don't have any server in the server list.\nDo you want aMule to download a new list now?")),
766 wxString(_("Server list download")),
767 wxYES_NO,
768 static_cast<wxWindow*>(theApp->amuledlg)))
769 #endif
771 // workaround amuled crash
772 #ifndef AMULE_DAEMON
773 serverlist->UpdateServerMetFromURL(
774 wxT("http://gruk.org/server.met.gz"));
775 #endif
780 // Autoconnect if that option is enabled
781 if (thePrefs::DoAutoConnect() && (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia())) {
782 AddLogLineM(true, _("Connecting"));
783 if (thePrefs::GetNetworkED2K()) {
784 theApp->serverconnect->ConnectToAnyServer();
787 StartKad();
791 // No webserver on Win at all (yet)
792 #ifndef __WXMSW__
793 // Run webserver?
794 if (thePrefs::GetWSIsEnabled()) {
795 wxString aMuleConfigFile = ConfigDir + wxT("amule.conf");
796 wxString amulewebPath = wxT("amuleweb");
798 #if defined(__WXMAC__) && !defined(AMULE_DAEMON)
799 // For the Mac GUI application, look for amuleweb in the bundle
800 CFURLRef amulewebUrl = CFBundleCopyAuxiliaryExecutableURL(
801 CFBundleGetMainBundle(), CFSTR("amuleweb"));
803 if (amulewebUrl) {
804 CFURLRef absoluteUrl = CFURLCopyAbsoluteURL(amulewebUrl);
805 CFRelease(amulewebUrl);
807 if (absoluteUrl) {
808 CFStringRef amulewebCfstr = CFURLCopyFileSystemPath(absoluteUrl, kCFURLPOSIXPathStyle);
809 CFRelease(absoluteUrl);
810 amulewebPath = wxMacCFStringHolder(amulewebCfstr).AsString(wxLocale::GetSystemEncoding());
813 #endif
815 wxString cmd =
816 wxT("'") +
817 amulewebPath +
818 wxT("' '--amule-config-file=") +
819 aMuleConfigFile +
820 wxT("'");
821 CTerminationProcessAmuleweb *p = new CTerminationProcessAmuleweb(cmd, &webserver_pid);
822 webserver_pid = wxExecute(cmd, wxEXEC_ASYNC, p);
823 bool webserver_ok = webserver_pid > 0;
824 if (webserver_ok) {
825 AddLogLineM(true, CFormat(_("webserver running on pid %d")) % webserver_pid);
826 } else {
827 delete p;
828 ShowAlert(_(
829 "You requested to run webserver from startup, "
830 "but the amuleweb binary cannot be run. "
831 "Please install the package containing aMule webserver, "
832 "or compile aMule using --enable-webserver and run make install"),
833 _("Error"), wxOK | wxICON_ERROR);
836 #endif /* ! __WXMSW__ */
838 // Start performing background tasks
839 CThreadScheduler::Start();
841 return true;
844 bool CamuleApp::ReinitializeNetwork(wxString* msg)
846 bool ok = true;
847 static bool firstTime = true;
849 if (!firstTime) {
850 // TODO: Destroy previously created sockets
852 firstTime = false;
854 // Some sanity checks first
855 if (thePrefs::ECPort() == thePrefs::GetPort()) {
856 // Select a random usable port in the range 1025 ... 2^16 - 1
857 uint16 port = thePrefs::ECPort();
858 while ( port < 1024 || port == thePrefs::GetPort() ) {
859 port = (uint16)rand();
861 thePrefs::SetECPort( port );
863 wxString err =
864 wxT("Network configuration failed! You cannot use the same port\n")
865 wxT("for the main TCP port and the External Connections port.\n")
866 wxT("The EC port has been changed to avoid conflict, see the\n")
867 wxT("preferences for the new value.\n");
868 *msg << err;
870 AddLogLineM( false, wxEmptyString );
871 AddLogLineM( true, err );
872 AddLogLineM( false, wxEmptyString );
874 ok = false;
877 if (thePrefs::GetUDPPort() == thePrefs::GetPort() + 3) {
878 // Select a random usable value in the range 1025 ... 2^16 - 1
879 uint16 port = thePrefs::GetUDPPort();
880 while ( port < 1024 || port == thePrefs::GetPort() + 3 ) {
881 port = (uint16)rand();
883 thePrefs::SetUDPPort( port );
885 wxString err =
886 wxT("Network configuration failed! You set your UDP port to\n")
887 wxT("the value of the main TCP port plus 3.\n")
888 wxT("This port has been reserved for the Server-UDP port. The\n")
889 wxT("port value has been changed to avoid conflict, see the\n")
890 wxT("preferences for the new value\n");
891 *msg << err;
893 AddLogLineM( false, wxEmptyString );
894 AddLogLineM( true, err );
895 AddLogLineM( false, wxEmptyString );
897 ok = false;
900 // Create the address where we are going to listen
901 // TODO: read this from configuration file
902 amuleIPV4Address myaddr[4];
904 // Create the External Connections Socket.
905 // Default is 4712.
906 // Get ready to handle connections from apps like amulecmd
907 if (thePrefs::GetECAddress().IsEmpty() || !myaddr[0].Hostname(thePrefs::GetECAddress())) {
908 myaddr[0].AnyAddress();
910 myaddr[0].Service(thePrefs::ECPort());
911 ECServerHandler = new ExternalConn(myaddr[0], msg);
913 // Create the UDP socket TCP+3.
914 // Used for source asking on servers.
915 if (thePrefs::GetAddress().IsEmpty()) {
916 myaddr[1].AnyAddress();
917 } else if (!myaddr[1].Hostname(thePrefs::GetAddress())) {
918 myaddr[1].AnyAddress();
919 AddLogLineM(true, CFormat(_("Could not bind ports to the specified address: %s"))
920 % thePrefs::GetAddress());
923 wxString ip = myaddr[1].IPAddress();
924 myaddr[1].Service(thePrefs::GetPort()+3);
925 serverconnect = new CServerConnect(serverlist, myaddr[1]);
926 *msg << CFormat( wxT("*** Server UDP socket (TCP+3) at %s:%u\n") )
927 % ip % ((unsigned int)thePrefs::GetPort() + 3u);
929 // Create the ListenSocket (aMule TCP socket).
930 // Used for Client Port / Connections from other clients,
931 // Client to Client Source Exchange.
932 // Default is 4662.
933 myaddr[2] = myaddr[1];
934 myaddr[2].Service(thePrefs::GetPort());
935 listensocket = new CListenSocket(myaddr[2]);
936 *msg << CFormat( wxT("*** TCP socket (TCP) listening on %s:%u\n") )
937 % ip % (unsigned int)(thePrefs::GetPort());
938 // This command just sets a flag to control maximum number of connections.
939 // Notify(true) has already been called to the ListenSocket, so events may
940 // be already comming in.
941 if (listensocket->Ok()) {
942 listensocket->StartListening();
943 } else {
944 // If we wern't able to start listening, we need to warn the user
945 wxString err;
946 err = CFormat(_("Port %u is not available. You will be LOWID\n")) %
947 (unsigned int)(thePrefs::GetPort());
948 *msg << err;
949 AddLogLineM(true, err);
950 err.Clear();
951 err = CFormat(
952 _("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.")) %
953 (unsigned int)(thePrefs::GetPort());
954 ShowAlert(err, _("Error"), wxOK | wxICON_ERROR);
957 // Create the UDP socket.
958 // Used for extended eMule protocol, Queue Rating, File Reask Ping.
959 // Also used for Kademlia.
960 // Default is port 4672.
961 myaddr[3] = myaddr[1];
962 myaddr[3].Service(thePrefs::GetUDPPort());
963 clientudp = new CClientUDPSocket(myaddr[3], thePrefs::GetProxyData());
964 if (!thePrefs::IsUDPDisabled()) {
965 *msg << CFormat( wxT("*** Client UDP socket (extended eMule) at %s:%u") )
966 % ip % thePrefs::GetUDPPort();
967 } else {
968 *msg << wxT("*** Client UDP socket (extended eMule) disabled on preferences");
971 #ifdef ENABLE_UPNP
972 if (thePrefs::GetUPnPEnabled()) {
973 try {
974 m_upnpMappings[0] = CUPnPPortMapping(
975 myaddr[0].Service(),
976 "TCP",
977 thePrefs::GetUPnPECEnabled(),
978 "aMule TCP External Connections Socket");
979 m_upnpMappings[1] = CUPnPPortMapping(
980 myaddr[1].Service(),
981 "UDP",
982 thePrefs::GetUPnPEnabled(),
983 "aMule UDP socket (TCP+3)");
984 m_upnpMappings[2] = CUPnPPortMapping(
985 myaddr[2].Service(),
986 "TCP",
987 thePrefs::GetUPnPEnabled(),
988 "aMule TCP Listen Socket");
989 m_upnpMappings[3] = CUPnPPortMapping(
990 myaddr[3].Service(),
991 "UDP",
992 thePrefs::GetUPnPEnabled(),
993 "aMule UDP Extended eMule Socket");
994 m_upnp = new CUPnPControlPoint(thePrefs::GetUPnPTCPPort());
995 m_upnp->AddPortMappings(m_upnpMappings);
996 } catch(CUPnPException &e) {
997 wxString error_msg;
998 error_msg << e.what();
999 AddLogLineM(true, error_msg);
1000 fprintf(stderr, "%s\n", (const char *)unicode2char(error_msg));
1003 #endif
1005 return ok;
1008 // Returns a magnet ed2k URI
1009 wxString CamuleApp::CreateMagnetLink(const CAbstractFile *f)
1011 CMagnetURI uri;
1013 uri.AddField(wxT("dn"), f->GetFileName().Cleanup(false).GetPrintable());
1014 uri.AddField(wxT("xt"), wxString(wxT("urn:ed2k:")) + f->GetFileHash().Encode().Lower());
1015 uri.AddField(wxT("xl"), wxString::Format(wxT("%") wxLongLongFmtSpec wxT("u"), f->GetFileSize()));
1017 return uri.GetLink();
1020 // Returns a ed2k file URL
1021 wxString CamuleApp::CreateED2kLink(const CAbstractFile *f, bool add_source, bool use_hostname, bool addcryptoptions)
1023 wxASSERT(!(!add_source && (use_hostname || addcryptoptions)));
1024 // Construct URL like this: ed2k://|file|<filename>|<size>|<hash>|/
1025 wxString strURL = CFormat(wxT("ed2k://|file|%s|%i|%s|/"))
1026 % f->GetFileName().Cleanup(false)
1027 % f->GetFileSize() % f->GetFileHash().Encode();
1029 if (add_source && IsConnected() && !IsFirewalled()) {
1030 // Create the first part of the URL
1031 strURL << wxT("|sources,");
1032 if (use_hostname) {
1033 strURL << thePrefs::GetYourHostname();
1034 } else {
1035 uint32 clientID = GetID();
1036 strURL << (uint8) clientID << wxT(".") <<
1037 (uint8)(clientID >> 8) << wxT(".") <<
1038 (uint8)(clientID >> 16) << wxT(".") <<
1039 (uint8)(clientID >> 24);
1042 strURL << wxT(":") <<
1043 thePrefs::GetPort();
1045 if (addcryptoptions) {
1046 const uint8 uSupportsCryptLayer = thePrefs::IsClientCryptLayerSupported() ? 1 : 0;
1047 const uint8 uRequestsCryptLayer = thePrefs::IsClientCryptLayerRequested() ? 1 : 0;
1048 const uint8 uRequiresCryptLayer = thePrefs::IsClientCryptLayerRequired() ? 1 : 0;
1049 const uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0) | (uSupportsCryptLayer ? 0x80 : 0x00);
1051 strURL << wxT(":") << byCryptOptions;
1053 if (byCryptOptions & 0x80) {
1054 strURL << wxT(":") << thePrefs::GetUserHash().Encode();
1057 strURL << wxT("|/");
1058 } else if (add_source) {
1059 AddLogLineM(true, _("WARNING: You can't add yourself as a source for a ed2k link while being lowid."));
1062 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|sources,[(<ip>|<hostname>):<port>[:cryptoptions[:hash]]]|/"
1063 return strURL;
1066 // Returns a ed2k link with AICH info if available
1067 wxString CamuleApp::CreateED2kAICHLink(const CKnownFile* f)
1069 // Create the first part of the URL
1070 wxString strURL = CreateED2kLink(f);
1071 // Append the AICH info
1072 if (f->HasProperAICHHashSet()) {
1073 strURL << wxT("|h=") << f->GetAICHMasterHash() << wxT("|/");
1076 // Result is "ed2k://|file|<filename>|<size>|<hash>|/|h=<AICH master hash>|/"
1077 return strURL;
1080 /* Original implementation by Bouc7 of the eMule Project.
1081 aMule Signature idea was designed by BigBob and implemented
1082 by Un-Thesis, with design inputs and suggestions from bothie.
1084 void CamuleApp::OnlineSig(bool zero /* reset stats (used on shutdown) */)
1086 // Do not do anything if online signature is disabled in Preferences
1087 if (!thePrefs::IsOnlineSignatureEnabled() || m_emulesig_path.IsEmpty()) {
1088 // We do not need to check m_amulesig_path because if m_emulesig_path is empty,
1089 // that means m_amulesig_path is empty too.
1090 return;
1093 // Remove old signature files
1094 if ( wxFileExists( m_emulesig_path ) ) { wxRemoveFile( m_emulesig_path ); }
1095 if ( wxFileExists( m_amulesig_path ) ) { wxRemoveFile( m_amulesig_path ); }
1098 wxTextFile amulesig_out;
1099 wxTextFile emulesig_out;
1101 // Open both files if needed
1102 if ( !emulesig_out.Create( m_emulesig_path) ) {
1103 AddLogLineM(true, _("Failed to create OnlineSig File"));
1104 // Will never try again.
1105 m_amulesig_path.Clear();
1106 m_emulesig_path.Clear();
1107 return;
1110 if ( !amulesig_out.Create(m_amulesig_path) ) {
1111 AddLogLineM(true, _("Failed to create aMule OnlineSig File"));
1112 // Will never try again.
1113 m_amulesig_path.Clear();
1114 m_emulesig_path.Clear();
1115 return;
1118 wxString emulesig_string;
1119 wxString temp;
1121 if (zero) {
1122 emulesig_string = wxT("0\xA0.0|0.0|0");
1123 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0\n0\n0.0\n0.0\n0\n0"));
1124 } else {
1125 if (IsConnectedED2K()) {
1127 temp = wxString::Format(wxT("%d"),serverconnect->GetCurrentServer()->GetPort());
1129 // We are online
1130 emulesig_string =
1131 // Connected
1132 wxT("1|")
1133 //Server name
1134 + serverconnect->GetCurrentServer()->GetListName()
1135 + wxT("|")
1136 // IP and port of the server
1137 + serverconnect->GetCurrentServer()->GetFullIP()
1138 + wxT("|")
1139 + temp;
1142 // Now for amule sig
1144 // Connected. State 1, full info
1145 amulesig_out.AddLine(wxT("1"));
1146 // Server Name
1147 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetListName());
1148 // Server IP
1149 amulesig_out.AddLine(serverconnect->GetCurrentServer()->GetFullIP());
1150 // Server Port
1151 amulesig_out.AddLine(temp);
1153 if (serverconnect->IsLowID()) {
1154 amulesig_out.AddLine(wxT("L"));
1155 } else {
1156 amulesig_out.AddLine(wxT("H"));
1159 } else if (serverconnect->IsConnecting()) {
1160 emulesig_string = wxT("0");
1162 // Connecting. State 2, No info.
1163 amulesig_out.AddLine(wxT("2\n0\n0\n0\n0"));
1164 } else {
1165 // Not connected to a server
1166 emulesig_string = wxT("0");
1168 // Not connected, state 0, no info
1169 amulesig_out.AddLine(wxT("0\n0\n0\n0\n0"));
1171 if (IsConnectedKad()) {
1172 if(Kademlia::CKademlia::IsFirewalled()) {
1173 // Connected. Firewalled. State 1.
1174 amulesig_out.AddLine(wxT("1"));
1175 } else {
1176 // Connected. State 2.
1177 amulesig_out.AddLine(wxT("2"));
1179 } else {
1180 // Not connected.State 0.
1181 amulesig_out.AddLine(wxT("0"));
1183 emulesig_string += wxT("\xA");
1185 // Datarate for downloads
1186 temp = wxString::Format(wxT("%.1f"), theStats::GetDownloadRate() / 1024.0);
1188 emulesig_string += temp + wxT("|");
1189 amulesig_out.AddLine(temp);
1191 // Datarate for uploads
1192 temp = wxString::Format(wxT("%.1f"), theStats::GetUploadRate() / 1024.0);
1194 emulesig_string += temp + wxT("|");
1195 amulesig_out.AddLine(temp);
1197 // Number of users waiting for upload
1198 temp = wxString::Format(wxT("%d"), theStats::GetWaitingUserCount());
1200 emulesig_string += temp;
1201 amulesig_out.AddLine(temp);
1203 // Number of shared files (not on eMule)
1204 amulesig_out.AddLine(wxString::Format(wxT("%d"), theStats::GetSharedFileCount()));
1207 // eMule signature finished here. Write the line to the wxTextFile.
1208 emulesig_out.AddLine(emulesig_string);
1210 // Now for aMule signature extras
1212 // Nick on the network
1213 amulesig_out.AddLine(thePrefs::GetUserNick());
1215 // Total received in bytes
1216 amulesig_out.AddLine( CFormat( wxT("%llu") ) % (theStats::GetSessionReceivedBytes() + thePrefs::GetTotalDownloaded()) );
1218 // Total sent in bytes
1219 amulesig_out.AddLine( CFormat( wxT("%llu") ) % (theStats::GetSessionSentBytes() + thePrefs::GetTotalUploaded()) );
1221 // amule version
1222 #ifdef SVNDATE
1223 amulesig_out.AddLine(wxT(VERSION " " SVNDATE));
1224 #else
1225 amulesig_out.AddLine(wxT(VERSION));
1226 #endif
1228 if (zero) {
1229 amulesig_out.AddLine(wxT("0"));
1230 amulesig_out.AddLine(wxT("0"));
1231 amulesig_out.AddLine(wxT("0"));
1232 } else {
1233 // Total received bytes in session
1234 amulesig_out.AddLine( CFormat( wxT("%llu") ) %
1235 theStats::GetSessionReceivedBytes() );
1237 // Total sent bytes in session
1238 amulesig_out.AddLine( CFormat( wxT("%llu") ) %
1239 theStats::GetSessionSentBytes() );
1241 // Uptime
1242 amulesig_out.AddLine(CFormat(wxT("%llu")) % theStats::GetUptimeSeconds());
1245 // Flush the files
1246 emulesig_out.Write();
1247 amulesig_out.Write();
1248 } //End Added By Bouc7
1251 // Gracefully handle fatal exceptions and print backtrace if possible
1252 void CamuleApp::OnFatalException()
1254 /* Print the backtrace */
1255 fprintf(stderr, "\n--------------------------------------------------------------------------------\n");
1256 fprintf(stderr, "A fatal error has occurred and aMule has crashed.\n");
1257 fprintf(stderr, "Please assist us in fixing this problem by posting the backtrace below in our\n");
1258 fprintf(stderr, "'aMule Crashes' forum and include as much information as possible regarding the\n");
1259 fprintf(stderr, "circumstances of this crash. The forum is located here:\n");
1260 fprintf(stderr, " http://forum.amule.org/index.php?board=67.0\n");
1261 fprintf(stderr, "If possible, please try to generate a real backtrace of this crash:\n");
1262 fprintf(stderr, " http://www.amule.org/wiki/index.php/Backtraces\n\n");
1263 fprintf(stderr, "----------------------------=| BACKTRACE FOLLOWS: |=----------------------------\n");
1264 fprintf(stderr, "Current version is: %s\n", strFullMuleVersion);
1265 fprintf(stderr, "Running on: %s\n\n", strOSDescription);
1267 print_backtrace(1); // 1 == skip this function.
1269 fprintf(stderr, "\n--------------------------------------------------------------------------------\n");
1273 // Sets the localization of aMule
1274 void CamuleApp::Localize_mule()
1276 InitCustomLanguages();
1277 InitLocale(m_locale, StrLang2wx(thePrefs::GetLanguageID()));
1278 if (!m_locale.IsOk()) {
1279 AddLogLineM(false,_("The selected locale seems not to be installed on your box. (Note: I'll try to set it anyway)"));
1284 // Displays information related to important changes in aMule.
1285 // Is called when the user runs a new version of aMule
1286 void CamuleApp::Trigger_New_version(wxString new_version)
1288 wxString info = wxT(" --- ") + CFormat(_("This is the first time you run aMule %s")) % new_version + wxT(" ---\n\n");
1289 if (new_version == wxT("SVN")) {
1290 info += _("This version is a testing version, updated daily, and\n");
1291 info += _("we give no warranty it won't break anything, burn your house,\n");
1292 info += _("or kill your dog. But it *should* be safe to use anyway.\n");
1293 } else if (new_version == wxT("2.2.0")) {
1294 thePrefs::SetAddServersFromServer(false);
1295 thePrefs::SetAddServersFromClient(false);
1296 info += _("The following options have been changed in this release for security reasons:\n");
1297 info += _("\n* Enabled Protocol Obfuscation support for incoming and outgoing connections.\n");
1298 info += _("\n* Disabled updating the server list from other server and clients.\n");
1299 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.");
1302 // General info
1303 info += wxT("\n");
1304 info += _("More information, support and new releases can found at our homepage,\n");
1305 info += _("at www.aMule.org, or in our IRC channel #aMule at irc.freenode.net.\n");
1306 info += wxT("\n");
1307 info += _("Feel free to report any bugs to http://forum.amule.org");
1309 ShowAlert(info, _("Info"), wxCENTRE | wxOK | wxICON_ERROR);
1313 void CamuleApp::SetOSFiles(const wxString new_path)
1315 if ( thePrefs::IsOnlineSignatureEnabled() ) {
1316 if ( ::wxDirExists(new_path) ) {
1317 m_emulesig_path = JoinPaths(new_path, wxT("onlinesig.dat"));
1318 m_amulesig_path = JoinPaths(new_path, wxT("amulesig.dat"));
1319 } else {
1320 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);
1321 m_emulesig_path.Clear();
1322 m_amulesig_path.Clear();
1324 } else {
1325 m_emulesig_path.Clear();
1326 m_amulesig_path.Clear();
1331 #ifdef __WXDEBUG__
1332 #ifndef wxUSE_STACKWALKER
1333 #define wxUSE_STACKWALKER 0
1334 #endif
1335 void CamuleApp::OnAssertFailure(const wxChar* file, int line,
1336 const wxChar* func, const wxChar* cond, const wxChar* msg)
1338 if (!wxUSE_STACKWALKER || !wxThread::IsMain() || !IsRunning()) {
1339 wxString errmsg = CFormat( wxT("%s:%s:%d: Assertion '%s' failed. %s") )
1340 % file % func % line % cond % ( msg ? msg : wxT("") );
1342 fprintf(stderr, "Assertion failed: %s\n", (const char*)unicode2char(errmsg));
1344 // Skip the function-calls directly related to the assert call.
1345 fprintf(stderr, "\nBacktrace follows:\n");
1346 print_backtrace(3);
1347 fprintf(stderr, "\n");
1350 if (wxThread::IsMain() && IsRunning()) {
1351 AMULE_APP_BASE::OnAssertFailure(file, line, func, cond, msg);
1352 } else {
1353 // Abort, allows gdb to catch the assertion
1354 raise( SIGABRT );
1357 #endif
1360 void CamuleApp::OnUDPDnsDone(CMuleInternalEvent& evt)
1362 CServerUDPSocket* socket =(CServerUDPSocket*)evt.GetClientData();
1363 socket->OnHostnameResolved(evt.GetExtraLong());
1367 void CamuleApp::OnSourceDnsDone(CMuleInternalEvent& evt)
1369 downloadqueue->OnHostnameResolved(evt.GetExtraLong());
1373 void CamuleApp::OnServerDnsDone(CMuleInternalEvent& evt)
1375 printf("Server hostname notified\n");
1376 serverconnect->OnServerHostnameResolved(evt.GetClientData(), evt.GetExtraLong());
1380 void CamuleApp::OnTCPTimer(CTimerEvent& WXUNUSED(evt))
1382 if(!IsRunning()) {
1383 return;
1385 serverconnect->StopConnectionTry();
1386 if (IsConnectedED2K() ) {
1387 return;
1389 serverconnect->ConnectToAnyServer();
1393 void CamuleApp::OnCoreTimer(CTimerEvent& WXUNUSED(evt))
1395 // Former TimerProc section
1396 static uint64 msPrev1, msPrev5, msPrevSave, msPrevHist, msPrevOS, msPrevKnownMet;
1397 uint64 msCur = theStats::GetUptimeMillis();
1399 if (!IsRunning()) {
1400 return;
1403 #ifndef AMULE_DAEMON
1404 // Check if we should terminate the app
1405 if ( g_shutdownSignal ) {
1406 wxWindow* top = GetTopWindow();
1408 if ( top ) {
1409 top->Close(true);
1410 } else {
1411 // No top-window, have to force termination.
1412 wxExit();
1415 #endif
1417 CLogger::FlushPendingEntries();
1419 uploadqueue->Process();
1420 downloadqueue->Process();
1421 //theApp->clientcredits->Process();
1422 theStats::CalculateRates();
1424 if (msCur-msPrevHist > 1000) {
1425 // unlike the other loop counters in this function this one will sometimes
1426 // produce two calls in quick succession (if there was a gap of more than one
1427 // second between calls to TimerProc) - this is intentional! This way the
1428 // history list keeps an average of one node per second and gets thinned out
1429 // correctly as time progresses.
1430 msPrevHist += 1000;
1432 m_statistics->RecordHistory();
1437 if (msCur-msPrev1 > 1000) { // approximately every second
1438 msPrev1 = msCur;
1439 clientcredits->Process();
1440 clientlist->Process();
1442 // Publish files to server if needed.
1443 sharedfiles->Process();
1445 if( Kademlia::CKademlia::IsRunning() ) {
1446 Kademlia::CKademlia::Process();
1447 if(Kademlia::CKademlia::GetPrefs()->HasLostConnection()) {
1448 StopKad();
1449 clientudp->Close();
1450 clientudp->Open();
1451 if (thePrefs::Reconnect()) {
1452 StartKad();
1457 if( serverconnect->IsConnecting() && !serverconnect->IsSingleConnect() ) {
1458 serverconnect->TryAnotherConnectionrequest();
1460 if (serverconnect->IsConnecting()) {
1461 serverconnect->CheckForTimeout();
1463 listensocket->UpdateConnectionsStatus();
1468 if (msCur-msPrev5 > 5000) { // every 5 seconds
1469 msPrev5 = msCur;
1470 listensocket->Process();
1473 if (msCur-msPrevSave >= 60000) {
1474 msPrevSave = msCur;
1475 wxString buffer;
1477 // Save total upload/download to preferences
1478 wxConfigBase* cfg = wxConfigBase::Get();
1479 buffer = CFormat(wxT("%llu")) % (theStats::GetSessionReceivedBytes() + thePrefs::GetTotalDownloaded());
1480 cfg->Write(wxT("/Statistics/TotalDownloadedBytes"), buffer);
1482 buffer = CFormat(wxT("%llu")) % (theStats::GetSessionSentBytes() + thePrefs::GetTotalUploaded());
1483 cfg->Write(wxT("/Statistics/TotalUploadedBytes"), buffer);
1485 // Write changes to file
1486 cfg->Flush();
1490 // Special
1491 if (msCur - msPrevOS >= thePrefs::GetOSUpdate() * 1000ull) {
1492 OnlineSig(); // Added By Bouc7
1493 msPrevOS = msCur;
1496 if (msCur - msPrevKnownMet >= 30*60*1000/*There must be a prefs option for this*/) {
1497 // Save Shared Files data
1498 knownfiles->Save();
1499 msPrevKnownMet = msCur;
1503 // Recomended by lugdunummaster himself - from emule 0.30c
1504 serverconnect->KeepConnectionAlive();
1509 void CamuleApp::OnFinishedHashing(CHashingEvent& evt)
1511 wxCHECK_RET(evt.GetResult(), wxT("No result of hashing"));
1513 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner());
1514 CKnownFile* result = evt.GetResult();
1516 if (owner) {
1517 // Check if the partfile still exists, as it might have
1518 // been deleted in the mean time.
1519 if (downloadqueue->IsPartFile(owner)) {
1520 // This cast must not be done before the IsPartFile
1521 // call, as dynamic_cast will barf on dangling pointers.
1522 dynamic_cast<CPartFile*>(owner)->PartFileHashFinished(result);
1524 } else {
1525 static int filecount;
1526 static uint64 bytecount;
1528 if (knownfiles->SafeAddKFile(result)) {
1529 AddDebugLogLineM(false, logKnownFiles,
1530 CFormat(wxT("Safe adding file to sharedlist: %s")) % result->GetFileName());
1531 sharedfiles->SafeAddKFile(result);
1533 filecount++;
1534 bytecount += result->GetFileSize();
1535 // If we have added 30 files or files with a total size of ~300mb
1536 if ( ( filecount == 30 ) || ( bytecount >= 314572800 ) ) {
1537 AddDebugLogLineM(false, logKnownFiles, wxT("Failsafe for crash on file hashing creation"));
1538 if ( m_app_state != APP_STATE_SHUTTINGDOWN ) {
1539 knownfiles->Save();
1540 filecount = 0;
1541 bytecount = 0;
1544 } else {
1545 AddDebugLogLineM(false, logKnownFiles,
1546 CFormat(wxT("File not added to sharedlist: %s")) % result->GetFileName());
1547 delete result;
1553 void CamuleApp::OnFinishedAICHHashing(CHashingEvent& evt)
1555 wxCHECK_RET(evt.GetResult(), wxT("No result of AICH-hashing"));
1557 CKnownFile* owner = const_cast<CKnownFile*>(evt.GetOwner());
1558 std::auto_ptr<CKnownFile> result(evt.GetResult());
1560 // Check that the owner is still valid
1561 if (knownfiles->IsKnownFile(owner)) {
1562 if (result->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE) {
1563 CAICHHashSet* oldSet = owner->GetAICHHashset();
1564 CAICHHashSet* newSet = result->GetAICHHashset();
1566 owner->SetAICHHashset(newSet);
1567 newSet->SetOwner(owner);
1569 result->SetAICHHashset(oldSet);
1570 oldSet->SetOwner(result.get());
1576 void CamuleApp::OnFinishedCompletion(CCompletionEvent& evt)
1578 CPartFile* completed = const_cast<CPartFile*>(evt.GetOwner());
1579 wxCHECK_RET(completed, wxT("Completion event sent for unspecified file"));
1580 wxASSERT_MSG(downloadqueue->IsPartFile(completed), wxT("CCompletionEvent for unknown partfile."));
1582 completed->CompleteFileEnded(evt.ErrorOccured(), evt.GetFullPath());
1583 if (evt.ErrorOccured()) {
1584 CUserEvents::ProcessEvent(CUserEvents::ErrorOnCompletion, completed);
1587 // Check if we should execute an script/app/whatever.
1588 CUserEvents::ProcessEvent(CUserEvents::DownloadCompleted, completed);
1592 void CamuleApp::OnNotifyEvent(CMuleGUIEvent& evt)
1594 #if defined(AMULE_DAEMON)
1595 evt.Notify();
1596 #else
1597 if (theApp->amuledlg) {
1598 evt.Notify();
1600 #endif
1604 void CamuleApp::ShutDown()
1606 // Log
1607 AddDebugLogLineM(false, logGeneral, wxT("CamuleApp::ShutDown() has started."));
1609 // Signal the hashing thread to terminate
1610 m_app_state = APP_STATE_SHUTTINGDOWN;
1612 StopKad();
1614 // Kry - Save the sources seeds on app exit
1615 if (thePrefs::GetSrcSeedsOn()) {
1616 downloadqueue->SaveSourceSeeds();
1619 OnlineSig(true); // Added By Bouc7
1621 // Close sockets to avoid new clients coming in
1622 if (listensocket) {
1623 listensocket->Close();
1624 listensocket->KillAllSockets();
1627 if (serverconnect) {
1628 serverconnect->Disconnect();
1631 ECServerHandler->KillAllSockets();
1633 #ifdef ENABLE_UPNP
1634 if (thePrefs::GetUPnPEnabled()) {
1635 if (m_upnp) {
1636 m_upnp->DeletePortMappings(m_upnpMappings);
1639 #endif
1641 // saving data & stuff
1642 if (knownfiles) {
1643 knownfiles->Save();
1646 thePrefs::Add2TotalDownloaded(theStats::GetSessionReceivedBytes());
1647 thePrefs::Add2TotalUploaded(theStats::GetSessionSentBytes());
1649 if (glob_prefs) {
1650 glob_prefs->Save();
1653 if (clientlist) {
1654 clientlist->DeleteAll();
1657 CThreadScheduler::Terminate();
1659 theApp->uploadBandwidthThrottler->EndThread();
1661 // Log
1662 AddDebugLogLineM(false, logGeneral, wxT("CamuleApp::ShutDown() has ended."));
1666 bool CamuleApp::AddServer(CServer *srv, bool fromUser)
1668 if ( serverlist->AddServer(srv, fromUser) ) {
1669 Notify_ServerAdd(srv);
1670 return true;
1672 return false;
1676 void CamuleApp::AddLogLine(const wxString &msg)
1678 // At most one trailing new-line, which we add
1679 wxString message = msg;
1680 while ( !message.IsEmpty() && message.Last() == wxT('\n') ) {
1681 message.RemoveLast();
1684 wxString full_line = wxDateTime::Now().FormatISODate() + wxT(" ") +
1685 wxDateTime::Now().FormatISOTime() + wxT(": ") + message + wxT("\n");
1687 wxStringInputStream stream(full_line);
1689 if (applog) { // This check is needed, because if we assert before the logger is created, it will crash.
1690 (*applog) << stream;
1691 applog->Sync();
1694 if (enable_stdout_log) {
1695 printf("%s", (const char*)unicode2char(full_line));
1700 uint32 CamuleApp::GetPublicIP(bool ignorelocal) const
1702 if (m_dwPublicIP == 0) {
1703 if (Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::GetIPAddress() ) {
1704 return wxUINT32_SWAP_ALWAYS(Kademlia::CKademlia::GetIPAddress());
1705 } else {
1706 return ignorelocal ? 0 : m_localip;
1710 return m_dwPublicIP;
1714 void CamuleApp::SetPublicIP(const uint32 dwIP)
1716 wxASSERT((dwIP == 0) || !IsLowID(dwIP));
1718 if (dwIP != 0 && dwIP != m_dwPublicIP && serverlist != NULL) {
1719 m_dwPublicIP = dwIP;
1720 serverlist->CheckForExpiredUDPKeys();
1721 } else {
1722 m_dwPublicIP = dwIP;
1727 wxString CamuleApp::GetLog(bool reset)
1729 ConfigDir = GetConfigDir();
1730 wxFile logfile;
1731 logfile.Open(ConfigDir + wxT("logfile"));
1732 if ( !logfile.IsOpened() ) {
1733 return wxTRANSLATE("ERROR: can't open logfile");
1735 int len = logfile.Length();
1736 if ( len == 0 ) {
1737 return wxTRANSLATE("WARNING: logfile is empty. Something is wrong.");
1739 char *tmp_buffer = new char[len + sizeof(wxChar)];
1740 logfile.Read(tmp_buffer, len);
1741 memset(tmp_buffer + len, 0, sizeof(wxChar));
1743 // try to guess file format
1744 wxString str;
1745 if (tmp_buffer[0] && tmp_buffer[1]) {
1746 str = wxString(UTF82unicode(tmp_buffer));
1747 } else {
1748 str = wxString((wxWCharBuffer&)tmp_buffer);
1751 delete [] tmp_buffer;
1752 if ( reset ) {
1753 delete applog;
1754 applog = new wxFFileOutputStream(ConfigDir + wxT("logfile"));
1755 if ( applog->Ok() ) {
1756 AddLogLine(_("Log has been reset"));
1757 } else {
1758 delete applog;
1759 applog = 0;
1762 return str;
1766 wxString CamuleApp::GetServerLog(bool reset)
1768 wxString ret = server_msg;
1769 if ( reset ) {
1770 server_msg.Clear();
1772 return ret;
1775 wxString CamuleApp::GetDebugLog(bool reset)
1777 return GetLog(reset);
1781 void CamuleApp::AddServerMessageLine(wxString &msg)
1783 server_msg += msg + wxT("\n");
1784 AddLogLine(CFormat(_("ServerMessage: %s")) % msg);
1789 void CamuleApp::OnFinishedHTTPDownload(CMuleInternalEvent& event)
1791 switch (event.GetInt()) {
1792 case HTTP_IPFilter:
1793 ipfilter->DownloadFinished(event.GetExtraLong());
1794 break;
1795 case HTTP_ServerMet:
1796 serverlist->DownloadFinished(event.GetExtraLong());
1797 break;
1798 case HTTP_ServerMetAuto:
1799 serverlist->AutoDownloadFinished(event.GetExtraLong());
1800 break;
1801 case HTTP_VersionCheck:
1802 CheckNewVersion(event.GetExtraLong());
1803 break;
1804 case HTTP_NodesDat:
1805 if (event.GetExtraLong() != -1) {
1807 wxString file = ConfigDir + wxT("nodes.dat");
1808 if (wxFileExists(file)) {
1809 wxRemoveFile(file);
1812 if ( Kademlia::CKademlia::IsRunning() ) {
1813 Kademlia::CKademlia::Stop();
1816 wxRenameFile(file + wxT(".download"),file);
1818 Kademlia::CKademlia::Start();
1819 theApp->ShowConnectionState();
1821 } else {
1822 AddLogLineM(true, _("Failed to download the nodes list."));
1824 break;
1828 void CamuleApp::CheckNewVersion(uint32 result)
1830 if (result == 1) {
1831 wxString filename = ConfigDir + wxT("last_version_check");
1832 wxTextFile file;
1834 if (!file.Open(filename)) {
1835 AddLogLineM(true, _("Failed to open the downloaded version check file") );
1836 return;
1837 } else if (!file.GetLineCount()) {
1838 AddLogLineM(true, _("Corrupted version check file"));
1839 } else {
1840 wxString versionLine = file.GetFirstLine();
1841 wxStringTokenizer tkz(versionLine, wxT("."));
1843 AddDebugLogLineM(false, logGeneral, wxString(wxT("Running: ")) + wxT(VERSION) + wxT(", Version check: ") + versionLine);
1845 long fields[] = {0, 0, 0};
1846 for (int i = 0; i < 3; ++i) {
1847 if (!tkz.HasMoreTokens()) {
1848 AddLogLineM(true, _("Corrupted version check file"));
1849 return;
1850 } else {
1851 wxString token = tkz.GetNextToken();
1853 if (!token.ToLong(&fields[i])) {
1854 AddLogLineM(true, _("Corrupted version check file"));
1855 return;
1860 long curVer = make_full_ed2k_version(VERSION_MJR, VERSION_MIN, VERSION_UPDATE);
1861 long newVer = make_full_ed2k_version(fields[0], fields[1], fields[2]);
1863 if (curVer < newVer) {
1864 AddLogLineM(true, _("You are using an outdated version of aMule!"));
1865 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]));
1866 AddLogLineM(false, _("The latest version can always be found at http://www.amule.org"));
1867 #ifdef AMULE_DAEMON
1868 printf("%s\n", (const char*)unicode2UTF8(wxString::Format(
1869 _("WARNING: Your aMuled version is outdated: %i.%i.%i < %li.%li.%li"),
1870 VERSION_MJR, VERSION_MIN, VERSION_UPDATE, fields[0], fields[1], fields[2])));
1871 #endif
1872 } else {
1873 AddLogLineM(false, _("Your copy of aMule is up to date."));
1877 file.Close();
1878 wxRemoveFile(filename);
1879 } else {
1880 AddLogLineM(true, _("Failed to download the version check file") );
1886 bool CamuleApp::IsConnected()
1888 return (IsConnectedED2K() || IsConnectedKad());
1892 bool CamuleApp::IsConnectedED2K()
1894 return serverconnect && serverconnect->IsConnected();
1898 bool CamuleApp::IsConnectedKad()
1900 return Kademlia::CKademlia::IsConnected();
1904 bool CamuleApp::IsFirewalled()
1906 if (theApp->IsConnectedED2K() && !theApp->serverconnect->IsLowID()) {
1907 return false; // we have an eD2K HighID -> not firewalled
1910 return IsFirewalledKad(); // If kad says ok, it's ok.
1913 bool CamuleApp::IsFirewalledKad()
1915 if (Kademlia::CKademlia::IsConnected() && !Kademlia::CKademlia::IsFirewalled()) {
1916 return false; // we have an Kad HighID -> not firewalled
1919 return true; // firewalled
1922 bool CamuleApp::IsKadRunning()
1924 return Kademlia::CKademlia::IsRunning();
1927 bool CamuleApp::DoCallback( CUpDownClient *client )
1929 if(Kademlia::CKademlia::IsConnected()) {
1930 if(IsConnectedED2K()) {
1931 if(serverconnect->IsLowID()) {
1932 if(Kademlia::CKademlia::IsFirewalled()) {
1933 //Both Connected - Both Firewalled
1934 return false;
1935 } else {
1936 if(client->GetServerIP() == theApp->serverconnect->GetCurrentServer()->GetIP() &&
1937 client->GetServerPort() == theApp->serverconnect->GetCurrentServer()->GetPort()) {
1938 // Both Connected - Server lowID, Kad Open - Client on same server
1939 // We prevent a callback to the server as this breaks the protocol
1940 // and will get you banned.
1941 return false;
1942 } else {
1943 // Both Connected - Server lowID, Kad Open - Client on remote server
1944 return true;
1947 } else {
1948 //Both Connected - Server HighID, Kad don't care
1949 return true;
1951 } else {
1952 if(Kademlia::CKademlia::IsFirewalled()) {
1953 //Only Kad Connected - Kad Firewalled
1954 return false;
1955 } else {
1956 //Only Kad Conected - Kad Open
1957 return true;
1960 } else {
1961 if( IsConnectedED2K() ) {
1962 if( serverconnect->IsLowID() ) {
1963 //Only Server Connected - Server LowID
1964 return false;
1965 } else {
1966 //Only Server Connected - Server HighID
1967 return true;
1969 } else {
1970 //We are not connected at all!
1971 return false;
1976 void CamuleApp::ShowUserCount() {
1977 uint32 totaluser = 0, totalfile = 0;
1979 theApp->serverlist->GetUserFileStatus( totaluser, totalfile );
1981 wxString buffer =
1982 CFormat(_("Users: E: %s K: %s | Files E: %s K: %s")) % CastItoIShort(totaluser) %
1983 CastItoIShort(Kademlia::CKademlia::GetKademliaUsers()) % CastItoIShort(totalfile) % CastItoIShort(Kademlia::CKademlia::GetKademliaFiles());
1985 Notify_ShowUserCount(buffer);
1989 void CamuleApp::ListenSocketHandler(wxSocketEvent& event)
1991 wxCHECK_RET(listensocket, wxT("Connection-event for NULL'd listen-socket"));
1992 wxCHECK_RET(event.GetSocketEvent() == wxSOCKET_CONNECTION,
1993 wxT("Invalid event received for listen-socket"));
1995 if (m_app_state == APP_STATE_RUNNING) {
1996 listensocket->OnAccept(0);
1997 } else if (m_app_state == APP_STATE_STARTING) {
1998 // When starting up, connection may be made before we are able
1999 // to handle them. However, if these are ignored, no futher
2000 // connection-events will be triggered, so we have to accept it.
2001 wxSocketBase* socket = listensocket->Accept(false);
2003 wxCHECK_RET(socket, wxT("NULL returned by Accept() during startup"));
2005 socket->Destroy();
2010 void CamuleApp::ShowConnectionState()
2012 static uint8 old_state = (1<<7); // This flag doesn't exist
2014 uint8 state = 0;
2016 if (theApp->serverconnect->IsConnected()) {
2017 state |= CONNECTED_ED2K;
2020 if (Kademlia::CKademlia::IsRunning()) {
2021 if (Kademlia::CKademlia::IsConnected()) {
2022 if (!Kademlia::CKademlia::IsFirewalled()) {
2023 state |= CONNECTED_KAD_OK;
2024 } else {
2025 state |= CONNECTED_KAD_FIREWALLED;
2027 } else {
2028 state |= CONNECTED_KAD_NOT;
2032 Notify_ShowConnState(state);
2034 if (old_state != state) {
2035 // Get the changed value
2036 int changed_flags = old_state ^ state;
2038 if (changed_flags & CONNECTED_ED2K) {
2039 // ED2K status changed
2040 wxString connected_server;
2041 CServer* ed2k_server = theApp->serverconnect->GetCurrentServer();
2042 if (ed2k_server) {
2043 connected_server = ed2k_server->GetListName();
2045 if (state & CONNECTED_ED2K) {
2046 // We connected to some server
2047 const wxString id = theApp->serverconnect->IsLowID() ? _("with LowID") : _("with HighID");
2049 AddLogLine(CFormat(_("Connected to %s %s")) % connected_server % id);
2050 } else {
2051 if ( theApp->serverconnect->IsConnecting() ) {
2052 AddLogLine(CFormat(_("Connecting to %s")) % connected_server);
2053 } else {
2054 AddLogLine(_("Disconnected from ED2K"));
2059 if (changed_flags & CONNECTED_KAD_NOT) {
2060 if (state & CONNECTED_KAD_NOT) {
2061 AddLogLine(_("Kad started."));
2062 } else {
2063 AddLogLine(_("Kad stopped."));
2067 if (changed_flags & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) {
2068 if (state & (CONNECTED_KAD_OK | CONNECTED_KAD_FIREWALLED)) {
2069 if (state & CONNECTED_KAD_OK) {
2070 AddLogLine(_("Connected to Kad (ok)"));
2071 } else {
2072 AddLogLine(_("Connected to Kad (firewalled)"));
2074 } else {
2075 AddLogLine(_("Disconnected from Kad"));
2079 old_state = state;
2081 theApp->downloadqueue->OnConnectionState(IsConnected());
2084 ShowUserCount();
2085 Notify_ShowConnState(state);
2089 void CamuleApp::UDPSocketHandler(wxSocketEvent& event)
2091 CMuleUDPSocket* socket = (CMuleUDPSocket*)(event.GetClientData());
2092 wxCHECK_RET(socket, wxT("No socket owner specified."));
2094 if (IsOnShutDown() || thePrefs::IsUDPDisabled()) return;
2096 if (!IsRunning()) {
2097 if (event.GetSocketEvent() == wxSOCKET_INPUT) {
2098 // Back to the queue!
2099 theApp->AddPendingEvent(event);
2100 return;
2104 switch (event.GetSocketEvent()) {
2105 case wxSOCKET_INPUT:
2106 socket->OnReceive(0);
2107 break;
2109 case wxSOCKET_OUTPUT:
2110 socket->OnSend(0);
2111 break;
2113 case wxSOCKET_LOST:
2114 socket->OnDisconnected(0);
2115 break;
2117 default:
2118 wxASSERT(0);
2119 break;
2124 void CamuleApp::OnUnhandledException()
2126 // Call the generic exception-handler.
2127 fprintf(stderr, "\taMule Version: %s\n", (const char*)unicode2char(GetFullMuleVersion()));
2128 ::OnUnhandledException();
2131 void CamuleApp::StartKad()
2133 if (!Kademlia::CKademlia::IsRunning() && thePrefs::GetNetworkKademlia()) {
2134 // Kad makes no sense without the Client-UDP socket.
2135 if (!thePrefs::IsUDPDisabled()) {
2136 Kademlia::CKademlia::Start();
2137 } else {
2138 AddLogLineM(true,_("Kad network cannot be used if UDP port is disabled on preferences, not starting."));
2140 } else if (!thePrefs::GetNetworkKademlia()) {
2141 AddLogLineM(true,_("Kad network disabled on preferences, not connecting."));
2145 void CamuleApp::StopKad()
2147 // Stop Kad if it's running
2148 if (Kademlia::CKademlia::IsRunning()) {
2149 Kademlia::CKademlia::Stop();
2154 void CamuleApp::BootstrapKad(uint32 ip, uint16 port)
2156 if (!Kademlia::CKademlia::IsRunning()) {
2157 Kademlia::CKademlia::Start();
2158 theApp->ShowConnectionState();
2161 Kademlia::CKademlia::Bootstrap(ip, port);
2165 void CamuleApp::UpdateNotesDat(const wxString& url)
2167 wxString strTempFilename(theApp->ConfigDir + wxT("nodes.dat.download"));
2169 CHTTPDownloadThread *downloader = new CHTTPDownloadThread(url, strTempFilename, HTTP_NodesDat);
2170 downloader->Create();
2171 downloader->Run();
2175 void CamuleApp::DisconnectED2K()
2177 // Stop Kad if it's running
2178 if (IsConnectedED2K()) {
2179 serverconnect->Disconnect();
2183 bool CamuleApp::CryptoAvailable() const
2185 return clientcredits && clientcredits->CryptoAvailable();
2188 uint32 CamuleApp::GetED2KID() const {
2189 return serverconnect ? serverconnect->GetClientID() : 0;
2192 uint32 CamuleApp::GetID() const {
2193 uint32 ID;
2195 if( Kademlia::CKademlia::IsConnected() && !Kademlia::CKademlia::IsFirewalled() ) {
2196 // We trust Kad above ED2K
2197 ID = ENDIAN_NTOHL(Kademlia::CKademlia::GetIPAddress());
2198 } else if( theApp->serverconnect->IsConnected() ) {
2199 ID = theApp->serverconnect->GetClientID();
2200 } else if ( Kademlia::CKademlia::IsConnected() && Kademlia::CKademlia::IsFirewalled() ) {
2201 // A firewalled Kad client get's a "1"
2202 ID = 1;
2203 } else {
2204 ID = 0;
2207 return ID;
2210 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_FINISHED_HTTP_DOWNLOAD)
2211 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SOURCE_DNS_DONE)
2212 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_UDP_DNS_DONE)
2213 DEFINE_LOCAL_EVENT_TYPE(wxEVT_CORE_SERVER_DNS_DONE)
2214 // File_checked_for_headers