Procedure for Calling C Encode Functions

This section describes the step-by-step procedure for calling a C 3GL3 encode function.

Before a 3GL3 encode function can be called, the user must first initialize an encoding 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 encoding, the rtxInitContextBuffer function would be called. This can be used to specify use of a static or dynamic memory buffer. Specification of a dynamic buffer is possible by setting the buffer address argument to null and the buffer size argument to zero.

An encode function can then be called to encode the message. If the return status indicates success (0), then the message will have been encoded in the given buffer or written to the given stream. 3GL3 encoding starts from the beginning of the buffer and proceeds from low memory to high memory until the message is complete. This differs from definite-length BER where encoding was done from back-to-front. Therefore, the buffer start address is where the encoded 3GL3 message begins. The length of the encoded message can be obtained by calling the rtxCtxtGetMsgLen run-time function. If dynamic encoding was specified (i.e., a buffer start address and length were not given), the rtxCtxtGetMsgPtr run-time function can be used to obtain the start address of the message. This routine will also return the length of the encoded message.

A program fragment that could be used to encode a 3G NAS Identity Request message is as follows:

   #include "rt3gppsrc/TS24008Msgs.h"   /* include file generated by ASN1C */

   main ()
   {
      TS24008Msg_PDU pdu;
      TS24008Msg_IdentityRequest idReq;
      OSCTXT     ctxt;
      OSOCTET    msgbuf[256], *msgptr;
      int        i, len, stat;
      const char* filename = "message.dat";

      /* Initialize context structure */

      stat = rtInitContext (&ctxt);
      if (0 != stat) {
         printf ("rtInitContext failed; status = %d\n", ret);
         rtxErrPrint (&ctxt);
         return ret;
      }

      /* Populate C structure */

      pdu.l3HdrOpts.t = T_TS24007L3_L3HdrOptions_skipInd;
      pdu.l3HdrOpts.u.skipInd = 0;
      asn1SetTC_TS24008Msg_PDU_obj_IdentityRequest (&ctxt, &pdu, &idReq);
   
      OSCRTLMEMSET (&idReq, 0, sizeof(idReq));
      idReq.value.typeOfIdent = TS24008IE_IdentityTypeValue_typeOfIdent_imei;

      /* Encode */

      rtxCtxtSetBufPtr (&ctxt, msgbuf, sizeof(msgbuf));

      stat = NASEnc_TS24008Msg_PDU (&ctxt, &pdu);
      if (0 != stat) {
         printf ("encode PDU failed; status = %d\n", ret);
         rtxErrPrint (&ctxt);
         return ret;
      }

      msgptr = rtxCtxtGetMsgPtr (&ctxt);
      len = rtxCtxtGetMsgLen (&ctxt);

      ...
   }

In general, static buffers should be used for encoding messages where possible as they offer a substantial performance benefit over dynamic buffer allocation. In the case of L3 messages, most are small because the length field is sized to hold a single octet. It is therefore possible to size the buffer at 256 bytes which is the maximum size.