From edfe3b2760268ec3c174a94733c355a9d0266134 Mon Sep 17 00:00:00 2001 From: oana Date: Tue, 1 Nov 2011 08:49:08 +0000 Subject: [PATCH] Added class for encoding and decoding ASN.1 tags. git-svn-id: http://voip.null.ro/svn/yate@4668 acf43c95-373e-0410-b603-e72c3f656dc1 --- libs/yasn/asn.cpp | 65 +++++++++++++++++++ libs/yasn/yateasn.h | 155 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+) diff --git a/libs/yasn/asn.cpp b/libs/yasn/asn.cpp index a0ec42f9..33d6d151 100644 --- a/libs/yasn/asn.cpp +++ b/libs/yasn/asn.cpp @@ -1186,6 +1186,71 @@ int ASNLib::encodeSet(DataBlock& data, bool tagCheck) return len.length(); } +/** + * AsnTag + */ +void AsnTag::decode(AsnTag& tag, DataBlock& data) +{ + XDebug(s_libName.c_str(),DebugAll,"AsnTag::decode()"); + tag.classType((Class)(data[0] & 0xc0)); + tag.type((Type)(data[0] & 0x20)); + + unsigned int code = 0; + code |= data[0] & 0x1f; + unsigned int len = 1; + if (IS_EXTENSION_ID(code) && data.length() >= 2) { // extended tag + code = 0; + while (len < data.length() && (data[len] & ASN_BIT8) == ASN_BIT8) { + code = code << 8; + code |= (data[len] & 0x7f); + len++; + } + code |= data[len] & 0x7f; + } + tag.code(code); + tag.encode(); +} + +void AsnTag::encode(Class clas, Type type, unsigned int code, DataBlock& data) +{ + XDebug(s_libName.c_str(),DebugAll,"AsnTag::encode(clas=0x%x, type=0x%x, code=%u)",clas,type,code); + if (code < 31) { + u_int8_t tag = clas | type | code; + data.insert(DataBlock(&tag,sizeof(tag))); + } + else { + u_int8_t last = clas | type | 31; + data.append(&last,sizeof(last)); + int size = sizeof(unsigned int); + bool start = false; + while (size > 1) { + u_int8_t msb = (code >> ((size - 1) * 8)); + if (start) { + msb |= 0x80; + data.append(&msb,sizeof(msb)); + } + else { + if (msb == 0) { + size--; + continue; + } + else { + start = true; + msb |= 0x80; + data.append(&msb,sizeof(msb)); + } + } + size--; + } + last = code; + data.append(&last,sizeof(last)); + } +#ifdef XDEBUG + String str; + str.hexify(data.data(),data.length(),' '); + XDebug(s_libName.c_str(),DebugAll,"AsnTag::encode(clas=0x%x, type=0x%x, code=%u) tag=%s",clas,type,code,str.c_str()); +#endif +} /** * ASNObjId diff --git a/libs/yasn/yateasn.h b/libs/yasn/yateasn.h index 628dcd06..4b2799ea 100644 --- a/libs/yasn/yateasn.h +++ b/libs/yasn/yateasn.h @@ -539,6 +539,161 @@ private: DataBlock m_ids; }; +/** + * Class AsnTag + * @short Class for ASN.1 tags + */ +class AsnTag { +public: + /** + * ASN.1 Tag class types enum + */ + enum Class { + Universal = 0x00, + Application = 0x40, + Context = 0x80, + Private = 0xc0, + }; + + /** + * ASN.1 Type of tag enum + */ + enum Type { + Primitive = 0x00, + Constructor = 0x20, + }; + + /** + * Constructor + */ + inline AsnTag() + : m_class(Universal), m_type(Primitive), m_code(0) + { } + + /** + * Constructor + * @param clas Class of the ASN.1 Tag + * @param type Type of the ASN.1 Tag + * @param code Code ot the ASN.1 Tag + */ + inline AsnTag(Class clas, Type type, unsigned int code) + : m_class(clas), m_type(type), m_code(code) + { + encode(); + } + + /** + * Destructor + */ + inline ~AsnTag() + {} + + /** + * Decode an ASN.1 tag from the given data + * @param tag Tag to fill + * @param data Data from which the tag should be filled + */ + static void decode(AsnTag& tag, DataBlock& data); + + /** + * Encode an ASN.1 tag and put the encoded form into the given data + * @param clas Class of the tag + * @param type Type of the tag + * @param code Tag code + * @param data DataBlock into which to insert the encoded tag + */ + static void encode(Class clas, Type type, unsigned int code, DataBlock& data); + + /** + * Encode self + */ + inline void encode() + { AsnTag::encode(m_class,m_type,m_code,m_coding); } + + /** + * Equality operator + */ + inline bool operator==(const AsnTag& tag) const + { + return (m_class == tag.classType() && m_type == tag.type() && m_code == tag.code()); + } + + /** + * Inequality operator + */ + inline bool operator!=(const AsnTag& tag) const + { + return !(m_class == tag.classType() && m_type == tag.type() && m_code == tag.code()); + } + + /** + * Assignment operator + */ + inline AsnTag& operator=(const AsnTag& value) + { + m_class = value.classType(); + m_type = value.type(); + m_code = value.code(); + encode(); + return *this; + } + + /** + * Get the tag class + * @return The class of the tag + */ + inline const Class classType() const + { return m_class; } + + /** + * Set the tag class + * @param clas The clas to set for the tag + */ + inline void classType(Class clas) + { m_class = clas; } + + /** + * Get the tag type + * @return The type of the tag + */ + inline const Type type() const + { return m_type; } + + /** + * Set the tag type + * @param type The type to set for the tag + */ + inline void type(Type type) + { m_type = type; } + + /** + * Get the tag code + * @return The code of the tag + */ + inline const unsigned int code() const + { return m_code; } + + /** + * Set the tag code + * @param code The code to set for the tag + */ + inline void code(unsigned int code) + { m_code = code; } + + /** + * Get the tag encoding + * @return The DataBlock containing the encoding for the tag + */ + inline const DataBlock& coding() const + { return m_coding; } + +private: + Class m_class; + Type m_type; + unsigned int m_code; + DataBlock m_coding; +}; + /** * Class ASNLib * @short Class containing functions for decoding/encoding ASN.1 basic data types