📄 pasn.cxx
字号:
/*
* 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 + -