1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-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 ECTAG_H
26 #define ECTAG_H
27 
28 #include <iostream>
29 #include <sstream>
30 
31 // Must be first!
32 #ifdef USE_WX_EXTENSIONS
33 #include <wx/string.h> // Do_not_auto_remove
34 #include <common/StringFunctions.h>
35 
36 #define EC_ASSERT(x)	wxASSERT(x)
37 #else
38 #define EC_ASSERT(x)	assert(x)
39 #endif
40 
41 /* aMule/libcommon generic includes */
42 #include "../../../MD4Hash.h"		// Needed for CMD4Hash
43 
44 namespace Kademlia {
45 	class CUInt128;
46 }
47 using Kademlia::CUInt128;
48 
49 /* EC specific includes */
50 #include "ECCodes.h"		// Needed for EC types
51 #include "ECTagTypes.h"	// Needed for TagTypes
52 
53 
54 class CECSocket;
55 class CValueMap;
56 
57 /**
58  * Class to hold IPv4 address.
59  */
60 class EC_IPv4_t {
61 	public:
EC_IPv4_t()62 		EC_IPv4_t() { }
EC_IPv4_t(uint32 ip,uint16 port)63 		EC_IPv4_t(uint32 ip, uint16 port)
64 		{
65 			m_ip[0] = ip & 0xff;
66 			m_ip[1] = (ip >> 8) & 0xff;
67 			m_ip[2] = (ip >> 16) & 0xff;
68 			m_ip[3] = (ip >> 24) & 0xff;
69 			m_port = port;
70 		}
71 
IP()72 		uint32 IP()
73 		{
74 			return m_ip[0] | (m_ip[1] << 8) | (m_ip[2] << 16) | (m_ip[3] << 24);
75 		}
76 
77 		std::string StringIPSTL(bool brackets = true)
78 		{
79 			std::ostringstream string_ip;
80 			if (brackets) string_ip << "[";
81 			string_ip << (int)m_ip[0] << "." << (int)m_ip[1] << "." << (int)m_ip[2] << "." << (int)m_ip[3] << ":" << m_port;
82 			if (brackets) string_ip << "]";
83 			return string_ip.str();
84 		}
85 
86 		#ifdef USE_WX_EXTENSIONS
87 		wxString StringIP(bool brackets = true) {
88 			return char2unicode(StringIPSTL(brackets).c_str());
89 		}
90 		#endif
91 
92 		uint8 m_ip[4];
93 		uint16 m_port;
94 };
95 
96 
97 /**
98  * High level EC packet TAGs handler class
99  */
100 
101 class CECTag {
102 	public:
103 		CECTag(ec_tagname_t name, unsigned int length, const void *data);
104 		// tag for custom data: just init object, alloc buffer and return pointer
105 		CECTag(ec_tagname_t name, unsigned int length, void **dataptr);
106 		// Routines for special data types.
107 		CECTag(ec_tagname_t name, bool data);
108 		CECTag(ec_tagname_t name, uint8_t data);
109 		CECTag(ec_tagname_t name, uint16_t data);
110 		CECTag(ec_tagname_t name, uint32_t data);
111 		CECTag(ec_tagname_t name, uint64_t data);
112 		CECTag(ec_tagname_t name, double data);
113 		CECTag(ec_tagname_t name, const std::string& data);
114 		CECTag(ec_tagname_t name, const EC_IPv4_t& data);
115 		CECTag(ec_tagname_t name, const CMD4Hash& data);
116 		CECTag(ec_tagname_t name, const CUInt128& data);
117 		#ifdef USE_WX_EXTENSIONS
118 		CECTag(ec_tagname_t name, const wxString& data);
119 		CECTag(ec_tagname_t name, const wxChar* data);
120 		#endif
CECTag(ec_tagname_t name,const char * data)121 		CECTag(ec_tagname_t name, const char* data) { ConstructStringTag(name, data); }
122 		CECTag();
123 		CECTag(const CECTag& tag);
124 		~CECTag(void);
125 
126 		CECTag&		operator=(const CECTag& rhs);
127 		bool		operator==(const CECTag& tag) const;
128 		bool		operator!=(const CECTag& tag) const	{ return !(*this == tag); }
129 		bool		AddTag(const CECTag& tag, CValueMap* valuemap = NULL);
130 		void		AddTag(ec_tagname_t name, uint64_t data, CValueMap* valuemap = NULL);
131 		void		AddTag(ec_tagname_t name, const CMD4Hash& data, CValueMap* valuemap);
132 		void		AddTag(ec_tagname_t name, const CUInt128& data, CValueMap* valuemap);
133 		#ifdef USE_WX_EXTENSIONS
134 		void		AddTag(ec_tagname_t name, const wxString& data, CValueMap* valuemap = NULL);
135 		#endif
136 
GetFirstTagSafe()137 		const CECTag*	GetFirstTagSafe() const { return m_tagList.empty() ? &s_theNullTag : & *m_tagList.begin(); }
138 
139 		const CECTag*	GetTagByName(ec_tagname_t name) const;
140 		CECTag*			GetTagByName(ec_tagname_t name);
141 		const CECTag*	GetTagByNameSafe(ec_tagname_t name) const;
142 
GetTagCount()143 		size_t			GetTagCount() const { return m_tagList.size(); }
HasChildTags()144 		bool			HasChildTags() const { return !m_tagList.empty(); }
GetTagData()145 		const void *	GetTagData() const {
146 			EC_ASSERT(m_dataType == EC_TAGTYPE_CUSTOM);
147 			return m_tagData;
148 		}
GetTagDataLen()149 		uint16_t		GetTagDataLen() const { return m_dataLen; }
150 		uint32_t		GetTagLen() const;
GetTagName()151 		ec_tagname_t		GetTagName() const { return m_tagName; }
152 
153 		// Retrieving special data types
154 		uint64_t		GetInt() const;
IsInt()155 		bool			IsInt() const { return m_dataType >= EC_TAGTYPE_UINT8 && m_dataType <= EC_TAGTYPE_UINT64; }
156 		double			GetDoubleData() const;
157 		std::string		GetStringDataSTL() const;
IsString()158 		bool			IsString() const { return m_dataType == EC_TAGTYPE_STRING; }
159 
160 		#ifdef USE_WX_EXTENSIONS
161 		wxString GetStringData() const;
162 		void SetStringData(const wxString& s);
163 		#endif
164 
165 		EC_IPv4_t	GetIPv4Data() const;
166 		CMD4Hash	GetMD4Data() const;
167 		CUInt128	GetInt128Data() const;
168 
169 		void		DebugPrint(int level, bool print_empty) const;
170 		void		swap(CECTag & t);
171 
172 		// If tag exists, return its value and store it in target (if target != NULL)
173 		// Else return safe value and don't touch target
174 		// Allows for one function for old and new style.
175 		bool		AssignIfExist(ec_tagname_t tagname, bool *target) const;
176 		uint8_t		AssignIfExist(ec_tagname_t tagname, uint8_t *target) const;
177 		uint16_t	AssignIfExist(ec_tagname_t tagname, uint16_t *target) const;
178 		uint32_t	AssignIfExist(ec_tagname_t tagname, uint32_t *target) const;
179 		uint64_t	AssignIfExist(ec_tagname_t tagname, uint64_t *target) const;
180 		time_t		AssignIfExist(ec_tagname_t tagname, time_t *target) const;
181 		double		AssignIfExist(ec_tagname_t tagname, double *target) const;
182 		float		AssignIfExist(ec_tagname_t tagname, float *target) const;
183 		CMD4Hash	AssignIfExist(ec_tagname_t tagname, CMD4Hash *target) const;
184 		CUInt128	AssignIfExist(ec_tagname_t tagname, CUInt128 *target) const;
185 		std::string	AssignIfExist(ec_tagname_t tagname, std::string *target) const;
186 		#ifdef USE_WX_EXTENSIONS
187 		wxString	AssignIfExist(ec_tagname_t tagname, wxString *target) const;
188 		#endif
189 
190 		// If tag exists, return true and store it in target
191 		// Else return false and don't touch target
192 		bool		AssignIfExist(ec_tagname_t tagname, bool &target) const;
193 		bool		AssignIfExist(ec_tagname_t tagname, uint8_t &target) const;
194 		bool		AssignIfExist(ec_tagname_t tagname, uint16_t &target) const;
195 		bool		AssignIfExist(ec_tagname_t tagname, uint32_t &target) const;
196 		bool		AssignIfExist(ec_tagname_t tagname, uint64_t &target) const;
197 		bool		AssignIfExist(ec_tagname_t tagname, time_t &target) const;
198 		bool		AssignIfExist(ec_tagname_t tagname, double &target) const;
199 		bool		AssignIfExist(ec_tagname_t tagname, float &target) const;
200 		bool		AssignIfExist(ec_tagname_t tagname, CMD4Hash &target) const;
201 		bool		AssignIfExist(ec_tagname_t tagname, CUInt128 &target) const;
202 		bool		AssignIfExist(ec_tagname_t tagname, std::string &target) const;
203 		#ifdef USE_WX_EXTENSIONS
204 		bool		AssignIfExist(ec_tagname_t tagname, wxString &target) const;
205 		#endif
206 
207 	protected:
208 
GetType()209 		uint8_t GetType() const { return m_dataType; }
210 
211 		bool		ReadFromSocket(CECSocket& socket);
212 		bool		WriteTag(CECSocket& socket) const;
213 		bool		ReadChildren(CECSocket& socket);
214 		bool		WriteChildren(CECSocket& socket) const;
215 
216 	private:
217 		// To init. the automatic int data
218 		void InitInt(uint64_t data);
219 
220 		ec_tagname_t	m_tagName;
221 		ec_tagtype_t	m_dataType;
222 		ec_taglen_t		m_dataLen;
223 		char *			m_tagData;
NewData()224 		void NewData()	{ m_tagData = new char[m_dataLen]; }
225 
226 		typedef std::list<CECTag> TagList;
227 		TagList m_tagList;
228 
229 		static const CECTag s_theNullTag;
230 
231 		// To be used by the string constructors.
232 		void ConstructStringTag(ec_tagname_t name, const std::string& data);
233 
234 	public:
235 		// Iteration through child tags
236 		typedef TagList::const_iterator const_iterator;
begin()237 		const_iterator begin()	const { return m_tagList.begin(); }
end()238 		const_iterator end()	const { return m_tagList.end(); }
239 };
240 
241 
242 /**
243  * An empty TAG
244  *
245  * Note, that an "empty" tag is empty because it contains no data, but it still
246  * may contain children.
247  */
248 class CECEmptyTag : public CECTag {
249 	public:
250 		CECEmptyTag(ec_tagname_t name = 0) : CECTag(name, 0, (const void *) NULL) {}
251 };
252 
253 /**
254  * An integer TAG
255  *
256  * This is just to easily overcome ctor ambiguity. It's prettier to write
257  *		CECIntTag(name, some_value)
258  * instead of
259  *		CECTag(name, (uint64)value)
260  */
261 class CECIntTag : public CECTag {
262 	public:
CECIntTag(ec_tagname_t name,uint64 data)263 		CECIntTag(ec_tagname_t name, uint64 data) : CECTag(name, data) {}
264 };
265 
266 #endif /* ECTAG_H */
267 // File_checked_for_headers
268