pasn.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:29k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * pasn.cxx
  3.  *
  4.  * ASN classes in support of the SNMP code.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: pasn.cxx,v $
  30.  * Revision 1.14  2000/05/05 10:08:29  robertj
  31.  * Fixed some GNU compiler warnings
  32.  *
  33.  * Revision 1.13  1999/05/01 11:29:20  robertj
  34.  * Alpha linux port changes.
  35.  *
  36.  * Revision 1.12  1999/05/01 03:52:20  robertj
  37.  * Fixed various egcs warnings.
  38.  *
  39.  * Revision 1.11  1999/03/02 01:53:38  craigs
  40.  * Fixed problem with creating IpAddress objects
  41.  *
  42.  * Revision 1.10  1999/02/16 08:08:06  robertj
  43.  * MSVC 6.0 compatibility changes.
  44.  *
  45.  * Revision 1.9  1998/11/30 04:52:04  robertj
  46.  * New directory structure
  47.  *
  48.  * Revision 1.8  1998/10/13 14:06:31  robertj
  49.  * Complete rewrite of memory leak detection code.
  50.  *
  51.  * Revision 1.7  1998/09/23 06:22:27  robertj
  52.  * Added open source copyright license.
  53.  *
  54.  * Revision 1.6  1998/02/16 06:57:05  robertj
  55.  * Moved pragma implemenetation in here so do not need upasn.cxx file.
  56.  *
  57.  * Revision 1.7  1998/01/26 02:49:21  robertj
  58.  * GNU support.
  59.  *
  60.  * Revision 1.6  1998/01/26 01:45:36  robertj
  61.  * Removed unused variable.
  62.  *
  63.  * Revision 1.5  1997/08/20 09:00:37  craigs
  64.  * Fixed problems with decoding of PASNNull
  65.  *
  66.  * Revision 1.4  1997/07/20 08:34:37  craigs
  67.  * Added ASN NULL type
  68.  *
  69.  * Revision 1.3  1997/07/16 05:52:48  craigs
  70.  * Changed ASN constructors to store value length separately so
  71.  * ASNString consctructor will worki correctly
  72.  *
  73.  * Revision 1.2  1996/11/04 03:58:34  robertj
  74.  * Added ASN types to class.
  75.  *
  76.  * Revision 1.1  1996/09/14 13:02:18  robertj
  77.  * Initial revision
  78.  *
  79.  */
  80. #ifdef __GNUC__
  81. #pragma implementation "pasn.h"
  82. #endif
  83. #include <ptlib.h>
  84. #include <ptclib/pasn.h>
  85. #define new PNEW
  86. #define ASN_BOOLEAN         (0x01)
  87. #define ASN_INTEGER         (0x02)
  88. #define ASN_BIT_STR         (0x03)
  89. #define ASN_OCTET_STR       (0x04)
  90. #define ASN_NULL            (0x05)
  91. #define ASN_OBJECT_ID       (0x06)
  92. #define ASN_SEQUENCE        (0x10)
  93. #define ASN_SET             (0x11)
  94. #define ASN_UNIVERSAL       (0x00)
  95. #define ASN_APPLICATION     (0x40)
  96. #define ASN_CONTEXT         (0x80)
  97. #define ASN_PRIVATE         (0xC0)
  98. #define ASN_PRIMITIVE       (0x00)
  99. #define ASN_CONSTRUCTOR     (0x20)
  100. #define ASN_LONG_LEN        (0x80)
  101. #define ASN_EXTENSION_ID    (0x1F)
  102. #define ASN_BIT8            (0x80)
  103. #define MAX_OID_LEN     64
  104. static char cannotPerformOnBaseTypeMsg[] =
  105.    "Cannot perform operation on base type PASNObject";
  106. BYTE PASNObject::ASNTypeToType[] = {
  107.   ASN_INTEGER   | ASN_UNIVERSAL | ASN_PRIMITIVE,    // Integer
  108.   ASN_OCTET_STR | ASN_UNIVERSAL | ASN_PRIMITIVE,    // String
  109.   ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE,    // ObjectID
  110.   ASN_CONSTRUCTOR | ASN_SEQUENCE,                 // Sequence
  111.   ASN_CONSTRUCTOR | ASN_CONTEXT,                 // Choice
  112.   ASN_APPLICATION | 0,                              // IPAddress
  113.   ASN_APPLICATION | 1,                              // Counter32
  114.   ASN_APPLICATION | 2,                              // Gauge32
  115.   ASN_APPLICATION | 3,                              // TimeTicks
  116. // SNMP v2 types
  117.   ASN_APPLICATION | 4,                              // Opaque
  118.   ASN_APPLICATION | 5,                              // NsapAddress
  119.   ASN_APPLICATION | 6,                              // Counter64
  120.   ASN_APPLICATION | 7,                              // UInteger32
  121.   
  122. // Oops - missed the Null type  
  123.   ASN_NULL | ASN_UNIVERSAL | ASN_PRIMITIVE,         // Null
  124.   0,     // Unknown
  125. };
  126. //////////////////////////////////////////////////////////////////////////
  127. //
  128. //  PASNObject
  129. //     All ASN objects descend from this class. It is the primitive type
  130. //  which can be put into the ASNSequence class
  131. //
  132. PASNObject::PASNObject()
  133. {
  134. }
  135. void PASNObject::PrintOn(ostream &) const
  136. {
  137.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  138. }
  139. void PASNObject::Encode(PBYTEArray &) 
  140. {
  141.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  142. }
  143. WORD PASNObject::GetEncodedLength() 
  144. {
  145.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  146.   return 0;
  147. }
  148. PASNObject::ASNType PASNObject::GetType() const
  149. {
  150.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  151.   return Unknown;
  152. }
  153. PString PASNObject::GetTypeAsString() const
  154. {
  155.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  156.   return PString();
  157. }
  158. PObject * PASNObject::Clone() const
  159. {
  160.   PAssertAlways(cannotPerformOnBaseTypeMsg);
  161.   return NULL;
  162. }
  163. void PASNObject::EncodeASNLength (PBYTEArray & buffer, WORD length)
  164. {
  165.   PINDEX offs = buffer.GetSize();
  166.   // handle lengths less then 128
  167.   if (length < 128) 
  168.     buffer[offs++] = (BYTE)length;
  169.   // handle lengths less than 256
  170.   else if (length < 256) {
  171.     buffer[offs++] = (BYTE)(0x01 | ASN_LONG_LEN);
  172.     buffer[offs++] = (BYTE)length;
  173.   }
  174.   // handle lengths up to 0xffff
  175.   else {
  176.     buffer[offs++] = (u_char)(0x02 | ASN_LONG_LEN);
  177.     buffer[offs++] = (u_char)((length >> 8) & 0xFF);
  178.     buffer[offs++] = (u_char)(length & 0xFF);
  179.   }
  180. }
  181. BOOL PASNObject::DecodeASNLength (const PBYTEArray & buffer, PINDEX & ptr, WORD & len)
  182. {
  183.   PINDEX s = buffer.GetSize();
  184.   if (ptr >= s)
  185.     return FALSE;
  186.   BYTE ch = buffer[ptr++];
  187.   if ((ch & ASN_LONG_LEN) == 0)
  188.     len = (WORD)ch;
  189.   else if ((ch & ~ASN_LONG_LEN) == 0x01) {
  190.     if (ptr >= s)
  191.       return FALSE;
  192.     len = (WORD)buffer[ptr++];
  193.   } else {
  194.     if (ptr + 1 >= s)
  195.       return FALSE;
  196.     len = (WORD)((buffer[ptr] << 8) + buffer[ptr+1]);
  197.     ptr += 2;
  198.   }
  199.   return TRUE;
  200. }
  201. WORD PASNObject::GetASNLengthLength (WORD  length) 
  202. {
  203.   // handle lengths less then 128
  204.   if (length < 128) 
  205.     return 1;
  206.   // handle lengths less than 256
  207.   else if (length < 256) 
  208.     return 2;
  209.   // handle lengths up to 0xffff
  210.   else 
  211.     return 3;
  212. }
  213. void PASNObject::EncodeASNSequenceStart(PBYTEArray & buffer, BYTE type, WORD length) 
  214. {
  215.   buffer[buffer.GetSize()] = type;
  216.   EncodeASNLength(buffer, length);
  217. }
  218. WORD PASNObject::GetASNSequenceStartLength(WORD length) 
  219. {
  220.   return (WORD)(1 + GetASNLengthLength(length));
  221. }
  222. void PASNObject::EncodeASNHeader(PBYTEArray & buffer, PASNObject::ASNType type, WORD length)
  223. {
  224.   buffer[buffer.GetSize()] = ASNTypeToType[type];
  225.   EncodeASNLength(buffer, length);
  226. }
  227. WORD PASNObject::GetASNHeaderLength(WORD length) 
  228. {
  229.   return (WORD)(1 + GetASNLengthLength(length));
  230. }
  231. void PASNObject::EncodeASNInteger (PBYTEArray & buffer, PASNInt data, PASNObject::ASNType type)
  232. {
  233.   DWORD mask;
  234.   WORD  intsize = sizeof(data);
  235.   // create a mask which is the top nine bits of a DWORD, or 0xFF800000
  236.   // on a big endian machine
  237.   mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
  238.   // remove all sequences of nine 0's or 1's at the start of the value
  239.   while ((((data & mask) == 0) || ((data & mask) == mask))
  240.   && intsize > 1) {
  241.     intsize--;
  242.     data <<= 8;
  243.   }
  244.   // insert the header
  245.   EncodeASNHeader(buffer, type, intsize);
  246.   // insert the data
  247.   PINDEX offs = buffer.GetSize();
  248.   mask = 0xFFL << (8 * (sizeof(DWORD) - 1));
  249.   while (intsize--) {
  250.     buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1)));
  251.     data <<= 8;
  252.   }
  253. }
  254. void PASNObject::EncodeASNUnsigned (PBYTEArray & buffer, PASNUnsigned data, PASNObject::ASNType type)
  255. {
  256.   long mask;
  257.   WORD intsize = sizeof(data);
  258.   int  add_null_byte = 0;
  259.   mask = 0xFFL << (8 * (sizeof(long) - 1));
  260.   /* mask is 0xFF000000 on a big-endian machine */
  261.   if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80){
  262.     /* if MSB is set */
  263.     add_null_byte = 1;
  264.     intsize++;
  265.   }
  266.   // create a mask which is the top nine bits of a DWORD, or 0xFF800000
  267.   // on a big endian machine
  268.   mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
  269.   // remove all sequences of nine 0's or 1's at the start of the value
  270.   while ((((data & mask) == 0) || (((long)data & mask) == mask))
  271.   && intsize > 1) {
  272.     intsize--;
  273.     data <<= 8;
  274.   }
  275.   // insert the header
  276.   EncodeASNHeader(buffer, type, intsize);
  277.   // insert the data
  278.   PINDEX offs = buffer.GetSize();
  279.   mask = 0xFFL << (8 * (sizeof(DWORD) - 1));
  280.   while (intsize--) {
  281.     buffer[offs++] = (u_char)((data & mask) >> (8 * (sizeof(DWORD) - 1)));
  282.     data <<= 8;
  283.   }
  284.   if (add_null_byte == 1)
  285.     buffer[offs++] = 0;
  286. }
  287. BOOL PASNObject::DecodeASNInteger(const PBYTEArray & buffer, PINDEX & ptr, PASNInt & value, PASNObject::ASNType theType)
  288. {
  289.   if (buffer[ptr++] != ASNTypeToType[theType])
  290.     return FALSE;
  291.   WORD len;
  292.   if (!DecodeASNLength(buffer, ptr, len))
  293.     return FALSE;
  294.   if (ptr + len > buffer.GetSize())
  295.     return FALSE;
  296.   if (buffer[ptr] & 0x80)
  297.     value = -1; /* integer is negative */
  298.   else
  299.     value = 0;
  300.   while (len--)
  301.     value = (value << 8) | buffer[ptr++];
  302.   return TRUE;
  303. }
  304. BOOL PASNObject::DecodeASNUnsigned(const PBYTEArray & buffer, PINDEX & ptr, PASNUnsigned & value, PASNObject::ASNType theType)
  305. {
  306.   if (buffer[ptr++] != ASNTypeToType[theType])
  307.     return FALSE;
  308.   WORD len;
  309.   if (!DecodeASNLength(buffer, ptr, len))
  310.     return FALSE;
  311.   if (ptr + len > buffer.GetSize())
  312.     return FALSE;
  313. //  if (buffer[ptr] & 0x80)
  314. //    value = -1; /* integer is negative */
  315.   value = 0;
  316.   while (len--)
  317.     value = (value << 8) | buffer[ptr++];
  318.   return TRUE;
  319. }
  320. WORD PASNObject::GetASNIntegerLength(PASNInt data) 
  321. {
  322.   DWORD mask;
  323.   WORD  intsize = sizeof(data);
  324.   // create a mask which is the top nine bits of a DWORD, or 0xFF800000
  325.   // on a big endian machine
  326.   mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
  327.   // remove all sequences of nine 0's or 1's at the start of the value
  328.   while ((((data & mask) == 0) || ((data & mask) == mask))
  329.   && intsize > 1) {
  330.     intsize--;
  331.     data <<= 8;
  332.   }
  333.   // get the length of the header
  334.   return (WORD)(intsize + GetASNHeaderLength(intsize));
  335. }
  336. WORD PASNObject::GetASNUnsignedLength (PASNUnsigned data)
  337. {
  338.   long mask;
  339.   WORD intsize = sizeof(data);
  340.   int  add_null_byte = 0;
  341.   mask = 0xFFL << (8 * (sizeof(long) - 1));
  342.   /* mask is 0xFF000000 on a big-endian machine */
  343.   if ((u_char)((data & mask) >> (8 * (sizeof(PASNUnsigned) - 1))) & 0x80) {
  344.     /* if MSB is set */
  345.     add_null_byte = 1;
  346.     intsize++;
  347.   }
  348.   // create a mask which is the top nine bits of a DWORD, or 0xFF800000
  349.   // on a big endian machine
  350.   mask = 0x1FFL << ((8 * (sizeof(DWORD) - 1)) - 1);
  351.   // remove all sequences of nine 0's or 1's at the start of the value
  352.   while ((((data & mask) == 0) || (((long)data & mask) == mask))
  353.   && intsize > 1) {
  354.     intsize--;
  355.     data <<= 8;
  356.   }
  357.   // insert the header
  358.   return (WORD)(intsize + GetASNHeaderLength(intsize) + add_null_byte);
  359. }
  360. PASNInt PASNObject::GetInteger () const
  361. {
  362.   PAssertAlways("Cannot return ASN object as Integer");
  363.   return 0;
  364. }
  365. PString PASNObject::GetString  () const
  366. {
  367.   PAssertAlways("Cannot return ASN object as String");
  368.   return PString();
  369. }
  370. PASNUnsigned PASNObject::GetUnsigned() const
  371. {
  372.   PAssertAlways("Cannot return ASN object as Unsigned");
  373.   return 0;
  374. }
  375. const PASNSequence & PASNObject::GetSequence() const
  376. {
  377.   PAssertAlways("Cannot return ASN object as Sequence");
  378.   PASNSequence * ptr = NULL;
  379.   return (PASNSequence &)*ptr;
  380. }
  381. PIPSocket::Address PASNObject::GetIPAddress () const
  382. {
  383.   PAssertAlways("Cannot return ASN object as IP Address");
  384.   return PIPSocket::Address();
  385. }
  386. //////////////////////////////////////////////////////////////////////////
  387. //
  388. //  PASNInteger
  389. //     A descendant of PASNObject which is a simple ASN integer type
  390. //
  391. PASNInteger::PASNInteger(PASNInt val)
  392. {
  393.   value = val;
  394. }
  395. PASNInteger::PASNInteger(const PBYTEArray & buffer, PINDEX & ptr)
  396. {
  397.   DecodeASNInteger(buffer, ptr, value, Integer);
  398. }
  399. void PASNInteger::PrintOn(ostream & strm) const
  400. {
  401.   strm << "Integer: "
  402.        << value
  403.        << endl;
  404. }
  405. void PASNInteger::Encode(PBYTEArray & buffer)
  406. {
  407.   EncodeASNInteger(buffer, value, Integer);
  408. }
  409. WORD PASNInteger::GetEncodedLength()
  410. {
  411.   return GetASNIntegerLength(value);
  412. }
  413. PASNObject::ASNType PASNInteger::GetType() const
  414. {
  415.   return Integer;
  416. }
  417. PString PASNInteger::GetTypeAsString() const
  418. {
  419.   return PString("Integer");
  420. }
  421. PASNInt PASNInteger::GetInteger () const
  422. {
  423.   return value;
  424. }
  425. PString PASNInteger::GetString () const
  426. {
  427.   return PString(PString::Signed, (long)value);
  428. }
  429. PObject * PASNInteger::Clone() const
  430. {
  431.   return new PASNInteger(*this);
  432. }
  433. //////////////////////////////////////////////////////////////////////////
  434. //
  435. //  PASNString
  436. //     A descendant of PASNObject which is a simple ASN OctetStr type
  437. //
  438. PASNString::PASNString(const PString & str)
  439. {
  440.   value    = str;
  441.   valueLen = (WORD)str.GetLength();
  442. }
  443. PASNString::PASNString(const BYTE * ptr, int len)
  444. {
  445.   value = PString((const char *)ptr, len);
  446.   valueLen = (WORD)len;
  447. }
  448. PASNString::PASNString(const PBYTEArray & buffer, PASNObject::ASNType type)
  449. {
  450.   PINDEX ptr = 0;
  451.   Decode(buffer, ptr, type);
  452. }
  453. PASNString::PASNString(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type)
  454. {
  455.   Decode(buffer, ptr, type);
  456. }
  457. BOOL PASNString::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType type)
  458. {
  459.   valueLen = 0;
  460.   if (buffer[ptr++] != ASNTypeToType[type])
  461.     return FALSE;
  462.   if (!DecodeASNLength(buffer, ptr, valueLen))
  463.     return FALSE;
  464.   if (ptr + valueLen > buffer.GetSize())
  465.     return FALSE;
  466.   value = PString(ptr + (const char *)(const BYTE *)buffer, valueLen);
  467.   ptr += valueLen;
  468.   return TRUE;
  469. }
  470. void PASNString::PrintOn(ostream & strm) const
  471. {
  472.   strm << GetTypeAsString()
  473.        << ": "
  474.        << value
  475.        << endl; 
  476. }
  477. void PASNString::Encode(PBYTEArray & buffer, PASNObject::ASNType type)
  478. {
  479.   // insert the header
  480.   EncodeASNHeader(buffer, type, valueLen);
  481.   // add the string
  482.   PINDEX offs = buffer.GetSize();
  483.   for (PINDEX i = 0; i < valueLen; i++)
  484.     buffer[offs+i] = value[i];
  485. }
  486. WORD PASNString::GetEncodedLength()
  487. {
  488.   return (WORD)(GetASNHeaderLength(valueLen) + (int)valueLen);
  489. }
  490. PASNObject::ASNType PASNString::GetType() const
  491. {
  492.   return String;
  493. }
  494. PString PASNString::GetTypeAsString() const
  495. {
  496.   return PString("String");
  497. }
  498. PString PASNString::GetString () const
  499. {
  500.   return value;
  501. }
  502. PObject * PASNString::Clone() const
  503. {
  504.   return new PASNString(*this);
  505. }
  506. //////////////////////////////////////////////////////////////////////////
  507. //
  508. //  PASNUnsignedInteger
  509. //     A descendant of PASNObject which is an unsigned integer
  510. BOOL PASNUnsignedInteger::Decode(const PBYTEArray & buffer, PINDEX & ptr, PASNObject::ASNType theType)
  511. {
  512.   return DecodeASNUnsigned(buffer, ptr, value, theType);
  513. }
  514. void PASNUnsignedInteger::Encode(PBYTEArray & buffer, PASNObject::ASNType theType)
  515. {
  516.   EncodeASNUnsigned(buffer, value, theType);
  517. }
  518. void PASNUnsignedInteger::PrintOn(ostream & strm) const
  519. {
  520.   strm << GetTypeAsString()
  521.        << " : "
  522.        << value
  523.        << endl; 
  524. }
  525. WORD PASNUnsignedInteger::GetEncodedLength()
  526. {
  527.   return GetASNUnsignedLength(value);
  528. }
  529. PString PASNUnsignedInteger::GetString() const
  530. {
  531.   return PString(PString::Unsigned, (long)value);
  532. }
  533. PASNUnsigned PASNUnsignedInteger::GetUnsigned() const
  534. {
  535.   return value;
  536. }
  537. //////////////////////////////////////////////////////////////////////////
  538. //
  539. //  PASNObjectID
  540. //     A descendant of PASNObject which is a simple ASN ObjID type
  541. //
  542. PASNObjectID::PASNObjectID(PASNOid * val, BYTE theLen)
  543. {
  544.   value.SetSize(theLen);
  545.   memcpy(value.GetPointer(theLen), val, theLen * sizeof(PASNOid)); 
  546. }
  547. PASNObjectID::PASNObjectID(const PString & str)
  548. {
  549.   PINDEX strLen = str.GetLength();
  550.   PINDEX i = 0;
  551.   PINDEX len = 0;
  552.   while (i < strLen) {
  553.     // find the first non-dot character
  554.     while (str[i] == '.' && i < strLen)
  555.       i++;
  556.     // find the next dot
  557.     PINDEX j = str.Find('.', i);
  558.     // convert to a PASNOid
  559.     value.SetSize(len+1);
  560.     value.SetAt(len++, str(i, j).AsInteger());
  561.     i = j;
  562.   }
  563. }
  564. PASNObjectID::PASNObjectID(const PBYTEArray & buffer)
  565. {
  566.   PINDEX ptr = 0;
  567.   Decode(buffer, ptr);
  568. }
  569. PASNObjectID::PASNObjectID(const PBYTEArray & buffer, PINDEX & ptr)
  570. {
  571.   Decode(buffer, ptr);
  572. }
  573. void PASNObjectID::PrintOn(ostream & strm) const
  574. {
  575.   strm << "ObjectId: ";
  576.   for (PINDEX i = 0 ; i < value.GetSize(); i++) {
  577.     strm << value[i];
  578.     if (i != value.GetSize()-1)
  579.       strm << '.';
  580.   }
  581.   strm << endl;
  582. }
  583. void PASNObjectID::Encode(PBYTEArray & buffer)
  584. {
  585.   PBYTEArray  eObjId;
  586.   PINDEX      offs = 0;
  587.   PASNOid     subId, mask, testmask;
  588.   int         bits, testbits;
  589.   PINDEX      objIdLen = value.GetSize();
  590.   PASNOid     *objId = value.GetPointer();
  591.   if (objIdLen < 2) {
  592.     eObjId [offs++] = 0;
  593.     objIdLen = 0;
  594.   } else {
  595.     eObjId [offs++] = (BYTE)(objId[1] + (objId[0] * 40));
  596.     objIdLen -= 2;
  597.     objId += 2;
  598.   }
  599.   while (objIdLen-- > 0) {
  600.     subId = *objId++;
  601.     if (subId < 128) 
  602.       eObjId [offs++] = (BYTE)subId;
  603.     else {
  604.       mask = 0x7F; /* handle subid == 0 case */
  605.       bits = 0;
  606.       /* testmask *MUST* !!!! be of an unsigned type */
  607.       for (testmask = 0x7F, testbits = 0;
  608.            testmask != 0;
  609.            testmask <<= 7, testbits += 7) {
  610.         if (subId & testmask) {  /* if any bits set */
  611.           mask = testmask;
  612.   bits = testbits;
  613. }
  614.       }
  615.       /* mask can't be zero here */
  616.       for(;mask != 0x7F; mask >>= 7, bits -= 7) {
  617.         /* fix a mask that got truncated above */
  618. if (mask == 0x1E00000)
  619.   mask = 0xFE00000;
  620.         eObjId [offs++] = (u_char)(((subId & mask) >> bits) | ASN_BIT8);
  621.       }
  622.       eObjId [offs++] = (u_char)(subId & mask);
  623.     }
  624.   }
  625.   PINDEX s = eObjId.GetSize();
  626.   EncodeASNHeader (buffer, ObjectID, (WORD)s);
  627.   offs = buffer.GetSize();
  628.   for (PINDEX i = 0; i < s; i++)
  629.     buffer [offs + i] = eObjId[i];
  630. }
  631. WORD PASNObjectID::GetEncodedLength()
  632. {
  633.   PASNOid    subId, mask, testmask;
  634.   int        bits, testbits;
  635.   PINDEX     objIdLen = value.GetSize();
  636.   WORD       theLen = 0;
  637.   PASNOid    *objId = value.GetPointer();
  638.   if (objIdLen < 2) {
  639.     theLen++;
  640.     objIdLen = 0;
  641.   } else {
  642.     theLen++;
  643.     objIdLen -= 2;
  644.     objId += 2;
  645.   }
  646.   while (objIdLen-- > 0) {
  647.     subId = *objId++;
  648.     if (subId < 128) 
  649.       theLen++;
  650.     else {
  651.       mask = 0x7F; /* handle subid == 0 case */
  652.       bits = 0;
  653.       /* testmask *MUST* !!!! be of an unsigned type */
  654.       for (testmask = 0x7F, testbits = 0;
  655.            testmask != 0;
  656.            testmask <<= 7, testbits += 7) {
  657.         if (subId & testmask) {  /* if any bits set */
  658.           mask = testmask;
  659.   bits = testbits;
  660. }
  661.       }
  662.       /* mask can't be zero here */
  663.       for(;mask != 0x7F; mask >>= 7, bits -= 7) {
  664.         /* fix a mask that got truncated above */
  665. if (mask == 0x1E00000)
  666.   mask = 0xFE00000;
  667.         theLen++;
  668.       }
  669.       theLen++;
  670.     }
  671.   }
  672.   return (WORD)(theLen + GetASNHeaderLength(theLen));
  673. }
  674. PASNObject::ASNType PASNObjectID::GetType() const
  675. {
  676.   return ObjectID;
  677. }
  678. PString PASNObjectID::GetTypeAsString() const
  679. {
  680.   return PString("Object ID");
  681. }
  682. PString PASNObjectID::GetString() const
  683. {
  684.   PStringStream str;
  685.   for (PINDEX i = 0; i < value.GetSize(); i++) {
  686.     if (i > 0)
  687.       str << '.';
  688.     str << value[i];
  689.   }
  690.   return str;
  691. }
  692. BOOL PASNObjectID::Decode(const PBYTEArray & buffer, PINDEX & offs)
  693. {
  694.   BYTE type = buffer[offs++];
  695.   PAssert(type == (ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE),
  696.           "Attempt to decode non-objectID");
  697.   PASNOid subId;
  698.   
  699.   WORD dataLen;
  700.   if (!DecodeASNLength(buffer, offs, dataLen))
  701.     return FALSE;
  702.   value.SetSize(2);
  703.   // handle zero length strings correctly
  704.   if (dataLen != 0)  {
  705.     // start at the second identifier in the buffer, because we will later
  706.     // expand the first number into the first two IDs
  707.     PINDEX i = 1;
  708.     PINDEX s = buffer.GetSize();
  709.     while (dataLen > 0) {
  710.       subId = 0;
  711.       do {    /* shift and add in low order 7 bits */
  712.         if (dataLen == 0 || offs >= s)
  713.           return FALSE;
  714.         subId = (subId << 7) + (buffer[offs] & ~ASN_BIT8);
  715.        dataLen--;
  716.       } while (buffer[offs++] & ASN_BIT8);
  717.       value.SetAt(i++, subId);
  718.     }
  719.     /*
  720.      * The first two subidentifiers are encoded into the first component
  721.      * with the value (X * 40) + Y, where:
  722.      *  X is the value of the first subidentifier.
  723.      *  Y is the value of the second subidentifier.
  724.      */
  725.     subId = value[1];
  726.     if (subId == 0x2B) {
  727.       value[0] = 1;
  728.       value[1] = 3;
  729.     } else {
  730.       value[1] = subId % 40;
  731.       value[0] = (subId - value[1]) / 40;
  732.     }
  733.   }
  734.   return TRUE;
  735. }
  736. PObject * PASNObjectID::Clone() const
  737. {
  738.   return new PASNObjectID(*this);
  739. }
  740. //////////////////////////////////////////////////////////////////////////
  741. //
  742. //  PASNSequence
  743. //     A descendant of PASNObject which is the complex sequence type
  744. //
  745. PASNSequence::PASNSequence()
  746. {
  747.   encodedLen = 0;
  748.   type    = ASNTypeToType[Sequence];
  749.   asnType = Sequence;
  750. }
  751. PASNSequence::PASNSequence(BYTE selector)
  752. {
  753.   encodedLen = 0;
  754.   PAssert(selector < ASN_CONSTRUCTOR, "Sequence selector too big");
  755.   type    = (BYTE)(ASNTypeToType[Choice] | selector);
  756.   asnType = Choice;
  757. }
  758. void PASNSequence::Append(PASNObject * obj)
  759. {
  760.   sequence.Append(obj);
  761. }
  762. void PASNSequence::AppendInteger(PASNInt value)
  763. {
  764.   Append(new PASNInteger(value));
  765. }
  766. void PASNSequence::AppendString (const PString & str)
  767. {
  768.   Append(new PASNString(str));
  769. }
  770. void PASNSequence::AppendObjectID(const PString & str)
  771. {
  772.   Append(new PASNObjectID(str));
  773. }
  774. void PASNSequence::AppendObjectID(PASNOid * val, BYTE len)
  775. {
  776.   Append(new PASNObjectID(val, len));
  777. }
  778. void PASNSequence::PrintOn(ostream & strm) const
  779. {
  780.   strm << "Sequence:" << endl;
  781.   for (PINDEX i = 0; i < sequence.GetSize(); i++)
  782.     strm << sequence[i];
  783.   strm << "End Sequence" << endl; 
  784. }
  785. void PASNSequence::Encode(PBYTEArray & buffer) 
  786. {
  787.   // calculate the length of the sequence, if it hasn't already been done
  788.   if (encodedLen == 0)
  789.     (void)GetEncodedLength();
  790.   // create the header for the sequence. Note that seqLen was calculated
  791.   // by the call to GetEncodedLength above
  792.   EncodeASNSequenceStart(buffer, type, seqLen);
  793.   // now encode the sequence itself
  794.   for (PINDEX i = 0; i < sequence.GetSize(); i++)
  795.     sequence[i].Encode(buffer);
  796. }
  797. BOOL PASNSequence::Encode(PBYTEArray & buffer, PINDEX maxLen) 
  798. {
  799.   // calculate the length of the sequence, if it hasn't already been done
  800.   if (encodedLen == 0)
  801.     (void)GetEncodedLength();
  802.   // create the header for the sequence. Note that seqLen was calculated
  803.   // by the call to GetEncodedLength above
  804.   EncodeASNSequenceStart(buffer, type, seqLen);
  805.   // now encode the sequence itself
  806.   for (PINDEX i = 0; i < sequence.GetSize(); i++) {
  807.     sequence[i].Encode(buffer);
  808.     if (buffer.GetSize() > maxLen)
  809.       return FALSE;
  810.   }
  811.   return TRUE;
  812. }
  813. WORD PASNSequence::GetEncodedLength()
  814. {
  815.   // calculate the length of the sequence
  816.   if (encodedLen == 0) {
  817.     seqLen = 0;
  818.     for (PINDEX i = 0; i < sequence.GetSize(); i++)
  819.       seqLen = (WORD)(seqLen + sequence[i].GetEncodedLength());
  820.     encodedLen = (WORD)(GetASNSequenceStartLength(seqLen) + seqLen);
  821.   }
  822.   return encodedLen;
  823. }
  824. PASNObject::ASNType PASNSequence::GetType() const
  825. {
  826.   return asnType;
  827. }
  828. int PASNSequence::GetChoice() const
  829. {
  830.   return type;
  831. }
  832. PString PASNSequence::GetTypeAsString() const
  833. {
  834.   return PString("Sequence");
  835. }
  836. PASNSequence::PASNSequence(const PBYTEArray & buffer)
  837. {
  838.   PINDEX ptr = 0;
  839.   if (!Decode(buffer, ptr))
  840.     sequence.RemoveAll();
  841. }
  842. PASNSequence::PASNSequence(const PBYTEArray & buffer, PINDEX & ptr)
  843. {
  844.   if (!Decode(buffer, ptr))
  845.     sequence.RemoveAll();
  846. }
  847. BOOL PASNSequence::Decode(const PBYTEArray & buffer, PINDEX & ptr)
  848. {
  849.   PINDEX s = buffer.GetSize();
  850.   BYTE   c;
  851.   // all sequences start with a sequence start
  852.   if (ptr >= s)
  853.     return FALSE;
  854.   // get the sequence header
  855.   c = buffer[ptr++];
  856.   if (c == (ASN_CONSTRUCTOR | ASN_SEQUENCE)) 
  857.     asnType = Sequence;
  858.   else if ((c & ~ASN_EXTENSION_ID) == (ASN_CONSTRUCTOR | ASN_CONTEXT)) {
  859.     type    = (BYTE)(c & ASN_EXTENSION_ID);
  860.     asnType = Choice;
  861.   } else
  862.     return FALSE;
  863.   // get the sequence length
  864.   WORD len;
  865.   if (!DecodeASNLength(buffer, ptr, len))
  866.     return FALSE;
  867.   // check the length
  868.   if (ptr + len > s)
  869.     return FALSE;
  870.   // set new length
  871.   s = ptr + len;
  872.   // now decode the elements
  873.   BOOL   ok = TRUE;
  874.   while (ptr < s && ok) {
  875.     c = buffer[ptr];
  876.     if ((c & ~ASN_EXTENSION_ID) == (ASN_CONSTRUCTOR | ASN_CONTEXT)) 
  877.       sequence.Append(new PASNSequence(buffer, ptr));
  878.     else switch (c) {
  879.       // Integer
  880.       case ASN_INTEGER | ASN_UNIVERSAL | ASN_PRIMITIVE:
  881.         sequence.Append(new PASNInteger(buffer, ptr));
  882.         break;
  883.       // Octet String
  884.       case ASN_OCTET_STR | ASN_UNIVERSAL | ASN_PRIMITIVE:
  885.         sequence.Append(new PASNString(buffer, ptr));
  886.         break;
  887.       // NULL
  888.       case ASN_NULL | ASN_UNIVERSAL | ASN_PRIMITIVE:
  889.         sequence.Append(new PASNNull(buffer, ptr));
  890.         break;
  891.       // Object ID
  892.       case ASN_OBJECT_ID | ASN_UNIVERSAL | ASN_PRIMITIVE:
  893.         sequence.Append(new PASNObjectID(buffer, ptr));
  894.         break;
  895.       // Sequence
  896.       case ASN_CONSTRUCTOR | ASN_SEQUENCE:
  897.         sequence.Append(new PASNSequence(buffer, ptr));
  898.         break;
  899.       // TimeTicks
  900.       case ASN_APPLICATION | 3:
  901.         sequence.Append(new PASNTimeTicks(buffer, ptr));
  902.         break;
  903.       // Counter
  904.       case ASN_APPLICATION | 1:
  905.         sequence.Append(new PASNCounter(buffer, ptr));
  906.         break;
  907.       // Gauge
  908.       case ASN_APPLICATION | 2:
  909.         sequence.Append(new PASNGauge(buffer, ptr));
  910.         break;
  911.       // IP Address
  912.       case ASN_APPLICATION | 0:
  913.         sequence.Append(new PASNIPAddress(buffer, ptr));
  914.         break;
  915.       default:
  916.         return TRUE;
  917.     }
  918.   }
  919.   return ok;
  920. }
  921. PINDEX PASNSequence::GetSize() const
  922. {
  923.   return sequence.GetSize();
  924. }
  925. PASNObject & PASNSequence::operator [] (PINDEX idx) const
  926. {
  927.   return sequence[idx];
  928. }
  929. const PASNSequence & PASNSequence::GetSequence() const
  930. {
  931.   return *this;
  932. }
  933. PString PASNTimeTicks::GetTypeAsString() const
  934. {
  935.   return PString("TimeTicks");
  936. }
  937. PString PASNCounter::GetTypeAsString() const
  938. {
  939.   return PString("Counter");
  940. }
  941. PString PASNGauge::GetTypeAsString() const
  942. {
  943.   return PString("Gauge");
  944. }
  945. PString PASNIPAddress::GetTypeAsString() const
  946. {
  947.   return PString("IPAddress");
  948. }
  949. PString PASNIPAddress::GetString() const
  950. {
  951.   PINDEX len = value.GetSize();
  952.   if (len == 0) 
  953.     return "(empty)";
  954.   if (len < 4) {
  955.     PString out = "Hex";
  956.     for (PINDEX i = 0; i < len; i++)
  957.       out &= psprintf("%02x", (BYTE)value[i]);
  958.     return out;
  959.   }
  960.   return psprintf("%i.%i.%i.%i",
  961.          (BYTE)value[0], (BYTE)value[1],
  962.          (BYTE)value[2], (BYTE)value[3]);
  963. }
  964. PASNIPAddress::PASNIPAddress(const PString & str)
  965.   : PASNString("")
  966. {
  967.   value.SetSize(4);
  968.   PIPSocket::Address addr;
  969.   if (!PIPSocket::GetHostAddress(str, addr))
  970.     addr = 0;
  971.   int i;
  972.   for (i = 0; i < 4; i++)
  973.     value[i] = addr[i];
  974.   valueLen = 4;
  975. }
  976. PIPSocket::Address PASNIPAddress::GetIPAddress () const
  977. {
  978.   return PIPSocket::Address((BYTE)value[0], (BYTE)value[1],
  979.                             (BYTE)value[2], (BYTE)value[3]);
  980. }
  981. PASNNull::PASNNull()
  982. {
  983. }
  984. PASNNull::PASNNull(const PBYTEArray & buffer, PINDEX & ptr)
  985. {
  986.   PAssert(((buffer.GetSize() - ptr) >= 2) &&
  987.           (buffer[ptr+0] == 0x05) &&
  988.           (buffer[ptr+1] == 0x00),
  989.     "Attempt to decode non-null");
  990.   ptr += 2 ;
  991. }
  992. void PASNNull::PrintOn(ostream & strm) const
  993. {
  994.   strm << "Null"
  995.        << endl;
  996. }
  997. void PASNNull::Encode(PBYTEArray & buffer)
  998. {
  999.   EncodeASNHeader(buffer, Null, 0);
  1000. }
  1001. WORD PASNNull::GetEncodedLength()
  1002. {
  1003.   return 2;
  1004. }
  1005. PObject * PASNNull::Clone() const
  1006. {
  1007.   return new PASNNull();
  1008. }
  1009. PASNObject::ASNType PASNNull::GetType() const
  1010. {
  1011.   return Null;
  1012. }
  1013. PString PASNNull::GetTypeAsString() const
  1014. {
  1015.   return PString("Null");
  1016. }
  1017. PString PASNNull::GetString() const
  1018. {
  1019.   return PString();
  1020. }
  1021. // End Of File ///////////////////////////////////////////////////////////////