Upstream tarball 9716
[amule.git] / src / libs / ec / cpp / ECTag.h
blob78239893d7a1def403d2fb8996ceb0d476ff4351
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2008 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.
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
25 #ifndef ECTAG_H
26 #define ECTAG_H
28 #include <iostream>
29 #include <sstream>
31 // Must be first!
32 #ifdef USE_WX_EXTENSIONS
33 #include <wx/string.h> // Do_not_auto_remove
34 #include <common/StringFunctions.h>
36 #define EC_ASSERT(x) wxASSERT(x)
37 #else
38 #define EC_ASSERT(x) assert(x)
39 #endif
41 /* aMule/libcommon generic includes */
42 #include "../../../MD4Hash.h" // Needed for CMD4Hash
44 /* EC specific includes */
45 #include "ECCodes.h" // Needed for EC types
46 #include "ECTagTypes.h" // Needed for TagTypes
49 class CECSocket;
50 class CValueMap;
52 /**
53 * Class to hold IPv4 address.
55 class EC_IPv4_t {
56 public:
57 EC_IPv4_t() { }
58 EC_IPv4_t(uint32 ip, uint16 port)
60 m_ip[0] = ip & 0xff;
61 m_ip[1] = (ip >> 8) & 0xff;
62 m_ip[2] = (ip >> 16) & 0xff;
63 m_ip[3] = (ip >> 24) & 0xff;
64 m_port = port;
67 uint32 IP()
69 return m_ip[0] | (m_ip[1] << 8) | (m_ip[2] << 16) | (m_ip[3] << 24);
72 std::string StringIPSTL(bool brackets = true)
74 std::ostringstream string_ip;
75 if (brackets) string_ip << "[";
76 string_ip << (int)m_ip[0] << "." << (int)m_ip[1] << "." << (int)m_ip[2] << "." << (int)m_ip[3] << ":" << m_port;
77 if (brackets) string_ip << "]";
78 return string_ip.str();
81 #ifdef USE_WX_EXTENSIONS
82 wxString StringIP(bool brackets = true) {
83 return char2unicode(StringIPSTL(brackets).c_str());
85 #endif
87 uint8 m_ip[4];
88 uint16 m_port;
92 /**
93 * High level EC packet TAGs handler class
96 class CECTag {
97 public:
98 CECTag(ec_tagname_t name, unsigned int length, const void *data, bool copy = true);
99 // tag for custom data: just init object, alloc buffer and return pointer
100 CECTag(ec_tagname_t name, unsigned int length, void **dataptr);
101 // Routines for special data types.
102 CECTag(ec_tagname_t name, bool data);
103 CECTag(ec_tagname_t name, uint8_t data);
104 CECTag(ec_tagname_t name, uint16_t data);
105 CECTag(ec_tagname_t name, uint32_t data);
106 CECTag(ec_tagname_t name, uint64_t data);
107 CECTag(ec_tagname_t name, double data);
108 CECTag(ec_tagname_t name, const std::string& data);
109 CECTag(ec_tagname_t name, const EC_IPv4_t& data);
110 CECTag(ec_tagname_t name, const CMD4Hash& data);
111 #ifdef USE_WX_EXTENSIONS
112 CECTag(ec_tagname_t name, const wxString& data);
113 CECTag(ec_tagname_t name, const wxChar* data);
114 CECTag(ec_tagname_t name, const char* data) { ConstructStringTag(name, data); }
115 CECTag();
116 #endif
117 CECTag(const CECTag& tag);
118 ~CECTag(void);
120 CECTag& operator=(const CECTag& rhs);
121 bool operator==(const CECTag& tag) const;
122 bool operator!=(const CECTag& tag) const { return !(*this == tag); }
123 bool AddTag(const CECTag& tag, CValueMap* valuemap = NULL);
124 void AddTag(ec_tagname_t name, uint64_t data, CValueMap* valuemap = NULL);
125 #ifdef USE_WX_EXTENSIONS
126 void AddTag(ec_tagname_t name, const wxString& data, CValueMap* valuemap = NULL);
127 #endif
129 const CECTag* GetTagByIndex(size_t index) const
130 { return ((index >= m_tagList.size()) ? NULL : &m_tagList[index]); }
131 CECTag* GetTagByIndex(size_t index)
132 { return ((index >= m_tagList.size()) ? NULL : &m_tagList[index]); }
133 const CECTag* GetTagByIndexSafe(size_t index) const
134 { const CECTag* result = GetTagByIndex(index); return result ? result : &s_theNullTag; }
136 const CECTag* GetTagByName(ec_tagname_t name) const;
137 CECTag* GetTagByName(ec_tagname_t name);
138 const CECTag* GetTagByNameSafe(ec_tagname_t name) const;
140 size_t GetTagCount(void) const { return m_tagList.size(); }
141 const void * GetTagData(void) const {
142 EC_ASSERT(m_dataType == EC_TAGTYPE_CUSTOM);
143 return m_tagData;
145 uint16_t GetTagDataLen() const { return m_dataLen; }
146 uint32_t GetTagLen() const;
147 ec_tagname_t GetTagName() const { return m_tagName; }
149 // Retrieving special data types
150 uint64_t GetInt() const;
151 double GetDoubleData() const;
152 std::string GetStringDataSTL() const;
153 bool IsString() const { return m_dataType == EC_TAGTYPE_STRING; }
155 #ifdef USE_WX_EXTENSIONS
156 wxString GetStringData() const;
157 #endif
159 EC_IPv4_t GetIPv4Data() const;
160 CMD4Hash GetMD4Data() const;
162 void DebugPrint(int level, bool print_empty) const;
164 bool AssignIfExist(ec_tagname_t tagname, bool *target) const
166 bool ret = false;
167 const CECTag *tag = GetTagByName(tagname);
168 if (tag) {
169 ret = tag->GetInt() > 0;
170 if (target) {
171 *target = ret;
174 return ret;
177 uint8_t AssignIfExist(ec_tagname_t tagname, uint8_t *target) const
179 uint8_t ret = 0;
180 const CECTag *tag = GetTagByName(tagname);
181 if (tag) {
182 EC_ASSERT((tag->GetType() == EC_TAGTYPE_UINT8) || (m_dataType == EC_TAGTYPE_UNKNOWN));
183 ret = tag->GetInt();
184 if (target) {
185 *target = ret;
188 return ret;
191 uint16_t AssignIfExist(ec_tagname_t tagname, uint16_t *target) const
193 uint16_t ret = 0;
194 const CECTag *tag = GetTagByName(tagname);
195 if (tag) {
196 EC_ASSERT(
197 (tag->GetType() == EC_TAGTYPE_UINT16)
198 || (tag->GetType() == EC_TAGTYPE_UINT8)
199 || (m_dataType == EC_TAGTYPE_UNKNOWN)
201 ret = tag->GetInt();
202 if (target) {
203 *target = ret;
206 return ret;
209 uint32_t AssignIfExist(ec_tagname_t tagname, uint32_t *target) const
211 uint32_t ret = 0;
212 const CECTag *tag = GetTagByName(tagname);
213 if (tag) {
214 EC_ASSERT(
215 (tag->GetType() == EC_TAGTYPE_UINT32)
216 || (tag->GetType() == EC_TAGTYPE_UINT16)
217 || (tag->GetType() == EC_TAGTYPE_UINT8)
218 || (m_dataType == EC_TAGTYPE_UNKNOWN)
220 ret = tag->GetInt();
221 if (target) {
222 *target = ret;
225 return ret;
228 uint64_t AssignIfExist(ec_tagname_t tagname, uint64_t *target) const
230 uint64_t ret = 0;
231 const CECTag *tag = GetTagByName(tagname);
232 if (tag) {
233 ret = tag->GetInt();
234 if (target) {
235 *target = ret;
238 return ret;
241 time_t AssignIfExist(ec_tagname_t tagname, time_t *target) const
243 time_t ret = 0;
244 const CECTag *tag = GetTagByName(tagname);
245 if (tag) {
246 ret = tag->GetInt();
247 if (target) {
248 *target = ret;
251 return ret;
254 double AssignIfExist(ec_tagname_t tagname, double *target) const
256 double ret = 0.0;
257 const CECTag *tag = GetTagByName(tagname);
258 if (tag) {
259 ret = tag->GetDoubleData();
260 if (target) {
261 *target = ret;
264 return ret;
267 CMD4Hash AssignIfExist(ec_tagname_t tagname, CMD4Hash *target) const
269 CMD4Hash ret;
270 const CECTag *tag = GetTagByName(tagname);
271 if (tag) {
272 ret = tag->GetMD4Data();
273 if (target) {
274 *target = ret;
277 return ret;
280 std::string AssignIfExist(ec_tagname_t tagname, std::string *target) const
282 std::string ret;
283 const CECTag *tag = GetTagByName(tagname);
284 if (tag) {
285 ret = tag->GetStringDataSTL();
286 if (target) {
287 *target = ret;
290 return ret;
293 #ifdef USE_WX_EXTENSIONS
294 wxString AssignIfExist(ec_tagname_t tagname, wxString *target) const
296 wxString ret;
297 const CECTag *tag = GetTagByName(tagname);
298 if (tag) {
299 ret = tag->GetStringData();
300 if (target) {
301 *target = ret;
304 return ret;
306 #endif
308 protected:
310 uint8_t GetType() const { return m_dataType; }
312 enum BuildState {
313 bsName,
314 bsType,
315 bsLength,
316 bsLengthChld,
317 bsChildCnt,
318 bsChildren,
319 bsData1,
320 bsData2,
321 bsFinished
324 CECTag(const CECSocket&)
325 : m_error(0), m_tagData(NULL), m_state(bsName), m_dataLen(0), m_dataType(EC_TAGTYPE_UNKNOWN), m_dynamic(true), m_haschildren(false)
328 bool ReadFromSocket(CECSocket& socket);
329 bool WriteTag(CECSocket& socket) const;
330 bool ReadChildren(CECSocket& socket);
331 bool WriteChildren(CECSocket& socket) const;
332 int m_error;
333 const void * m_tagData;
335 BuildState m_state;
337 bool IsOk() const { return m_state == bsFinished; }
339 private:
340 // To init. the automatic int data
341 void InitInt(uint64_t data);
343 ec_tagname_t m_tagName;
344 ec_taglen_t m_dataLen;
345 mutable ec_tagtype_t m_dataType;
346 bool m_dynamic;
348 typedef std::vector<CECTag> TagList;
349 TagList m_tagList;
351 bool m_haschildren;
353 static const CECTag s_theNullTag;
354 static const uint32_t s_theNullTagData[4];
356 // To be used by the string constructors.
357 void ConstructStringTag(ec_tagname_t name, const std::string& data);
362 * An empty TAG
364 * Note, that an "empty" tag is empty because it contains no data, but it still
365 * may contain children.
367 class CECEmptyTag : public CECTag {
368 public:
369 CECEmptyTag(ec_tagname_t name) : CECTag(name, 0, NULL, false) {}
370 protected:
371 CECEmptyTag(const CECSocket& socket) : CECTag(socket) {}
374 #endif /* ECTAG_H */
375 // File_checked_for_headers