How do I use the ANY type?

The ANY type, like the open type, is encoded and decoded separately from its containing structure. Suppose we have the following ASN.1 definition:

Module DEFINITIONS ::= BEGIN
MyASN1DataType ::= SEQUENCE {
field1 REAL,
field2 INTEGER,
field3 ANY
}
SeparateType ::= IA5String
END

the resultant header file will contain:

#define MyASN1DataType_PDU 1
#define SeparateType_PDU 2

typedef struct Any {
unsigned long length;
unsigned char *value;
} Any;

typedef struct MyASN1DataType {
double field1;
int field2;
Any field3;
} MyASN1DataType;

typedef char *SeparateType;

Then, before passing MyASN1DataType for encoding, we would encode the data to be stored in field3 (which is of type ANY). In this particular example, we wish to fill the ANY type with character data to be stored in a variable of type SeparateType.

After encoding the data for the ANY type, we would set the fields of the ANY type to reference this pre-encoded data. After which, the containing structure (i.e. MyASN1DataType) could be passed for encoding. The encoder will recognize field3 as an ANY type and pass its contents to the output buffer without modification.

Similarly when decoding, the data in the ANY type would be decoded separately from its containing structure. So after the rest of the structure is decoded, the encoding contained in the Any type will have to be copied to a new OssBuf type variable and sent for decoding by itself again.

The above noted process is illustrated by the following simple application program:

/* Application Program: test.c */
/* Illustrates the use of the ANY type */

#include <stdio.h>
#include <string.h>
#include "asn1data.h" /* compiler-generated header file */

/* Tries to encode a data packet and then decodes it. */

int main(void)
{
OssBuf encodedData; /* length and address of encoded data */
OssBuf anyTypePreEncoding, anyTypePostEncoding;
MyASN1DataType myData, *decodedDataPtr = NULL;
SeparateType anyTypeValue, *anyTypeDecodedPtr = NULL;
int anyTypePduNum, myPduNum = 0;
int retcode;
ossGlobal w, *world = &w;
char *bufBookmark, *anyTypeBufBookmark;
char tempStr[50];

/*
* Do initializations.
*/
retcode = ossinit(world, asn1data);
if (retcode) {
printf("Error. Call to ossinit() unsuccessful.\n");
return retcode;
}
ossSetEncodingFlags(world, DEBUGPDU); /* Turn on trace capabilities. */
ossSetDecodingFlags(world, DEBUGPDU); 
/*
* Fill compiler-generated structure with values.
*/
myPduNum = MyASN1DataType_PDU;
myData.field1 = 1.123;
myData.field2 = 456;
strcpy(tempStr, "A message for the ANY type.");
anyTypeValue = tempStr;
anyTypePreEncoding.value = NULL; /* initialize encoder's output buffer */
anyTypePreEncoding.length = 0;
ossPrint(world, "Pre-encoding ANY type value:\n\n");
/*
* Pre-encode value for the ANY type.
*/
anyTypePduNum = SeparateType_PDU;
if(ossEncode(world, anyTypePduNum, &anyTypeValue, &anyTypePreEncoding)) {
ossPrint(world, "Error pre-encoding ANY type value: %s",
ossGetErrMsg(world));
ossterm(world);
return 1;
}
ossPrint(world, "\nANY type value pre-encoded to:\n\n");
ossPrintHex(world, anyTypePreEncoding.value, anyTypePreEncoding.length);
anyTypeBufBookmark = (char *)anyTypePreEncoding.value;
/*
* Set ANY type to reference pre-encoded data.
*/
myData.field3.value = anyTypePreEncoding.value;
myData.field3.length = anyTypePreEncoding.length;
/*
* Print to stdout the intended input to the encoder.
*/
ossPrint(world, "\nThe input to the encoder is:\n\n");
ossPrintPDU(world, myPduNum, &myData);
encodedData.value = NULL; /* Initialize encoder's output buffer */
encodedData.length = 0;
ossPrint(world, "\nCalling the encoder...\n\n");
if(ossEncode(world, MyASN1DataType_PDU, &myData, &encodedData)) {
ossPrint(world, "Error encoding containing type: %s",
ossGetErrMsg(world));
retcode = 1;
}
else {
/*
* Encoded containing type value successfully.
*/
ossPrint(world, "\nData encoded.\n\n"); /* successfully encoded */
bufBookmark = (char *)encodedData.value; /* save the address of the buffer with the encoded data. */
ossPrint(world, "\nCalling the decoder...\n\n");
if(ossDecode(world, &myPduNum, &encodedData, (void **) &decodedDataPtr)) {
ossPrint(world, "Error decoding containing type: %s", ossGetErrMsg(world));
ossterm(world);
return 2;
}
else {
/*
* Decoded containing type value successfully.
*/
/*
* Print out the data that was just decoded.
*/
ossPrint(world, "\nData decoded.\n\n"); /* successfully decoded */
ossPrint(world, "The decoded Data has \n field1: %3.3f", decodedDataPtr->field1);
ossPrint(world, "\n field2: %d\n", decodedDataPtr->field2);
/*
* Now, do a decode of the ANY type value.
*/
anyTypePduNum = SeparateType_PDU;
anyTypePostEncoding.value =
(char*)malloc(decodedDataPtr->field3.length*sizeof(char));
memcpy(anyTypePostEncoding.value, decodedDataPtr->field3.value, decodedDataPtr->field3.length);
anyTypePostEncoding.length = decodedDataPtr->field3.length;
ossPrint(world, "\nPost-Decoding ANY type...\n\n");
if (ossDecode(world, &anyTypePduNum, &anyTypePostEncoding,(void **)&anyTypeDecodedPtr)) {
ossPrint(world, "Error decoding ANY type: %s", ossGetErrMsg(world));
retcode = 2;
}
else {
/*
* Decoded ANY type value successfully.
*/
ossPrint(world, "\n field3: %s\n", *anyTypeDecodedPtr);
/*
* Free up PDU.
*/
ossFreePDU(world, anyTypePduNum, anyTypeDecodedPtr);

}
free(anyTypePostEncoding.value); /* free up allocated memory */
ossFreePDU(world, myPduNum, decodedDataPtr); /* free up PDU. */
}
ossFreeBuf(world, bufBookmark); /* free main encoding buffer */
}
ossFreeBuf(world, anyTypeBufBookmark); /* Free ANY type pre-encoding */
ossterm(world); /* Wrap up use of OSS API functions */
return retcode;
}

Warning: You should never simply pass the Any type cast as an OssBuf variable to the decoder. The decoder may modify the buffer referenced by the value field leading to memory problems when you try to free this buffer.

 


The samples included with some of the Knowledge Center answers are meant for your general understanding of the OSS products. Different versions of the products might produce slightly different outputs. Consult the products documentation and samples for the most up-to-date products information and code examples.



Contact Support
contact Our office hours
24 hours/day, 7 days/week

  • Phone: 1-888-OSS-2761 (USA and Canada)
  • Phone: 1-732-302-9669 (International)
  • Fax: 1-732-302-0023
  • Email: support@oss.com
Free Trial
download

Test drive the OSS Nokalva ASN.1, 4G and XML Tools now! Your trial includes complete software, documentation, sample programs, free 24x7 technical support and more.




Learn ASN.1
Learn ASN.1

Our expert personnel can help you learn ASN.1!

We offer 4-day ASN.1 courses at our headquarters or your premises.