English

Getting Started with ASN.1 C Compiler

The best way of learning any language or notation is to read some examples of it. In this tutorial, we will walk you through creating and running a simple ASN.1 application. For more details, please see the ASN.1 C Compiler User's Guide.

Installing the ASN.1 C Compiler

Click here for instructions on how to download and install the ASN.1 SDK and ASN.1 C Compiler plugin.

Setting up the License

Request a trial license or purchase a permanent license from ASN Lab website. in Eclipse click Windows (on Mac, Eclipse) > Preferences > ASN.1 > ASN.1 C Compiler to open the ASN.1 C Compiler preference page, enter the serial number of license in the General section and click OK.

The MyHTTP Example

The MyHTTP example is adapted from https://www.w3.org/Protocols/HTTP-NG/asn1.html, it's a simplified form of the the GET request from FHTTP. For our example, suppose that we need to employ the ASN.1 module as we have seen in the ASN.1 Development Tools getting started tutorial.

  1. Select File > New > Project...
  2. Under ASN.1 category, select ASN.1 Project, then click Next.
  3. For project name, enter 'MyHTTP' and click Finish.
  4. ASN.1 files may now be added to the project by copying to the source folder, or creating ASN.1 files from scratch by
  5. Select File > New > Other...
  6. Under the ASN.1 category, select ASN.1 Module, then click Next.
  7. For module name, enter 'MyHTTP' and click Finish.
  8. Enter the following content in the opening editor:
    MyHTTP DEFINITIONS
    AUTOMATIC TAGS ::=
    BEGIN
    
       GetRequest ::= SEQUENCE {
          header-only   BOOLEAN,
          lock          BOOLEAN,
          accept-types  AcceptTypes,
          url           Url,
          ...,
          timestamp     GeneralizedTime
       }
    
       AcceptTypes ::= SET {
          standards   BIT STRING { html(0), plain-text(1), gif(2), jpeg(3) } (SIZE(4)) OPTIONAL,
          others      SEQUENCE OF VisibleString (SIZE(4)) OPTIONAL
       }
    
       Url ::= VisibleString (FROM("a".."z"|"A".."Z"|"0".."9"|"./-_~%#"))
    
       myRequest GetRequest ::= {
          header-only  TRUE,
          lock         FALSE,
          accept-types {
             standards { html, plain-text }
          },
          url          "www.asnlab.org",
          timestamp    "20121221121221Z"
       }
    
    END
  9. Save the ASN.1 file, then the compiled C data structure files will be automatically generated (If not, please set up license).
  10. Create a test.c file with the following contents:
    #include "stdio.h"
    #include "stdlib.h"
    #include "stdarg.h"
    #include "GetRequest.h"
    
    static int print(AsnPrinter* printer, const char* __format, ...);
    
    AsnPrinter printer = { 0, print };
    
    int main(void) {
       int result;
    
       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 */,
          { 2012, 12, 21, 12, 12, 21, 0, 0, 0 } /* timestamp */
       };
    
       /*
        * Allocate the memory for the buffer
        */
       AsnBuffer* buffer = alloc_buffer(160, true, BASIC_ENCODING_RULES);
    
       /*
        * Do the encoding
        */
       result = encode_GetRequest(buffer, &myRequest);
    
       if(result==0) {
          /*
           * Print out the content of the buffer
           */
          int i;
          for(i=0; i<buffer->limit; i++) {
             char byte = buffer->array[i];
             printf("%02X ", byte & 0xFF);
          }
       }
       else {
          fprintf(stderr, "Error in encoding, error code: %d.\n", result);
          print_problem_marks(buffer, &myRequest, &GETREQUEST_TYPE, &printer);
       }
    
       /*
        * Deallocate the memory for the buffer
        */
       free_buffer(buffer);
    
       return 0;
    }
    
    static int print(AsnPrinter* printer, const char* __format, ...) {
       va_list arg_ptr;
       int cnt;
       va_start(arg_ptr, __format);
       cnt = vprintf(__format, arg_ptr);
       va_end(arg_ptr);
       return cnt;
    }
  11. Copy the runtime library and the include header files (extracted from the ASN.1 C Runtime Package) into the same folder as the generated files.
  12. Compile every .c file together:

    $ gcc -c *.c

  13. Link .o file against the ASN.1 runtime library:

    $ gcc -o test *.o -L. -lasnrt

  14. Run it:

    $ ./test
    30 2D 80 01 FF 81 01 00 A2 04 80 02 04 C0 83 0E 77 77 77 2E 61 73 6E 6C 61 62 2E 6F 72 67 84 0F 32 30 31 32 31 32 32 31 31 32 31 32 32 31 5A

Here's the explanation of the encoded bits and bytes in BER:

0x30 -- [0011|0000], [UNIVERSAL, CONSTRUCTED, 16(SEQUENCE)] - GetRequest
0x2D -- [0010|1101], length 45

0x80 -- [1000|0000], [CONTEXT, PRIMITIVE, 0(BOOLEAN)] GetRequest.header_only
0x01 -- [0000|0001], length 1
0xFF -- [0000|1111], value TRUE

0x81 -- [1000|0001], [CONTEXT, PRIMITIVE, 1(BOOLEAN)] GetRequest.lock
0x01 -- [0000|0001], length 1
0x00 -- [0000|0000], value FALSE

0xA2 -- [1010|0010], [CONTEXT, CONSTRUCTED, 2(SET)] - GetRequest.accept_types
0x04 -- [0000|0100], length 4

0x80 -- [1000|0000], [CONTEXT, PRIMITIVE, 0(BIT STRING)] AcceptTypes.standards
0x02 -- [0000|0010], length 2
0x04 -- [0000|0100], 4 unused bits
0xC0 -- [1100|0000], {html, plaint_text}

0x83 -- [1000|0011], [CONTEXT, PRIMITIVE, 3(VisibleString)] GetRequest.url
0x0E -- [0000|1100], length 14
0x77 0x77 0x77 0x2E 0x61 0x73 0x6E 0x6C 0x61 0x62 0x2E 0x6F 0x72 0x67 -- www.asnlab.org

0x84 -- [1000|0011], [CONTEXT, PRIMITIVE, 4(GeneralizedTime)] GetRequest.timestamp
0x0F -- [0000|1100], length 15
0x32 0x30 0x31 0x32 0x31 0x32 0x32 0x31 0x31 0x32 0x31 0x32 0x32 0x31 0x5A -- 20121221121221Z

More Information

For more information regarding ASN.1 Runtime Library, please refer to the ASN.1 C Runtime Library User Guide.