diff options
author | Lev Walkin <vlm@lionet.info> | 2010-11-08 02:04:55 -0800 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2010-11-08 02:04:55 -0800 |
commit | ed44bf4164ad337a6dd52c05477bcddcab1c9640 (patch) | |
tree | 0fe59bb19f0b1b7e5fb01220a406544a3b95375f /doc | |
parent | 9027260f34457a17b3e989068c06704b95130c02 (diff) |
Jump from LyX to LaTeX
Diffstat (limited to 'doc')
-rw-r--r-- | doc/asn1c-usage.lyx | 4332 | ||||
-rw-r--r-- | doc/asn1c-usage.tex | 1588 |
2 files changed, 1588 insertions, 4332 deletions
diff --git a/doc/asn1c-usage.lyx b/doc/asn1c-usage.lyx deleted file mode 100644 index fb7f98d7..00000000 --- a/doc/asn1c-usage.lyx +++ /dev/null @@ -1,4332 +0,0 @@ -#LyX 1.3 created this file. For more info see http://www.lyx.org/ -\lyxformat 221 -\textclass book -\begin_preamble -\usepackage{extramarks} -\lhead{\firstxmark} -\rfoot{\lastxmark} -\usepackage{color} -\definecolor{gray40}{gray}{.4} -\definecolor{urlblue}{rgb}{0,0,.6} -\usepackage[colorlinks=true, -linkcolor={gray40}, -urlcolor={urlblue}, -pdfauthor={Lev Walkin}, -pdftitle={Using the Open Source ASN.1 Compiler}, -pdfkeywords={ASN.1,asn1c,compiler} -]{hyperref} -%\fancyhf{} -%\fancyhead[LE,RO]{\thepage} -%\fancyhead[LO]{\rightmark} -%\fancyhead[RE]{\leftmark} -%\fancyfoot[R]{\lastxmark} -\end_preamble -\language english -\inputencoding latin1 -\fontscheme times -\graphics default -\paperfontsize default -\spacing single -\papersize Default -\paperpackage a4 -\use_geometry 0 -\use_amsmath 0 -\use_natbib 0 -\use_numerical_citations 0 -\paperorientation portrait -\secnumdepth 2 -\tocdepth 2 -\paragraph_separation indent -\defskip medskip -\quotes_language swedish -\quotes_times 2 -\papercolumns 1 -\papersides 2 -\paperpagestyle fancy - -\layout Title - -Using the Open Source ASN.1 Compiler -\layout Author - -Lev Walkin < -\begin_inset ERT -status Collapsed - -\layout Standard - -\backslash -href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info} -\end_inset - -> -\layout Standard - - -\begin_inset ERT -status Open - -\layout Standard - -\backslash -lhead{This document describes -\backslash -href{http://lionet.info/asn1c}{asn1c-0.9.21}} -\layout Standard - -\backslash -rhead{$Revision$} -\end_inset - - -\layout Standard - - -\begin_inset LatexCommand \tableofcontents{} - -\end_inset - - -\layout Standard - - -\begin_inset ERT -status Open - -\layout Standard - -\backslash -pagestyle{headings} -\end_inset - - -\layout Part - -Using the ASN.1 Compiler -\layout Chapter - -Introduction to the ASN.1 Compiler -\layout Standard - -The purpose of the ASN.1 compiler is to convert the specifications in ASN.1 - notation into some other language. - At this moment, only C and C++ target languages are supported, the latter - is in upward compatibility mode. -\layout Standard - -The compiler reads the specification and emits a series of target language - structures (C's structs, unions, enums) describing the corresponding ASN.1 - types. - The compiler also creates the code which allows automatic serialization - and deserialization of these structures using several standardized encoding - rules (BER, DER, XER). -\layout Standard - -For example, suppose the following ASN.1 module is given -\begin_inset Foot -collapsed true - -\layout Standard - -Please look into Part -\begin_inset LatexCommand \vref{par:ASN.1-Basics} - -\end_inset - - for a quick reference on how to understand the ASN.1 notation. -\end_inset - -: -\layout LyX-Code - -RectangleTest DEFINITIONS ::= -\layout LyX-Code - -BEGIN -\layout LyX-Code - - -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER, -- Height of the rectangle -\layout LyX-Code - - width INTEGER -- Width of the rectangle -\layout LyX-Code - -} -\layout LyX-Code - - -\layout LyX-Code - -END -\layout Standard - -The compiler would read this ASN.1 definition and produce the following C - type -\begin_inset Foot -collapsed false - -\layout Standard - - -\emph on --fnative-types -\emph default - compiler option is used to produce basic C -\emph on -int -\emph default - types instead of infinite width INTEGER_t structures. - See Section -\begin_inset LatexCommand \vref{sec:Command-line-options} - -\end_inset - -. -\end_inset - -: -\layout LyX-Code - -typedef struct Rectangle_s { -\layout LyX-Code - - int height; -\layout LyX-Code - - int width; -\layout LyX-Code - -} Rectangle_t; -\layout Standard - -It would also create the code for converting this structure into platform-indepe -ndent wire representation (a serializer API) and the decoder of such wire - representation back into local, machine-specific type (a deserializer API). -\layout Section - -Quick start with asn1c -\layout Standard - -After building and installing the compiler, the -\emph on -asn1c -\begin_inset Foot -collapsed false - -\layout Standard - -The 1 symbol in asn -\series bold -1 -\series default -c is a digit, not an -\begin_inset Quotes sld -\end_inset - -ell -\begin_inset Quotes srd -\end_inset - - letter. -\end_inset - - -\emph default - command may be used to compile the ASN.1 module -\begin_inset Foot -collapsed false - -\layout Standard - -This is probably -\series bold -not -\series default - what you want to try out right now -- read through the rest of this chapter - and check the Section -\begin_inset LatexCommand \vref{sec:Command-line-options} - -\end_inset - - to find out about -\series bold --P -\series default - and -\series bold --R -\series default - options. -\end_inset - -: -\layout LyX-Code - -asn1c -\emph on -<module.asn1> -\layout Standard - -If several ASN.1 modules contain interdependencies, all of the files must - be specified altogether: -\layout LyX-Code - -asn1c -\emph on -<module1.asn1> <module2.asn1> ... -\layout Standard - -The compiler -\series bold --E -\series default - and -\series bold --EF -\series default - options are used for testing the parser and the semantic fixer, respectively. - These options will instruct the compiler to dump out the parsed (and fixed, - if -\series bold --F -\series default - is involved) ASN.1 specification as it was "understood" by the compiler. - It might be useful to check whether a particular syntactic construction - is properly supported by the compiler. -\layout LyX-Code - -asn1c -\series bold --EF -\series default - -\emph on -<module-to-test.asn1> -\layout Standard - -The -\series bold --P -\series default - option is used to dump the compiled output on the screen instead of creating - a bunch of .c and .h files on disk in the current directory. - You would probably want to start with -\series bold --P -\series default - option instead of creating a mess in your current directory. - Another option, -\series bold --R -\series default -, asks compiler to only generate the files which need to be generated, and - supress linking in the numerous support files. -\layout Standard - -Print the compiled output instead of creating multiple source files: -\layout LyX-Code - -asn1c -\series bold --P -\series default - -\emph on -<module-to-compile-and-print.asn1> -\layout Section - -Recognizing compiler output -\layout Standard - -After compiling, the following entities will be created in your current - directory: -\layout Itemize - -A set of .c and .h files, generally a single pair for each type defined in - the ASN.1 specifications. - These files will be named similarly to the ASN.1 types ( -\emph on -Rectangle.c -\emph default - and -\emph on -Rectangle.h -\emph default - for the RectangleTest ASN.1 module defined in the beginning of this document). -\layout Itemize - -A set of helper .c and .h files which contain generic encoders, decoders and - other useful routines. - There will be quite a few of them, some of them even are not always necessary, - but the overall amount of code after compilation will be rather small anyway. -\layout Itemize - -A -\emph on -Makefile.am.sample -\emph default - file mentioning all the files created at the earlier steps. - This file is suitable for either automake suite or the plain `make` utility. -\layout Standard - -It is your responsibility to create .c file with the -\emph on - int main() -\emph default - routine. -\layout Standard - -In other words, after compiling the Rectangle module, you have the following - set of files: { Makefile.am.sample, Rectangle.c, Rectangle.h, -\series bold -\SpecialChar \ldots{} - -\series default - }, where -\series bold - -\begin_inset Quotes sld -\end_inset - -\SpecialChar \ldots{} - -\begin_inset Quotes srd -\end_inset - - -\series default - stands for the set of additional -\begin_inset Quotes sld -\end_inset - -helper -\begin_inset Quotes srd -\end_inset - - files created by the compiler. - If you add a simple file with the -\emph on -int main() -\emph default - routine, it would even be possible to compile everything with the single - instruction: -\layout LyX-Code - -cc -I. - -o rectangle.exe *.c # It could be -\emph on -that -\emph default - simple -\layout Standard - -Refer to the Chapter -\begin_inset LatexCommand \vref{cha:Step-by-step-examples} - -\end_inset - - for a sample -\emph on -int main() -\emph default - routine. -\layout Section - - -\begin_inset LatexCommand \label{sec:Command-line-options} - -\end_inset - -Command line options -\layout Standard - -The following table summarizes the asn1c command line options. -\layout Standard - - -\begin_inset Tabular -<lyxtabular version="3" rows="28" columns="2"> -<features islongtable="true"> -<column alignment="left" valignment="top" leftline="true" width="0"> -<column alignment="block" valignment="top" leftline="true" rightline="true" width="3in"> -<row topline="true" bottomline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Overall Options -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Description -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --E -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Stop after the parsing stage and print the reconstructed ASN.1 specification - code to the standard output. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --F -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Used together with -E, instructs the compiler to stop after the ASN.1 syntax - tree fixing stage and dump the reconstructed ASN.1 specification to the - standard output. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --P -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Dump the compiled output to the standard output instead of cre- ating the - target language files on disk. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --R -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Restrict the compiler to generate only the ASN.1 tables, omit- ting the usual - support code. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --S -\emph on -<directory> -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Use the specified directory with ASN.1 skeleton files. -\end_inset -</cell> -</row> -<row topline="true" bottomline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --X -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Generate the XML DTD for the specified ASN.1 modules. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Warning Options -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Description -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --Werror -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Treat warnings as errors; abort if any warning is produced. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --Wdebug-lexer -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Enable lexer debugging during the ASN.1 parsing stage. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --Wdebug-fixer -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small - Enable ASN.1 syntax tree fixer debugging during the fixing stage. -\end_inset -</cell> -</row> -<row topline="true" bottomline="true" newpage="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --Wdebug-compiler -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Enable debugging during the actual compile time. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Language Options -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Description -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fbless-SIZE -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Allow SIZE() constraint for INTEGER, ENUMERATED, and other types for which - this constraint is normally prohibited by the standard. - This is a violation of an ASN.1 standard and compiler may fail to produce - the meaningful code. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fcompound-names -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Use complex names for C structures. - Using complex names prevents name clashes in case the module reuses the - same identifiers in multiple contexts. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --findirect-choice -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -When generating code for a CHOICE type, compile the CHOICE members as indirect - pointers instead of declaring them inline. - Consider using this option together with -\series bold --fno-include-deps -\series default - to prevent circular references. - -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fknown-extern-type= -\emph on -<name> -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Pretend the specified type is known. - The compiler will assume the target language source files for the given - type have been provided manually. - -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fnative-types -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Use the native machine's data types (int, double) whenever possible, instead - of the compound INTEGER_t, ENUMERATED_t and REAL_t types. - -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fno-constraints -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Do not generate ASN.1 subtype constraint checking code. - This may produce a shorter executable. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fno-include-deps -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Do not generate courtesy #include lines for non-critical dependencies. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --funnamed-unions -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Enable unnamed unions in the definitions of target language's structures. -\end_inset -</cell> -</row> -<row topline="true" bottomline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --fskeletons-copy -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Copy support files rather than symlink them. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Codecs Generation Options -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Description -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --gen-PER -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Generate Packed Encoding Rules (PER) support code. -\end_inset -</cell> -</row> -<row topline="true" bottomline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --pdu= -\emph on -auto -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Generate PDU tables by discovering Protocol Data Units automatically. -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Output Options -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\series bold -\size small -Description -\end_inset -</cell> -</row> -<row topline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --print-constraints -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -When -EF are also specified, this option forces the compiler to explain - its internal understanding of subtype constraints. -\end_inset -</cell> -</row> -<row topline="true" bottomline="true"> -<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small --print-lines -\end_inset -</cell> -<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none"> -\begin_inset Text - -\layout Standard - - -\size small -Generate "-- #line" comments in -E output. -\end_inset -</cell> -</row> -</lyxtabular> - -\end_inset - - -\layout Chapter - -Using the ASN.1 Compiler -\layout Section - -Invoking the ASN.1 helper code -\begin_inset OptArg -collapsed true - -\layout Standard - -Invoking the helper code -\end_inset - - -\layout Standard - -First of all, you should include one or more header files into your application. - Typically, it is enough to include the header file of the main PDU type. - For our Rectangle module, including the Rectangle.h file is sufficient: -\layout LyX-Code - -#include <Rectangle.h> -\layout Standard - -The header files defines the C structure corresponding to the ASN.1 definition - of a rectangle and the declaration of the ASN.1 type descriptor, which is - used as an argument to most of the functions provided by the ASN.1 module. - For example, here is the code which frees the Rectangle_t structure: -\layout LyX-Code - -Rectangle_t *rect = ...; -\layout LyX-Code - - -\layout LyX-Code - -asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, -\layout LyX-Code - - rect, 0); -\layout Standard - -This code defines a -\emph on -rect -\emph default - pointer which points to the Rectangle_t structure which needs to be freed. - The second line invokes the generic -\emph on -free_struct() -\emph default - routine created specifically for this Rectangle_t structure. - The -\emph on -asn_DEF_Rectangle -\emph default - is the type descriptor, which holds a collection of routines to deal with - the Rectangle_t structure. -\layout Standard - -The following member functions of the asn_DEF_Rectangle type descriptor - are of interest: -\layout Description - -ber_decoder This is the generic -\emph on -restartable -\begin_inset Foot -collapsed false - -\layout Standard - -Restartable means that if the decoder encounters the end of the buffer, - it will fail, but may later be invoked again with the rest of the buffer - to continue decoding. -\end_inset - - -\emph default -BER decoder (Basic Encoding Rules). - This decoder would create and/or fill the target structure for you. - See Section -\begin_inset LatexCommand \vref{sub:Decoding-BER} - -\end_inset - -. -\layout Description - -der_encoder This is the generic DER encoder (Distinguished Encoding Rules). - This encoder will take the target structure and encode it into a series - of bytes. - See Section -\begin_inset LatexCommand \vref{sub:Encoding-DER} - -\end_inset - -. - NOTE: DER encoding is a subset of BER. - Any BER decoder should be able to handle DER input. -\layout Description - -xer_decoder This is the generic XER decoder. - It takes both BASIC-XER or CANONICAL-XER encodings and deserializes the - data into a local, machine-dependent representation. - See Section -\begin_inset LatexCommand \vref{sub:Decoding-XER} - -\end_inset - -. -\layout Description - -xer_encoder This is the XER encoder (XML Encoding Rules). - This encoder will take the target structure and represent it as an XML - (text) document using either BASIC-XER or CANONICAL-XER encoding rules. - See Section -\begin_inset LatexCommand \vref{sub:Encoding-XER} - -\end_inset - -. -\layout Description - -uper_decoder This is the Unaligned PER decoder. -\layout Description - -uper_encoder This is the Unaligned Basic PER encoder. - This encoder will take the target structure and encode it into a series - of bytes. -\layout Description - -check_constraints Check that the contents of the target structure are semantical -ly valid and constrained to appropriate implicit or explicit subtype constraints. - See Section -\begin_inset LatexCommand \vref{sub:Validating-the-target} - -\end_inset - -. -\layout Description - -print_struct This function convert the contents of the passed target structure - into human readable form. - This form is not formal and cannot be converted back into the structure, - but it may turn out to be useful for debugging or quick-n-dirty printing. - See Section -\begin_inset LatexCommand \vref{sub:Printing-the-target} - -\end_inset - -. -\layout Description - -free_struct This is a generic disposal which frees the target structure. - See Section -\begin_inset LatexCommand \vref{sub:Freeing-the-target} - -\end_inset - -. -\layout Standard - -Each of the above function takes the type descriptor ( -\emph on -asn_DEF_\SpecialChar \ldots{} - -\emph default -) and the target structure ( -\emph on -rect -\emph default -, in the above example). -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Decoding-BER} - -\end_inset - -Decoding BER -\layout Standard - -The Basic Encoding Rules describe the most widely used (by the ASN.1 community) - way to encode and decode a given structure in a machine-independent way. - Several other encoding rules (CER, DER) define a more restrictive versions - of BER, so the generic BER parser is also capable of decoding the data - encoded by CER and DER encoders. - The opposite is not true. -\layout Standard - - -\emph on -The ASN.1 compiler provides the generic BER decoder which is implicitly capable - of decoding BER, CER and DER encoded data. -\layout Standard - -The decoder is restartable (stream-oriented), which means that in case the - buffer has less data than it is expected, the decoder will process whatever - there is available and ask for more data to be provided. - Please note that the decoder may actually process less data than it was - given in the buffer, which means that you must be able to make the next - buffer contain the unprocessed part of the previous buffer. -\layout Standard - -Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. -\layout Itemize - -You may concatenate these buffers and feed the BER decoder with 300 bytes - of data, or -\layout Itemize - -You may feed it the first buffer of 100 bytes of data, realize that the - ber_decoder consumed only 95 bytes from it and later feed the decoder with - 205 bytes buffer which consists of 5 unprocessed bytes from the first buffer - and the additional 200 bytes from the second buffer. -\layout Standard - -This is not as convenient as it could be (like, the BER encoder could consume - the whole 100 bytes and keep these 5 bytes in some temporary storage), - but in case of existing stream based processing it might actually fit well - into existing algorithm. - Suggestions are welcome. -\layout Standard - -Here is the simplest example of BER decoding. -\layout LyX-Code - -Rectangle_t * -\layout LyX-Code - -simple_deserializer(const void *buffer, size_t buf_size) { -\layout LyX-Code - - Rectangle_t *rect = 0; /* Note this 0! */ -\layout LyX-Code - - asn_dec_rval_t rval; -\layout LyX-Code - - -\layout LyX-Code - - rval = -\series bold -asn_DEF_Rectangle.ber_decoder -\series default -(0, -\layout LyX-Code - - &asn_DEF_Rectangle, -\layout LyX-Code - - (void **)&rect, -\layout LyX-Code - - buffer, buf_size, -\layout LyX-Code - - 0); -\layout LyX-Code - - -\layout LyX-Code - - if(rval -\series bold -.code -\series default - == RC_OK) { -\layout LyX-Code - - return rect; /* Decoding succeeded */ -\layout LyX-Code - - } else { -\layout LyX-Code - - /* Free partially decoded rect */ -\layout LyX-Code - - asn_DEF_Rectangle.free_struct( -\layout LyX-Code - - &asn_DEF_Rectangle, rect, 0); -\layout LyX-Code - - return 0; -\layout LyX-Code - - } -\layout LyX-Code - -} -\layout Standard - -The code above defines a function, -\emph on -simple_deserializer -\emph default -, which takes a buffer and its length and is expected to return a pointer - to the Rectangle_t structure. - Inside, it tries to convert the bytes passed into the target structure - (rect) using the BER decoder and returns the rect pointer afterwards. - If the structure cannot be deserialized, it frees the memory which might - be left allocated by the unfinished -\emph on -ber_decoder -\emph default - routine and returns 0 (no data). - (This -\series bold - freeing is necessary -\series default - because the ber_decoder is a restartable procedure, and may fail just because - there is more data needs to be provided before decoding could be finalized). - The code above obviously does not take into account the way the -\emph on -ber_decoder() -\emph default - failed, so the freeing is necessary because the part of the buffer may - already be decoded into the structure by the time something goes wrong. -\layout Standard - -A little less wordy would be to invoke a globally available -\emph on -ber_decode() -\emph default - function instead of dereferencing the asn_DEF_Rectangle type descriptor: -\layout LyX-Code - -rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, -\layout LyX-Code - - buffer, buf_size); -\layout Standard - -Note that the initial (asn_DEF_Rectangle.ber_decoder) reference is gone, - and also the last argument (0) is no longer necessary. -\layout Standard - -These two ways of BER decoder invocations are fully equivalent. -\layout Standard - -The BER de -\emph on -coder -\emph default - may fail because of ( -\emph on -the following RC_\SpecialChar \ldots{} - codes are defined in ber_decoder.h -\emph default -): -\layout Itemize - -RC_WMORE: There is more data expected than it is provided (stream mode continuat -ion feature); -\layout Itemize - -RC_FAIL: General failure to decode the buffer; -\layout Itemize - -\SpecialChar \ldots{} - other codes may be defined as well. -\layout Standard - -Together with the return code (.code) the asn_dec_rval_t type contains the - number of bytes which is consumed from the buffer. - In the previous hypothetical example of two buffers (of 100 and 200 bytes), - the first call to ber_decode() would return with .code = RC_WMORE and .consumed - = 95. - The .consumed field of the BER decoder return value is -\series bold -always -\series default - valid, even if the decoder succeeds or fails with any other return code. -\layout Standard - -Please look into ber_decoder.h for the precise definition of ber_decode() - and related types. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Encoding-DER} - -\end_inset - -Encoding DER -\layout Standard - -The Distinguished Encoding Rules is the -\emph on -canonical -\emph default - variant of BER encoding rules. - The DER is best suited to encode the structures where all the lengths are - known beforehand. - This is probably exactly how you want to encode: either after a BER decoding - or after a manual fill-up, the target structure contains the data which - size is implicitly known before encoding. - Among other uses, the DER encoding is used to encode X.509 certificates. -\layout Standard - -As with BER decoder, the DER encoder may be invoked either directly from - the ASN.1 type descriptor (asn_DEF_Rectangle) or from the stand-alone function, - which is somewhat simpler: -\layout LyX-Code - - -\layout LyX-Code - -/* -\layout LyX-Code - - * This is the serializer itself, -\layout LyX-Code - - * it supplies the DER encoder with the -\layout LyX-Code - - * pointer to the custom output function. -\layout LyX-Code - - */ -\layout LyX-Code - -ssize_t -\layout LyX-Code - -simple_serializer(FILE *ostream, Rectangle_t *rect) { -\layout LyX-Code - - asn_enc_rval_t er; /* Encoder return value */ -\layout LyX-Code - - -\layout LyX-Code - - er = der_encode(&asn_DEF_Rect, rect, -\layout LyX-Code - - write_stream, ostream); -\layout LyX-Code - - if(er. -\series bold -encoded -\series default - == -1) { -\layout LyX-Code - - /* -\layout LyX-Code - - * Failed to encode the rectangle data. -\layout LyX-Code - - */ -\layout LyX-Code - - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -Cannot encode %s: %s -\backslash -n -\begin_inset Quotes srd -\end_inset - -, -\layout LyX-Code - - er. -\series bold -failed_type -\series default -->name, -\layout LyX-Code - - strerror(errno)); -\layout LyX-Code - - return -1; -\layout LyX-Code - - } else { -\layout LyX-Code - - /* Return the number of bytes */ -\layout LyX-Code - - return er.encoded; -\layout LyX-Code - - } -\layout LyX-Code - -} -\layout Standard - -As you see, the DER encoder does not write into some sort of buffer or something. - It just invokes the custom function (possible, multiple times) which would - save the data into appropriate storage. - The optional argument -\emph on -app_key -\emph default - is opaque for the DER encoder code and just used by -\emph on -_write_stream() -\emph default - as the pointer to the appropriate output stream to be used. -\layout Standard - -If the custom write function is not given (passed as 0), then the DER encoder - will essentially do the same thing (i.e., encode the data) but no callbacks - will be invoked (so the data goes nowhere). - It may prove useful to determine the size of the structure's encoding before - actually doing the encoding -\begin_inset Foot -collapsed false - -\layout Standard - -It is actually faster too: the encoder might skip over some computations - which aren't important for the size determination. -\end_inset - -. -\layout Standard - -Please look into der_encoder.h for the precise definition of der_encode() - and related types. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Encoding-XER} - -\end_inset - -Encoding XER -\layout Standard - -The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible - Markup Language, a text-based format for information exchange. - The encoder routine API comes in two flavors: stdio-based and callback-based. - With the callback-based encoder, the encoding process is very similar to - the DER one, described in Section -\begin_inset LatexCommand \vref{sub:Encoding-DER} - -\end_inset - -. - The following example uses the definition of write_stream() from up there. -\layout LyX-Code - -/* -\layout LyX-Code - - * This procedure generates the XML document -\layout LyX-Code - - * by invoking the XER encoder. -\layout LyX-Code - - * NOTE: Do not copy this code verbatim! -\layout LyX-Code - - * If the stdio output is necessary, -\layout LyX-Code - - * use the xer_fprint() procedure instead. -\layout LyX-Code - - * See Section -\begin_inset LatexCommand \vref{sub:Printing-the-target} - -\end_inset - -. -\layout LyX-Code - - */ -\layout LyX-Code - -int -\layout LyX-Code - -print_as_XML(FILE *ostream, Rectangle_t *rect) { -\layout LyX-Code - - asn_enc_rval_t er; /* Encoder return value */ -\layout LyX-Code - - -\layout LyX-Code - - er = xer_encode(&asn_DEF_Rectangle, rect, -\layout LyX-Code - - XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */ -\layout LyX-Code - - write_stream, ostream); -\layout LyX-Code - - -\layout LyX-Code - - return (er.encoded == -1) ? -1 : 0; -\layout LyX-Code - -} -\layout Standard - -Please look into xer_encoder.h for the precise definition of xer_encode() - and related types. -\layout Standard - -See Section -\begin_inset LatexCommand \ref{sub:Printing-the-target} - -\end_inset - - for the example of stdio-based XML encoder and other pretty-printing suggestion -s. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Decoding-XER} - -\end_inset - -Decoding XER -\layout Standard - -The data encoded using the XER rules can be subsequently decoded using the - xer_decode() API call: -\layout LyX-Code - -Rectangle_t * -\layout LyX-Code - -XML_to_Rectangle(const void *buffer, size_t buf_size) { -\layout LyX-Code - - Rectangle_t *rect = 0; /* Note this 0! */ -\layout LyX-Code - - asn_dec_rval_t rval; -\layout LyX-Code - - -\layout LyX-Code - - rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, -\layout LyX-Code - - buffer, buf_size); -\layout LyX-Code - - if(rval -\series bold -.code -\series default - == RC_OK) { -\layout LyX-Code - - return rect; /* Decoding succeeded */ -\layout LyX-Code - - } else { -\layout LyX-Code - - /* Free partially decoded rect */ -\layout LyX-Code - - asn_DEF_Rectangle.free_struct( -\layout LyX-Code - - &asn_DEF_Rectangle, rect, 0); -\layout LyX-Code - - return 0; -\layout LyX-Code - - } -\layout LyX-Code - -} -\layout Standard - -The decoder takes both BASIC-XER and CANONICAL-XER encodings. -\layout Standard - -The decoder shares its data consumption properties with BER decoder; please - read the Section -\begin_inset LatexCommand \vref{sub:Decoding-BER} - -\end_inset - - to know more. -\layout Standard - -Please look into xer_decoder.h for the precise definition of xer_decode() - and related types. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Validating-the-target} - -\end_inset - -Validating the target structure -\layout Standard - -Sometimes the target structure needs to be validated. - For example, if the structure was created by the application (as opposed - to being decoded from some external source), some important information - required by the ASN.1 specification might be missing. - On the other hand, the successful decoding of the data from some external - source does not necessarily mean that the data is fully valid either. - It might well be the case that the specification describes some subtype - constraints that were not taken into account during decoding, and it would - actually be useful to perform the last check when the data is ready to - be encoded or when the data has just been decoded to ensure its validity - according to some stricter rules. -\layout Standard - -The asn_check_constraints() function checks the type for various implicit - and explicit constraints. - It is recommended to use asn_check_constraints() function after each decoding - and before each encoding. -\layout Standard - -Please look into constraints.h for the precise definition of asn_check_constraint -s() and related types. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Printing-the-target} - -\end_inset - -Printing the target structure -\layout Standard - -There are two ways to print the target structure: either invoke the print_struct - member of the ASN.1 type descriptor, or using the asn_fprint() function, - which is a simpler wrapper of the former: -\layout LyX-Code - -asn_fprint(stdout, &asn_DEF_Rectangle, rect); -\layout Standard - -Please look into constr_TYPE.h for the precise definition of asn_fprint() - and related types. -\layout Standard - -Another practical alternative to this custom format printing would be to - invoke XER encoder. - The default BASIC-XER encoder performs reasonable formatting for the output - to be useful and human readable. - To invoke the XER decoder in a manner similar to asn_fprint(), use the - xer_fprint() call: -\layout LyX-Code - -xer_fprint(stdout, &asn_DEF_Rectangle, rect); -\layout Standard - -See Section -\begin_inset LatexCommand \vref{sub:Encoding-XER} - -\end_inset - - for XML-related details. -\layout Subsection - - -\begin_inset LatexCommand \label{sub:Freeing-the-target} - -\end_inset - -Freeing the target structure -\layout Standard - -Freeing the structure is slightly more complex than it may seem to. - When the ASN.1 structure is freed, all the members of the structure and - their submembers are recursively freed as well. - But it might not be feasible to free the structure itself. - Consider the following case: -\layout LyX-Code - -struct my_figure { /* The custom structure */ -\layout LyX-Code - - int flags; /* <some custom member> */ -\layout LyX-Code - - /* The type is generated by the ASN.1 compiler */ -\layout LyX-Code - - -\emph on -Rectangle_t rect; -\layout LyX-Code - - /* other members of the structure */ -\layout LyX-Code - -}; -\layout Standard - -In this example, the application programmer defined a custom structure with - one ASN.1-derived member (rect). - This member is not a reference to the Rectangle_t, but an in-place inclusion - of the Rectangle_t structure. - If the freeing is necessary, the usual procedure of freeing everything - must not be applied to the &rect pointer itself, because it does not point - to the memory block directly allocated by the memory allocation routine, - but instead lies within a block allocated for the my_figure structure. -\layout Standard - -To solve this problem, the free_struct routine has the additional argument - (besides the obvious type descriptor and target structure pointers), which - is the flag specifying whether the outer pointer itself must be freed (0, - default) or it should be left intact (non-zero value). -\layout LyX-Code - - -\series bold -/* 1. - Rectangle_t is defined within my_figure */ -\layout LyX-Code - -struct my_figure { -\layout LyX-Code - - Rectangle_t rect; -\layout LyX-Code - -} *mf = -\series bold -... -\series default -; -\layout LyX-Code - -/* -\layout LyX-Code - - * Freeing the Rectangle_t -\layout LyX-Code - - * without freeing the mf->rect area -\layout LyX-Code - - */ -\layout LyX-Code - -asn_DEF_Rectangle.free_struct( -\layout LyX-Code - - &asn_DEF_Rectangle, &mf->rect, -\series bold -1 -\emph on - -\emph default -/* !free */ -\series default -); -\layout LyX-Code - - -\layout LyX-Code - - -\layout LyX-Code - - -\series bold -/* 2. - Rectangle_t is a stand-alone pointer */ -\layout LyX-Code - -Rectangle_t *rect = -\series bold -... -\series default -; -\layout LyX-Code - -/* -\layout LyX-Code - - * Freeing the Rectangle_t -\layout LyX-Code - - * and freeing the rect pointer -\layout LyX-Code - - */ -\layout LyX-Code - -asn_DEF_Rectangle.free_struct( -\layout LyX-Code - - &asn_DEF_Rectangle, rect, -\series bold -0 -\emph on - -\emph default -/* free the pointer too */ -\series default -); -\layout Standard - -It is safe to invoke the -\emph on -free_struct -\emph default - function with the target structure pointer set to 0 (NULL), the function - will do nothing. -\layout Standard - -For the programmer's convenience, the following macros are available: -\layout LyX-Code - -ASN_STRUCT_FREE(asn_DEF, ptr); -\layout LyX-Code - -ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr); -\layout Standard - -These macros bear the same semantics as the -\emph on -free_struct -\emph default - function invocation, discussed above. -\layout Chapter - - -\begin_inset LatexCommand \label{cha:Step-by-step-examples} - -\end_inset - -Step by step examples -\layout Section - -A -\begin_inset Quotes sld -\end_inset - -Rectangle -\begin_inset Quotes srd -\end_inset - - Encoder -\layout Standard - -This example will help you create a simple BER and XER encoder of a -\begin_inset Quotes sld -\end_inset - -Rectangle -\begin_inset Quotes srd -\end_inset - - type used throughout this document. -\layout Enumerate - -Create a file named -\series bold -rectangle.asn1 -\series default - with the following contents: -\begin_deeper -\layout LyX-Code - -RectangleModule1 DEFINITIONS ::= -\layout LyX-Code - -BEGIN -\layout LyX-Code - - -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER, -\layout LyX-Code - - width INTEGER -\layout LyX-Code - -} -\layout LyX-Code - - -\layout LyX-Code - -END -\end_deeper -\layout Enumerate - -Compile it into the set of .c and .h files using asn1c compiler -\begin_inset LatexCommand \cite{ASN1C} - -\end_inset - -: -\begin_deeper -\layout LyX-Code - - -\emph on -asn1c -fnative-types -\series bold -\emph default -rectangle.asn1 -\end_deeper -\layout Enumerate - -Alternatively, use the Online ASN.1 compiler -\begin_inset LatexCommand \cite{AONL} - -\end_inset - - by uploading the -\series bold -rectangle.asn1 -\series default - file into the Web form and unpacking the produced archive on your computer. -\layout Enumerate - -By this time, you should have gotten multiple files in the current directory, - including the -\series bold -Rectangle.c -\series default - and -\series bold -Rectangle.h -\series default -. -\layout Enumerate - -Create a main() routine which creates the Rectangle_t structure in memory - and encodes it using BER and XER encoding rules. - Let's name the file -\series bold -main.c -\series default -: -\begin_inset ERT -status Open - -\layout Standard - -\backslash -clearpage{} -\end_inset - - -\begin_deeper -\layout LyX-Code - - -\size small -#include <stdio.h> -\layout LyX-Code - - -\size small -#include <sys/types.h> -\layout LyX-Code - - -\size small -#include <Rectangle.h> /* Rectangle ASN.1 type */ -\layout LyX-Code - - -\layout LyX-Code - - -\size small -/* -\layout LyX-Code - - -\size small - * This is a custom function which writes the -\layout LyX-Code - - -\size small - * encoded output into some FILE stream. -\layout LyX-Code - - -\size small - */ -\layout LyX-Code - - -\size small -static int -\layout LyX-Code - - -\size small -write_out(const void *buffer, size_t size, void *app_key) { -\layout LyX-Code - - -\size small - FILE *out_fp = app_key; -\layout LyX-Code - - -\size small - size_t wrote; -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - wrote = fwrite(buffer, 1, size, out_fp); -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - return (wrote == size) ? 0 : -1; -\layout LyX-Code - - -\size small -} -\layout LyX-Code - - -\layout LyX-Code - - -\size small -int main(int ac, char **av) { -\layout LyX-Code - - -\size small - Rectangle_t *rectangle; /* Type to encode */ -\layout LyX-Code - - -\size small - asn_enc_rval_t ec; /* Encoder return value */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Allocate the Rectangle_t */ -\layout LyX-Code - - -\size small - rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */ -\layout LyX-Code - - -\size small - if(!rectangle) { -\layout LyX-Code - - -\size small - perror( -\begin_inset Quotes sld -\end_inset - -calloc() failed -\begin_inset Quotes srd -\end_inset - -); -\layout LyX-Code - - -\size small - exit(71); /* better, EX_OSERR */ -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Initialize the Rectangle members */ -\layout LyX-Code - - -\size small - rectangle->height = 42; /* any random value */ -\layout LyX-Code - - -\size small - rectangle->width = 23; /* any random value */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* BER encode the data if filename is given */ -\layout LyX-Code - - -\size small - if(ac < 2) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -Specify filename for BER output -\backslash -n -\begin_inset Quotes srd -\end_inset - -); -\layout LyX-Code - - -\size small - } else { -\layout LyX-Code - - -\size small - const char *filename = av[1]; -\layout LyX-Code - - -\size small - FILE *fp = fopen(filename, -\begin_inset Quotes sld -\end_inset - -wb -\begin_inset Quotes srd -\end_inset - -); /* for BER output */ -\layout LyX-Code - - -\layout LyX-Code - - -\size small - if(!fp) { -\layout LyX-Code - - -\size small - perror(filename); -\layout LyX-Code - - -\size small - exit(71); /* better, EX_OSERR */ -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Encode the Rectangle type as BER (DER) */ -\layout LyX-Code - - -\size small - ec = der_encode(&asn_DEF_Rectangle, -\layout LyX-Code - - -\size small - rectangle, write_out, fp); -\layout LyX-Code - - -\size small - fclose(fp); -\layout LyX-Code - - -\size small - if(ec.encoded == -1) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\layout LyX-Code - - -\size small - -\begin_inset Quotes sld -\end_inset - -Could not encode Rectangle (at %s) -\backslash -n -\begin_inset Quotes srd -\end_inset - -, -\layout LyX-Code - - -\size small - ec.failed_type ? ec.failed_type->name : -\begin_inset Quotes sld -\end_inset - -unknown -\begin_inset Quotes srd -\end_inset - -); -\layout LyX-Code - - -\size small - exit(65); /* better, EX_DATAERR */ -\layout LyX-Code - - -\size small - } else { -\layout LyX-Code - - -\size small - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -Created %s with BER encoded Rectangle -\backslash -n -\begin_inset Quotes srd -\end_inset - -, -\layout LyX-Code - - -\size small - filename); -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Also print the constructed Rectangle XER encoded (XML) */ -\layout LyX-Code - - -\size small - xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - return 0; /* Encoding finished successfully */ -\layout LyX-Code - - -\size small -} -\end_deeper -\layout Enumerate - -Compile all files together using C compiler (varies by platform): -\begin_deeper -\layout LyX-Code - - -\emph on -cc -I. - -o -\series bold -rencode -\series default - *.c -\end_deeper -\layout Enumerate - -Voila! You have just created the BER and XER encoder of a Rectangle type, - named -\series bold -rencode -\series default -! -\layout Standard - - -\begin_inset ERT -status Collapsed - -\layout Standard - -\backslash -clearpage{} -\end_inset - - -\layout Section - - -\begin_inset LatexCommand \label{sec:A-Rectangle-Decoder} - -\end_inset - -A -\begin_inset Quotes sld -\end_inset - -Rectangle -\begin_inset Quotes srd -\end_inset - - Decoder -\layout Standard - -This example will help you to create a simple BER decoder of a simple -\begin_inset Quotes sld -\end_inset - -Rectangle -\begin_inset Quotes srd -\end_inset - - type used throughout this document. -\layout Enumerate - -Create a file named -\series bold -rectangle.asn1 -\series default - with the following contents: -\begin_deeper -\layout LyX-Code - -RectangleModule1 DEFINITIONS ::= -\layout LyX-Code - -BEGIN -\layout LyX-Code - - -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER, -\layout LyX-Code - - width INTEGER -\layout LyX-Code - -} -\layout LyX-Code - - -\layout LyX-Code - -END -\end_deeper -\layout Enumerate - -Compile it into the set of .c and .h files using asn1c compiler -\begin_inset LatexCommand \cite{ASN1C} - -\end_inset - -: -\begin_deeper -\layout LyX-Code - - -\emph on -asn1c -fnative-types -\series bold -\emph default -rectangle.asn1 -\end_deeper -\layout Enumerate - -Alternatively, use the Online ASN.1 compiler -\begin_inset LatexCommand \cite{AONL} - -\end_inset - - by uploading the -\series bold -rectangle.asn1 -\series default - file into the Web form and unpacking the produced archive on your computer. -\layout Enumerate - -By this time, you should have gotten multiple files in the current directory, - including the -\series bold -Rectangle.c -\series default - and -\series bold -Rectangle.h -\series default -. -\layout Enumerate - -Create a main() routine which takes the binary input file, decodes it as - it were a BER-encoded Rectangle type, and prints out the text (XML) representat -ion of the Rectangle type. - Let's name the file -\series bold -main.c -\series default -: -\begin_inset ERT -status Collapsed - -\layout Standard - -\backslash -clearpage{} -\end_inset - - -\begin_deeper -\layout LyX-Code - - -\size small -#include <stdio.h> -\layout LyX-Code - - -\size small -#include <sys/types.h> -\layout LyX-Code - - -\size small -#include <Rectangle.h> /* Rectangle ASN.1 type */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small -int main(int ac, char **av) { -\layout LyX-Code - - -\size small - char buf[1024]; /* Temporary buffer */ -\layout LyX-Code - - -\size small - Rectangle_t *rectangle = 0; /* Type to decode */ -\layout LyX-Code - - -\size small - asn_dec_rval_t rval; /* Decoder return value */ -\layout LyX-Code - - -\size small - FILE *fp; /* Input file handler */ -\layout LyX-Code - - -\size small - size_t size; /* Number of bytes read */ -\layout LyX-Code - - -\size small - char *filename; /* Input file name */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Require a single filename argument */ -\layout LyX-Code - - -\size small - if(ac != 2) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -Usage: %s <file.ber> -\backslash -n -\begin_inset Quotes srd -\end_inset - -, av[0]); -\layout LyX-Code - - -\size small - exit(64); /* better, EX_USAGE */ -\layout LyX-Code - - -\size small - } else { -\layout LyX-Code - - -\size small - filename = av[1]; -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Open input file as read-only binary */ -\layout LyX-Code - - -\size small - fp = fopen(filename, -\begin_inset Quotes sld -\end_inset - -rb -\begin_inset Quotes srd -\end_inset - -); -\layout LyX-Code - - -\size small - if(!fp) { -\layout LyX-Code - - -\size small - perror(filename); -\layout LyX-Code - - -\size small - exit(66); /* better, EX_NOINPUT */ -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Read up to the buffer size */ -\layout LyX-Code - - -\size small - size = fread(buf, 1, sizeof(buf), fp); -\layout LyX-Code - - -\size small - fclose(fp); -\layout LyX-Code - - -\size small - if(!size) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -%s: Empty or broken -\backslash -n -\begin_inset Quotes srd -\end_inset - -, filename); -\layout LyX-Code - - -\size small - exit(65); /* better, EX_DATAERR */ -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Decode the input buffer as Rectangle type */ -\layout LyX-Code - - -\size small - rval = ber_decode(0, &asn_DEF_Rectangle, -\layout LyX-Code - - -\size small - (void **)&rectangle, buf, size); -\layout LyX-Code - - -\size small - if(rval.code != RC_OK) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\layout LyX-Code - - -\size small - -\begin_inset Quotes sld -\end_inset - -%s: Broken Rectangle encoding at byte %ld -\backslash -n -\begin_inset Quotes srd -\end_inset - -, -\layout LyX-Code - - -\size small - filename, (long)rval.consumed); -\layout LyX-Code - - -\size small - exit(65); /* better, EX_DATAERR */ -\layout LyX-Code - - -\size small - } -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - /* Print the decoded Rectangle type as XML */ -\layout LyX-Code - - -\size small - xer_fprint(stdout, &asn_DEF_Rectangle, rectangle); -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small - return 0; /* Decoding finished successfully */ -\layout LyX-Code - - -\size small -} -\end_deeper -\layout Enumerate - -Compile all files together using C compiler (varies by platform): -\begin_deeper -\layout LyX-Code - - -\emph on -cc -I. - -o -\series bold -rdecode -\series default - *.c -\end_deeper -\layout Enumerate - -Voila! You have just created the BER decoder of a Rectangle type, named - -\series bold -rdecode -\series default -! -\layout Chapter - -Constraint validation examples -\layout Standard - -This chapter shows how to define ASN.1 constraints and use the generated - validation code. -\layout Section - -Adding constraints into -\begin_inset Quotes sld -\end_inset - -Rectangle -\begin_inset Quotes srd -\end_inset - - type -\layout Standard - -This example shows how to add basic constraints to the ASN.1 specification - and how to invoke the constraints validation code in your application. -\layout Enumerate - -Create a file named -\series bold -rectangle.asn1 -\series default - with the following contents: -\begin_deeper -\layout LyX-Code - -RectangleModuleWithConstraints DEFINITIONS ::= -\layout LyX-Code - -BEGIN -\layout LyX-Code - - -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER (0..100), -- Value range constraint -\layout LyX-Code - - width INTEGER (0..MAX) -- Makes width non-negative -\layout LyX-Code - -} -\layout LyX-Code - - -\layout LyX-Code - -END -\end_deeper -\layout Enumerate - -Compile the file according to procedures shown in the previous chapter. -\layout Enumerate - -Modify the Rectangle type processing routine (you can start with the main() - routine shown in the Section -\begin_inset LatexCommand \vref{sec:A-Rectangle-Decoder} - -\end_inset - -) by placing the following snippet of code -\emph on -before -\emph default - encoding and/or -\emph on -after -\emph default - decoding the Rectangle type -\begin_inset Foot -collapsed true - -\layout Standard - -Placing the constraint checking code -\emph on -before -\emph default - encoding helps to make sure you know the data is correct and within constraints - before sharing the data with anyone else. -\layout Standard - -Placing the constraint checking code -\emph on -after -\emph default - decoding, but before any further action depending on the decoded data, - helps to make sure the application got the valid contents before making - use of it. -\end_inset - -: -\begin_inset ERT -status Collapsed - -\layout Standard - -\backslash -clearpage{} -\end_inset - - -\begin_deeper -\layout LyX-Code - - -\size small -int ret; /* Return value */ -\layout LyX-Code - - -\size small -char errbuf[128]; /* Buffer for error message */ -\layout LyX-Code - - -\size small -size_t errlen = sizeof(errbuf); /* Size of the buffer */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small -/* ... - here may go Rectangle decoding code ... - */ -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small -ret = asn_check_constraints(&asn_DEF_Rectangle, -\layout LyX-Code - - -\size small - rectangle, errbuf, &errlen); -\layout LyX-Code - - -\size small -/* assert(errlen < sizeof(errbuf)); // you may rely on that */ -\layout LyX-Code - - -\size small -if(ret) { -\layout LyX-Code - - -\size small - fprintf(stderr, -\begin_inset Quotes sld -\end_inset - -Constraint validation failed: %s -\backslash -n -\begin_inset Quotes srd -\end_inset - -, -\layout LyX-Code - - -\size small - errbuf /* errbuf is properly nul-terminated */ -\layout LyX-Code - - -\size small - ); -\layout LyX-Code - - -\size small - /* exit(...); // Replace with appropriate action */ -\layout LyX-Code - - -\size small -} -\layout LyX-Code - - -\size small - -\layout LyX-Code - - -\size small -/* ... - here may go Rectangle encoding code ... - */ -\end_deeper -\layout Enumerate - -Compile the resulting C code as shown in the previous chapters. -\layout Enumerate - -Try to test the constraints checking code by assigning integer value 101 - to the -\series bold -.height -\series default - member of the Rectangle structure, or a negative value to the -\series bold -.width -\series default - member. - In either case, the program should print -\begin_inset Quotes sld -\end_inset - -Constraint validation failed -\begin_inset Quotes srd -\end_inset - - message, followed by the short explanation why validation did not succeed. -\layout Enumerate - -Done. -\layout Part - - -\begin_inset LatexCommand \label{par:ASN.1-Basics} - -\end_inset - -ASN.1 Basics -\layout Chapter - - -\begin_inset LatexCommand \label{cha:Abstract-Syntax-Notation:} - -\end_inset - -Abstract Syntax Notation: ASN.1 -\layout Standard - - -\emph on -This chapter defines some basic ASN.1 concepts and describes several most - widely used types. - It is by no means an authoritative or complete reference. - For more complete ASN.1 description, please refer to Olivier Dubuisson's - book -\begin_inset LatexCommand \cite{Dub00} - -\end_inset - - or the ASN.1 body of standards itself -\begin_inset LatexCommand \cite{ITU-T/ASN.1} - -\end_inset - -. -\layout Standard - -The Abstract Syntax Notation One is used to formally describe the semantics - of data transmitted across the network. - Two communicating parties may have different formats of their native data - types (i.e. - number of bits in the integer type), thus it is important to have a way - to describe the data in a manner which is independent from the particular - machine's representation. - The ASN.1 specifications are used to achieve the following: -\layout Itemize - -The specification expressed in the ASN.1 notation is a formal and precise - way to communicate the data semantics to human readers; -\layout Itemize - -The ASN.1 specifications may be used as input for automatic compilers which - produce the code for some target language (C, C++, Java, etc) to encode - and decode the data according to some encoding rules (which are also defined - by the ASN.1 standard). -\layout Standard - -Consider the following example: -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER, -\layout LyX-Code - - width INTEGER -\layout LyX-Code - -} -\layout Standard - -This ASN.1 specification describes a constructed type, -\emph on -Rectangle -\emph default -, containing two integer fields. - This specification may tell the reader that there exists this kind of data - structure and that some entity may be prepared to send or receive it. - The question on -\emph on -how -\emph default - that entity is going to send or receive the -\emph on -encoded data -\emph default - is outside the scope of ASN.1. - For example, this data structure may be encoded according to some encoding - rules and sent to the destination using the TCP protocol. - The ASN.1 specifies several ways of encoding (or -\begin_inset Quotes sld -\end_inset - -serializing -\begin_inset Quotes srd -\end_inset - -, or -\begin_inset Quotes sld -\end_inset - -marshaling -\begin_inset Quotes srd -\end_inset - -) the data: BER, PER, XER and others, including CER and DER derivatives - from BER. -\layout Standard - -The complete specification must be wrapped in a module, which looks like - this: -\layout LyX-Code - -RectangleModule1 -\layout LyX-Code - - { iso org(3) dod(6) internet(1) private(4) -\layout LyX-Code - - enterprise(1) spelio(9363) software(1) -\layout LyX-Code - - asn1c(5) docs(2) rectangle(1) 1 } -\layout LyX-Code - - DEFINITIONS AUTOMATIC TAGS ::= -\layout LyX-Code - -BEGIN -\layout LyX-Code - - -\layout LyX-Code - --- This is a comment which describes nothing. -\layout LyX-Code - -Rectangle ::= SEQUENCE { -\layout LyX-Code - - height INTEGER, -- Height of the rectangle -\layout LyX-Code - - width INTEGER -- Width of the rectangle -\layout LyX-Code - -} -\layout LyX-Code - - -\layout LyX-Code - -END -\layout Standard - -The module header consists of module name (RectangleModule1), the module - object identifier ({...}), a keyword -\begin_inset Quotes sld -\end_inset - -DEFINITIONS -\begin_inset Quotes srd -\end_inset - -, a set of module flags (AUTOMATIC TAGS) and -\begin_inset Quotes sld -\end_inset - -::= BEGIN -\begin_inset Quotes srd -\end_inset - -. - The module ends with an -\begin_inset Quotes sld -\end_inset - -END -\begin_inset Quotes srd -\end_inset - - statement. -\layout Section - -Some of the ASN.1 Basic Types -\layout Subsection - -The BOOLEAN type -\layout Standard - -The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF or - a similar kind of two-way choice. -\layout Subsection - -The INTEGER type -\layout Standard - -The INTEGER type is a signed natural number type without any restrictions - on its size. - If the automatic checking on INTEGER value bounds are necessary, the subtype - constraints must be used. -\layout LyX-Code - -SimpleInteger ::= INTEGER -\layout LyX-Code - - -\layout LyX-Code - --- An integer with a very limited range -\layout LyX-Code - -SmallPositiveInt ::= INTEGER (0..127) -\layout LyX-Code - - -\layout LyX-Code - --- Integer, negative -\layout LyX-Code - -NegativeInt ::= INTEGER (MIN..0) -\layout Subsection - -The ENUMERATED type -\layout Standard - -The ENUMERATED type is semantically equivalent to the INTEGER type with - some integer values explicitly named. -\layout LyX-Code - -FruitId ::= ENUMERATED { apple(1), orange(2) } -\layout LyX-Code - - -\layout LyX-Code - --- The numbers in braces are optional, -\layout LyX-Code - --- the enumeration can be performed -\layout LyX-Code - --- automatically by the compiler -\layout LyX-Code - -ComputerOSType ::= ENUMERATED { -\layout LyX-Code - - FreeBSD, -- acquires value 0 -\layout LyX-Code - - Windows, -- acquires value 1 -\layout LyX-Code - - Solaris(5), -- remains 5 -\layout LyX-Code - - Linux, -- becomes 6 -\layout LyX-Code - - MacOS -- becomes 7 -\layout LyX-Code - -} -\layout Subsection - -The OCTET STRING type -\layout Standard - -This type models the sequence of 8-bit bytes. - This may be used to transmit some opaque data or data serialized by other - types of encoders (i.e. - video file, photo picture, etc). -\layout Subsection - -The OBJECT IDENTIFIER type -\layout Standard - -The OBJECT IDENTIFIER is used to represent the unique identifier of any - object, starting from the very root of the registration tree. - If your organization needs to uniquely identify something (a router, a - room, a person, a standard, or whatever), you are encouraged to get your - own identification subtree at -\begin_inset LatexCommand \htmlurl{http://www.iana.org/protocols/forms.htm} - -\end_inset - -. -\layout Standard - -For example, the very first ASN.1 module in this Chapter (RectangleModule1) - has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1. -\layout LyX-Code - -ExampleOID ::= OBJECT IDENTIFIER -\layout LyX-Code - - -\layout LyX-Code - -rectangleModule1-oid ExampleOID -\layout LyX-Code - - ::= { 1 3 6 1 4 1 9363 1 5 2 1 1 } -\layout LyX-Code - - -\layout LyX-Code - --- An identifier of the Internet. -\layout LyX-Code - -internet-id OBJECT IDENTIFIER -\layout LyX-Code - - ::= { iso(1) identified-organization(3) -\layout LyX-Code - - dod(6) internet(1) } -\layout Standard - -As you see, names are optional. -\layout Subsection - -The RELATIVE-OID type -\layout Standard - -The RELATIVE-OID type has the semantics of a subtree of an OBJECT IDENTIFIER. - There may be no need to repeat the whole sequence of numbers from the root - of the registration tree where the only thing of interest is some of the - tree's subsequence. -\layout LyX-Code - -this-document RELATIVE-OID ::= { docs(2) usage(1) } -\layout LyX-Code - - -\layout LyX-Code - -this-example RELATIVE-OID ::= { -\layout LyX-Code - - this-document assorted-examples(0) this-example(1) } -\layout Section - -Some of the ASN.1 String Types -\layout Subsection - -The IA5String type -\layout Standard - -This is essentially the ASCII, with 128 character codes available (7 lower - bits of an 8-bit byte). -\layout Subsection - -The UTF8String type -\layout Standard - -This is the character string which encodes the full Unicode range (4 bytes) - using multibyte character sequences. -\layout Subsection - -The NumericString type -\layout Standard - -This type represents the character string with the alphabet consisting of - numbers ( -\begin_inset Quotes sld -\end_inset - -0 -\begin_inset Quotes srd -\end_inset - - to -\begin_inset Quotes sld -\end_inset - -9 -\begin_inset Quotes srd -\end_inset - -) and a space. -\layout Subsection - -The PrintableString type -\layout Standard - -The character string with the following alphabet: space, -\begin_inset Quotes sld -\end_inset - - -\series bold -' -\series default - -\begin_inset Quotes srd -\end_inset - - (single quote), -\begin_inset Quotes sld -\end_inset - - -\series bold -( -\series default - -\begin_inset Quotes sld -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -) -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -+ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -, -\series default - -\begin_inset Quotes srd -\end_inset - - (comma), -\begin_inset Quotes sld -\end_inset - - -\series bold -- -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -. -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -/ -\series default - -\begin_inset Quotes srd -\end_inset - -, digits ( -\begin_inset Quotes sld -\end_inset - -0 -\begin_inset Quotes srd -\end_inset - - to -\begin_inset Quotes sld -\end_inset - -9 -\begin_inset Quotes srd -\end_inset - -), -\begin_inset Quotes sld -\end_inset - - -\series bold -: -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -= -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -? -\series default - -\begin_inset Quotes srd -\end_inset - -, upper-case and lower-case letters ( -\begin_inset Quotes sld -\end_inset - -A -\begin_inset Quotes srd -\end_inset - - to -\begin_inset Quotes sld -\end_inset - -Z -\begin_inset Quotes srd -\end_inset - - and -\begin_inset Quotes sld -\end_inset - -a -\begin_inset Quotes srd -\end_inset - - to -\begin_inset Quotes sld -\end_inset - -z -\begin_inset Quotes srd -\end_inset - -). -\layout Subsection - -The VisibleString type -\layout Standard - -The character string with the alphabet which is more or less a subset of - ASCII between the space and the -\begin_inset Quotes sld -\end_inset - - -\series bold -~ -\series default - -\begin_inset Quotes srd -\end_inset - - symbol (tilde). -\layout Standard - -Alternatively, the alphabet may be described as the PrintableString alphabet - presented earlier, plus the following characters: -\begin_inset Quotes sld -\end_inset - - -\series bold -! -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold - -\begin_inset Quotes srd -\end_inset - - -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -# -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -$ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -% -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -& -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -* -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -; -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -< -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -> -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -[ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold - -\backslash - -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -] -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -^ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -_ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -` -\series default - -\begin_inset Quotes srd -\end_inset - - (single left quote), -\begin_inset Quotes sld -\end_inset - - -\series bold -{ -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -| -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -} -\series default - -\begin_inset Quotes srd -\end_inset - -, -\begin_inset Quotes sld -\end_inset - - -\series bold -~ -\series default - -\begin_inset Quotes srd -\end_inset - -. -\layout Section - -ASN.1 Constructed Types -\layout Subsection - -The SEQUENCE type -\layout Standard - -This is an ordered collection of other simple or constructed types. - The SEQUENCE constructed type resembles the C -\begin_inset Quotes sld -\end_inset - -struct -\begin_inset Quotes srd -\end_inset - - statement. -\layout LyX-Code - -Address ::= SEQUENCE { -\layout LyX-Code - - -- The apartment number may be omitted -\layout LyX-Code - - apartmentNumber NumericString OPTIONAL, -\layout LyX-Code - - streetName PrintableString, -\layout LyX-Code - - cityName PrintableString, -\layout LyX-Code - - stateName PrintableString, -\layout LyX-Code - - -- This one may be omitted too -\layout LyX-Code - - zipNo NumericString OPTIONAL -\layout LyX-Code - -} -\layout Subsection - -The SET type -\layout Standard - -This is a collection of other simple or constructed types. - Ordering is not important. - The data may arrive in the order which is different from the order of specifica -tion. - Data is encoded in the order not necessarily corresponding to the order - of specification. -\layout Subsection - -The CHOICE type -\layout Standard - -This type is just a choice between the subtypes specified in it. - The CHOICE type contains at most one of the subtypes specified, and it - is always implicitly known which choice is being decoded or encoded. - This one resembles the C -\begin_inset Quotes sld -\end_inset - -union -\begin_inset Quotes srd -\end_inset - - statement. -\layout Standard - -The following type defines a response code, which may be either an integer - code or a boolean -\begin_inset Quotes sld -\end_inset - -true -\begin_inset Quotes srd -\end_inset - -/ -\begin_inset Quotes srd -\end_inset - -false -\begin_inset Quotes srd -\end_inset - - code. -\layout LyX-Code - -ResponseCode ::= CHOICE { -\layout LyX-Code - - intCode INTEGER, -\layout LyX-Code - - boolCode BOOLEAN -\layout LyX-Code - -} -\layout LyX-Code - -\layout Subsection - -The SEQUENCE OF type -\layout Standard - -This one is the list (array) of simple or constructed types: -\layout LyX-Code - --- Example 1 -\layout LyX-Code - -ManyIntegers ::= SEQUENCE OF INTEGER -\layout LyX-Code - - -\layout LyX-Code - --- Example 2 -\layout LyX-Code - -ManyRectangles ::= SEQUENCE OF Rectangle -\layout LyX-Code - - -\layout LyX-Code - --- More complex example: -\layout LyX-Code - --- an array of structures defined in place. -\layout LyX-Code - -ManyCircles ::= SEQUENCE OF SEQUENCE { -\layout LyX-Code - - radius INTEGER -\layout LyX-Code - - } -\layout Subsection - -The SET OF type -\layout Standard - -The SET OF type models the bag of structures. - It resembles the SEQUENCE OF type, but the order is not important: i.e. - the elements may arrive in the order which is not necessarily the same - as the in-memory order on the remote machines. -\layout LyX-Code - --- A set of structures defined elsewhere -\layout LyX-Code - -SetOfApples :: SET OF Apple -\layout LyX-Code - - -\layout LyX-Code - --- Set of integers encoding the kind of a fruit -\layout LyX-Code - -FruitBag ::= SET OF ENUMERATED { apple, orange } -\layout Bibliography -\bibitem [ASN1C]{ASN1C} - -The Open Source ASN.1 Compiler. - -\begin_inset LatexCommand \htmlurl{http://lionet.info/asn1c} - -\end_inset - - -\layout Bibliography -\bibitem [AONL]{AONL} - -Online ASN.1 Compiler. - -\begin_inset LatexCommand \htmlurl{http://lionet.info/asn1c/asn1c.cgi} - -\end_inset - - -\layout Bibliography -\bibitem [Dub00]{Dub00} - -Olivier Dubuisson --- -\emph on -ASN.1 Communication between heterogeneous systems -\emph default - --- Morgan Kaufmann Publishers, 2000. - -\begin_inset LatexCommand \htmlurl{http://asn1.elibel.tm.fr/en/book/} - -\end_inset - -. - ISBN:0-12-6333361-0. -\layout Bibliography -\bibitem [ITU-T/ASN.1]{ITU-T/ASN.1} - -ITU-T Study Group 17 -- Languages for Telecommunication Systems -\begin_inset LatexCommand \url{http://www.itu.int/ITU-T/studygroups/com17/languages/} - -\end_inset - - -\the_end diff --git a/doc/asn1c-usage.tex b/doc/asn1c-usage.tex new file mode 100644 index 00000000..c65b256a --- /dev/null +++ b/doc/asn1c-usage.tex @@ -0,0 +1,1588 @@ +%% LyX 1.6.7 created this file. For more info, see http://www.lyx.org/. +%% Do not edit unless you really know what you are doing. +\documentclass[english]{book} +\usepackage{mathptmx} +\usepackage[T1]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage{fancyhdr} +\pagestyle{fancy} +\usepackage{array} +\usepackage{longtable} +\usepackage{varioref} +\usepackage{url} + +\makeatletter + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. +%% Because html converters don't know tabularnewline +\providecommand{\tabularnewline}{\\} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands. +\newenvironment{lyxcode} +{\par\begin{list}{}{ +\setlength{\rightmargin}{\leftmargin} +\setlength{\listparindent}{0pt}% needed for AMS classes +\raggedright +\setlength{\itemsep}{0pt} +\setlength{\parsep}{0pt} +\normalfont\ttfamily}% + \item[]} +{\end{list}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. +\usepackage{extramarks} +\lhead{\firstxmark} +\rfoot{\lastxmark} +\usepackage{color} +\definecolor{gray40}{gray}{.4} +\definecolor{urlblue}{rgb}{0,0,.6} +\usepackage[colorlinks=true, +linkcolor={gray40}, +urlcolor={urlblue}, +pdfauthor={Lev Walkin}, +pdftitle={Using the Open Source ASN.1 Compiler}, +pdfkeywords={ASN.1,asn1c,compiler} +]{hyperref} +%\fancyhf{} +%\fancyhead[LE,RO]{\thepage} +%\fancyhead[LO]{\rightmark} +%\fancyhead[RE]{\leftmark} +%\fancyfoot[R]{\lastxmark} + +\makeatother + +\usepackage{babel} + +\begin{document} + +\title{Using the Open Source ASN.1 Compiler} + + +\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>} + +\maketitle +\lhead{This document describes \href{http://lionet.info/asn1c}{asn1c-0.9.21}} + +\rhead{$Revision$} + +\tableofcontents{} + +\pagestyle{headings} + + +\part{Using the ASN.1 Compiler} + + +\chapter{Introduction to the ASN.1 Compiler} + +The purpose of the ASN.1 compiler is to convert the specifications +in ASN.1 notation into some other language. At this moment, only C +and C++ target languages are supported, the latter is in upward compatibility +mode. + +The compiler reads the specification and emits a series of target +language structures (C's structs, unions, enums) describing the corresponding +ASN.1 types. The compiler also creates the code which allows automatic +serialization and deserialization of these structures using several +standardized encoding rules (BER, DER, XER). + +For example, suppose the following ASN.1 module is given% +\footnote{Please look into Part \vref{par:ASN.1-Basics} for a quick reference +on how to understand the ASN.1 notation.% +}: +\begin{lyxcode} +RectangleTest~DEFINITIONS~::= + +BEGIN + +~ + +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle + +~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle + +\} + +~ + +END +\end{lyxcode} +The compiler would read this ASN.1 definition and produce the following +C type% +\footnote{\emph{-fnative-types} compiler option is used to produce basic C \emph{int} +types instead of infinite width INTEGER\_t structures. See Section +\vref{sec:Command-line-options}.% +}: +\begin{lyxcode} +typedef~struct~Rectangle\_s~\{ + +~~~~int~height; + +~~~~int~width; + +\}~Rectangle\_t; +\end{lyxcode} +It would also create the code for converting this structure into platform-independent +wire representation (a serializer API) and the decoder of such wire +representation back into local, machine-specific type (a deserializer +API). + + +\section{Quick start with asn1c} + +After building and installing the compiler, the \emph{asn1c}% +\footnote{The 1 symbol in asn\textbf{1}c is a digit, not an ''ell'' letter.% +} command may be used to compile the ASN.1 module% +\footnote{This is probably \textbf{not} what you want to try out right now -- +read through the rest of this chapter and check the Section \vref{sec:Command-line-options} +to find out about \textbf{-P} and \textbf{-R} options.% +}: +\begin{lyxcode} +asn1c~\emph{<module.asn1>} +\end{lyxcode} +If several ASN.1 modules contain interdependencies, all of the files +must be specified altogether: +\begin{lyxcode} +asn1c~\emph{<module1.asn1>~<module2.asn1>~...} +\end{lyxcode} +The compiler \textbf{-E} and \textbf{-EF} options are used for testing +the parser and the semantic fixer, respectively. These options will +instruct the compiler to dump out the parsed (and fixed, if \textbf{-F} +is involved) ASN.1 specification as it was \textquotedbl{}understood\textquotedbl{} +by the compiler. It might be useful to check whether a particular +syntactic construction is properly supported by the compiler. +\begin{lyxcode} +asn1c~\textbf{-EF}~\emph{<module-to-test.asn1>} +\end{lyxcode} +The \textbf{-P} option is used to dump the compiled output on the +screen instead of creating a bunch of .c and .h files on disk in the +current directory. You would probably want to start with \textbf{-P} +option instead of creating a mess in your current directory. Another +option, \textbf{-R}, asks compiler to only generate the files which +need to be generated, and supress linking in the numerous support +files. + +Print the compiled output instead of creating multiple source files: +\begin{lyxcode} +asn1c~\textbf{-P}~\emph{<module-to-compile-and-print.asn1>} +\end{lyxcode} + +\section{Recognizing compiler output} + +After compiling, the following entities will be created in your current +directory: +\begin{itemize} +\item A set of .c and .h files, generally a single pair for each type defined +in the ASN.1 specifications. These files will be named similarly to +the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the +RectangleTest ASN.1 module defined in the beginning of this document). +\item A set of helper .c and .h files which contain generic encoders, decoders +and other useful routines. There will be quite a few of them, some +of them even are not always necessary, but the overall amount of code +after compilation will be rather small anyway. +\item A \emph{Makefile.am.sample} file mentioning all the files created +at the earlier steps. This file is suitable for either automake suite +or the plain `make` utility. +\end{itemize} +It is your responsibility to create .c file with the \emph{int main()} +routine. + +In other words, after compiling the Rectangle module, you have the +following set of files: \{ Makefile.am.sample, Rectangle.c, Rectangle.h, +\textbf{\ldots{}} \}, where \textbf{''\ldots{}''} stands for the +set of additional ''helper'' files created by the compiler. If you +add a simple file with the \emph{int main()} routine, it would even +be possible to compile everything with the single instruction: +\begin{lyxcode} +cc~-I.~-o~rectangle.exe~{*}.c~~~\#~It~could~be~\emph{that}~simple +\end{lyxcode} +Refer to the Chapter \vref{cha:Step-by-step-examples} for a sample +\emph{int main()} routine. + + +\section{\label{sec:Command-line-options}Command line options} + +The following table summarizes the asn1c command line options. + +\begin{longtable}{|l|p{3in}|} +\hline +\textbf{\small Overall Options} & \textbf{\small Description}\tabularnewline +\hline +\hline +{\small -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1 +specification code to the standard output.}\tabularnewline +\hline +{\small -F} & {\small Used together with -E, instructs the compiler to stop after +the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1 +specification to the standard output.}\tabularnewline +\hline +{\small -P} & {\small Dump the compiled output to the standard output instead of +cre- ating the target language files on disk.}\tabularnewline +\hline +{\small -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omit- +ting the usual support code.}\tabularnewline +\hline +{\small -S }\emph{\small <directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\tabularnewline +\hline +{\small -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\tabularnewline +\hline +\hline +\textbf{\small Warning Options} & \textbf{\small Description}\tabularnewline +\hline +{\small -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\tabularnewline +\hline +{\small -Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\tabularnewline +\hline +{\small -Wdebug-fixer} & {\small{} Enable ASN.1 syntax tree fixer debugging during the + fixing stage.}\tabularnewline +\hline +{\small -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\tabularnewline +\hline +\newpage +\hline +\textbf{\small Language Options} & \textbf{\small Description}\tabularnewline +\hline +{\small -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other +types for which this constraint is normally prohibited by the standard. +This is a violation of an ASN.1 standard and compiler may fail to +produce the meaningful code.}\tabularnewline +\hline +{\small -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents +name clashes in case the module reuses the same identifiers in multiple +contexts.}\tabularnewline +\hline +{\small -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE +members as indirect pointers instead of declaring them inline. Consider +using this option together with }\textbf{\small -fno-include-deps}{\small{} +to prevent circular references. }\tabularnewline +\hline +{\small -fknown-extern-type=}\emph{\small <name>} & {\small Pretend the specified type is known. The compiler will assume +the target language source files for the given type have been provided +manually. }\tabularnewline +\hline +{\small -fnative-types} & {\small Use the native machine's data types (int, double) whenever +possible, instead of the compound INTEGER\_t, ENUMERATED\_t and REAL\_t +types. }\tabularnewline +\hline +{\small -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This +may produce a shorter executable.}\tabularnewline +\hline +{\small -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical +dependencies.}\tabularnewline +\hline +{\small -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's +structures.}\tabularnewline +\hline +{\small -fskeletons-copy} & {\small Copy support files rather than symlink them.}\tabularnewline +\hline +\hline +\textbf{\small Codecs Generation Options} & \textbf{\small Description}\tabularnewline +\hline +{\small -gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\tabularnewline +\hline +{\small -pdu=}\emph{\small auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically.}\tabularnewline +\hline +\hline +\textbf{\small Output Options} & \textbf{\small Description}\tabularnewline +\hline +{\small -print-constraints} & {\small When -EF are also specified, this option forces the compiler +to explain its internal understanding of subtype constraints.}\tabularnewline +\hline +{\small -print-lines} & {\small Generate \textquotedbl{}-- \#line\textquotedbl{} comments +in -E output.}\tabularnewline +\hline +\end{longtable} + + +\chapter{Using the ASN.1 Compiler} + + +\section[Invoking the helper code]{Invoking the ASN.1 helper code} + +First of all, you should include one or more header files into your +application. Typically, it is enough to include the header file of +the main PDU type. For our Rectangle module, including the Rectangle.h +file is sufficient: +\begin{lyxcode} +\#include~<Rectangle.h> +\end{lyxcode} +The header files defines the C structure corresponding to the ASN.1 +definition of a rectangle and the declaration of the ASN.1 type descriptor, +which is used as an argument to most of the functions provided by +the ASN.1 module. For example, here is the code which frees the Rectangle\_t +structure: +\begin{lyxcode} +Rectangle\_t~{*}rect~=~...; + +~ + +asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle, + +~~~~rect,~0); +\end{lyxcode} +This code defines a \emph{rect} pointer which points to the Rectangle\_t +structure which needs to be freed. The second line invokes the generic +\emph{free\_struct()} routine created specifically for this Rectangle\_t +structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor, +which holds a collection of routines to deal with the Rectangle\_t +structure. + +The following member functions of the asn\_DEF\_Rectangle type descriptor +are of interest: +\begin{description} +\item [{ber\_decoder}] This is the generic \emph{restartable}% +\footnote{Restartable means that if the decoder encounters the end of the buffer, +it will fail, but may later be invoked again with the rest of the +buffer to continue decoding.% +} BER decoder (Basic Encoding Rules). This decoder would create and/or +fill the target structure for you. See Section \vref{sub:Decoding-BER}. +\item [{der\_encoder}] This is the generic DER encoder (Distinguished Encoding +Rules). This encoder will take the target structure and encode it +into a series of bytes. See Section \vref{sub:Encoding-DER}. NOTE: +DER encoding is a subset of BER. Any BER decoder should be able to +handle DER input. +\item [{xer\_decoder}] This is the generic XER decoder. It takes both BASIC-XER +or CANONICAL-XER encodings and deserializes the data into a local, +machine-dependent representation. See Section \vref{sub:Decoding-XER}. +\item [{xer\_encoder}] This is the XER encoder (XML Encoding Rules). This +encoder will take the target structure and represent it as an XML +(text) document using either BASIC-XER or CANONICAL-XER encoding rules. +See Section \vref{sub:Encoding-XER}. +\item [{uper\_decoder}] This is the Unaligned PER decoder. +\item [{uper\_encoder}] This is the Unaligned Basic PER encoder. This encoder +will take the target structure and encode it into a series of bytes. +\item [{check\_constraints}] Check that the contents of the target structure +are semantically valid and constrained to appropriate implicit or +explicit subtype constraints. See Section \vref{sub:Validating-the-target}. +\item [{print\_struct}] This function convert the contents of the passed +target structure into human readable form. This form is not formal +and cannot be converted back into the structure, but it may turn out +to be useful for debugging or quick-n-dirty printing. See Section +\vref{sub:Printing-the-target}. +\item [{free\_struct}] This is a generic disposal which frees the target +structure. See Section \vref{sub:Freeing-the-target}. +\end{description} +Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}}) +and the target structure (\emph{rect}, in the above example). + + +\subsection{\label{sub:Decoding-BER}Decoding BER} + +The Basic Encoding Rules describe the most widely used (by the ASN.1 +community) way to encode and decode a given structure in a machine-independent +way. Several other encoding rules (CER, DER) define a more restrictive +versions of BER, so the generic BER parser is also capable of decoding +the data encoded by CER and DER encoders. The opposite is not true. + +\emph{The ASN.1 compiler provides the generic BER decoder which is +implicitly capable of decoding BER, CER and DER encoded data.} + +The decoder is restartable (stream-oriented), which means that in +case the buffer has less data than it is expected, the decoder will +process whatever there is available and ask for more data to be provided. +Please note that the decoder may actually process less data than it +was given in the buffer, which means that you must be able to make +the next buffer contain the unprocessed part of the previous buffer. + +Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. +\begin{itemize} +\item You may concatenate these buffers and feed the BER decoder with 300 +bytes of data, or +\item You may feed it the first buffer of 100 bytes of data, realize that +the ber\_decoder consumed only 95 bytes from it and later feed the +decoder with 205 bytes buffer which consists of 5 unprocessed bytes +from the first buffer and the additional 200 bytes from the second +buffer. +\end{itemize} +This is not as convenient as it could be (like, the BER encoder could +consume the whole 100 bytes and keep these 5 bytes in some temporary +storage), but in case of existing stream based processing it might +actually fit well into existing algorithm. Suggestions are welcome. + +Here is the simplest example of BER decoding. +\begin{lyxcode} +Rectangle\_t~{*} + +simple\_deserializer(const~void~{*}buffer,~size\_t~buf\_size)~\{ + +~~~~Rectangle\_t~{*}rect~=~0;~~~~/{*}~Note~this~0!~{*}/ + +~~~~asn\_dec\_rval\_t~rval; + +~ + +~~~~rval~=~\textbf{asn\_DEF\_Rectangle.ber\_decoder}(0, + +~~~~~~~~~~\&asn\_DEF\_Rectangle, + +~~~~~~~~~~(void~{*}{*})\&rect, + +~~~~~~~~~~buffer,~buf\_size, + +~~~~~~~~~~0); + +~ + +~~~~if(rval\textbf{.code}~==~RC\_OK)~\{ + +~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/ + +~~~~\}~else~\{ + +~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/ + +~~~~~~~~asn\_DEF\_Rectangle.free\_struct( + +~~~~~~~~~~~~\&asn\_DEF\_Rectangle,~rect,~0); + +~~~~~~~~return~0; + +~~~~\} + +\} +\end{lyxcode} +The code above defines a function, \emph{simple\_deserializer}, which +takes a buffer and its length and is expected to return a pointer +to the Rectangle\_t structure. Inside, it tries to convert the bytes +passed into the target structure (rect) using the BER decoder and +returns the rect pointer afterwards. If the structure cannot be deserialized, +it frees the memory which might be left allocated by the unfinished +\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing +is necessary} because the ber\_decoder is a restartable procedure, +and may fail just because there is more data needs to be provided +before decoding could be finalized). The code above obviously does +not take into account the way the \emph{ber\_decoder()} failed, so +the freeing is necessary because the part of the buffer may already +be decoded into the structure by the time something goes wrong. + +A little less wordy would be to invoke a globally available \emph{ber\_decode()} +function instead of dereferencing the asn\_DEF\_Rectangle type descriptor: +\begin{lyxcode} +rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect, + +~~~~buffer,~buf\_size); +\end{lyxcode} +Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference +is gone, and also the last argument (0) is no longer necessary. + +These two ways of BER decoder invocations are fully equivalent. + +The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{} +codes are defined in ber\_decoder.h}): +\begin{itemize} +\item RC\_WMORE: There is more data expected than it is provided (stream +mode continuation feature); +\item RC\_FAIL: General failure to decode the buffer; +\item \ldots{} other codes may be defined as well. +\end{itemize} +Together with the return code (.code) the asn\_dec\_rval\_t type contains +the number of bytes which is consumed from the buffer. In the previous +hypothetical example of two buffers (of 100 and 200 bytes), the first +call to ber\_decode() would return with .code = RC\_WMORE and .consumed += 95. The .consumed field of the BER decoder return value is \textbf{always} +valid, even if the decoder succeeds or fails with any other return +code. + +Please look into ber\_decoder.h for the precise definition of ber\_decode() +and related types. + + +\subsection{\label{sub:Encoding-DER}Encoding DER} + +The Distinguished Encoding Rules is the \emph{canonical} variant of +BER encoding rules. The DER is best suited to encode the structures +where all the lengths are known beforehand. This is probably exactly +how you want to encode: either after a BER decoding or after a manual +fill-up, the target structure contains the data which size is implicitly +known before encoding. Among other uses, the DER encoding is used +to encode X.509 certificates. + +As with BER decoder, the DER encoder may be invoked either directly +from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone +function, which is somewhat simpler: +\begin{lyxcode} +~ + +/{*} + +~{*}~This~is~the~serializer~itself, + +~{*}~it~supplies~the~DER~encoder~with~the + +~{*}~pointer~to~the~custom~output~function. + +~{*}/ + +ssize\_t + +simple\_serializer(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{ + +~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/ + +~ + +~~~~er~=~der\_encode(\&asn\_DEF\_Rect,~rect, + +~~~~~~~~write\_stream,~ostream); + +~~~~if(er.\textbf{encoded}~==~-1)~\{ + +~~~~~~~~/{*} + +~~~~~~~~~{*}~Failed~to~encode~the~rectangle~data. + +~~~~~~~~~{*}/ + +~~~~~~~~fprintf(stderr,~''Cannot~encode~\%s:~\%s\textbackslash{}n'', + +~~~~~~~~~~~~er.\textbf{failed\_type}->name, + +~~~~~~~~~~~~strerror(errno)); + +~~~~~~~~return~-1; + +~~~~\}~else~\{ + +~~~~~~~~/{*}~Return~the~number~of~bytes~{*}/ + +~~~~~~~~return~er.encoded; + +~~~~\} + +\} +\end{lyxcode} +As you see, the DER encoder does not write into some sort of buffer +or something. It just invokes the custom function (possible, multiple +times) which would save the data into appropriate storage. The optional +argument \emph{app\_key} is opaque for the DER encoder code and just +used by \emph{\_write\_stream()} as the pointer to the appropriate +output stream to be used. + +If the custom write function is not given (passed as 0), then the +DER encoder will essentially do the same thing (i.e., encode the data) +but no callbacks will be invoked (so the data goes nowhere). It may +prove useful to determine the size of the structure's encoding before +actually doing the encoding% +\footnote{It is actually faster too: the encoder might skip over some computations +which aren't important for the size determination.% +}. + +Please look into der\_encoder.h for the precise definition of der\_encode() +and related types. + + +\subsection{\label{sub:Encoding-XER}Encoding XER} + +The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible +Markup Language, a text-based format for information exchange. The +encoder routine API comes in two flavors: stdio-based and callback-based. +With the callback-based encoder, the encoding process is very similar +to the DER one, described in Section \vref{sub:Encoding-DER}. The +following example uses the definition of write\_stream() from up there. +\begin{lyxcode} +/{*} + +~{*}~This~procedure~generates~the~XML~document + +~{*}~by~invoking~the~XER~encoder. + +~{*}~NOTE:~Do~not~copy~this~code~verbatim! + +~{*}~~~~~~~If~the~stdio~output~is~necessary, + +~{*}~~~~~~~use~the~xer\_fprint()~procedure~instead. + +~{*}~~~~~~~See~Section~\vref{sub:Printing-the-target}. + +~{*}/ + +int + +print\_as\_XML(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{ + +~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/ + +~ + +~~~~er~=~xer\_encode(\&asn\_DEF\_Rectangle,~rect, + +~~~~~~~~XER\_F\_BASIC,~/{*}~BASIC-XER~or~CANONICAL-XER~{*}/ + +~~~~~~~~write\_stream,~ostream); + +~ + +~~~~return~(er.encoded~==~-1)~?~-1~:~0; + +\} +\end{lyxcode} +Please look into xer\_encoder.h for the precise definition of xer\_encode() +and related types. + +See Section \ref{sub:Printing-the-target} for the example of stdio-based +XML encoder and other pretty-printing suggestions. + + +\subsection{\label{sub:Decoding-XER}Decoding XER} + +The data encoded using the XER rules can be subsequently decoded using +the xer\_decode() API call: +\begin{lyxcode} +Rectangle\_t~{*} + +XML\_to\_Rectangle(const~void~{*}buffer,~size\_t~buf\_size)~\{ + +~~~~Rectangle\_t~{*}rect~=~0;~/{*}~Note~this~0!~{*}/ + +~~~~asn\_dec\_rval\_t~rval; + +~~ + +~~~~rval~=~xer\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect, + +~~~~~~~~buffer,~buf\_size); + +~~~~if(rval\textbf{.code}~==~RC\_OK)~\{ + +~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/ + +~~~~\}~else~\{ + +~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/ + +~~~~~~~~asn\_DEF\_Rectangle.free\_struct( + +~~~~~~~~~~~~\&asn\_DEF\_Rectangle,~rect,~0); + +~~~~~~~~return~0; + +~~~~\} + +\} +\end{lyxcode} +The decoder takes both BASIC-XER and CANONICAL-XER encodings. + +The decoder shares its data consumption properties with BER decoder; +please read the Section \vref{sub:Decoding-BER} to know more. + +Please look into xer\_decoder.h for the precise definition of xer\_decode() +and related types. + + +\subsection{\label{sub:Validating-the-target}Validating the target structure} + +Sometimes the target structure needs to be validated. For example, +if the structure was created by the application (as opposed to being +decoded from some external source), some important information required +by the ASN.1 specification might be missing. On the other hand, the +successful decoding of the data from some external source does not +necessarily mean that the data is fully valid either. It might well +be the case that the specification describes some subtype constraints +that were not taken into account during decoding, and it would actually +be useful to perform the last check when the data is ready to be encoded +or when the data has just been decoded to ensure its validity according +to some stricter rules. + +The asn\_check\_constraints() function checks the type for various +implicit and explicit constraints. It is recommended to use asn\_check\_constraints() +function after each decoding and before each encoding. + +Please look into constraints.h for the precise definition of asn\_check\_constraints() +and related types. + + +\subsection{\label{sub:Printing-the-target}Printing the target structure} + +There are two ways to print the target structure: either invoke the +print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint() +function, which is a simpler wrapper of the former: +\begin{lyxcode} +asn\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect); +\end{lyxcode} +Please look into constr\_TYPE.h for the precise definition of asn\_fprint() +and related types. + +Another practical alternative to this custom format printing would +be to invoke XER encoder. The default BASIC-XER encoder performs reasonable +formatting for the output to be useful and human readable. To invoke +the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint() +call: +\begin{lyxcode} +xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect); +\end{lyxcode} +See Section \vref{sub:Encoding-XER} for XML-related details. + + +\subsection{\label{sub:Freeing-the-target}Freeing the target structure} + +Freeing the structure is slightly more complex than it may seem to. +When the ASN.1 structure is freed, all the members of the structure +and their submembers are recursively freed as well. But it might not +be feasible to free the structure itself. Consider the following case: +\begin{lyxcode} +struct~my\_figure~\{~~~~~~~/{*}~The~custom~structure~{*}/ + +~~~~int~flags;~~~~~~~~~~~/{*}~<some~custom~member>~{*}/ + +~~~~/{*}~The~type~is~generated~by~the~ASN.1~compiler~{*}/ + +~~~~\emph{Rectangle\_t~rect;} + +~~~~/{*}~other~members~of~the~structure~{*}/ + +\}; +\end{lyxcode} +In this example, the application programmer defined a custom structure +with one ASN.1-derived member (rect). This member is not a reference +to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t +structure. If the freeing is necessary, the usual procedure of freeing +everything must not be applied to the \&rect pointer itself, because +it does not point to the memory block directly allocated by the memory +allocation routine, but instead lies within a block allocated for +the my\_figure structure. + +To solve this problem, the free\_struct routine has the additional +argument (besides the obvious type descriptor and target structure +pointers), which is the flag specifying whether the outer pointer +itself must be freed (0, default) or it should be left intact (non-zero +value). +\begin{lyxcode} +\textbf{/{*}~1.~Rectangle\_t~is~defined~within~my\_figure~{*}/} + +struct~my\_figure~\{ + +~~~~Rectangle\_t~rect; + +\}~{*}mf~=~\textbf{...}; + +/{*} + +~{*}~Freeing~the~Rectangle\_t + +~{*}~without~freeing~the~mf->rect~area + +~{*}/ + +asn\_DEF\_Rectangle.free\_struct( + +~~~~\&asn\_DEF\_Rectangle,~\&mf->rect,~\textbf{1}~\textbf{/{*}~!free~{*}/}); + +~~~~ + +~~ + +\textbf{/{*}~2.~Rectangle\_t~is~a~stand-alone~pointer~{*}/} + +Rectangle\_t~{*}rect~=~\textbf{...}; + +/{*} + +~{*}~Freeing~the~Rectangle\_t + +~{*}~and~freeing~the~rect~pointer + +~{*}/ + +asn\_DEF\_Rectangle.free\_struct( + +~~~~\&asn\_DEF\_Rectangle,~rect,~\textbf{0}~\textbf{/{*}~free~the~pointer~too~{*}/}); +\end{lyxcode} +It is safe to invoke the \emph{free\_struct} function with the target +structure pointer set to 0 (NULL), the function will do nothing. + +For the programmer's convenience, the following macros are available: +\begin{lyxcode} +ASN\_STRUCT\_FREE(asn\_DEF,~ptr); + +ASN\_STRUCT\_FREE\_CONTENTS\_ONLY(asn\_DEF,~ptr); +\end{lyxcode} +These macros bear the same semantics as the \emph{free\_struct} function +invocation, discussed above. + + +\chapter{\label{cha:Step-by-step-examples}Step by step examples} + + +\section{A ''Rectangle'' Encoder} + +This example will help you create a simple BER and XER encoder of +a ''Rectangle'' type used throughout this document. +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn1} with the following contents: + +\begin{lyxcode} +RectangleModule1~DEFINITIONS~::= + +BEGIN + +~ + +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER, + +~~~~width~~~INTEGER + +\} + +~ + +END +\end{lyxcode} +\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: + +\begin{lyxcode} +\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1} +\end{lyxcode} +\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading +the \textbf{rectangle.asn1} file into the Web form and unpacking the +produced archive on your computer. +\item By this time, you should have gotten multiple files in the current +directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. +\item Create a main() routine which creates the Rectangle\_t structure in +memory and encodes it using BER and XER encoding rules. Let's name +the file \textbf{main.c}:\clearpage{} + +\begin{lyxcode} +{\small \#include~<stdio.h>}{\small \par} + +{\small \#include~<sys/types.h>}{\small \par} + +{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par} + +~ + +{\small /{*}}{\small \par} + +{\small{}~{*}~This~is~a~custom~function~which~writes~the}{\small \par} + +{\small{}~{*}~encoded~output~into~some~FILE~stream.}{\small \par} + +{\small{}~{*}/}{\small \par} + +{\small static~int}{\small \par} + +{\small write\_out(const~void~{*}buffer,~size\_t~size,~void~{*}app\_key)~\{}{\small \par} + +{\small{}~~~~FILE~{*}out\_fp~=~app\_key;}{\small \par} + +{\small{}~~~~size\_t~wrote;}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~wrote~=~fwrite(buffer,~1,~size,~out\_fp);}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~return~(wrote~==~size)~?~0~:~-1;}{\small \par} + +{\small \}}{\small \par} + +~ + +{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par} + +{\small{}~~~~Rectangle\_t~{*}rectangle;~/{*}~Type~to~encode~~~~~~~~{*}/}{\small \par} + +{\small{}~~~~asn\_enc\_rval\_t~ec;~~~~~~/{*}~Encoder~return~value~~{*}/}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Allocate~the~Rectangle\_t~{*}/}{\small \par} + +{\small{}~~~~rectangle~=~calloc(1,~sizeof(Rectangle\_t));~/{*}~not~malloc!~{*}/}{\small \par} + +{\small{}~~~~if(!rectangle)~\{}{\small \par} + +{\small{}~~~~~~perror(''calloc()~failed'');}{\small \par} + +{\small{}~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Initialize~the~Rectangle~members~{*}/}{\small \par} + +{\small{}~~~~rectangle->height~=~42;~~/{*}~any~random~value~{*}/}{\small \par} + +{\small{}~~~~rectangle->width~~=~23;~~/{*}~any~random~value~{*}/}{\small \par} + +{\small{}~~~~~}{\small \par} + +{\small{}~~~~/{*}~BER~encode~the~data~if~filename~is~given~{*}/}{\small \par} + +{\small{}~~~~if(ac~<~2)~\{}{\small \par} + +{\small{}~~~~~~fprintf(stderr,~''Specify~filename~for~BER~output\textbackslash{}n'');}{\small \par} + +{\small{}~~~~\}~else~\{}{\small \par} + +{\small{}~~~~~~const~char~{*}filename~=~av{[}1{]};}{\small \par} + +{\small{}~~~~~~FILE~{*}fp~=~fopen(filename,~''wb'');~~~/{*}~for~BER~output~{*}/}{\small \par} + +~ + +{\small{}~~~~~~if(!fp)~\{}{\small \par} + +{\small{}~~~~~~~~perror(filename);}{\small \par} + +{\small{}~~~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par} + +{\small{}~~~~~~\}}{\small \par} + +{\small{}~~}{\small \par} + +{\small{}~~~~~~/{*}~Encode~the~Rectangle~type~as~BER~(DER)~{*}/}{\small \par} + +{\small{}~~~~~~ec~=~der\_encode(\&asn\_DEF\_Rectangle,}{\small \par} + +{\small{}~~~~~~~~~~~~rectangle,~write\_out,~fp);}{\small \par} + +{\small{}~~~~~~fclose(fp);}{\small \par} + +{\small{}~~~~~~if(ec.encoded~==~-1)~\{}{\small \par} + +{\small{}~~~~~~~~fprintf(stderr,}{\small \par} + +{\small{}~~~~~~~~~~''Could~not~encode~Rectangle~(at~\%s)\textbackslash{}n'',}{\small \par} + +{\small{}~~~~~~~~~~ec.failed\_type~?~ec.failed\_type->name~:~''unknown'');}{\small \par} + +{\small{}~~~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par} + +{\small{}~~~~~~\}~else~\{}{\small \par} + +{\small{}~~~~~~~~fprintf(stderr,~''Created~\%s~with~BER~encoded~Rectangle\textbackslash{}n'',}{\small \par} + +{\small{}~~~~~~~~~~filename);}{\small \par} + +{\small{}~~~~~~\}}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Also~print~the~constructed~Rectangle~XER~encoded~(XML)~{*}/}{\small \par} + +{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~return~0;~/{*}~Encoding~finished~successfully~{*}/}{\small \par} + +{\small \}}{\small \par} +\end{lyxcode} +\item Compile all files together using C compiler (varies by platform): + +\begin{lyxcode} +\emph{cc~-I.~-o}~\textbf{\emph{rencode}}~\emph{{*}.c} +\end{lyxcode} +\item Voila! You have just created the BER and XER encoder of a Rectangle +type, named \textbf{rencode}! +\end{enumerate} +\clearpage{} + + +\section{\label{sec:A-Rectangle-Decoder}A ''Rectangle'' Decoder} + +This example will help you to create a simple BER decoder of a simple +''Rectangle'' type used throughout this document. +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn1} with the following contents: + +\begin{lyxcode} +RectangleModule1~DEFINITIONS~::= + +BEGIN + +~ + +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER, + +~~~~width~~~INTEGER + +\} + +~ + +END +\end{lyxcode} +\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: + +\begin{lyxcode} +\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1} +\end{lyxcode} +\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading +the \textbf{rectangle.asn1} file into the Web form and unpacking the +produced archive on your computer. +\item By this time, you should have gotten multiple files in the current +directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. +\item Create a main() routine which takes the binary input file, decodes +it as it were a BER-encoded Rectangle type, and prints out the text +(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:\clearpage{} + +\begin{lyxcode} +{\small \#include~<stdio.h>}{\small \par} + +{\small \#include~<sys/types.h>}{\small \par} + +{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par} + +{\small{}~}{\small \par} + +{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par} + +{\small{}~~~~char~buf{[}1024{]};~~~~~~/{*}~Temporary~buffer~~~~~~{*}/}{\small \par} + +{\small{}~~~~Rectangle\_t~{*}rectangle~=~0;~/{*}~Type~to~decode~{*}/}{\small \par} + +{\small{}~~~~asn\_dec\_rval\_t~rval;~/{*}~Decoder~return~value~~{*}/}{\small \par} + +{\small{}~~~~FILE~{*}fp;~~~~~~~~~~~~/{*}~Input~file~handler~~~~{*}/}{\small \par} + +{\small{}~~~~size\_t~size;~~~~~~~~~/{*}~Number~of~bytes~read~~{*}/}{\small \par} + +{\small{}~~~~char~{*}filename;~~~~~~/{*}~Input~file~name~{*}/}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Require~a~single~filename~argument~{*}/}{\small \par} + +{\small{}~~~~if(ac~!=~2)~\{}{\small \par} + +{\small{}~~~~~~fprintf(stderr,~''Usage:~\%s~<file.ber>\textbackslash{}n'',~av{[}0{]});}{\small \par} + +{\small{}~~~~~~exit(64);~/{*}~better,~EX\_USAGE~{*}/}{\small \par} + +{\small{}~~~~\}~else~\{}{\small \par} + +{\small{}~~~~~~filename~=~av{[}1{]};}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Open~input~file~as~read-only~binary~{*}/}{\small \par} + +{\small{}~~~~fp~=~fopen(filename,~''rb'');}{\small \par} + +{\small{}~~~~if(!fp)~\{}{\small \par} + +{\small{}~~~~~~perror(filename);}{\small \par} + +{\small{}~~~~~~exit(66);~/{*}~better,~EX\_NOINPUT~{*}/}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~~}{\small \par} + +{\small{}~~~~/{*}~Read~up~to~the~buffer~size~{*}/}{\small \par} + +{\small{}~~~~size~=~fread(buf,~1,~sizeof(buf),~fp);}{\small \par} + +{\small{}~~~~fclose(fp);}{\small \par} + +{\small{}~~~~if(!size)~\{}{\small \par} + +{\small{}~~~~~~fprintf(stderr,~''\%s:~Empty~or~broken\textbackslash{}n'',~filename);}{\small \par} + +{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Decode~the~input~buffer~as~Rectangle~type~{*}/}{\small \par} + +{\small{}~~~~rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,}{\small \par} + +{\small{}~~~~~~(void~{*}{*})\&rectangle,~buf,~size);}{\small \par} + +{\small{}~~~~if(rval.code~!=~RC\_OK)~\{}{\small \par} + +{\small{}~~~~~~fprintf(stderr,}{\small \par} + +{\small{}~~~~~~~~''\%s:~Broken~Rectangle~encoding~at~byte~\%ld\textbackslash{}n'',}{\small \par} + +{\small{}~~~~~~~~filename,~(long)rval.consumed);}{\small \par} + +{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par} + +{\small{}~~~~\}}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~/{*}~Print~the~decoded~Rectangle~type~as~XML~{*}/}{\small \par} + +{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par} + +{\small{}~}{\small \par} + +{\small{}~~~~return~0;~/{*}~Decoding~finished~successfully~{*}/}{\small \par} + +{\small \}}{\small \par} +\end{lyxcode} +\item Compile all files together using C compiler (varies by platform): + +\begin{lyxcode} +\emph{cc~-I.~-o}~\textbf{\emph{rdecode}}~\emph{{*}.c} +\end{lyxcode} +\item Voila! You have just created the BER decoder of a Rectangle type, +named \textbf{rdecode}! +\end{enumerate} + +\chapter{Constraint validation examples} + +This chapter shows how to define ASN.1 constraints and use the generated +validation code. + + +\section{Adding constraints into ''Rectangle'' type} + +This example shows how to add basic constraints to the ASN.1 specification +and how to invoke the constraints validation code in your application. +\begin{enumerate} +\item Create a file named \textbf{rectangle.asn1} with the following contents: + +\begin{lyxcode} +RectangleModuleWithConstraints~DEFINITIONS~::= + +BEGIN + +~ + +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER~(0..100),~-{}-~Value~range~constraint + +~~~~width~~~INTEGER~(0..MAX)~~-{}-~Makes~width~non-negative~ + +\} + +~ + +END +\end{lyxcode} +\item Compile the file according to procedures shown in the previous chapter. +\item Modify the Rectangle type processing routine (you can start with the +main() routine shown in the Section \vref{sec:A-Rectangle-Decoder}) +by placing the following snippet of code \emph{before} encoding and/or +\emph{after} decoding the Rectangle type% +\footnote{Placing the constraint checking code \emph{before} encoding helps +to make sure you know the data is correct and within constraints before +sharing the data with anyone else. + +Placing the constraint checking code \emph{after} decoding, but before +any further action depending on the decoded data, helps to make sure +the application got the valid contents before making use of it.% +}:\clearpage{} + +\begin{lyxcode} +{\small int~ret;~~~~~~~~~~~/{*}~Return~value~{*}/}{\small \par} + +{\small char~errbuf{[}128{]};~~/{*}~Buffer~for~error~message~{*}/}{\small \par} + +{\small size\_t~errlen~=~sizeof(errbuf);~~/{*}~Size~of~the~buffer~{*}/}{\small \par} + +{\small{}~~}{\small \par} + +{\small /{*}~...~here~may~go~Rectangle~decoding~code~...~{*}/}{\small \par} + +{\small{}~}{\small \par} + +{\small ret~=~asn\_check\_constraints(\&asn\_DEF\_Rectangle,}{\small \par} + +{\small{}~~~~~~~~rectangle,~errbuf,~\&errlen);}{\small \par} + +{\small /{*}~assert(errlen~<~sizeof(errbuf));~//~you~may~rely~on~that~{*}/}{\small \par} + +{\small if(ret)~\{}{\small \par} + +{\small{}~~~~~~~~fprintf(stderr,~''Constraint~validation~failed:~\%s\textbackslash{}n'',}{\small \par} + +{\small{}~~~~~~~~~~errbuf~~~/{*}~errbuf~is~properly~nul-terminated~{*}/}{\small \par} + +{\small{}~~~~~~~~);}{\small \par} + +{\small{}~~~~~~~~/{*}~exit(...);~//~Replace~with~appropriate~action~{*}/}{\small \par} + +{\small \}}{\small \par} + +{\small{}~}{\small \par} + +{\small /{*}~...~here~may~go~Rectangle~encoding~code~...~{*}/}{\small \par} +\end{lyxcode} +\item Compile the resulting C code as shown in the previous chapters. +\item Try to test the constraints checking code by assigning integer value +101 to the \textbf{.height} member of the Rectangle structure, or +a negative value to the \textbf{.width} member. In either case, the +program should print ''Constraint validation failed'' message, followed +by the short explanation why validation did not succeed. +\item Done. +\end{enumerate} + +\part{\label{par:ASN.1-Basics}ASN.1 Basics} + + +\chapter{\label{cha:Abstract-Syntax-Notation:}Abstract Syntax Notation: ASN.1} + +\emph{This chapter defines some basic ASN.1 concepts and describes +several most widely used types. It is by no means an authoritative +or complete reference. For more complete ASN.1 description, please +refer to Olivier Dubuisson's book \cite{Dub00} or the ASN.1 body +of standards itself \cite{ITU-T/ASN.1}.} + +The Abstract Syntax Notation One is used to formally describe the +semantics of data transmitted across the network. Two communicating +parties may have different formats of their native data types (i.e. +number of bits in the integer type), thus it is important to have +a way to describe the data in a manner which is independent from the +particular machine's representation. The ASN.1 specifications are +used to achieve the following: +\begin{itemize} +\item The specification expressed in the ASN.1 notation is a formal and +precise way to communicate the data semantics to human readers; +\item The ASN.1 specifications may be used as input for automatic compilers +which produce the code for some target language (C, C++, Java, etc) +to encode and decode the data according to some encoding rules (which +are also defined by the ASN.1 standard). +\end{itemize} +Consider the following example: +\begin{lyxcode} +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER, + +~~~~width~~~INTEGER + +\} +\end{lyxcode} +This ASN.1 specification describes a constructed type, \emph{Rectangle}, +containing two integer fields. This specification may tell the reader +that there exists this kind of data structure and that some entity +may be prepared to send or receive it. The question on \emph{how} +that entity is going to send or receive the \emph{encoded data} is +outside the scope of ASN.1. For example, this data structure may be +encoded according to some encoding rules and sent to the destination +using the TCP protocol. The ASN.1 specifies several ways of encoding +(or ''serializing'', or ''marshaling'') the data: BER, PER, XER +and others, including CER and DER derivatives from BER. + +The complete specification must be wrapped in a module, which looks +like this: +\begin{lyxcode} +RectangleModule1 + +~~~~\{~iso~org(3)~dod(6)~internet(1)~private(4) + +~~~~~~enterprise(1)~spelio(9363)~software(1) + +~~~~~~asn1c(5)~docs(2)~rectangle(1)~1~\}~ + +~~~~DEFINITIONS~AUTOMATIC~TAGS~::= + +BEGIN + +~ + +-{}-~This~is~a~comment~which~describes~nothing. + +Rectangle~::=~SEQUENCE~\{ + +~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle + +~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle + +\} + +~ + +END +\end{lyxcode} +The module header consists of module name (RectangleModule1), the +module object identifier (\{...\}), a keyword ''DEFINITIONS'', a +set of module flags (AUTOMATIC TAGS) and ''::= BEGIN''. The module +ends with an ''END'' statement. + + +\section{Some of the ASN.1 Basic Types} + + +\subsection{The BOOLEAN type} + +The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF +or a similar kind of two-way choice. + + +\subsection{The INTEGER type} + +The INTEGER type is a signed natural number type without any restrictions +on its size. If the automatic checking on INTEGER value bounds are +necessary, the subtype constraints must be used. +\begin{lyxcode} +SimpleInteger~::=~INTEGER + +~ + +-{}-~An~integer~with~a~very~limited~range + +SmallPositiveInt~::=~INTEGER~(0..127) + +~ + +-{}-~Integer,~negative + +NegativeInt~::=~INTEGER~(MIN..0) +\end{lyxcode} + +\subsection{The ENUMERATED type} + +The ENUMERATED type is semantically equivalent to the INTEGER type +with some integer values explicitly named. +\begin{lyxcode} +FruitId~::=~ENUMERATED~\{~apple(1),~orange(2)~\} + +~ + +-{}-~The~numbers~in~braces~are~optional, + +-{}-~the~enumeration~can~be~performed + +-{}-~automatically~by~the~compiler + +ComputerOSType~::=~ENUMERATED~\{ + +~~~~FreeBSD,~~~~~~~~~~-{}-~acquires~value~0 + +~~~~Windows,~~~~~~~~~~-{}-~acquires~value~1 + +~~~~Solaris(5),~~~~~~~-{}-~remains~5 + +~~~~Linux,~~~~~~~~~~~~-{}-~becomes~6 + +~~~~MacOS~~~~~~~~~~~~~-{}-~becomes~7 + +\} +\end{lyxcode} + +\subsection{The OCTET STRING type} + +This type models the sequence of 8-bit bytes. This may be used to +transmit some opaque data or data serialized by other types of encoders +(i.e. video file, photo picture, etc). + + +\subsection{The OBJECT IDENTIFIER type} + +The OBJECT IDENTIFIER is used to represent the unique identifier of +any object, starting from the very root of the registration tree. +If your organization needs to uniquely identify something (a router, +a room, a person, a standard, or whatever), you are encouraged to +get your own identification subtree at \url{http://www.iana.org/protocols/forms.htm}. + +For example, the very first ASN.1 module in this Chapter (RectangleModule1) +has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1. +\begin{lyxcode} +ExampleOID~::=~OBJECT~IDENTIFIER + +~ + +rectangleModule1-oid~ExampleOID + +~~::=~\{~1~3~6~1~4~1~9363~1~5~2~1~1~\} + +~ + +-{}-~An~identifier~of~the~Internet. + +internet-id~OBJECT~IDENTIFIER + +~~::=~\{~iso(1)~identified-organization(3) + +~~~~~~~~dod(6)~internet(1)~\} +\end{lyxcode} +As you see, names are optional. + + +\subsection{The RELATIVE-OID type} + +The RELATIVE-OID type has the semantics of a subtree of an OBJECT +IDENTIFIER. There may be no need to repeat the whole sequence of numbers +from the root of the registration tree where the only thing of interest +is some of the tree's subsequence. +\begin{lyxcode} +this-document~RELATIVE-OID~::=~\{~docs(2)~usage(1)~\} + +~ + +this-example~RELATIVE-OID~::=~\{ + +~~~~this-document~assorted-examples(0)~this-example(1)~\} +\end{lyxcode} + +\section{Some of the ASN.1 String Types} + + +\subsection{The IA5String type} + +This is essentially the ASCII, with 128 character codes available +(7 lower bits of an 8-bit byte). + + +\subsection{The UTF8String type} + +This is the character string which encodes the full Unicode range +(4 bytes) using multibyte character sequences. + + +\subsection{The NumericString type} + +This type represents the character string with the alphabet consisting +of numbers (''0'' to ''9'') and a space. + + +\subsection{The PrintableString type} + +The character string with the following alphabet: space, ''\textbf{'}'' +(single quote), ''\textbf{(}'', ''\textbf{)}'', ''\textbf{+}'', +''\textbf{,}'' (comma), ''\textbf{-}'', ''\textbf{.}'', ''\textbf{/}'', +digits (''0'' to ''9''), ''\textbf{:}'', ''\textbf{=}'', ''\textbf{?}'', +upper-case and lower-case letters (''A'' to ''Z'' and ''a'' +to ''z''). + + +\subsection{The VisibleString type} + +The character string with the alphabet which is more or less a subset +of ASCII between the space and the ''\textbf{\textasciitilde{}}'' +symbol (tilde). + +Alternatively, the alphabet may be described as the PrintableString +alphabet presented earlier, plus the following characters: ''\textbf{!}'', +''\textbf{''}'', ''\textbf{\#}'', ''\textbf{\$}'', ''\textbf{\%}'', +''\textbf{\&}'', ''\textbf{{*}}'', ''\textbf{;}'', ''\textbf{<}'', +''\textbf{>}'', ''\textbf{{[}}'', ''\textbf{\textbackslash{}}'', +''\textbf{{]}}'', ''\textbf{\textasciicircum{}}'', ''\textbf{\_}'', +''\textbf{`}'' (single left quote), ''\textbf{\{}'', ''\textbf{|}'', +''\textbf{\}}'', ''\textbf{\textasciitilde{}}''. + + +\section{ASN.1 Constructed Types} + + +\subsection{The SEQUENCE type} + +This is an ordered collection of other simple or constructed types. +The SEQUENCE constructed type resembles the C ''struct'' statement. +\begin{lyxcode} +Address~::=~SEQUENCE~\{ + +~~~~-{}-~The~apartment~number~may~be~omitted + +~~~~apartmentNumber~~~~~~NumericString~OPTIONAL, + +~~~~streetName~~~~~~~~~~~PrintableString, + +~~~~cityName~~~~~~~~~~~~~PrintableString, + +~~~~stateName~~~~~~~~~~~~PrintableString, + +~~~~-{}-~This~one~may~be~omitted~too + +~~~~zipNo~~~~~~~~~~~~~~~~NumericString~OPTIONAL + +\} +\end{lyxcode} + +\subsection{The SET type} + +This is a collection of other simple or constructed types. Ordering +is not important. The data may arrive in the order which is different +from the order of specification. Data is encoded in the order not +necessarily corresponding to the order of specification. + + +\subsection{The CHOICE type} + +This type is just a choice between the subtypes specified in it. The +CHOICE type contains at most one of the subtypes specified, and it +is always implicitly known which choice is being decoded or encoded. +This one resembles the C ''union'' statement. + +The following type defines a response code, which may be either an +integer code or a boolean ''true''/''false'' code. +\begin{lyxcode} +ResponseCode~::=~CHOICE~\{ + +~~~~intCode~~~~INTEGER, + +~~~~boolCode~~~BOOLEAN + +\} + + +\end{lyxcode} + +\subsection{The SEQUENCE OF type} + +This one is the list (array) of simple or constructed types: +\begin{lyxcode} +-{}-~Example~1 + +ManyIntegers~::=~SEQUENCE~OF~INTEGER + +~ + +-{}-~Example~2 + +ManyRectangles~::=~SEQUENCE~OF~Rectangle + +~ + +-{}-~More~complex~example: + +-{}-~an~array~of~structures~defined~in~place. + +ManyCircles~::=~SEQUENCE~OF~SEQUENCE~\{ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~radius~INTEGER + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~\} +\end{lyxcode} + +\subsection{The SET OF type} + +The SET OF type models the bag of structures. It resembles the SEQUENCE +OF type, but the order is not important: i.e. the elements may arrive +in the order which is not necessarily the same as the in-memory order +on the remote machines. +\begin{lyxcode} +-{}-~A~set~of~structures~defined~elsewhere + +SetOfApples~::~SET~OF~Apple + +~ + +-{}-~Set~of~integers~encoding~the~kind~of~a~fruit + +FruitBag~::=~SET~OF~ENUMERATED~\{~apple,~orange~\}\end{lyxcode} +\begin{thebibliography}{ITU-T/ASN.1} +\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c} + +\bibitem[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi} + +\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication +between heterogeneous systems} --- Morgan Kaufmann Publishers, 2000. +\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0. + +\bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 -- Languages +for Telecommunication Systems \url{http://www.itu.int/ITU-T/studygroups/com17/languages/} +\end{thebibliography} + +\end{document} |