The best way of learning any language or notation is to read some examples of it. This example is adapted from http://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 following ASN.1 module MyHTTP.asn:
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 "20100202020202Z"
}
END1. 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 above content in the opening editor.
9. Save the ASN.1 file, then the compiled C data structure files will be automatically generated.
10. Create a test.c file with the following contents:
#include "GetRequest.h"
#include "stdio.h"
void write_byte(char byte);
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 */,
{ 2010, 02, 02, 02, 02, 02, 0, 0, 0 } /* timestamp */
};
/*
* Allocate the memory for the buffer
*/
Buffer* buffer = allocBuffer(160, true, BASIC_ENCODING_RULES);
/*
* Do the encoding
*/
result = encode_GetRequest(buffer, &myRequest);
if(result==0) {
/*
* Flush the buffer with writer callback
*/
flush_buffer(buffer, write_byte);
}
else {
fprintf(stderr, "Error in encoding, error code: %d.\n", result);
}
/*
* Deallocate the memory for the buffer
*/
freeBuffer(buffer);
return 0;
}
/**
* Callback routine: write a byte to output stream
**/
void write_byte(char byte) {
printf("%02X ", byte & 0xFF);
}11. Copy the Runtime Library and the include header files into the same folder as the generated files.
12. Compile every .c file together:
$ gcc -c *.c
13. Link .o file with the 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 63 6F 6D 84 0F 32 30 31 30 30 32 30 32 30 32 30 32 30 32 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 0x63 0x6F 0x6D -- www.asnlab.org
0x84 -- [1000|0011], [CONTEXT, PRIMITIVE, 4(GeneralizedTime)] GetRequest.timestamp
0x0F -- [0000|1100], length 15
0x32 0x30 0x31 0x30 0x30 0x32 0x30 0x32 0x30 0x32 0x30 0x32 0x30 0x32 0x5A -- 20100202020202Z