1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
6// Any parts of this program derived from the xMule, lMule or eMule project,
7// or contributed by third-party developers are copyrighted by their
8// respective authors.
9//
10// This program is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 2 of the License, or
13// (at your option) any later version.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
23//
24
25#ifndef LOGGER_H
26#define LOGGER_H
27
28#include <wx/log.h>
29#include <wx/event.h>
30#include <iosfwd>
31
32
33enum DebugType
34{
35	//! Standard warning, not debug
36	logStandard = -1,
37	//! General warnings/errors.
38	logGeneral = 0,
39	//! Warnings/Errors for the main hashing thread.
40	logHasher,
41	//! Warnings/Errors for client-objects.
42	logClient,
43	//! Warnings/Errors for the local client protocol.
44	logLocalClient,
45	//! Warnings/Errors for the remote client protocol.
46	logRemoteClient,
47	//! Warnings/Errors when parsing packets.
48	logPacketErrors,
49	//! Warnings/Errors for the CFile class.
50	logCFile,
51	//! Warnings/Errors related to reading/writing files.
52	logFileIO,
53	//! Warnings/Errors when using the zLib library.
54	logZLib,
55	//! Warnings/Errors for the AICH-syncronization thread.
56	logAICHThread,
57	//! Warnings/Errors for transfering AICH hash-sets.
58	logAICHTransfer,
59	//! Warnings/Errors when recovering with AICH.
60	logAICHRecovery,
61	//! Warnings/Errors for the CListenSocket class.
62	logListenSocket,
63	//! Warnings/Errors for Client-Credits.
64	logCredits,
65	//! Warnings/Errors for the client UDP socket.
66	logClientUDP,
67	//! Warnings/Errors for the download-queue.
68	logDownloadQueue,
69	//! Warnings/Errors for the IP-Filter.
70	logIPFilter,
71	//! Warnings/Errors for known-files.
72	logKnownFiles,
73	//! Warnings/Errors for part-files.
74	logPartFile,
75	//! Warnings/Errors for SHA-hashset creation.
76	logSHAHashSet,
77	//! Warnings/Errors for servers, server connections.
78	logServer,
79	//! Warnings/Errors for proxy.
80	logProxy,
81	//! Warnings/Errors related to searching.
82	logSearch,
83	//! Warnings/Errors related to the server UDP socket.
84	logServerUDP,
85	//! Warning/Errors related to Kademlia UDP comunication on client
86	logClientKadUDP,
87	//! Warning/Errors related to Kademlia Search
88	logKadSearch,
89	//! Warning/Errors related to Kademlia Routing
90	logKadRouting,
91	//! Warning/Errors related to Kademlia Indexing
92	logKadIndex,
93	//! Warning/Errors related to Kademlia Main Thread
94	logKadMain,
95	//! Warning/Errors related to Kademlia Preferences
96	logKadPrefs,
97	//! Warnings/Errors related to partfile importer
98	logPfConvert,
99	//! Warnings/Errors related to the basic UDP socket-class.
100	logMuleUDP,
101	//! Warnings/Errors related to the thread-scheduler.
102	logThreads,
103	//! Warnings/Errors related to the Universal Plug and Play subsystem.
104	logUPnP,
105	//! Warnings/Errors related to the UDP Firewall Tester
106	logKadUdpFwTester,
107	//! Warnings/Errors related to Kad packet tracking.
108	logKadPacketTracking,
109	//! Warnings/Errors related to Kad entry tracking.
110	logKadEntryTracking,
111	//! Full log of external connection packets
112	logEC,
113	//! Warnings/Errors related to HTTP traffic
114	logHTTP
115	// IMPORTANT NOTE: when you add values to this enum, update the g_debugcats
116	// array in Logger.cpp!
117};
118
119
120
121/**
122 * Container-class for the debugging categories.
123 */
124class CDebugCategory
125{
126public:
127	/**
128	 * Constructor.
129	 *
130	 * @param type The actual debug-category type.
131	 * @param name The user-readable name.
132	 */
133	CDebugCategory( DebugType type, const wxString& name )
134		: m_name(name), m_type(type), m_enabled(false)
135	{}
136
137
138	/**
139	 * Returns true if the category is enabled.
140	 */
141	bool IsEnabled() const		{ return m_enabled; }
142
143	/**
144	 * Enables/Disables the category.
145	 */
146	void SetEnabled( bool enabled )	{ m_enabled = enabled; }
147
148
149	/**
150	 * Returns the user-readable name.
151	 */
152	const wxString& GetName() const	{ return m_name; }
153
154	/**
155	 * Returns the actual type.
156	 */
157	DebugType GetType() const	{ return m_type; }
158
159private:
160	//! The user-readable name.
161	wxString	m_name;
162	//! The actual type.
163	DebugType	m_type;
164	//! Whenever or not the category is enabled.
165	bool		m_enabled;
166};
167
168
169/**
170 * Functions for logging operations.
171 */
172class CLogger: public wxEvtHandler
173{
174public:
175	/**
176	 * Returns true if debug-messages should be generated for a specific category.
177	 */
178#ifdef __DEBUG__
179	bool IsEnabled( DebugType ) const;
180#else
181	bool IsEnabled( DebugType ) const 	{ return false; }
182#endif
183
184	/**
185	 * Enables or disables debug-messages for a specific category.
186	 */
187	void SetEnabled( DebugType type, bool enabled );
188
189	/**
190	 * Returns true if logging to stdout is enabled
191	 */
192	bool IsEnabledStdoutLog() const		{ return m_StdoutLog; }
193
194	/**
195	 * Enables or disables logging to stdout.
196	 */
197	void SetEnabledStdoutLog(bool enabled)	{ m_StdoutLog = enabled; }
198
199
200	/**
201	 * Logs the specified line of text, prefixed with the name of the DebugType.
202	 * (except for logStandard)
203	 *
204	 * @param file
205	 * @param line
206	 * @param critical If true, then the message will be made visible directly to the user.
207	 * @param type The debug-category, the name of which will be prepended to the line.
208	 * @param str The actual line of text.
209	 *
210	 * This function is thread-safe. If it is called by the main thread, the
211	 * event will be sent directly to the application, otherwise it will be
212	 * queued in the event-loop.
213	 */
214	void AddLogLine(
215		const wxString &file,
216		int line,
217		bool critical,
218		DebugType type,
219		const wxString &str,
220		bool toStdout = false,
221		bool toGUI = true);
222
223	// for UPnP
224	void AddLogLine(
225		const wxString &file,
226		int line,
227		bool critical,
228		DebugType type,
229		const std::ostringstream &msg);
230
231	void AddLogLine(
232		const wxString &file,
233		int line,
234		bool critical,
235		const std::ostringstream &msg);
236
237
238	/**
239	 * Returns a category specified by index.
240	 */
241	const CDebugCategory&	GetDebugCategory( int index );
242
243	/**
244	 * Returns the number of debug-categories.
245	 */
246	unsigned int GetDebugCategoryCount();
247
248	/**
249	 * Open Logfile, true on success
250	 */
251	bool OpenLogfile(const wxString & name);
252
253	/**
254	 * Close Logfile
255	 */
256	void CloseLogfile();
257
258	/**
259	 * Get name of Logfile
260	 */
261	const wxString & GetLogfileName() const {
262		return m_LogfileName;
263	}
264
265	/**
266	 * Event handler
267	 */
268	void OnLoggingEvent(class CLoggingEvent& evt);
269
270	/**
271	 * Construct
272	 */
273	CLogger() {
274		applog = NULL;
275		m_StdoutLog = false;
276		m_count = 0;
277	}
278
279private:
280	class wxFFileOutputStream* applog; 	// the logfile
281	wxString m_LogfileName;
282	wxString m_ApplogBuf;
283	bool m_StdoutLog;
284	int  m_count;			// output line counter
285
286	/**
287	 * Write all waiting log info to the logfile
288	 */
289	void FlushApplog();
290
291	/**
292	 * Really output a single line
293	 */
294	void DoLine(const wxString & line, bool toStdout, bool toGUI);
295
296	DECLARE_EVENT_TABLE()
297};
298
299extern CLogger theLogger;
300
301/**
302 * This class forwards log-lines from wxWidgets to CLogger.
303 */
304class CLoggerTarget : public wxLog
305{
306public:
307	CLoggerTarget();
308
309	/**
310	 * @see wxLog::DoLogString
311	 */
312#if wxCHECK_VERSION(2, 9, 0)
313	void DoLogText(const wxString &msg);
314#else
315	void DoLogString(const wxChar *msg, time_t);
316#endif
317};
318
319
320DECLARE_LOCAL_EVENT_TYPE(MULE_EVT_LOGLINE, -1)
321
322
323/** This event is sent when a log-line is queued. */
324class CLoggingEvent : public wxEvent
325{
326public:
327	CLoggingEvent(bool critical, bool toStdout, bool toGUI, const wxString& msg)
328		: wxEvent(-1, MULE_EVT_LOGLINE)
329		, m_critical(critical)
330		, m_stdout(toStdout)
331		, m_GUI(toGUI)
332		// Deep copy, to avoid thread-unsafe reference counting. */
333		, m_msg(msg.c_str(), msg.Length())
334	{
335	}
336
337	const wxString& Message() const {
338		return m_msg;
339	}
340
341	bool IsCritical() const {
342		return m_critical;
343	}
344
345	bool ToStdout() const {
346		return m_stdout;
347	}
348
349	bool ToGUI() const {
350		return m_GUI;
351	}
352
353	wxEvent* Clone() const {
354		return new CLoggingEvent(m_critical, m_stdout, m_GUI, m_msg);
355	}
356
357private:
358	bool		m_critical;
359	bool		m_stdout;
360	bool		m_GUI;
361	wxString	m_msg;
362};
363
364
365typedef void (wxEvtHandler::*MuleLogEventFunction)(CLoggingEvent&);
366
367//! Event-handler for completed hashings of new shared files and partfiles.
368#define EVT_MULE_LOGGING(func) \
369	DECLARE_EVENT_TABLE_ENTRY(MULE_EVT_LOGLINE, -1, -1, \
370	(wxObjectEventFunction) (wxEventFunction) \
371	wxStaticCastEvent(MuleLogEventFunction, &func), (wxObject*) NULL),
372
373
374// access the logfile for EC
375class CLoggerAccess
376{
377private:
378	class wxFFileInputStream * m_logfile;
379	class wxCharBuffer * m_buffer;
380	size_t m_bufferlen;
381	size_t m_pos;
382
383	bool m_ready;
384public:
385	//
386	// construct/destruct
387	//
388	CLoggerAccess();
389	~CLoggerAccess();
390	//
391	// Reset (used when logfile is cleared)
392	//
393	void Reset();
394	//
395	// get a String (if there is one)
396	//
397	bool GetString(wxString & s);
398	//
399	// is a String available ?
400	//
401	bool HasString();
402};
403
404
405/**
406 * These macros should be used when logging. The
407 * AddLogLineM macro will simply call one of the
408 * two CLogger::AddLogLine functions depending on
409 * parameters, but AddDebugLogLine* will only log
410 * a message if the message is either critical or
411 * the specified debug-type is enabled in the
412 * preferences.
413 * AddLogLineMS will also always print to stdout.
414 */
415#ifdef MULEUNIT
416	#define AddDebugLogLineN(...) do {} while (false)
417	#define AddLogLineN(...) do {} while (false)
418	#define AddLogLineNS(...) do {} while (false)
419	#define AddDebugLogLineC(...) do {} while (false)
420	#define AddLogLineC(...) do {} while (false)
421	#define AddLogLineCS(...) do {} while (false)
422#else
423// Macro for UPnP. This is not a debug macro, but wants its category printed nevertheless (sigh).
424	#define AddLogLineU(critical, type, string) theLogger.AddLogLine(__TFILE__, __LINE__, critical, type, string)
425// Macros for 'N'on critical logging
426	#ifdef __DEBUG__
427		#define AddDebugLogLineN(type, string) theLogger.AddLogLine(__TFILE__, __LINE__, false, type, string)
428	#else
429		#define AddDebugLogLineN(type, string)	do {} while (false)
430	#endif
431	#define AddLogLineN(string) theLogger.AddLogLine(__TFILE__, __LINE__, false, logStandard, string)
432	#define AddLogLineNS(string) theLogger.AddLogLine(__TFILE__, __LINE__, false, logStandard, string, true)
433// Macros for 'C'ritical logging
434	#define AddDebugLogLineC(type, string) theLogger.AddLogLine(__TFILE__, __LINE__, true, type, string)
435	#define AddLogLineC(string) theLogger.AddLogLine(__TFILE__, __LINE__, true, logStandard, string)
436	#define AddLogLineCS(string) theLogger.AddLogLine(__TFILE__, __LINE__, true, logStandard, string, true)
437// Macros for logging to logfile only
438	#define AddDebugLogLineF(type, string) theLogger.AddLogLine(__TFILE__, __LINE__, false, type, string, false, false)
439	#define AddLogLineF(string) theLogger.AddLogLine(__TFILE__, __LINE__, false, logStandard, string, false, false)
440#endif
441
442#endif
443// File_checked_for_headers
444