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