The general procedure of encoding a message is as this:
This step varies from case to case. In most case, this step is done in another function before jump into this encoding procedure.
The following is an example of creating the message data struct variable myRequest
:
char bytes[1] = { 0xC0 };
Bits standards = { 4, bytes };
struct GetRequest myRequest = {
true /* header_only */,
false /* lock */,
{
&standards /* standards */,
NULL /* others */
} /* accept_types */,
"www.asnlab.org" /* url */,
{ 2010, 02, 02, 02, 02, 02, 0, 0, 0 } /* timestamp */
};
The variable myRequest
and all its members here are allocated in the stack, so there is no need to deallocate the memory for them;
such step 6 is not required. But if there are dynamic memory allocated in this step,
the programmer is responsible for deallocating these memory when this variable is no longer need.
The rule to follow here is: Who created it who destroy it.
The buffer can be allocated by calling this function:
/** * Allocates a new byte buffer. * * For Basic Encoding Rules, the new buffer's capacity and limit will be numBytes, * and for Pack Encoding Rules, the new buffer's capacity and limit will be numBytes*8. */ Buffer* allocBuffer(unsigned long numBytes, boolean autoExpand, char encodingRules);
This function will allocate the memory for the byte array and the memory for the buffer itself, if it fails to do so, a NULL pointer is return. The user of this function should check if the return buffer is NULL or not and handle it appropreately.
Another way to create a buffer is through this function:
/** * Wraps a byte array into a buffer. * * The new buffer will be backed by the given byte array; * that is, modifications to the buffer will cause the array to be modified and vice versa. * For Basic Encoding Rules, the new buffer's capacity and limit will be numBytes, * and for Pack Encoding Rules, the new buffer's capacity and limit will be numBytes*8. */ Buffer* wrapBuffer(char* array, unsigned long numBytes, char encodingRules);
But the length of the buffer created by this function is fixed to numBytes
,
this is not suitable for encoding while the buffer length is unknown beforehand.
This is done by calling the struct specific encode routine, or generic routine from the ASN.1 C Runtime Library. The example here uses the generated struct specific encoding routine:
/* * Do the encoding */ result = encode_GetRequest(buffer, &myRequest);
The return result of the encoding is zero if the encoding is successful, non-zero error code otherwise. Error codes are defined in asnrt.h:
/* error codes */ #define INVALID_TAG 1 #define INVALID_LENGTH 2 #define INVALID_INTEGER 3 #define INVALID_ENUM 4 #define INVALID_REAL 5 #define OUT_OF_MEMORY 6 #define INVALID_TIME 7 #define MISSING_COMPONENT 8 #define EXTRA_COMPONENT 9 #define INVALID_INDEX 10 #define BUFFER_OVERFLOW 11 #define BUFFER_UNDERFLOW 12 #define INVALID_ENCODE_RULE 13 #define NULL_POINTER_EXCEPTION 14 #define NOT_PERMITTED_ALPHABET 15 #define NO_MATCH_INFO_OBJ 16 #define INVALID_LICENSE 17 #define INVALID_SIZE 18
To retrieve the encoding result, you can:
/* * Flush the buffer with writer callback */ flush_buffer(buffer, write_byte);The write_byte is a callback functiondeclared as:
/** * Callback routine: write a byte to output stream **/ typedef void (*WriteByte)(char byte);
array
field,
length is determined by buffer's position
field. Note that the unit of positron is bit for PER encoding, but byte.
The following code snippet shows how to get the encoding bytes and it's length (in bytes):
char* bytes = buffer->array; unsigned long length = buffer->encoding_rules<=DISTINGUISHED_ENCODING_RULES? buffer->limit:((buffer->limit-1)/8+1);
The buffer is deallocated by:
/* * Deallocate the memory for the buffer */ freeBuffer(buffer);if this buffer is created by calling allocBuffer(). This function will free the buffer's content (byte array) and itself. If this buffer is created by calling wrapBuffer(), call asn_free() to free the buffer itself without freeing its content.
As mentioned in step 1, if the variable myRequest
is not allocated dynamically, this step is skipped.
This step is required only there are dynamical memory allocated in creating the message data struct variable.