Thoughts on the current state of ASN.1 and XML technologies.

ASN1C v7.3 released

Objective Systems is proud to announce the release of version 7.3 of its ASN1C ASN.1 Compiler product.

ASN1C is an ASN.1 compiler (code generator) capable of generating C, C++, C#, or Java source code from Abstract Syntax Notation 1 (ASN.1) or XML Schema Definition Language (XSD) syntax.

One of the key new features in this release is support for the JSON Encoding Rules (JER) introduced this past year in the ITU-T X.697 standard. Support has been added for generating encoders and decoders in all supported programming languages.

In addition, support was added for 3GPP TS 24.501 NAS Protocol for 5GS. Although this is not an ASN.1 standard, the ASN1C compiler can be used to generate 3GPP layer 3 encoders and decoders that support these message types in the C language. An ASN.1 specification was developed that provides an approximation of the data structures in ASN.1. To work around the parts that can’t be encoded or decoded using standard ASN.1 PER bit-wise operations, special control directives and custom code were used. The specification is available in our ASN1C NAS/RRC Add-on Kit.

The following other new capabilities have been added in this release:

– New compact libraries for PER and UPER encoding and decoding in C that reduce code size by as much as half.

– Support for Canonical Octet Encoding Rules (COER) in Java and C#

– Generation of build artifacts for the Maven or Gradle build frameworks

Further information can be found on the release notes page. A free 30-day trial version may be downloaded from from https://obj-sys.com/products/asn1c/download.php.

No Comments

Improved TBCD and BCD Support for Java/C#

Our next release of ASN1C (v 7.3) will include improved support for TBCD and BCD strings for Java and C#.  In short, for these types, the toString/ToString function will return the TBCD/BCD interpretation of the octets, rather than merely their hexadecimal representation.  This also improves the print functionality.

TBCD stands for Telephony Binary-coded Decimal and BCD stands for Binary-coded Decimal.  So, what are TBCD and BCD strings?  They are OCTET STRINGS in which a series of digits or telephony digits are encoded, using one nibble (4 bits) per digit.  There isn’t an authoritative definition, but there are a few standards out there that provide definitions of TBCD or BCD and these are what we’ve followed, as described below.

As you will see in the following descriptions, TBCD and BCD strings are similar.  The differences are 1) the set of digit characters and 2) the ordering of the nibbles within the bytes.

TBCD Strings

For TBCD, we follow 3GPP 29.002.  This is also the document that happens to be referenced in the section on TBCD in the Wikipedia entry for BCD.  Here is how 29.002 defines TBCD:

TBCD-STRING ::= OCTET STRING
-- This type (Telephony Binary Coded Decimal String) is used to
-- represent several digits from 0 through 9, *, #, a, b, c, two
-- digits per octet, each digit encoded 0000 to 1001 (0 to 9),
-- 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used
-- as filler when there is an odd number of digits.
-- bits 8765 of octet n encoding digit 2n
-- bits 4321 of octet n encoding digit 2(n-1) +1

To summarize the characteristics for 3GPP 29.002 TBCD-STRING:
• Uses characters 0-9,*,#,a-c.
• F nibble is used as filler when there is an odd number of digits.
• The low nibble contains the first digit.

Note that 3GPP 24.008 §10.5.4.7 “Called party BCD number” specifies the same encoding, though it simply refers to it as “BCD”.  24.008 also calls for BCD in §10.5.1.4 “Mobile Identity” (for the  IMSI, IMEI and IMEISV), (presumably) meaning BCD as defined in §10.5.4.7, i.e. TBCD.

BCD Strings

For BCD, we have followed the TAP3 (GSM TD.57) specification of BCD.  Here is how they define BCD:

-- The BCDString data type (Binary Coded Decimal String) is used to represent 
-- several digits from 0 through 9, a, b, c, d, e. 
-- Two digits are encoded per octet. The four leftmost bits of the octet represent 
-- the first digit while the four remaining bits represent the following digit. 
-- A single f must be used as a filler when the total number of digits to be 
-- encoded is odd. 
-- No other filler is allowed.

To summarize the characteristics of TAP3 BCDString:

• Uses characters 0-9,a-e.
• F nibble is used as filler when there is an odd number of digits.
• The high nibble contains the first digit.

ITU-T Q.825 TBCD-STRING

Q.825 was another candidate for a definition of TBCD strings.  At this point, we haven’t added special support for it.  This section merely points out the differences between Q.825 TBCD-STRING and 3GPP 29.002 TBCD-STRING.  The differences are:

  • In Q.825, TBCD-STRING is defined as part of an OCTET STRING, not as a standalone type.  Prior to the TBCD-STRING content, the OCTET STRING contains an odd/even indicator octet, and, in some cases, another octet.
  • Q.825 orders the nibbles differently.
  • Q.825 uses the F nibble to mark the end of the TBCD string (“end of pulsing signal-ST”)
  • Q.825 uses the 0 nibble as filler when there is an odd number of digits.  So, in some cases, a zero nibble is merely filler, but in other cases it is a ‘0’ digit.  [Note: we’re not sure why Q.825 specifies that filler is required when there is an odd number of digits; it seem it should be required when there is an even number of digits.  By our reading, “123” would map to 0x123F (no filler), while “1234” would map to 0x12340F (filler).]

 

