⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pasn.cxx

📁 开源代码的pwlib的1.10.0版本,使用openh323的1.18.0版本毕备
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * pasn.cxx
 *
 * ASN classes in support of the SNMP code.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-2002 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.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: pasn.cxx,v $
 * Revision 1.17  2005/11/30 12:47:41  csoutheren
 * Removed tabs, reformatted some code, and changed tags for Doxygen
 *
 * Revision 1.16  2004/04/03 06:54:25  rjongbloed
 * Many and various changes to support new Visual C++ 2003
 *
 * Revision 1.15  2002/11/06 22:47:25  robertj
 * Fixed header comment (copyright etc)
 *
 * 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 = 0x1FFUL << ((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 = 0xFFUL << (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 = 0xFFUL << (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 = 0x1FFUL << ((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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -