// // This file is part of the aMule Project. // // Copyright (c) 2004-2006 aMule Team ( admin@amule.org / http://www.amule.org ) // // Any parts of this program derived from the xMule, lMule or eMule project, // or contributed by third-party developers are copyrighted by their // respective authors. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // #ifndef ECPACKET_H #define ECPACKET_H #include // Needed for wxString #include // Needed for aMuleConv define #include "Types.h" // Needed for uint* types #include "MD4Hash.h" // Needed for CMD4Hash #include "ArchSpecific.h" // Needed for ENDIAN_NTOHL #include "ECCodes.h" // Needed for EC types #include // Define this to keep partial packets // (those that had an error upon reception/creation) #undef KEEP_PARTIAL_PACKETS /** * Class to hold IPv4 address. */ class EC_IPv4_t { public: EC_IPv4_t() { } EC_IPv4_t(uint32 ip, uint16 port) { m_ip[0] = ip & 0xff; m_ip[1] = (ip >> 8) & 0xff; m_ip[2] = (ip >> 16) & 0xff; m_ip[3] = (ip >> 24) & 0xff; m_port = port; } uint32 IP() { return m_ip[0] | (m_ip[1] << 8) | (m_ip[2] << 16) | (m_ip[3] << 24); } wxString StringIP(bool brackets = true) { return wxString::Format(brackets ? wxT("[%d.%d.%d.%d:%d]") : wxT("%d.%d.%d.%d : %d"), m_ip[0], m_ip[1], m_ip[2], m_ip[3], m_port); } uint8 m_ip[4]; uint16 m_port; }; class CECTag; class CECSocket; class wxSocketBase; /** * High level EC packet TAGs handler class */ class CECTag { public: CECTag(ec_tagname_t name, unsigned int length, const void *data, bool copy = true); // tag for custom data: just init object, alloc buffer and return pointer CECTag(ec_tagname_t name, unsigned int length, void **dataptr); // Routines for special data types. CECTag(ec_tagname_t name, uint8 data); CECTag(ec_tagname_t name, uint16 data); CECTag(ec_tagname_t name, uint32 data); CECTag(ec_tagname_t name, uint64 data); CECTag(ec_tagname_t name, double data); CECTag(ec_tagname_t name, const wxString& data); CECTag(ec_tagname_t name, const EC_IPv4_t& data); CECTag(ec_tagname_t name, const CMD4Hash& data); CECTag(const CECTag& tag); ~CECTag(void); CECTag& operator=(const CECTag& rhs); bool AddTag(const CECTag& tag); const CECTag* GetTagByIndex(unsigned int index) const { return ((index >= m_tagList.size()) ? NULL : &m_tagList[index]); } CECTag* GetTagByIndex(unsigned int index) { return ((index >= m_tagList.size()) ? NULL : &m_tagList[index]); } const CECTag* GetTagByIndexSafe(unsigned int index) const { const CECTag* result = GetTagByIndex(index); return result ? result : &s_theNullTag; } const CECTag* GetTagByName(ec_tagname_t name) const; CECTag* GetTagByName(ec_tagname_t name); const CECTag* GetTagByNameSafe(ec_tagname_t name) const; uint16 GetTagCount(void) const { return m_tagList.size(); } const void * GetTagData(void) const { return m_tagData; } uint16 GetTagDataLen(void) const { return m_dataLen; } uint32 GetTagLen(void) const; ec_tagname_t GetTagName(void) const { return m_tagName; } // Retrieving special data types uint8 GetInt8Data(void) const { return PeekUInt8(m_tagData); } uint16 GetInt16Data(void) const { return ENDIAN_NTOHS( RawPeekUInt16( m_tagData ) ); } uint32 GetInt32Data(void) const { return ENDIAN_NTOHL( RawPeekUInt32( m_tagData ) ); } uint64 GetInt64Data(void) const { uint32 high = ENDIAN_NTOHL(RawPeekUInt32(m_tagData)); uint32 low = ENDIAN_NTOHL(RawPeekUInt32(((unsigned char *)m_tagData)+sizeof(uint32))); return low | (((uint64)high) << 32); } double GetDoubleData(void) const; wxString GetStringData(void) const { return wxString(wxConvUTF8.cMB2WC((const char *)m_tagData), aMuleConv); } EC_IPv4_t GetIPv4Data(void) const; CMD4Hash GetMD4Data(void) const { return CMD4Hash((const unsigned char *)m_tagData); } void AssignIfExist(ec_tagname_t tagname, uint8 &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetInt8Data(); } void AssignIfExist(ec_tagname_t tagname, uint16 &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetInt16Data(); } void AssignIfExist(ec_tagname_t tagname, uint32 &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetInt32Data(); } void AssignIfExist(ec_tagname_t tagname, uint64 &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetInt64Data(); } void AssignIfExist(ec_tagname_t tagname, double &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetDoubleData(); } void AssignIfExist(ec_tagname_t tagname, CMD4Hash &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetMD4Data(); } void AssignIfExist(ec_tagname_t tagname, wxString &target) { CECTag *tag = GetTagByName(tagname); if ( tag ) target = tag->GetStringData(); } protected: enum BuildState { bsName, bsLength, bsLengthChld, bsChildCnt, bsChildren, bsData1, bsData2, bsFinished }; CECTag(const CECSocket&) : m_error(0), m_tagData(NULL), m_state(bsName), m_dataLen(0), m_dynamic(true) {} bool ReadFromSocket(CECSocket& socket); bool WriteTag(CECSocket& socket) const; bool ReadChildren(CECSocket& socket); bool WriteChildren(CECSocket& socket) const; int m_error; const void * m_tagData; BuildState m_state; bool IsOk() const { return m_state == bsFinished; } private: // Special type used to invoke the Null tag constructor struct NullTagConstructorSelector { }; // Special constructor to construct the Null tag. explicit CECTag(const NullTagConstructorSelector*); ec_tagname_t m_tagName; unsigned int m_dataLen; bool m_dynamic; typedef std::vector TagList; TagList m_tagList; static const CECTag s_theNullTag; static const uint32 s_theNullTagData[4]; }; /** * An empty TAG * * Note, that an "empty" tag is empty because it contains no data, but it still * may contain children. */ class CECEmptyTag : public CECTag { public: CECEmptyTag(ec_tagname_t name) : CECTag(name, 0, NULL, false) {} protected: CECEmptyTag(const CECSocket& socket) : CECTag(socket) {} }; /** * High level EC packet handler class */ class CECPacket : protected CECEmptyTag { friend class CECSocket; public: CECPacket(ec_opcode_t opCode, EC_DETAIL_LEVEL detail_level = EC_DETAIL_FULL) : CECEmptyTag(0), m_opCode(opCode) { // since EC_DETAIL_FULL is default - no point transmit it if ( detail_level != EC_DETAIL_FULL ) { AddTag(CECTag(EC_TAG_DETAIL_LEVEL, (uint8)detail_level)); } } CECTag::AddTag; CECTag::GetTagByIndex; CECTag::GetTagByIndexSafe; CECTag::GetTagByName; CECTag::GetTagByNameSafe; CECTag::GetTagCount; ec_opcode_t GetOpCode(void) const { return m_opCode; } uint32 GetPacketLength(void) const { return CECTag::GetTagLen(); } EC_DETAIL_LEVEL GetDetailLevel() const { const CECTag *tag = GetTagByName(EC_TAG_DETAIL_LEVEL); return (tag) ? (EC_DETAIL_LEVEL)tag->GetInt8Data() : EC_DETAIL_FULL; } private: CECPacket(const CECSocket& socket) : CECEmptyTag(socket) {} bool ReadFromSocket(CECSocket& socket); bool WritePacket(CECSocket& socket) const; ec_opcode_t m_opCode; }; #endif /* ECPACKET_H */