4 * ASN classes in support of the SNMP code.
6 * Portable Windows Library
8 * Copyright (c) 1993-2002 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.16 2004/04/03 06:54:25 rjongbloed
28 * Many and various changes to support new Visual C++ 2003
30 * Revision 1.15 2002/11/06 22:47:25 robertj
31 * Fixed header comment (copyright etc)
33 * Revision 1.14 2000/05/05 10:08:29 robertj
34 * Fixed some GNU compiler warnings
36 * Revision 1.13 1999/05/01 11:29:20 robertj
37 * Alpha linux port changes.
39 * Revision 1.12 1999/05/01 03:52:20 robertj
40 * Fixed various egcs warnings.
42 * Revision 1.11 1999/03/02 01:53:38 craigs
43 * Fixed problem with creating IpAddress objects
45 * Revision 1.10 1999/02/16 08:08:06 robertj
46 * MSVC 6.0 compatibility changes.
48 * Revision 1.9 1998/11/30 04:52:04 robertj
49 * New directory structure
51 * Revision 1.8 1998/10/13 14:06:31 robertj
52 * Complete rewrite of memory leak detection code.
54 * Revision 1.7 1998/09/23 06:22:27 robertj
55 * Added open source copyright license.
57 * Revision 1.6 1998/02/16 06:57:05 robertj
58 * Moved pragma implemenetation in here so do not need upasn.cxx file.
60 * Revision 1.7 1998/01/26 02:49:21 robertj
63 * Revision 1.6 1998/01/26 01:45:36 robertj
64 * Removed unused variable.
66 * Revision 1.5 1997/08/20 09:00:37 craigs
67 * Fixed problems with decoding of PASNNull
69 * Revision 1.4 1997/07/20 08:34:37 craigs
72 * Revision 1.3 1997/07/16 05:52:48 craigs
73 * Changed ASN constructors to store value length separately so
74 * ASNString consctructor will worki correctly
76 * Revision 1.2 1996/11/04 03:58:34 robertj
77 * Added ASN types to class.
79 * Revision 1.1 1996/09/14 13:02:18 robertj
85 #pragma implementation "pasn.h"
89 #include <ptclib/pasn.h>
94 #define ASN_BOOLEAN (0x01)
95 #define ASN_INTEGER (0x02)
96 #define ASN_BIT_STR (0x03)
97 #define ASN_OCTET_STR (0x04)
98 #define ASN_NULL (0x05)
99 #define ASN_OBJECT_ID (0x06)
100 #define ASN_SEQUENCE (0x10)
101 #define ASN_SET (0x11)
103 #define ASN_UNIVERSAL (0x00)
104 #define ASN_APPLICATION (0x40)
105 #define ASN_CONTEXT (0x80)
106 #define ASN_PRIVATE (0xC0)
108 #define ASN_PRIMITIVE (0x00)
109 #define ASN_CONSTRUCTOR (0x20)
111 #define ASN_LONG_LEN (0x80)
112 #define ASN_EXTENSION_ID (0x1F)
113 #define ASN_BIT8 (0x80)
115 #define MAX_OID_LEN 64
118 static char cannotPerformOnBaseTypeMsg
[] =
119 "Cannot perform operation on base type PASNObject";
122 BYTE
PASNObject::ASNTypeToType
[] = {
123 ASN_INTEGER
| ASN_UNIVERSAL
| ASN_PRIMITIVE
, // Integer
124 ASN_OCTET_STR
| ASN_UNIVERSAL
| ASN_PRIMITIVE
, // String
125 ASN_OBJECT_ID
| ASN_UNIVERSAL
| ASN_PRIMITIVE
, // ObjectID
126 ASN_CONSTRUCTOR
| ASN_SEQUENCE
, // Sequence
127 ASN_CONSTRUCTOR
| ASN_CONTEXT
, // Choice
128 ASN_APPLICATION
| 0, // IPAddress
129 ASN_APPLICATION
| 1, // Counter32
130 ASN_APPLICATION
| 2, // Gauge32
131 ASN_APPLICATION
| 3, // TimeTicks
134 ASN_APPLICATION
| 4, // Opaque
135 ASN_APPLICATION
| 5, // NsapAddress
136 ASN_APPLICATION
| 6, // Counter64
137 ASN_APPLICATION
| 7, // UInteger32
139 // Oops - missed the Null type
140 ASN_NULL
| ASN_UNIVERSAL
| ASN_PRIMITIVE
, // Null
147 //////////////////////////////////////////////////////////////////////////
150 // All ASN objects descend from this class. It is the primitive type
151 // which can be put into the ASNSequence class
154 PASNObject::PASNObject()
159 void PASNObject::PrintOn(ostream
&) const
161 PAssertAlways(cannotPerformOnBaseTypeMsg
);
165 void PASNObject::Encode(PBYTEArray
&)
167 PAssertAlways(cannotPerformOnBaseTypeMsg
);
171 WORD
PASNObject::GetEncodedLength()
173 PAssertAlways(cannotPerformOnBaseTypeMsg
);
178 PASNObject::ASNType
PASNObject::GetType() const
180 PAssertAlways(cannotPerformOnBaseTypeMsg
);
185 PString
PASNObject::GetTypeAsString() const
187 PAssertAlways(cannotPerformOnBaseTypeMsg
);
192 PObject
* PASNObject::Clone() const
194 PAssertAlways(cannotPerformOnBaseTypeMsg
);
199 void PASNObject::EncodeASNLength (PBYTEArray
& buffer
, WORD length
)
201 PINDEX offs
= buffer
.GetSize();
203 // handle lengths less then 128
205 buffer
[offs
++] = (BYTE
)length
;
207 // handle lengths less than 256
208 else if (length
< 256) {
209 buffer
[offs
++] = (BYTE
)(0x01 | ASN_LONG_LEN
);
210 buffer
[offs
++] = (BYTE
)length
;
213 // handle lengths up to 0xffff
215 buffer
[offs
++] = (u_char
)(0x02 | ASN_LONG_LEN
);
216 buffer
[offs
++] = (u_char
)((length
>> 8) & 0xFF);
217 buffer
[offs
++] = (u_char
)(length
& 0xFF);
222 BOOL
PASNObject::DecodeASNLength (const PBYTEArray
& buffer
, PINDEX
& ptr
, WORD
& len
)
224 PINDEX s
= buffer
.GetSize();
229 BYTE ch
= buffer
[ptr
++];
231 if ((ch
& ASN_LONG_LEN
) == 0)
233 else if ((ch
& ~ASN_LONG_LEN
) == 0x01) {
236 len
= (WORD
)buffer
[ptr
++];
240 len
= (WORD
)((buffer
[ptr
] << 8) + buffer
[ptr
+1]);
247 WORD
PASNObject::GetASNLengthLength (WORD length
)
249 // handle lengths less then 128
253 // handle lengths less than 256
254 else if (length
< 256)
257 // handle lengths up to 0xffff
263 void PASNObject::EncodeASNSequenceStart(PBYTEArray
& buffer
, BYTE type
, WORD length
)
265 buffer
[buffer
.GetSize()] = type
;
266 EncodeASNLength(buffer
, length
);
270 WORD
PASNObject::GetASNSequenceStartLength(WORD length
)
272 return (WORD
)(1 + GetASNLengthLength(length
));
276 void PASNObject::EncodeASNHeader(PBYTEArray
& buffer
, PASNObject::ASNType type
, WORD length
)
279 buffer
[buffer
.GetSize()] = ASNTypeToType
[type
];
280 EncodeASNLength(buffer
, length
);
284 WORD
PASNObject::GetASNHeaderLength(WORD length
)
286 return (WORD
)(1 + GetASNLengthLength(length
));
290 void PASNObject::EncodeASNInteger (PBYTEArray
& buffer
, PASNInt data
, PASNObject::ASNType type
)
293 WORD intsize
= sizeof(data
);
295 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
296 // on a big endian machine
297 mask
= 0x1FFUL
<< ((8 * (sizeof(DWORD
) - 1)) - 1);
299 // remove all sequences of nine 0's or 1's at the start of the value
300 while ((((data
& mask
) == 0) || ((data
& mask
) == mask
))
307 EncodeASNHeader(buffer
, type
, intsize
);
310 PINDEX offs
= buffer
.GetSize();
311 mask
= 0xFFUL
<< (8 * (sizeof(DWORD
) - 1));
313 buffer
[offs
++] = (u_char
)((data
& mask
) >> (8 * (sizeof(DWORD
) - 1)));
319 void PASNObject::EncodeASNUnsigned (PBYTEArray
& buffer
, PASNUnsigned data
, PASNObject::ASNType type
)
322 WORD intsize
= sizeof(data
);
323 int add_null_byte
= 0;
325 mask
= 0xFFUL
<< (8 * (sizeof(long) - 1));
326 /* mask is 0xFF000000 on a big-endian machine */
327 if ((u_char
)((data
& mask
) >> (8 * (sizeof(PASNUnsigned
) - 1))) & 0x80){
333 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
334 // on a big endian machine
335 mask
= 0x1FFL
<< ((8 * (sizeof(DWORD
) - 1)) - 1);
337 // remove all sequences of nine 0's or 1's at the start of the value
338 while ((((data
& mask
) == 0) || (((long)data
& mask
) == mask
))
345 EncodeASNHeader(buffer
, type
, intsize
);
348 PINDEX offs
= buffer
.GetSize();
349 mask
= 0xFFL
<< (8 * (sizeof(DWORD
) - 1));
351 buffer
[offs
++] = (u_char
)((data
& mask
) >> (8 * (sizeof(DWORD
) - 1)));
355 if (add_null_byte
== 1)
360 BOOL
PASNObject::DecodeASNInteger(const PBYTEArray
& buffer
, PINDEX
& ptr
, PASNInt
& value
, PASNObject::ASNType theType
)
362 if (buffer
[ptr
++] != ASNTypeToType
[theType
])
366 if (!DecodeASNLength(buffer
, ptr
, len
))
369 if (ptr
+ len
> buffer
.GetSize())
372 if (buffer
[ptr
] & 0x80)
373 value
= -1; /* integer is negative */
378 value
= (value
<< 8) | buffer
[ptr
++];
383 BOOL
PASNObject::DecodeASNUnsigned(const PBYTEArray
& buffer
, PINDEX
& ptr
, PASNUnsigned
& value
, PASNObject::ASNType theType
)
385 if (buffer
[ptr
++] != ASNTypeToType
[theType
])
389 if (!DecodeASNLength(buffer
, ptr
, len
))
392 if (ptr
+ len
> buffer
.GetSize())
395 // if (buffer[ptr] & 0x80)
396 // value = -1; /* integer is negative */
400 value
= (value
<< 8) | buffer
[ptr
++];
405 WORD
PASNObject::GetASNIntegerLength(PASNInt data
)
408 WORD intsize
= sizeof(data
);
410 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
411 // on a big endian machine
412 mask
= 0x1FFUL
<< ((8 * (sizeof(DWORD
) - 1)) - 1);
414 // remove all sequences of nine 0's or 1's at the start of the value
415 while ((((data
& mask
) == 0) || ((data
& mask
) == mask
))
421 // get the length of the header
422 return (WORD
)(intsize
+ GetASNHeaderLength(intsize
));
426 WORD
PASNObject::GetASNUnsignedLength (PASNUnsigned data
)
429 WORD intsize
= sizeof(data
);
430 int add_null_byte
= 0;
432 mask
= 0xFFL
<< (8 * (sizeof(long) - 1));
433 /* mask is 0xFF000000 on a big-endian machine */
434 if ((u_char
)((data
& mask
) >> (8 * (sizeof(PASNUnsigned
) - 1))) & 0x80) {
440 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
441 // on a big endian machine
442 mask
= 0x1FFL
<< ((8 * (sizeof(DWORD
) - 1)) - 1);
444 // remove all sequences of nine 0's or 1's at the start of the value
445 while ((((data
& mask
) == 0) || (((long)data
& mask
) == mask
))
452 return (WORD
)(intsize
+ GetASNHeaderLength(intsize
) + add_null_byte
);
456 PASNInt
PASNObject::GetInteger () const
458 PAssertAlways("Cannot return ASN object as Integer");
463 PString
PASNObject::GetString () const
465 PAssertAlways("Cannot return ASN object as String");
470 PASNUnsigned
PASNObject::GetUnsigned() const
472 PAssertAlways("Cannot return ASN object as Unsigned");
477 const PASNSequence
& PASNObject::GetSequence() const
479 PAssertAlways("Cannot return ASN object as Sequence");
480 PASNSequence
* ptr
= NULL
;
481 return (PASNSequence
&)*ptr
;
485 PIPSocket::Address
PASNObject::GetIPAddress () const
487 PAssertAlways("Cannot return ASN object as IP Address");
488 return PIPSocket::Address();
492 //////////////////////////////////////////////////////////////////////////
495 // A descendant of PASNObject which is a simple ASN integer type
498 PASNInteger::PASNInteger(PASNInt val
)
504 PASNInteger::PASNInteger(const PBYTEArray
& buffer
, PINDEX
& ptr
)
506 DecodeASNInteger(buffer
, ptr
, value
, Integer
);
510 void PASNInteger::PrintOn(ostream
& strm
) const
517 void PASNInteger::Encode(PBYTEArray
& buffer
)
519 EncodeASNInteger(buffer
, value
, Integer
);
523 WORD
PASNInteger::GetEncodedLength()
525 return GetASNIntegerLength(value
);
529 PASNObject::ASNType
PASNInteger::GetType() const
535 PString
PASNInteger::GetTypeAsString() const
537 return PString("Integer");
541 PASNInt
PASNInteger::GetInteger () const
547 PString
PASNInteger::GetString () const
549 return PString(PString::Signed
, (long)value
);
553 PObject
* PASNInteger::Clone() const
555 return new PASNInteger(*this);
559 //////////////////////////////////////////////////////////////////////////
562 // A descendant of PASNObject which is a simple ASN OctetStr type
565 PASNString::PASNString(const PString
& str
)
568 valueLen
= (WORD
)str
.GetLength();
571 PASNString::PASNString(const BYTE
* ptr
, int len
)
573 value
= PString((const char *)ptr
, len
);
574 valueLen
= (WORD
)len
;
577 PASNString::PASNString(const PBYTEArray
& buffer
, PASNObject::ASNType type
)
580 Decode(buffer
, ptr
, type
);
584 PASNString::PASNString(const PBYTEArray
& buffer
, PINDEX
& ptr
, PASNObject::ASNType type
)
586 Decode(buffer
, ptr
, type
);
590 BOOL
PASNString::Decode(const PBYTEArray
& buffer
, PINDEX
& ptr
, PASNObject::ASNType type
)
593 if (buffer
[ptr
++] != ASNTypeToType
[type
])
596 if (!DecodeASNLength(buffer
, ptr
, valueLen
))
599 if (ptr
+ valueLen
> buffer
.GetSize())
602 value
= PString(ptr
+ (const char *)(const BYTE
*)buffer
, valueLen
);
609 void PASNString::PrintOn(ostream
& strm
) const
611 strm
<< GetTypeAsString()
618 void PASNString::Encode(PBYTEArray
& buffer
, PASNObject::ASNType type
)
621 EncodeASNHeader(buffer
, type
, valueLen
);
624 PINDEX offs
= buffer
.GetSize();
625 for (PINDEX i
= 0; i
< valueLen
; i
++)
626 buffer
[offs
+i
] = value
[i
];
630 WORD
PASNString::GetEncodedLength()
632 return (WORD
)(GetASNHeaderLength(valueLen
) + (int)valueLen
);
636 PASNObject::ASNType
PASNString::GetType() const
642 PString
PASNString::GetTypeAsString() const
644 return PString("String");
648 PString
PASNString::GetString () const
654 PObject
* PASNString::Clone() const
656 return new PASNString(*this);
660 //////////////////////////////////////////////////////////////////////////
662 // PASNUnsignedInteger
663 // A descendant of PASNObject which is an unsigned integer
665 BOOL
PASNUnsignedInteger::Decode(const PBYTEArray
& buffer
, PINDEX
& ptr
, PASNObject::ASNType theType
)
667 return DecodeASNUnsigned(buffer
, ptr
, value
, theType
);
671 void PASNUnsignedInteger::Encode(PBYTEArray
& buffer
, PASNObject::ASNType theType
)
673 EncodeASNUnsigned(buffer
, value
, theType
);
677 void PASNUnsignedInteger::PrintOn(ostream
& strm
) const
679 strm
<< GetTypeAsString()
686 WORD
PASNUnsignedInteger::GetEncodedLength()
688 return GetASNUnsignedLength(value
);
692 PString
PASNUnsignedInteger::GetString() const
694 return PString(PString::Unsigned
, (long)value
);
698 PASNUnsigned
PASNUnsignedInteger::GetUnsigned() const
704 //////////////////////////////////////////////////////////////////////////
707 // A descendant of PASNObject which is a simple ASN ObjID type
710 PASNObjectID::PASNObjectID(PASNOid
* val
, BYTE theLen
)
712 value
.SetSize(theLen
);
713 memcpy(value
.GetPointer(theLen
), val
, theLen
* sizeof(PASNOid
));
717 PASNObjectID::PASNObjectID(const PString
& str
)
719 PINDEX strLen
= str
.GetLength();
725 // find the first non-dot character
726 while (str
[i
] == '.' && i
< strLen
)
730 PINDEX j
= str
.Find('.', i
);
732 // convert to a PASNOid
733 value
.SetSize(len
+1);
734 value
.SetAt(len
++, str(i
, j
).AsInteger());
740 PASNObjectID::PASNObjectID(const PBYTEArray
& buffer
)
747 PASNObjectID::PASNObjectID(const PBYTEArray
& buffer
, PINDEX
& ptr
)
753 void PASNObjectID::PrintOn(ostream
& strm
) const
755 strm
<< "ObjectId: ";
756 for (PINDEX i
= 0 ; i
< value
.GetSize(); i
++) {
758 if (i
!= value
.GetSize()-1)
765 void PASNObjectID::Encode(PBYTEArray
& buffer
)
769 PASNOid subId
, mask
, testmask
;
771 PINDEX objIdLen
= value
.GetSize();
772 PASNOid
*objId
= value
.GetPointer();
778 eObjId
[offs
++] = (BYTE
)(objId
[1] + (objId
[0] * 40));
783 while (objIdLen
-- > 0) {
786 eObjId
[offs
++] = (BYTE
)subId
;
788 mask
= 0x7F; /* handle subid == 0 case */
791 /* testmask *MUST* !!!! be of an unsigned type */
792 for (testmask
= 0x7F, testbits
= 0;
794 testmask
<<= 7, testbits
+= 7) {
795 if (subId
& testmask
) { /* if any bits set */
801 /* mask can't be zero here */
802 for(;mask
!= 0x7F; mask
>>= 7, bits
-= 7) {
803 /* fix a mask that got truncated above */
804 if (mask
== 0x1E00000)
806 eObjId
[offs
++] = (u_char
)(((subId
& mask
) >> bits
) | ASN_BIT8
);
808 eObjId
[offs
++] = (u_char
)(subId
& mask
);
812 PINDEX s
= eObjId
.GetSize();
813 EncodeASNHeader (buffer
, ObjectID
, (WORD
)s
);
814 offs
= buffer
.GetSize();
815 for (PINDEX i
= 0; i
< s
; i
++)
816 buffer
[offs
+ i
] = eObjId
[i
];
820 WORD
PASNObjectID::GetEncodedLength()
822 PASNOid subId
, mask
, testmask
;
824 PINDEX objIdLen
= value
.GetSize();
826 PASNOid
*objId
= value
.GetPointer();
837 while (objIdLen
-- > 0) {
842 mask
= 0x7F; /* handle subid == 0 case */
845 /* testmask *MUST* !!!! be of an unsigned type */
846 for (testmask
= 0x7F, testbits
= 0;
848 testmask
<<= 7, testbits
+= 7) {
849 if (subId
& testmask
) { /* if any bits set */
855 /* mask can't be zero here */
856 for(;mask
!= 0x7F; mask
>>= 7, bits
-= 7) {
857 /* fix a mask that got truncated above */
858 if (mask
== 0x1E00000)
866 return (WORD
)(theLen
+ GetASNHeaderLength(theLen
));
870 PASNObject::ASNType
PASNObjectID::GetType() const
876 PString
PASNObjectID::GetTypeAsString() const
878 return PString("Object ID");
882 PString
PASNObjectID::GetString() const
886 for (PINDEX i
= 0; i
< value
.GetSize(); i
++) {
896 BOOL
PASNObjectID::Decode(const PBYTEArray
& buffer
, PINDEX
& offs
)
898 BYTE type
= buffer
[offs
++];
899 PAssert(type
== (ASN_OBJECT_ID
| ASN_UNIVERSAL
| ASN_PRIMITIVE
),
900 "Attempt to decode non-objectID");
904 if (!DecodeASNLength(buffer
, offs
, dataLen
))
909 // handle zero length strings correctly
912 // start at the second identifier in the buffer, because we will later
913 // expand the first number into the first two IDs
915 PINDEX s
= buffer
.GetSize();
917 while (dataLen
> 0) {
919 do { /* shift and add in low order 7 bits */
920 if (dataLen
== 0 || offs
>= s
)
922 subId
= (subId
<< 7) + (buffer
[offs
] & ~ASN_BIT8
);
924 } while (buffer
[offs
++] & ASN_BIT8
);
925 value
.SetAt(i
++, subId
);
929 * The first two subidentifiers are encoded into the first component
930 * with the value (X * 40) + Y, where:
931 * X is the value of the first subidentifier.
932 * Y is the value of the second subidentifier.
939 value
[1] = subId
% 40;
940 value
[0] = (subId
- value
[1]) / 40;
948 PObject
* PASNObjectID::Clone() const
950 return new PASNObjectID(*this);
955 //////////////////////////////////////////////////////////////////////////
958 // A descendant of PASNObject which is the complex sequence type
961 PASNSequence::PASNSequence()
964 type
= ASNTypeToType
[Sequence
];
969 PASNSequence::PASNSequence(BYTE selector
)
972 PAssert(selector
< ASN_CONSTRUCTOR
, "Sequence selector too big");
973 type
= (BYTE
)(ASNTypeToType
[Choice
] | selector
);
978 void PASNSequence::Append(PASNObject
* obj
)
980 sequence
.Append(obj
);
984 void PASNSequence::AppendInteger(PASNInt value
)
986 Append(new PASNInteger(value
));
990 void PASNSequence::AppendString (const PString
& str
)
992 Append(new PASNString(str
));
996 void PASNSequence::AppendObjectID(const PString
& str
)
998 Append(new PASNObjectID(str
));
1002 void PASNSequence::AppendObjectID(PASNOid
* val
, BYTE len
)
1004 Append(new PASNObjectID(val
, len
));
1008 void PASNSequence::PrintOn(ostream
& strm
) const
1010 strm
<< "Sequence:" << endl
;
1011 for (PINDEX i
= 0; i
< sequence
.GetSize(); i
++)
1012 strm
<< sequence
[i
];
1013 strm
<< "End Sequence" << endl
;
1017 void PASNSequence::Encode(PBYTEArray
& buffer
)
1019 // calculate the length of the sequence, if it hasn't already been done
1020 if (encodedLen
== 0)
1021 (void)GetEncodedLength();
1023 // create the header for the sequence. Note that seqLen was calculated
1024 // by the call to GetEncodedLength above
1025 EncodeASNSequenceStart(buffer
, type
, seqLen
);
1027 // now encode the sequence itself
1028 for (PINDEX i
= 0; i
< sequence
.GetSize(); i
++)
1029 sequence
[i
].Encode(buffer
);
1032 BOOL
PASNSequence::Encode(PBYTEArray
& buffer
, PINDEX maxLen
)
1034 // calculate the length of the sequence, if it hasn't already been done
1035 if (encodedLen
== 0)
1036 (void)GetEncodedLength();
1038 // create the header for the sequence. Note that seqLen was calculated
1039 // by the call to GetEncodedLength above
1040 EncodeASNSequenceStart(buffer
, type
, seqLen
);
1042 // now encode the sequence itself
1043 for (PINDEX i
= 0; i
< sequence
.GetSize(); i
++) {
1044 sequence
[i
].Encode(buffer
);
1045 if (buffer
.GetSize() > maxLen
)
1053 WORD
PASNSequence::GetEncodedLength()
1055 // calculate the length of the sequence
1056 if (encodedLen
== 0) {
1058 for (PINDEX i
= 0; i
< sequence
.GetSize(); i
++)
1059 seqLen
= (WORD
)(seqLen
+ sequence
[i
].GetEncodedLength());
1060 encodedLen
= (WORD
)(GetASNSequenceStartLength(seqLen
) + seqLen
);
1066 PASNObject::ASNType
PASNSequence::GetType() const
1072 int PASNSequence::GetChoice() const
1078 PString
PASNSequence::GetTypeAsString() const
1080 return PString("Sequence");
1084 PASNSequence::PASNSequence(const PBYTEArray
& buffer
)
1088 if (!Decode(buffer
, ptr
))
1089 sequence
.RemoveAll();
1093 PASNSequence::PASNSequence(const PBYTEArray
& buffer
, PINDEX
& ptr
)
1095 if (!Decode(buffer
, ptr
))
1096 sequence
.RemoveAll();
1100 BOOL
PASNSequence::Decode(const PBYTEArray
& buffer
, PINDEX
& ptr
)
1102 PINDEX s
= buffer
.GetSize();
1105 // all sequences start with a sequence start
1109 // get the sequence header
1111 if (c
== (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
1113 else if ((c
& ~ASN_EXTENSION_ID
) == (ASN_CONSTRUCTOR
| ASN_CONTEXT
)) {
1114 type
= (BYTE
)(c
& ASN_EXTENSION_ID
);
1119 // get the sequence length
1121 if (!DecodeASNLength(buffer
, ptr
, len
))
1131 // now decode the elements
1133 while (ptr
< s
&& ok
) {
1135 if ((c
& ~ASN_EXTENSION_ID
) == (ASN_CONSTRUCTOR
| ASN_CONTEXT
))
1136 sequence
.Append(new PASNSequence(buffer
, ptr
));
1140 case ASN_INTEGER
| ASN_UNIVERSAL
| ASN_PRIMITIVE
:
1141 sequence
.Append(new PASNInteger(buffer
, ptr
));
1145 case ASN_OCTET_STR
| ASN_UNIVERSAL
| ASN_PRIMITIVE
:
1146 sequence
.Append(new PASNString(buffer
, ptr
));
1150 case ASN_NULL
| ASN_UNIVERSAL
| ASN_PRIMITIVE
:
1151 sequence
.Append(new PASNNull(buffer
, ptr
));
1155 case ASN_OBJECT_ID
| ASN_UNIVERSAL
| ASN_PRIMITIVE
:
1156 sequence
.Append(new PASNObjectID(buffer
, ptr
));
1160 case ASN_CONSTRUCTOR
| ASN_SEQUENCE
:
1161 sequence
.Append(new PASNSequence(buffer
, ptr
));
1165 case ASN_APPLICATION
| 3:
1166 sequence
.Append(new PASNTimeTicks(buffer
, ptr
));
1170 case ASN_APPLICATION
| 1:
1171 sequence
.Append(new PASNCounter(buffer
, ptr
));
1175 case ASN_APPLICATION
| 2:
1176 sequence
.Append(new PASNGauge(buffer
, ptr
));
1180 case ASN_APPLICATION
| 0:
1181 sequence
.Append(new PASNIPAddress(buffer
, ptr
));
1193 PINDEX
PASNSequence::GetSize() const
1195 return sequence
.GetSize();
1199 PASNObject
& PASNSequence::operator [] (PINDEX idx
) const
1201 return sequence
[idx
];
1205 const PASNSequence
& PASNSequence::GetSequence() const
1211 PString
PASNTimeTicks::GetTypeAsString() const
1213 return PString("TimeTicks");
1217 PString
PASNCounter::GetTypeAsString() const
1219 return PString("Counter");
1223 PString
PASNGauge::GetTypeAsString() const
1225 return PString("Gauge");
1229 PString
PASNIPAddress::GetTypeAsString() const
1231 return PString("IPAddress");
1235 PString
PASNIPAddress::GetString() const
1237 PINDEX len
= value
.GetSize();
1242 PString out
= "Hex";
1243 for (PINDEX i
= 0; i
< len
; i
++)
1244 out
&= psprintf("%02x", (BYTE
)value
[i
]);
1248 return psprintf("%i.%i.%i.%i",
1249 (BYTE
)value
[0], (BYTE
)value
[1],
1250 (BYTE
)value
[2], (BYTE
)value
[3]);
1254 PASNIPAddress::PASNIPAddress(const PString
& str
)
1259 PIPSocket::Address addr
;
1260 if (!PIPSocket::GetHostAddress(str
, addr
))
1264 for (i
= 0; i
< 4; i
++)
1271 PIPSocket::Address
PASNIPAddress::GetIPAddress () const
1273 return PIPSocket::Address((BYTE
)value
[0], (BYTE
)value
[1],
1274 (BYTE
)value
[2], (BYTE
)value
[3]);
1277 PASNNull::PASNNull()
1281 PASNNull::PASNNull(const PBYTEArray
& buffer
, PINDEX
& ptr
)
1283 PAssert(((buffer
.GetSize() - ptr
) >= 2) &&
1284 (buffer
[ptr
+0] == 0x05) &&
1285 (buffer
[ptr
+1] == 0x00),
1286 "Attempt to decode non-null");
1290 void PASNNull::PrintOn(ostream
& strm
) const
1296 void PASNNull::Encode(PBYTEArray
& buffer
)
1298 EncodeASNHeader(buffer
, Null
, 0);
1301 WORD
PASNNull::GetEncodedLength()
1306 PObject
* PASNNull::Clone() const
1308 return new PASNNull();
1311 PASNObject::ASNType
PASNNull::GetType() const
1316 PString
PASNNull::GetTypeAsString() const
1318 return PString("Null");
1321 PString
PASNNull::GetString() const
1328 // End Of File ///////////////////////////////////////////////////////////////