pasn.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:29k
- /*
- * pasn.cxx
- *
- * ASN classes in support of the SNMP code.
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: pasn.cxx,v $
- * Revision 1.14 2000/05/05 10:08:29 robertj
- * Fixed some GNU compiler warnings
- *
- * Revision 1.13 1999/05/01 11:29:20 robertj
- * Alpha linux port changes.
- *
- * Revision 1.12 1999/05/01 03:52:20 robertj
- * Fixed various egcs warnings.
- *
- * Revision 1.11 1999/03/02 01:53:38 craigs
- * Fixed problem with creating IpAddress objects
- *
- * Revision 1.10 1999/02/16 08:08:06 robertj
- * MSVC 6.0 compatibility changes.
- *
- * Revision 1.9 1998/11/30 04:52:04 robertj
- * New directory structure
- *
- * Revision 1.8 1998/10/13 14:06:31 robertj
- * Complete rewrite of memory leak detection code.
- *
- * Revision 1.7 1998/09/23 06:22:27 robertj
- * Added open source copyright license.
- *
- * Revision 1.6 1998/02/16 06:57:05 robertj
- * Moved pragma implemenetation in here so do not need upasn.cxx file.
- *
- * Revision 1.7 1998/01/26 02:49:21 robertj
- * GNU support.
- *
- * Revision 1.6 1998/01/26 01:45:36 robertj
- * Removed unused variable.
- *
- * Revision 1.5 1997/08/20 09:00:37 craigs
- * Fixed problems with decoding of PASNNull
- *
- * Revision 1.4 1997/07/20 08:34:37 craigs
- * Added ASN NULL type
- *
- * Revision 1.3 1997/07/16 05:52:48 craigs
- * Changed ASN constructors to store value length separately so
- * ASNString consctructor will worki correctly
- *
- * Revision 1.2 1996/11/04 03:58:34 robertj
- * Added ASN types to class.
- *
- * Revision 1.1 1996/09/14 13:02:18 robertj
- * Initial revision
- *
- */
- #ifdef __GNUC__
- #pragma implementation "pasn.h"
- #endif
- #include <ptlib.h>
- #include <ptclib/pasn.h>
- #define new PNEW
- #define ASN_BOOLEAN (0x01)
- #define ASN_INTEGER (0x02)
- #define ASN_BIT_STR (0x03)
- #define ASN_OCTET_STR (0x04)
- #define ASN_NULL (0x05)
- #define ASN_OBJECT_ID (0x06)
- #define ASN_SEQUENCE (0x10)
- #define ASN_SET (0x11)
- #define ASN_UNIVERSAL (0x00)
- #define ASN_APPLICATION (0x40)
- #define ASN_CONTEXT (0x80)
- #define ASN_PRIVATE (0xC0)
- #define ASN_PRIMITIVE (0x00)
- #define ASN_CONSTRUCTOR (0x20)
- #define ASN_LONG_LEN (0x80)
- #define ASN_EXTENSION_ID (0x1F)
- #define ASN_BIT8 (0x80)
- #define MAX_OID_LEN 64
- static char cannotPerformOnBaseTypeMsg[] =
- "Cannot perform operation on base type PASNObject";
- BYTE PASNObject::ASNTypeToType[] = {
- ASN_INTEGER | ASN_UNIVERSAL | ASN_PRIMITIVE, // Integer
- ASN_OCTET_STR | ASN_UNIVERSAL | ASN_PRIMITIVE, // String
- ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE, // ObjectID
- ASN_CONSTRUCTOR | ASN_SEQUENCE, // Sequence
- ASN_CONSTRUCTOR | ASN_CONTEXT, // Choice
- ASN_APPLICATION | 0, // IPAddress
- ASN_APPLICATION | 1, // Counter32
- ASN_APPLICATION | 2, // Gauge32
- ASN_APPLICATION | 3, // TimeTicks
- // SNMP v2 types
- ASN_APPLICATION | 4, // Opaque
- ASN_APPLICATION | 5, // NsapAddress
- ASN_APPLICATION | 6, // Counter64
- ASN_APPLICATION | 7, // UInteger32
-
- // Oops - missed the Null type
- ASN_NULL | ASN_UNIVERSAL | ASN_PRIMITIVE, // Null
- 0, // Unknown
- };
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNObject
- // All ASN objects descend from this class. It is the primitive type
- // which can be put into the ASNSequence class
- //
- PASNObject::PASNObject()
- {
- }
- void PASNObject::PrintOn(ostream &) const
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- }
- void PASNObject::Encode(PBYTEArray &)
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- }
- WORD PASNObject::GetEncodedLength()
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- return 0;
- }
- PASNObject::ASNType PASNObject::GetType() const
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- return Unknown;
- }
- PString PASNObject::GetTypeAsString() const
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- return PString();
- }
- PObject * PASNObject::Clone() const
- {
- PAssertAlways(cannotPerformOnBaseTypeMsg);
- return NULL;
- }
- void PASNObject::EncodeASNLength (PBYTEArray & buffer, WORD length)
- {
- PINDEX offs = buffer.GetSize();
- // handle lengths less then 128
- if (length < 128)
- buffer[offs++] = (BYTE)length;
- // handle lengths less than 256
- else if (length < 256) {
- buffer[offs++] = (BYTE)(0x01 | ASN_LONG_LEN);
- buffer[offs++] = (BYTE)length;
- }
- // handle lengths up to 0xffff
- else {
- buffer[offs++] = (u_char)(0x02 | ASN_LONG_LEN);
- buffer[offs++] = (u_char)((length >> 8) & 0xFF);
- buffer[offs++] = (u_char)(length & 0xFF);
- }
- }
- BOOL PASNObject::DecodeASNLength (const PBYTEArray & buffer, PINDEX & ptr, WORD & len)
- {
- PINDEX s = buffer.GetSize();
- if (ptr >= s)
- return FALSE;
- BYTE ch = buffer[ptr++];
- if ((ch & ASN_LONG_LEN) == 0)
- len = (WORD)ch;
- else if ((ch & ~ASN_LONG_LEN) == 0x01) {
- if (ptr >= s)
- return FALSE;
- len = (WORD)buffer[ptr++];
- } else {
- if (ptr + 1 >= s)
- return FALSE;
- len = (WORD)((buffer[ptr] << 8) + buffer[ptr+1]);
- ptr += 2;
- }
- return TRUE;
- }
- WORD PASNObject::GetASNLengthLength (WORD length)
- {
- // handle lengths less then 128
- if (length < 128)
- return 1;
- // handle lengths less than 256
- else if (length < 256)
- return 2;
- // handle lengths up to 0xffff
- else
- return 3;
- }
- void PASNObject::EncodeASNSequenceStart(PBYTEArray & buffer, BYTE type, WORD length)
- {
- buffer[buffer.GetSize()] = type;
- EncodeASNLength(buffer, length);
- }
- WORD PASNObject::GetASNSequenceStartLength(WORD length)
- {
- return (WORD)(1 + GetASNLengthLength(length));
- }
- void PASNObject::EncodeASNHeader(PBYTEArray & buffer, PASNObject::ASNType type, WORD length)
- {
- buffer[buffer.GetSize()] = ASNTypeToType[type];
- EncodeASNLength(buffer, length);
- }
- WORD PASNObject::GetASNHeaderLength(WORD length)
- {
- return (WORD)(1 + GetASNLengthLength(length));
- }
- void PASNObject::EncodeASNInteger (PBYTEArray & buffer, PASNInt data, PASNObject::ASNType type)
- {
- DWORD mask;
- WORD intsize = sizeof(data);
- // create a mask which is the top nine bits of a DWORD, or 0xFF800000
- // on a big endian machine
- mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
- // remove all sequences of nine 0's or 1's at the start of the value
- while ((((data & mask) == 0) || ((data & mask) == mask))
- && intsize > 1) {
- intsize--;
- data <<= 8;
- }
- // insert the header
- EncodeASNHeader(buffer, type, intsize);
- // insert the data
- PINDEX offs = buffer.GetSize();
- mask = 0xFFL << (8 * (sizeof(DWORD) - 1));
- while (intsize--) {
- buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1)));
- data <<= 8;
- }
- }
- void PASNObject::EncodeASNUnsigned (PBYTEArray & buffer, PASNUnsigned data, PASNObject::ASNType type)
- {
- long mask;
- WORD intsize = sizeof(data);
- int add_null_byte = 0;
- mask = 0xFFL << (8 * (sizeof(long) - 1));
- /* mask is 0xFF000000 on a big-endian machine */
- if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80){
- /* if MSB is set */
- add_null_byte = 1;
- intsize++;
- }
- // create a mask which is the top nine bits of a DWORD, or 0xFF800000
- // on a big endian machine
- mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
- // remove all sequences of nine 0's or 1's at the start of the value
- while ((((data & mask) == 0) || (((long)data & mask) == mask))
- && intsize > 1) {
- intsize--;
- data <<= 8;
- }
- // insert the header
- EncodeASNHeader(buffer, type, intsize);
- // insert the data
- PINDEX offs = buffer.GetSize();
- mask = 0xFFL << (8 * (sizeof(DWORD) - 1));
- while (intsize--) {
- buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1)));
- data <<= 8;
- }
- if (add_null_byte == 1)
- buffer[offs++] = 0;
- }
- BOOL PASNObject::DecodeASNInteger(const PBYTEArray & buffer, PINDEX & ptr, PASNInt & value, PASNObject::ASNType theType)
- {
- if (buffer[ptr++] != ASNTypeToType[theType])
- return FALSE;
- WORD len;
- if (!DecodeASNLength(buffer, ptr, len))
- return FALSE;
- if (ptr + len > buffer.GetSize())
- return FALSE;
- if (buffer[ptr] & 0x80)
- value = -1; /* integer is negative */
- else
- value = 0;
- while (len--)
- value = (value << 8) | buffer[ptr++];
- return TRUE;
- }
- BOOL PASNObject::DecodeASNUnsigned(const PBYTEArray & buffer, PINDEX & ptr, PASNUnsigned & value, PASNObject::ASNType theType)
- {
- if (buffer[ptr++] != ASNTypeToType[theType])
- return FALSE;
- WORD len;
- if (!DecodeASNLength(buffer, ptr, len))
- return FALSE;
- if (ptr + len > buffer.GetSize())
- return FALSE;
- // if (buffer[ptr] & 0x80)
- // value = -1; /* integer is negative */
- value = 0;
- while (len--)
- value = (value << 8) | buffer[ptr++];
- return TRUE;
- }
- WORD PASNObject::GetASNIntegerLength(PASNInt data)
- {
- DWORD mask;
- WORD intsize = sizeof(data);
- // create a mask which is the top nine bits of a DWORD, or 0xFF800000
- // on a big endian machine
- mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
- // remove all sequences of nine 0's or 1's at the start of the value
- while ((((data & mask) == 0) || ((data & mask) == mask))
- && intsize > 1) {
- intsize--;
- data <<= 8;
- }
- // get the length of the header
- return (WORD)(intsize + GetASNHeaderLength(intsize));
- }
- WORD PASNObject::GetASNUnsignedLength (PASNUnsigned data)
- {
- long mask;
- WORD intsize = sizeof(data);
- int add_null_byte = 0;
- mask = 0xFFL << (8 * (sizeof(long) - 1));
- /* mask is 0xFF000000 on a big-endian machine */
- if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80) {
- /* if MSB is set */
- add_null_byte = 1;
- intsize++;
- }
- // create a mask which is the top nine bits of a DWORD, or 0xFF800000
- // on a big endian machine
- mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
- // remove all sequences of nine 0's or 1's at the start of the value
- while ((((data & mask) == 0) || (((long)data & mask) == mask))
- && intsize > 1) {
- intsize--;
- data <<= 8;
- }
- // insert the header
- return (WORD)(intsize + GetASNHeaderLength(intsize) + add_null_byte);
- }
- PASNInt PASNObject::GetInteger () const
- {
- PAssertAlways("Cannot return ASN object as Integer");
- return 0;
- }
- PString PASNObject::GetString () const
- {
- PAssertAlways("Cannot return ASN object as String");
- return PString();
- }
- PASNUnsigned PASNObject::GetUnsigned() const
- {
- PAssertAlways("Cannot return ASN object as Unsigned");
- return 0;
- }
- const PASNSequence & PASNObject::GetSequence() const
- {
- PAssertAlways("Cannot return ASN object as Sequence");
- PASNSequence * ptr = NULL;
- return (PASNSequence &)*ptr;
- }
- PIPSocket::Address PASNObject::GetIPAddress () const
- {
- PAssertAlways("Cannot return ASN object as IP Address");
- return PIPSocket::Address();
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNInteger
- // A descendant of PASNObject which is a simple ASN integer type
- //
- PASNInteger::PASNInteger(PASNInt val)
- {
- value = val;
- }
- PASNInteger::PASNInteger(const PBYTEArray & buffer, PINDEX & ptr)
- {
- DecodeASNInteger(buffer, ptr, value, Integer);
- }
- void PASNInteger::PrintOn(ostream & strm) const
- {
- strm << "Integer: "
- << value
- << endl;
- }
- void PASNInteger::Encode(PBYTEArray & buffer)
- {
- EncodeASNInteger(buffer, value, Integer);
- }
- WORD PASNInteger::GetEncodedLength()
- {
- return GetASNIntegerLength(value);
- }
- PASNObject::ASNType PASNInteger::GetType() const
- {
- return Integer;
- }
- PString PASNInteger::GetTypeAsString() const
- {
- return PString("Integer");
- }
- PASNInt PASNInteger::GetInteger () const
- {
- return value;
- }
- PString PASNInteger::GetString () const
- {
- return PString(PString::Signed, (long)value);
- }
- PObject * PASNInteger::Clone() const
- {
- return new PASNInteger(*this);
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNString
- // A descendant of PASNObject which is a simple ASN OctetStr type
- //
- PASNString::PASNString(const PString & str)
- {
- value = str;
- valueLen = (WORD)str.GetLength();
- }
- PASNString::PASNString(const BYTE * ptr, int len)
- {
- value = PString((const char *)ptr, len);
- valueLen = (WORD)len;
- }
- PASNString::PASNString(const PBYTEArray & buffer, PASNObject::ASNType type)
- {
- PINDEX ptr = 0;
- Decode(buffer, ptr, type);
- }
- PASNString::PASNString(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type)
- {
- Decode(buffer, ptr, type);
- }
- BOOL PASNString::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type)
- {
- valueLen = 0;
- if (buffer[ptr++] != ASNTypeToType[type])
- return FALSE;
- if (!DecodeASNLength(buffer, ptr, valueLen))
- return FALSE;
- if (ptr + valueLen > buffer.GetSize())
- return FALSE;
- value = PString(ptr + (const char *)(const BYTE *)buffer, valueLen);
- ptr += valueLen;
- return TRUE;
- }
- void PASNString::PrintOn(ostream & strm) const
- {
- strm << GetTypeAsString()
- << ": "
- << value
- << endl;
- }
- void PASNString::Encode(PBYTEArray & buffer, PASNObject::ASNType type)
- {
- // insert the header
- EncodeASNHeader(buffer, type, valueLen);
- // add the string
- PINDEX offs = buffer.GetSize();
- for (PINDEX i = 0; i < valueLen; i++)
- buffer[offs+i] = value[i];
- }
- WORD PASNString::GetEncodedLength()
- {
- return (WORD)(GetASNHeaderLength(valueLen) + (int)valueLen);
- }
- PASNObject::ASNType PASNString::GetType() const
- {
- return String;
- }
- PString PASNString::GetTypeAsString() const
- {
- return PString("String");
- }
- PString PASNString::GetString () const
- {
- return value;
- }
- PObject * PASNString::Clone() const
- {
- return new PASNString(*this);
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNUnsignedInteger
- // A descendant of PASNObject which is an unsigned integer
- BOOL PASNUnsignedInteger::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType theType)
- {
- return DecodeASNUnsigned(buffer, ptr, value, theType);
- }
- void PASNUnsignedInteger::Encode(PBYTEArray & buffer, PASNObject::ASNType theType)
- {
- EncodeASNUnsigned(buffer, value, theType);
- }
- void PASNUnsignedInteger::PrintOn(ostream & strm) const
- {
- strm << GetTypeAsString()
- << " : "
- << value
- << endl;
- }
- WORD PASNUnsignedInteger::GetEncodedLength()
- {
- return GetASNUnsignedLength(value);
- }
- PString PASNUnsignedInteger::GetString() const
- {
- return PString(PString::Unsigned, (long)value);
- }
- PASNUnsigned PASNUnsignedInteger::GetUnsigned() const
- {
- return value;
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNObjectID
- // A descendant of PASNObject which is a simple ASN ObjID type
- //
- PASNObjectID::PASNObjectID(PASNOid * val, BYTE theLen)
- {
- value.SetSize(theLen);
- memcpy(value.GetPointer(theLen), val, theLen * sizeof(PASNOid));
- }
- PASNObjectID::PASNObjectID(const PString & str)
- {
- PINDEX strLen = str.GetLength();
- PINDEX i = 0;
- PINDEX len = 0;
- while (i < strLen) {
- // find the first non-dot character
- while (str[i] == '.' && i < strLen)
- i++;
- // find the next dot
- PINDEX j = str.Find('.', i);
- // convert to a PASNOid
- value.SetSize(len+1);
- value.SetAt(len++, str(i, j).AsInteger());
- i = j;
- }
- }
- PASNObjectID::PASNObjectID(const PBYTEArray & buffer)
- {
- PINDEX ptr = 0;
- Decode(buffer, ptr);
- }
- PASNObjectID::PASNObjectID(const PBYTEArray & buffer, PINDEX & ptr)
- {
- Decode(buffer, ptr);
- }
- void PASNObjectID::PrintOn(ostream & strm) const
- {
- strm << "ObjectId: ";
- for (PINDEX i = 0 ; i < value.GetSize(); i++) {
- strm << value[i];
- if (i != value.GetSize()-1)
- strm << '.';
- }
- strm << endl;
- }
- void PASNObjectID::Encode(PBYTEArray & buffer)
- {
- PBYTEArray eObjId;
- PINDEX offs = 0;
- PASNOid subId, mask, testmask;
- int bits, testbits;
- PINDEX objIdLen = value.GetSize();
- PASNOid *objId = value.GetPointer();
- if (objIdLen < 2) {
- eObjId [offs++] = 0;
- objIdLen = 0;
- } else {
- eObjId [offs++] = (BYTE)(objId[1] + (objId[0] * 40));
- objIdLen -= 2;
- objId += 2;
- }
- while (objIdLen-- > 0) {
- subId = *objId++;
- if (subId < 128)
- eObjId [offs++] = (BYTE)subId;
- else {
- mask = 0x7F; /* handle subid == 0 case */
- bits = 0;
- /* testmask *MUST* !!!! be of an unsigned type */
- for (testmask = 0x7F, testbits = 0;
- testmask != 0;
- testmask <<= 7, testbits += 7) {
- if (subId & testmask) { /* if any bits set */
- mask = testmask;
- bits = testbits;
- }
- }
- /* mask can't be zero here */
- for(;mask != 0x7F; mask >>= 7, bits -= 7) {
- /* fix a mask that got truncated above */
- if (mask == 0x1E00000)
- mask = 0xFE00000;
- eObjId [offs++] = (u_char)(((subId & mask) >> bits) | ASN_BIT8);
- }
- eObjId [offs++] = (u_char)(subId & mask);
- }
- }
- PINDEX s = eObjId.GetSize();
- EncodeASNHeader (buffer, ObjectID, (WORD)s);
- offs = buffer.GetSize();
- for (PINDEX i = 0; i < s; i++)
- buffer [offs + i] = eObjId[i];
- }
- WORD PASNObjectID::GetEncodedLength()
- {
- PASNOid subId, mask, testmask;
- int bits, testbits;
- PINDEX objIdLen = value.GetSize();
- WORD theLen = 0;
- PASNOid *objId = value.GetPointer();
- if (objIdLen < 2) {
- theLen++;
- objIdLen = 0;
- } else {
- theLen++;
- objIdLen -= 2;
- objId += 2;
- }
- while (objIdLen-- > 0) {
- subId = *objId++;
- if (subId < 128)
- theLen++;
- else {
- mask = 0x7F; /* handle subid == 0 case */
- bits = 0;
- /* testmask *MUST* !!!! be of an unsigned type */
- for (testmask = 0x7F, testbits = 0;
- testmask != 0;
- testmask <<= 7, testbits += 7) {
- if (subId & testmask) { /* if any bits set */
- mask = testmask;
- bits = testbits;
- }
- }
- /* mask can't be zero here */
- for(;mask != 0x7F; mask >>= 7, bits -= 7) {
- /* fix a mask that got truncated above */
- if (mask == 0x1E00000)
- mask = 0xFE00000;
- theLen++;
- }
- theLen++;
- }
- }
- return (WORD)(theLen + GetASNHeaderLength(theLen));
- }
- PASNObject::ASNType PASNObjectID::GetType() const
- {
- return ObjectID;
- }
- PString PASNObjectID::GetTypeAsString() const
- {
- return PString("Object ID");
- }
- PString PASNObjectID::GetString() const
- {
- PStringStream str;
- for (PINDEX i = 0; i < value.GetSize(); i++) {
- if (i > 0)
- str << '.';
- str << value[i];
- }
- return str;
- }
- BOOL PASNObjectID::Decode(const PBYTEArray & buffer, PINDEX & offs)
- {
- BYTE type = buffer[offs++];
- PAssert(type == (ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE),
- "Attempt to decode non-objectID");
- PASNOid subId;
-
- WORD dataLen;
- if (!DecodeASNLength(buffer, offs, dataLen))
- return FALSE;
- value.SetSize(2);
- // handle zero length strings correctly
- if (dataLen != 0) {
- // start at the second identifier in the buffer, because we will later
- // expand the first number into the first two IDs
- PINDEX i = 1;
- PINDEX s = buffer.GetSize();
- while (dataLen > 0) {
- subId = 0;
- do { /* shift and add in low order 7 bits */
- if (dataLen == 0 || offs >= s)
- return FALSE;
- subId = (subId << 7) + (buffer[offs] & ~ASN_BIT8);
- dataLen--;
- } while (buffer[offs++] & ASN_BIT8);
- value.SetAt(i++, subId);
- }
- /*
- * The first two subidentifiers are encoded into the first component
- * with the value (X * 40) + Y, where:
- * X is the value of the first subidentifier.
- * Y is the value of the second subidentifier.
- */
- subId = value[1];
- if (subId == 0x2B) {
- value[0] = 1;
- value[1] = 3;
- } else {
- value[1] = subId % 40;
- value[0] = (subId - value[1]) / 40;
- }
- }
- return TRUE;
- }
- PObject * PASNObjectID::Clone() const
- {
- return new PASNObjectID(*this);
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // PASNSequence
- // A descendant of PASNObject which is the complex sequence type
- //
- PASNSequence::PASNSequence()
- {
- encodedLen = 0;
- type = ASNTypeToType[Sequence];
- asnType = Sequence;
- }
- PASNSequence::PASNSequence(BYTE selector)
- {
- encodedLen = 0;
- PAssert(selector < ASN_CONSTRUCTOR, "Sequence selector too big");
- type = (BYTE)(ASNTypeToType[Choice] | selector);
- asnType = Choice;
- }
- void PASNSequence::Append(PASNObject * obj)
- {
- sequence.Append(obj);
- }
- void PASNSequence::AppendInteger(PASNInt value)
- {
- Append(new PASNInteger(value));
- }
- void PASNSequence::AppendString (const PString & str)
- {
- Append(new PASNString(str));
- }
- void PASNSequence::AppendObjectID(const PString & str)
- {
- Append(new PASNObjectID(str));
- }
- void PASNSequence::AppendObjectID(PASNOid * val, BYTE len)
- {
- Append(new PASNObjectID(val, len));
- }
- void PASNSequence::PrintOn(ostream & strm) const
- {
- strm << "Sequence:" << endl;
- for (PINDEX i = 0; i < sequence.GetSize(); i++)
- strm << sequence[i];
- strm << "End Sequence" << endl;
- }
- void PASNSequence::Encode(PBYTEArray & buffer)
- {
- // calculate the length of the sequence, if it hasn't already been done
- if (encodedLen == 0)
- (void)GetEncodedLength();
- // create the header for the sequence. Note that seqLen was calculated
- // by the call to GetEncodedLength above
- EncodeASNSequenceStart(buffer, type, seqLen);
- // now encode the sequence itself
- for (PINDEX i = 0; i < sequence.GetSize(); i++)
- sequence[i].Encode(buffer);
- }
- BOOL PASNSequence::Encode(PBYTEArray & buffer, PINDEX maxLen)
- {
- // calculate the length of the sequence, if it hasn't already been done
- if (encodedLen == 0)
- (void)GetEncodedLength();
- // create the header for the sequence. Note that seqLen was calculated
- // by the call to GetEncodedLength above
- EncodeASNSequenceStart(buffer, type, seqLen);
- // now encode the sequence itself
- for (PINDEX i = 0; i < sequence.GetSize(); i++) {
- sequence[i].Encode(buffer);
- if (buffer.GetSize() > maxLen)
- return FALSE;
- }
- return TRUE;
- }
- WORD PASNSequence::GetEncodedLength()
- {
- // calculate the length of the sequence
- if (encodedLen == 0) {
- seqLen = 0;
- for (PINDEX i = 0; i < sequence.GetSize(); i++)
- seqLen = (WORD)(seqLen + sequence[i].GetEncodedLength());
- encodedLen = (WORD)(GetASNSequenceStartLength(seqLen) + seqLen);
- }
- return encodedLen;
- }
- PASNObject::ASNType PASNSequence::GetType() const
- {
- return asnType;
- }
- int PASNSequence::GetChoice() const
- {
- return type;
- }
- PString PASNSequence::GetTypeAsString() const
- {
- return PString("Sequence");
- }
- PASNSequence::PASNSequence(const PBYTEArray & buffer)
- {
- PINDEX ptr = 0;
- if (!Decode(buffer, ptr))
- sequence.RemoveAll();
- }
- PASNSequence::PASNSequence(const PBYTEArray & buffer, PINDEX & ptr)
- {
- if (!Decode(buffer, ptr))
- sequence.RemoveAll();
- }
- BOOL PASNSequence::Decode(const PBYTEArray & buffer, PINDEX & ptr)
- {
- PINDEX s = buffer.GetSize();
- BYTE c;
- // all sequences start with a sequence start
- if (ptr >= s)
- return FALSE;
- // get the sequence header
- c = buffer[ptr++];
- if (c == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
- asnType = Sequence;
- else if ((c & ~ASN_EXTENSION_ID) == (ASN_CONSTRUCTOR | ASN_CONTEXT)) {
- type = (BYTE)(c & ASN_EXTENSION_ID);
- asnType = Choice;
- } else
- return FALSE;
- // get the sequence length
- WORD len;
- if (!DecodeASNLength(buffer, ptr, len))
- return FALSE;
- // check the length
- if (ptr + len > s)
- return FALSE;
- // set new length
- s = ptr + len;
- // now decode the elements
- BOOL ok = TRUE;
- while (ptr < s && ok) {
- c = buffer[ptr];
- if ((c & ~ASN_EXTENSION_ID) == (ASN_CONSTRUCTOR | ASN_CONTEXT))
- sequence.Append(new PASNSequence(buffer, ptr));
- else switch (c) {
- // Integer
- case ASN_INTEGER | ASN_UNIVERSAL | ASN_PRIMITIVE:
- sequence.Append(new PASNInteger(buffer, ptr));
- break;
- // Octet String
- case ASN_OCTET_STR | ASN_UNIVERSAL | ASN_PRIMITIVE:
- sequence.Append(new PASNString(buffer, ptr));
- break;
- // NULL
- case ASN_NULL | ASN_UNIVERSAL | ASN_PRIMITIVE:
- sequence.Append(new PASNNull(buffer, ptr));
- break;
- // Object ID
- case ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE:
- sequence.Append(new PASNObjectID(buffer, ptr));
- break;
- // Sequence
- case ASN_CONSTRUCTOR | ASN_SEQUENCE:
- sequence.Append(new PASNSequence(buffer, ptr));
- break;
- // TimeTicks
- case ASN_APPLICATION | 3:
- sequence.Append(new PASNTimeTicks(buffer, ptr));
- break;
- // Counter
- case ASN_APPLICATION | 1:
- sequence.Append(new PASNCounter(buffer, ptr));
- break;
- // Gauge
- case ASN_APPLICATION | 2:
- sequence.Append(new PASNGauge(buffer, ptr));
- break;
- // IP Address
- case ASN_APPLICATION | 0:
- sequence.Append(new PASNIPAddress(buffer, ptr));
- break;
- default:
- return TRUE;
- }
- }
- return ok;
- }
- PINDEX PASNSequence::GetSize() const
- {
- return sequence.GetSize();
- }
- PASNObject & PASNSequence::operator [] (PINDEX idx) const
- {
- return sequence[idx];
- }
- const PASNSequence & PASNSequence::GetSequence() const
- {
- return *this;
- }
- PString PASNTimeTicks::GetTypeAsString() const
- {
- return PString("TimeTicks");
- }
- PString PASNCounter::GetTypeAsString() const
- {
- return PString("Counter");
- }
- PString PASNGauge::GetTypeAsString() const
- {
- return PString("Gauge");
- }
- PString PASNIPAddress::GetTypeAsString() const
- {
- return PString("IPAddress");
- }
- PString PASNIPAddress::GetString() const
- {
- PINDEX len = value.GetSize();
- if (len == 0)
- return "(empty)";
- if (len < 4) {
- PString out = "Hex";
- for (PINDEX i = 0; i < len; i++)
- out &= psprintf("%02x", (BYTE)value[i]);
- return out;
- }
- return psprintf("%i.%i.%i.%i",
- (BYTE)value[0], (BYTE)value[1],
- (BYTE)value[2], (BYTE)value[3]);
- }
- PASNIPAddress::PASNIPAddress(const PString & str)
- : PASNString("")
- {
- value.SetSize(4);
- PIPSocket::Address addr;
- if (!PIPSocket::GetHostAddress(str, addr))
- addr = 0;
- int i;
- for (i = 0; i < 4; i++)
- value[i] = addr[i];
- valueLen = 4;
- }
- PIPSocket::Address PASNIPAddress::GetIPAddress () const
- {
- return PIPSocket::Address((BYTE)value[0], (BYTE)value[1],
- (BYTE)value[2], (BYTE)value[3]);
- }
- PASNNull::PASNNull()
- {
- }
- PASNNull::PASNNull(const PBYTEArray & buffer, PINDEX & ptr)
- {
- PAssert(((buffer.GetSize() - ptr) >= 2) &&
- (buffer[ptr+0] == 0x05) &&
- (buffer[ptr+1] == 0x00),
- "Attempt to decode non-null");
- ptr += 2 ;
- }
- void PASNNull::PrintOn(ostream & strm) const
- {
- strm << "Null"
- << endl;
- }
- void PASNNull::Encode(PBYTEArray & buffer)
- {
- EncodeASNHeader(buffer, Null, 0);
- }
- WORD PASNNull::GetEncodedLength()
- {
- return 2;
- }
- PObject * PASNNull::Clone() const
- {
- return new PASNNull();
- }
- PASNObject::ASNType PASNNull::GetType() const
- {
- return Null;
- }
- PString PASNNull::GetTypeAsString() const
- {
- return PString("Null");
- }
- PString PASNNull::GetString() const
- {
- return PString();
- }
- // End Of File ///////////////////////////////////////////////////////////////