Two-phase Decoding

Two-phase decoding is the reverse operation of two-phase encoding. In this scenario, a message is received and decoded. The header and payload are contained in the message, and the payload type and content must be decoded after the message is received.

This example shows how to decode the message encoded in the previous section. As before, some setup is required to perform the decode:

   ApduType data;
   OSCTXT      ctxt;
   OSBOOL      trace = TRUE, verbose = FALSE;
   const char* filename = "message.dat";
   int         i, stat;

   /* Initialize context structure */
   stat = rtInitContext (&ctxt);
   if (stat != 0) {
      rtxErrPrint (&ctxt);
      return stat;
   }
   rtxSetDiag (&ctxt, verbose);

In this case, the content is read from an input file, so a file stream is created using rtxStreamFileCreateReader. Thereafter, the PDU data type is initialized using its initialization function and the message is decoded with the generated MDERDec function:

   /* Create file input stream */
   stat = rtxStreamFileCreateReader (&ctxt, filename);
   if (0 != stat) {
      rtxErrPrint (&ctxt);
      rtFreeContext (&ctxt);
      return stat;
   }
   
   asn1Init_ApduType (&data);

   /* Call compiler generated decode function */
   stat = MDERDec_ApduType (&ctxt, &data);
   if (stat != 0) {
      printf ("decode of ApduType failed\n");
      rtxErrPrint (&ctxt);
      rtFreeContext (&ctxt);
      return -1;
   }
   
      rtxStreamClose (&ctxt);

The second phase of the decode can now proceed. Because the open type data can appear in a list, a while loop is used to cycle through the data:

   /* Decode APDU open type data */
   if (data.t == T_ApduType_aarq) {
      OSRTDListNode* pnode = data.u.aarq->data_proto_list.head;
      while (0 != pnode) {
         PhdAssociationInformation phdAssocInfo;
         DataProto* pDataProto = (DataProto*) pnode->data;

         /* Create memory input stream */
         stat = rtxStreamMemoryCreateReader 
            (&ctxt, (OSOCTET*)pDataProto->data_proto_info.data, 
             pDataProto->data_proto_info.numocts);

Note here that the rtxStreamMemoryCreateReader function is used to stream data from the previously decoded message. It points to the octets held inside of the open type. After initializing the stream reader, the data can be decoded into the appropriate structure using the corresponding MDERDec function:

         /* Decode PhdAssociationInformation */
         asn1Init_PhdAssociationInformation (&phdAssocInfo);

         stat = MDERDec_PhdAssociationInformation (&ctxt, &phdAssocInfo);
         if (stat != 0) {
            printf ("decode of ApduType failed\n");
            rtxErrPrint (&ctxt);
            rtFreeContext (&ctxt);
            return -1;
         }

         rtxStreamClose (&ctxt);

         pnode = pnode->next;
      }
   }