No Comments

New 5G NR (New Radio) 3GPP/LTE APIs available

We have added the new 3GPP/LTE 5G NR (New Radio) ASN.1 API’s for use with ASN1C.  These 5G API’s are extended sample programs that contain the complete ASN.1 specifications extracted from the relevant 3GPP 5G standard documents.  The API’s are available at the following URL (“LTE ASN.1 APIs” tab):

http://www.obj-sys.com/lte_3gpp_apis.php

There are API’s available for 3GPP release 15 of the different 5G AP specification types.  API’s are currently available for LTE-RRC 5G NR, E1AP 5G NR, F1AP 5G NR, NGAP 5G NR, and XnAP 5G NR LTE ASN.1 specifications.

Additionally, the existing 3GPP LTE APIs (such as S1AP, e.g.) have been updated to their latest releases (rel 14 or 15).

Finally, support for specification TS 24.501 (NAS protocol for 5G Systems) has been added to the NAS DLL.  Support for the SDK add-on will be included in the next release of ASN1C.

No Comments

Using -prttostrm (print-to-stream) vs -prttostr (print-to-string) in generated C code

The capability to print the contents of binary-encoded data in a human-readable form has always been an often used feature of our code generation products.  We have had since the beginning the standard -print code generation option for generating code that would print the contents of generated data structures to standard output.  These are straight-forward and simple to use.  But it was not long after that users wanted a way to print to other mediums, most commonly to a text buffer (i.e character array) so that the printed data could be sent to other places, for example, a display window within a GUI.

For this, the “print-to-string” capability was added.  The command-line option -prttostr was added for this purpose and the generated functions allowed a text buffer and size to be passed to receive the printed data.

This worked OK and was fine for printing small amounts of data.  But what we found was that users frequently wanted to print very large data structures using this capability and this led to very slow performance.  The primary reason for this was because in order to append to the buffer that was passed, the end of the string buffer had to be found and the only way to do this lacking any other state information was to make a call to the string length (strlen) run-time function.  If this was done over and over on a very large buffer containing a very large string, it quickly became a compute-intensive operation.

In order to remedy this, we introduced the “print-to-stream” capability.  This provided more flexibility in printing as a user-defined callback function could be declared that would be invoked to handle the printing of each individual data item.  Users could provide their own user-defined data structures to the callback functions making it possible to maintain state between operations.  One example of this would be in keeping track of where the end of a string buffer was after each print operation making the appending of additional data much faster.

We declared “print-to-string” to be deprecated in favor of the new “print-to-stream” capability, but what we have found 15 years down the road is print-to-string still being used.  A few possible reasons for this are 1) that is the way some users started doing it and did not want to change, and 2) it is simpler to use these functions as all that is necessary is to pass a string buffer directly to the function instead of having to design a callback function.

To address the latter point, as part of our next ASN1C release next year, we will provide a built-in callback function that can be used to model print-to-string using print-to-stream.  If users don’t want to wait that long, the code for the new callback is shown below:

void rtxPrintStreamToStringCB
(void* pPrntStrmInfo, const char* fmtspec, va_list arglist)
{
   OSRTStrBuf* bufp = (OSRTStrBuf*) pPrntStrmInfo;
   if (bufp->bufsize > bufp->endx) {
      vsnprintf (&bufp->strbuf[bufp->endx], bufp->bufsize - bufp->endx,
                 fmtspec, arglist);
      bufp->endx += strlen (&bufp->strbuf[bufp->endx]);
   }
}

The OSRTStrBuf structure is defined as follows:

typedef struct {
   char* strbuf;
   OSSIZE bufsize;
   OSSIZE endx;
} OSRTStrBuf;

The code can then be inserted into a C program to print a populated type structure:

OSRTStrBuf strBufDescr;
char strbuf[10240];
...
/* Set up print-to-stream callback to write to character string buffer */
strBufDescr.strbuf = strbuf;
strBufDescr.bufsize = sizeof(strbuf);
strBufDescr.endx = 0;

rtxSetPrintStream (&ctxt, &rtxPrintStreamToStringCB, (void*)&strBufDescr);

asn1PrtToStrm_<type> (&ctxt, "Data", &data);

In this code snippet, <type> would be replaced with the type name of the data structure to be printed. The result of the call would be the data printed to the strbuf character array. Be sure to create a large enough array to hold all of the printed data. If not large enough, the data will be truncated.

No Comments

XBinder Version 2.6 Release

We recently released a new major version of our XBinder XML Schema Compiler product.  XBinder generates C, C++, Java, or C# code from XML Schema (XSD) definitions, making it easier to create and consume compliant XML documents in a programmatic way.

New features in this release include the following:

    • Generation of C/C++ Code to Better Support 64-bit Architectures
    • Generation of Visual Studio Projects for 64-bits
    • Ability to Use Qt Types
    • Use of Newer Versions of Visual Studio for Windows
    • XML Validation in XBinder Editor
    • Generation of Visual Studio Projects in XBinder Editor

A full list of changes, and additional details on the above changes, are available in the release notes.

No Comments