2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
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
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.
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
26 #define DEBUG_EC_IMPLEMENTATION
28 #include <common/Format.h> // Needed for CFormat
31 #include "ECTag.h" // Needed for ECTag
32 #include "ECSocket.h" // Needed for CECSocket
33 #include "ECSpecialTags.h" // Needed for CValueMap
35 /**********************************************************
39 **********************************************************/
41 //! Defines the Null tag which may be returned by GetTagByNameSafe.
42 const CECTag
CECTag::s_theNullTag
;
45 * Creates a new null-valued CECTag instance
48 * @see GetTagByNameSafe
52 m_dataType(EC_TAGTYPE_UNKNOWN
),
54 m_tagData(NULL
) // All access functions check m_dataType, so no need to allocate a dummy buffer.
59 * Creates a new CECTag instance from the given data
61 * @param name TAG name
62 * @param length length of data buffer
63 * @param data TAG data
66 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, const void *data
) : m_tagName(name
)
71 memcpy(m_tagData
, data
, m_dataLen
);
75 m_dataType
= EC_TAGTYPE_CUSTOM
;
79 * Creates a new CECTag instance for custom data
81 * @param name TAG name
82 * @param length length of data buffer that will be alloc'ed
83 * @param dataptr pointer to a void pointer which will be assigned the internal TAG data buffer
85 * \note TAG data buffer has to be filled with valid data after the ctor
87 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, void **dataptr
) : m_tagName(name
)
92 m_dataType
= EC_TAGTYPE_CUSTOM
;
96 * Creates a new CECTag instance, which contains an IPv4 address.
98 * This function takes care of the endianness of the port number.
100 * @param name TAG name
101 * @param data The EC_IPv4_t class containing the IPv4 address.
105 CECTag::CECTag(ec_tagname_t name
, const EC_IPv4_t
& data
) : m_tagName(name
)
108 m_dataLen
= sizeof(EC_IPv4_t
);
110 RawPokeUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
, RawPeekUInt32( data
.m_ip
) );
111 ((EC_IPv4_t
*)m_tagData
)->m_port
= ENDIAN_HTONS(data
.m_port
);
112 m_dataType
= EC_TAGTYPE_IPV4
;
116 * Creates a new CECTag instance, which contains a MD4 hash.
118 * This function takes care to store hash in network byte order.
120 * @param name TAG name
121 * @param data The CMD4Hash class containing the MD4 hash.
125 CECTag::CECTag(ec_tagname_t name
, const CMD4Hash
& data
) : m_tagName(name
)
129 RawPokeUInt64( m_tagData
, RawPeekUInt64( data
.GetHash() ) );
130 RawPokeUInt64( m_tagData
+ 8, RawPeekUInt64( data
.GetHash() + 8 ) );
131 m_dataType
= EC_TAGTYPE_HASH16
;
135 * Creates a new CECTag instance, which contains a string
137 * @param name TAG name
138 * @param data wxString object, it's contents are converted to UTF-8.
140 * @see GetStringDataSTL()
142 CECTag::CECTag(ec_tagname_t name
, const std::string
& data
) : m_tagName(name
)
144 ConstructStringTag(name
, data
);
148 * Creates a new CECTag instance, which contains a string
150 * @param name TAG name
151 * @param data wxString object, it's contents are converted to UTF-8.
153 * @see GetStringData()
155 CECTag::CECTag(ec_tagname_t name
, const wxString
& data
) : m_tagName(name
)
157 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
159 CECTag::CECTag(ec_tagname_t name
, const wxChar
* data
) : m_tagName(name
)
161 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
167 CECTag::CECTag(const CECTag
& tag
)
173 * Creates a new CECTag instance, which contains an int value.
175 * This takes care of endianness problems with numbers.
177 * @param name TAG name.
178 * @param data number.
182 CECTag::CECTag(ec_tagname_t name
, bool data
) : m_tagName(name
)
186 CECTag::CECTag(ec_tagname_t name
, uint8 data
) : m_tagName(name
)
190 CECTag::CECTag(ec_tagname_t name
, uint16 data
) : m_tagName(name
)
194 CECTag::CECTag(ec_tagname_t name
, uint32 data
) : m_tagName(name
)
198 CECTag::CECTag(ec_tagname_t name
, uint64 data
) : m_tagName(name
)
203 void CECTag::InitInt(uint64 data
)
206 m_dataType
= EC_TAGTYPE_UINT8
;
208 } else if (data
<= 0xFFFF) {
209 m_dataType
= EC_TAGTYPE_UINT16
;
211 } else if (data
<= 0xFFFFFFFF) {
212 m_dataType
= EC_TAGTYPE_UINT32
;
215 m_dataType
= EC_TAGTYPE_UINT64
;
221 switch (m_dataType
) {
222 case EC_TAGTYPE_UINT8
:
223 PokeUInt8( m_tagData
, (uint8
) data
);
225 case EC_TAGTYPE_UINT16
:
226 PokeUInt16( m_tagData
, wxUINT16_SWAP_ALWAYS((uint16
) data
));
228 case EC_TAGTYPE_UINT32
:
229 PokeUInt32( m_tagData
, wxUINT32_SWAP_ALWAYS((uint32
) data
));
231 case EC_TAGTYPE_UINT64
:
232 PokeUInt64( m_tagData
, wxUINT64_SWAP_ALWAYS(data
) );
238 * Creates a new CECTag instance, which contains a double precision floating point number
240 * @param name TAG name
241 * @param data double number
243 * @note The actual data is converted to string representation, because we have not found
244 * yet an effective and safe way to transmit floating point numbers.
246 * @see GetDoubleData()
248 CECTag::CECTag(ec_tagname_t name
, double data
) : m_tagName(name
)
250 std::ostringstream double_str
;
252 const char * double_chr
= double_str
.str().c_str();
253 m_dataLen
= (ec_taglen_t
)strlen(double_chr
) + 1;
255 memcpy(m_tagData
, double_chr
, m_dataLen
);
256 m_dataType
= EC_TAGTYPE_DOUBLE
;
260 * Destructor - frees allocated data and deletes child TAGs.
262 CECTag::~CECTag(void)
268 * Copy assignment operator.
270 * std::vector uses this, but the compiler-supplied version wouldn't properly
271 * handle m_dynamic and m_tagData. This wouldn't be necessary if m_tagData
272 * was a smart pointer (Hi, Kry!).
274 CECTag
& CECTag::operator=(const CECTag
& tag
)
277 m_state
= tag
.m_state
;
278 m_tagName
= tag
.m_tagName
;
279 m_dataLen
= tag
.m_dataLen
;
280 m_dataType
= tag
.m_dataType
;
281 if (m_dataLen
!= 0) {
283 memcpy(m_tagData
, tag
.m_tagData
, m_dataLen
);
288 if (!tag
.m_tagList
.empty()) {
289 m_tagList
.reserve(tag
.m_tagList
.size());
290 for (TagList::size_type i
=0; i
<tag
.m_tagList
.size(); i
++) {
291 m_tagList
.push_back(tag
.m_tagList
[i
]);
292 if (m_tagList
.back().HasError()) {
294 #ifndef KEEP_PARTIAL_PACKETS
295 m_tagList
.pop_back();
310 bool CECTag::operator==(const CECTag
& tag
) const
312 return m_dataType
== tag
.m_dataType
313 && m_tagName
== tag
.m_tagName
314 && m_dataLen
== tag
.m_dataLen
316 || !memcmp(m_tagData
, tag
.m_tagData
, m_dataLen
))
317 && m_tagList
== tag
.m_tagList
;
321 * Add a child tag to this one.
323 * Be very careful that this creates a copy of \e tag. Thus, the following code won't work as expected:
326 * CECPacket *p = new CECPacket(whatever);
327 * CECTag *t1 = new CECTag(whatever);
328 * CECTag *t2 = new CECTag(whatever);
330 * t1.AddTag(*t2); // t2 won't be part of p !!!
334 * To get the desired results, the above should be replaced with something like:
338 * CECPacket *p = new CECPacket(whatever);
339 * CECTag *t1 = new CECTag(whatever);
340 * CECTag *t2 = new CECTag(whatever);
342 * delete t2; // we can safely delete t2 here, because t1 holds a copy
344 * delete t1; // now p holds a copy of both t1 and t2
348 * Then why copying? The answer is to enable simplifying the code like this:
352 * CECPacket *p = new CECPacket(whatever);
353 * CECTag t1(whatever);
354 * t1.AddTag(CECTag(whatever)); // t2 is now created on-the-fly
355 * p.AddTag(t1); // now p holds a copy of both t1 and t2
359 * @param tag a CECTag class instance to add.
360 * @return \b true on succcess, \b false when an error occured
362 bool CECTag::AddTag(const CECTag
& tag
, CValueMap
* valuemap
)
365 return valuemap
->AddTag(tag
, this);
367 // cannot have more than 64k tags
368 wxASSERT(m_tagList
.size() < 0xffff);
370 m_tagList
.push_back(tag
);
371 if (m_tagList
.back().HasError()) {
373 #ifndef KEEP_PARTIAL_PACKETS
374 m_tagList
.pop_back();
382 void CECTag::AddTag(ec_tagname_t name
, uint64_t data
, CValueMap
* valuemap
)
385 valuemap
->CreateTag(name
, data
, this);
387 AddTag(CECTag(name
, data
));
391 void CECTag::AddTag(ec_tagname_t name
, const wxString
& data
, CValueMap
* valuemap
)
394 valuemap
->CreateTag(name
, data
, this);
396 AddTag(CECTag(name
, data
));
400 bool CECTag::ReadFromSocket(CECSocket
& socket
)
402 if (m_state
== bsName
) {
403 ec_tagname_t tmp_tagName
;
404 if (!socket
.ReadNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) {
408 m_tagName
= tmp_tagName
>> 1;
409 m_state
= (tmp_tagName
& 0x01) ? bsTypeChld
: bsType
;
413 if (m_state
== bsType
|| m_state
== bsTypeChld
) {
415 if (!socket
.ReadNumber(&type
, sizeof(ec_tagtype_t
))) {
416 m_dataType
= EC_TAGTYPE_UNKNOWN
;
420 m_state
= (m_state
== bsTypeChld
) ? bsLengthChld
: bsLength
;
424 if (m_state
== bsLength
|| m_state
== bsLengthChld
) {
426 if (!socket
.ReadNumber(&tagLen
, sizeof(ec_taglen_t
))) {
430 if (m_state
== bsLength
) {
433 m_state
= bsChildCnt
;
438 if (m_state
== bsChildCnt
|| m_state
== bsChildren
) {
439 if (!ReadChildren(socket
)) {
444 if (m_state
== bsData1
) {
445 unsigned int tmp_len
= m_dataLen
;
447 m_dataLen
= tmp_len
- GetTagLen();
453 m_state
= bsFinished
;
457 if (m_state
== bsData2
) {
458 if (m_tagData
!= NULL
) {
459 if (!socket
.ReadBuffer(m_tagData
, m_dataLen
)) {
462 m_state
= bsFinished
;
474 bool CECTag::WriteTag(CECSocket
& socket
) const
476 ec_tagname_t tmp_tagName
= (m_tagName
<< 1) | (m_tagList
.empty() ? 0 : 1);
477 ec_tagtype_t type
= m_dataType
;
478 ec_taglen_t tagLen
= GetTagLen();
479 wxASSERT(type
!= EC_TAGTYPE_UNKNOWN
);
481 if (!socket
.WriteNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) return false;
482 if (!socket
.WriteNumber(&type
, sizeof(ec_tagtype_t
))) return false;
483 if (!socket
.WriteNumber(&tagLen
, sizeof(ec_taglen_t
))) return false;
485 if (!m_tagList
.empty()) {
486 if (!WriteChildren(socket
)) return false;
490 if (m_tagData
!= NULL
) { // This is here only to make sure everything, it should not be NULL at this point
491 if (!socket
.WriteBuffer(m_tagData
, m_dataLen
)) return false;
498 bool CECTag::ReadChildren(CECSocket
& socket
)
500 if (m_state
== bsChildCnt
) {
502 if (!socket
.ReadNumber(&tmp_tagCount
, sizeof(uint16
))) {
506 if (tmp_tagCount
> 0) {
507 m_tagList
.reserve(tmp_tagCount
);
508 for (int i
=0; i
<tmp_tagCount
; i
++) {
509 m_tagList
.push_back(CECTag(socket
));
511 m_state
= bsChildren
;
518 if (m_state
== bsChildren
) {
519 for (unsigned int i
=0; i
<m_tagList
.size(); i
++) {
520 CECTag
& tag
= m_tagList
[i
];
522 if (!tag
.ReadFromSocket(socket
)) {
523 if (tag
.HasError()) {
536 bool CECTag::WriteChildren(CECSocket
& socket
) const
538 wxASSERT(m_tagList
.size() < 0xFFFF);
539 uint16 tmp
= (uint16
)m_tagList
.size();
540 if (!socket
.WriteNumber(&tmp
, sizeof(tmp
))) return false;
541 if (!m_tagList
.empty()) {
542 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++) {
543 if (!m_tagList
[i
].WriteTag(socket
)) return false;
550 * Finds the (first) child tag with given name.
552 * @param name TAG name to look for.
553 * @return the tag found, or NULL.
555 const CECTag
* CECTag::GetTagByName(ec_tagname_t name
) const
557 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++)
558 if (m_tagList
[i
].m_tagName
== name
) return &m_tagList
[i
];
563 * Finds the (first) child tag with given name.
565 * @param name TAG name to look for.
566 * @return the tag found, or NULL.
568 CECTag
* CECTag::GetTagByName(ec_tagname_t name
)
570 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++)
571 if (m_tagList
[i
].m_tagName
== name
) return &m_tagList
[i
];
576 * Finds the (first) child tag with given name.
578 * @param name TAG name to look for.
579 * @return the tag found, or a special null-valued tag otherwise.
583 const CECTag
* CECTag::GetTagByNameSafe(ec_tagname_t name
) const
585 const CECTag
* result
= GetTagByName(name
);
587 result
= &s_theNullTag
;
592 * Query TAG length that is suitable for the TAGLEN field (i.e.\
593 * without it's own header size).
595 * @return Tag length, containing its childs' length.
597 uint32
CECTag::GetTagLen(void) const
599 uint32 length
= m_dataLen
;
600 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++) {
601 length
+= m_tagList
[i
].GetTagLen();
602 length
+= sizeof(ec_tagname_t
) + sizeof(ec_tagtype_t
) + sizeof(ec_taglen_t
) + ((m_tagList
[i
].GetTagCount() > 0) ? 2 : 0);
608 uint64_t CECTag::GetInt() const
610 if (m_tagData
== NULL
) {
611 // Empty tag - This is NOT an error.
612 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
616 switch (m_dataType
) {
617 case EC_TAGTYPE_UINT8
:
618 return PeekUInt8(m_tagData
);
619 case EC_TAGTYPE_UINT16
:
620 return ENDIAN_NTOHS( RawPeekUInt16( m_tagData
) );
621 case EC_TAGTYPE_UINT32
:
622 return ENDIAN_NTOHL( RawPeekUInt32( m_tagData
) );
623 case EC_TAGTYPE_UINT64
:
624 return ENDIAN_NTOHLL( RawPeekUInt64( m_tagData
) );
625 case EC_TAGTYPE_UNKNOWN
:
626 // Empty tag - This is NOT an error.
635 std::string
CECTag::GetStringDataSTL() const
637 if (m_dataType
!= EC_TAGTYPE_STRING
) {
638 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
639 return std::string();
640 } else if (m_tagData
== NULL
) {
642 return std::string();
645 return std::string(m_tagData
);
649 #ifdef USE_WX_EXTENSIONS
650 wxString
CECTag::GetStringData() const
652 return UTF82unicode(GetStringDataSTL().c_str());
657 CMD4Hash
CECTag::GetMD4Data() const
659 if (m_dataType
!= EC_TAGTYPE_HASH16
) {
660 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
664 EC_ASSERT(m_tagData
!= NULL
);
666 // Doesn't matter if m_tagData is NULL in CMD4Hash(),
667 // that'll just result in an empty hash.
668 return CMD4Hash((const unsigned char *)m_tagData
);
673 * Returns an EC_IPv4_t class.
675 * This function takes care of the enadianness of the port number.
677 * @return EC_IPv4_t class.
679 * @see CECTag(ec_tagname_t, const EC_IPv4_t&)
681 EC_IPv4_t
CECTag::GetIPv4Data() const
685 if (m_dataType
!= EC_TAGTYPE_IPV4
) {
686 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
687 } else if (m_tagData
== NULL
) {
690 RawPokeUInt32( p
.m_ip
, RawPeekUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
) );
691 p
.m_port
= ENDIAN_NTOHS(((EC_IPv4_t
*)m_tagData
)->m_port
);
698 * Returns a double value.
700 * @note The returned value is what we get by converting the string form
701 * of the number to a double.
703 * @return The double value of the tag.
705 * @see CECTag(ec_tagname_t, double)
707 double CECTag::GetDoubleData(void) const
709 if (m_dataType
!= EC_TAGTYPE_DOUBLE
) {
710 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
712 } else if (m_tagData
== NULL
) {
717 std::istringstream
double_str(m_tagData
);
725 void CECTag::ConstructStringTag(ec_tagname_t
/*name*/, const std::string
& data
)
727 m_dataLen
= (ec_taglen_t
)strlen(data
.c_str()) + 1;
729 memcpy(m_tagData
, data
.c_str(), m_dataLen
);
730 m_dataType
= EC_TAGTYPE_STRING
;
733 void CECTag::SetStringData(const wxString
& s
)
737 ConstructStringTag(0, (const char*)unicode2UTF8(s
));
742 void CECTag::DebugPrint(int level
, bool print_empty
) const
744 if (m_dataLen
|| print_empty
) {
746 for (int i
= level
; i
--;) space
+= wxT(" ");
747 wxString s1
= CFormat(wxT("%s%s %d = ")) % space
% GetDebugNameECTagNames(m_tagName
) % m_dataLen
;
750 case EC_TAG_DETAIL_LEVEL
:
751 s2
= GetDebugNameEC_DETAIL_LEVEL(GetInt()); break;
752 case EC_TAG_SEARCH_TYPE
:
753 s2
= GetDebugNameEC_SEARCH_TYPE(GetInt()); break;
754 case EC_TAG_STAT_VALUE_TYPE
:
755 s2
= GetDebugNameEC_STATTREE_NODE_VALUE_TYPE(GetInt()); break;
757 switch (m_dataType
) {
758 case EC_TAGTYPE_UINT8
:
759 case EC_TAGTYPE_UINT16
:
760 case EC_TAGTYPE_UINT32
:
761 case EC_TAGTYPE_UINT64
:
762 s2
= CFormat(wxT("%d")) % GetInt(); break;
763 case EC_TAGTYPE_STRING
:
764 s2
= GetStringData(); break;
765 case EC_TAGTYPE_DOUBLE
:
766 s2
= CFormat(wxT("%.1f")) % GetDoubleData(); break;
767 case EC_TAGTYPE_HASH16
:
768 s2
= GetMD4Data().Encode(); break;
770 s2
= GetDebugNameECTagTypes(m_dataType
);
773 DoECLogLine(s1
+ s2
);
775 for (TagList::const_iterator it
= m_tagList
.begin(); it
!= m_tagList
.end(); ++it
) {
776 it
->DebugPrint(level
+ 1, true);
782 * \fn CMD4Hash CECTag::GetMD4Data(void) const
784 * \brief Returns a CMD4Hash class.
786 * This function takes care of converting from MSB to LSB as necessary.
788 * \return CMD4Hash class.
790 * \sa CECTag(ec_tagname_t, const CMD4Hash&)
794 * \fn CECTag *CECTag::GetTagByIndex(size_t index) const
796 * \brief Finds the indexth child tag.
798 * \param index 0-based index, 0 <= \e index < GetTagCount()
800 * \return The child tag, or NULL if index out of range.
804 * \fn CECTag *CECTag::GetTagByIndexSafe(size_t index) const
806 * \brief Finds the indexth child tag.
808 * \param index 0-based index, 0 <= \e index < GetTagCount()
810 * \return The child tag, or a special null-valued tag if index out of range.
814 * \fn size_t CECTag::GetTagCount(void) const
816 * \brief Returns the number of child tags.
818 * \return The number of child tags.
822 * \fn const void *CECTag::GetTagData(void) const
824 * \brief Returns a pointer to the TAG DATA.
826 * \return A pointer to the TAG DATA. (As specified with the data field of the constructor.)
830 * \fn uint16 CECTag::GetTagDataLen(void) const
832 * \brief Returns the length of the data buffer.
834 * \return The length of the data buffer.
838 * \fn ec_tagname_t CECTag::GetTagName(void) const
840 * \brief Returns TAGNAME.
842 * \return The name of the tag.
846 * \fn wxString CECTag::GetStringData(void) const
848 * \brief Returns the string data of the tag.
850 * Returns a wxString created from TAGDATA. It is automatically
851 * converted from UTF-8 to the internal application encoding.
852 * Should be used with care (only on tags created with the
853 * CECTag(ec_tagname_t, const wxString&) constructor),
854 * becuse it does not perform any check to see if the tag really contains a
857 * \return The string data of the tag.
859 * \sa CECTag(ec_tagname_t, const wxString&)
863 * \fn uint8 CECTag::GetInt(void) const
865 * \brief Returns the uint8 data of the tag.
867 * This function takes care of the endianness problems with numbers.
869 * \return The uint8 data of the tag.
871 * \sa CECTag(ec_tagname_t, uint8)
875 * \fn uint16 CECTag::GetInt(void) const
877 * \brief Returns the uint16 data of the tag.
879 * This function takes care of the endianness problems with numbers.
881 * \return The uint16 data of the tag.
883 * \sa CECTag(ec_tagname_t, uint16)
887 * \fn uint32 CECTag::GetInt(void) const
889 * \brief Returns the uint32 data of the tag.
891 * This function takes care of the endianness problems with numbers.
893 * \return The uint32 data of the tag.
895 * \sa CECTag(ec_tagname_t, uint32)
899 * \fn uint64 CECTag::GetInt(void) const
901 * \brief Returns the uint64 data of the tag.
903 * This function takes care of the endianness problems with numbers.
905 * \return The uint64 data of the tag.
907 * \sa CECTag(ec_tagname_t, uint64)
909 // File_checked_for_headers