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