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