This section describes the step-by-step procedure for calling a C 3GL3 decode function.
A Protocol Data Unit (PDU) function is normally defined that includes all of the message that make up a given protocol. These are grouped together using an Information Object Set that sets up a relation between the protocol discriminator/message type field combination and the associated message data type. This PDU function is then called to decode both the header and payload data in one call.
The following are the basic steps in calling the PDU decode function:
Prepare a context variable for decoding
Initialize the data structure to receive the decoded data
Call the PDU decode function to decode the message
Free the context after use of the decoded data is complete to free allocated memory structures
Before a 3GL3 decode function can be called, the user must first initialize a context block structure. The context block is initialized by calling the rtInitContext function.
Only memory-buffer based encoding is supported for 3GPP layer 3 because the message sizes are generally small (normally less than 256 bytes).
To do memory-based decoding, the rtxInitContextBuffer function would be called. The message to be decoded must reside in memory. The arguments to this function would then specify the message buffer in which the data to be decoded exists.
The PDU variable that is to receive the decoded data must then be initialized. This can be done by either initializing the variable to zero using memset, or by calling the ASN1C generated initialization function.
The PDU decode function can then be called to decode the message. If the return status indicates success (0), then the message will have been decoded into the PDU type variable. The decode function may automatically allocate dynamic memory to hold variable length variables during the course of decoding. This memory will be tracked in the context structure, so the programmer does not need to worry about freeing it. It will be released when the either the context is freed or explicitly when the rtxMemFree or rtxMemReset function is called.
The final step of the procedure is to free the context block. This must be done regardless of whether the block is static (declared on the stack and initialized using rtInitContext), or dynamic (created using rtNewContext). The function to free the context is rtFreeContext.
A program fragment that could be used to decode a 3G NAS PDU is as follows:
#include "rt3gppsrc/TS24008Msgs.h" /* include file generated by ASN1C */ main () { TS24008Msg_PDU data; OSCTXT ctxt; OSOCTET* msgbuf; const char* filename = "message.dat"; int stat; OSSIZE len; /* step 1: initialize context */ stat = rtInitContext (&ctxt); if (stat != 0) { printf (“rtInitContext failed (check license)\n“); rtErrPrint (&ctxt); return stat; } /* step 2: read input file into a memory buffer */ stat = rtxFileReadBinary (&ctxt, filename, &pMsgBuf, &len); if (0 == stat) { stat = rtxInitContextBuffer (&ctxt, pMsgBuf, len); } if (0 != stat) { rtxErrPrint (&ctxt); rtFreeContext (&ctxt); return stat; } /* step 3: set protocol version number */ rtxCtxtSetProtocolVersion (&ctxt, 8); /* step 4: call the decode function */ stat = NASDec_TS24008Msg_PDU (&ctxt, &data); if (stat == 0) { process received data.. } else { /* error processing... */ rtxErrPrint (&ctxt); } /* step 4: free the context */ rtFreeContext (&ctxt); }