Commit 11c9a8c7 authored by Lev Walkin's avatar Lev Walkin

update asn1c-usage.pdf

parent 2655eb3f
???: ???:
* Made -fskeletons-copy a default one; removed cmdline option. * Made -fskeletons-copy a default one; removed cmdline option.
* Updated asn1c-usage.pdf.
0.9.24: 2013-Mar-16 0.9.24: 2013-Mar-16
......
No preview for this file type
...@@ -3,58 +3,88 @@ ...@@ -3,58 +3,88 @@
\usepackage{xunicode} \usepackage{xunicode}
\usepackage{xltxtra} \usepackage{xltxtra}
\usepackage[hmargin={1in,1in},vmargin={2in,2in}]{geometry} \usepackage[hmargin={1in,1in},vmargin={1.5in,1.5in}]{geometry}
\defaultfontfeatures{Mapping=tex-text} \defaultfontfeatures{Mapping=tex-text}
\setmainfont{Myriad Pro} \setmainfont{PT Sans}
\setsansfont{Myriad Pro} \setsansfont{PT Sans}
\setmonofont{Consolas} \setmonofont{Consolas}
\usepackage{fancyhdr} \usepackage{fancyhdr}
\pagestyle{fancy}
\usepackage{longtable} \usepackage{longtable}
\usepackage{booktabs} \usepackage{booktabs}
\usepackage{varioref} \usepackage{varioref}
\usepackage{url} \usepackage{url}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{setspace}
\makeatletter \setstretch{1.1}
% Courier 10 Pitch
\def\courierFont{Courier10 BT WGL4}
%\def\courierFont{Consolas}
\setmonofont[Scale=1.05]{\courierFont}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
%% Because html converters don't know tabularnewline \makeatletter
\providecommand{\tabularnewline}{\\}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
\newenvironment{lyxcode} \lstloadlanguages{C,bash}
{\par\begin{list}{}{ \newfontfamily\listingfont[Scale=1.05]{\courierFont}
\setlength{\rightmargin}{\leftmargin} \newfontfamily\inlinelistingfont[Scale=1.05]{\courierFont}
\setlength{\listparindent}{0pt}% needed for AMS classes \definecolor{clrlcomment}{gray}{0.3}
\raggedright \definecolor{clrlkeyword}{rgb}{0.588,0.145,0.18}
\setlength{\itemsep}{0pt} \newcommand{\listingkeyword}[1]{\color{clrlkeyword}{#1}}
\setlength{\parsep}{0pt} \newcommand{\listingstring}[1]{\color{clrlcomment}{#1}}
\normalfont\ttfamily}% \newcommand{\listingcomment}[1]{\color{clrlcomment}{#1}}
\item[]} \lstset{tabsize=4,
{\end{list}} showstringspaces=false,
showtabs=false,
showspaces=false,
keywordstyle=\listingkeyword,
stringstyle=\listingstring,
commentstyle=\listingcomment,
xleftmargin=\parindent,
columns=fixed,
escapechar=\%,
texcl
}
\lstdefinestyle{listingStyle}{
basicstyle=\small\listingfont,
stringstyle=\listingstring,
breaklines=true,
breakatwhitespace=true,
flexiblecolumns=false
}
\lstdefinelanguage{asn1}{
morekeywords={DEFINITIONS,BEGIN,END,SEQUENCE,SET,OF,CHOICE,OPTIONAL},
morecomment=[l]{--},
morecomment=[n]{/*}{*/}
}
\lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{}
\lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,morekeywords={-fnative-types},language=bash,#1}}{}
\lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{}
\def\code{lstinline}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
\usepackage{extramarks} \usepackage{extramarks}
\lhead{\firstxmark} \lhead{\firstxmark}
\rfoot{\lastxmark} \rfoot{\lastxmark}
\usepackage{color} \definecolor{clrlink}{rgb}{0,0.4,0}
\definecolor{linkred}{rgb}{0.8235,0.0863,0.1843} \definecolor{clrurl}{rgb}{0,0,.6}
\definecolor{urlblue}{rgb}{0,0,.6}
\usepackage[colorlinks=true, \usepackage[colorlinks=true,
linkcolor={linkred}, linkcolor={clrlink},
urlcolor={urlblue}, citecolor={clrlink},
pdfauthor={Lev Walkin}, urlcolor={clrurl},
pdftitle={Using the Open Source ASN.1 Compiler}, pdfauthor={Lev Walkin},
pdfkeywords={ASN.1,asn1c,compiler}, pdftitle={Using the Open Source ASN.1 Compiler},
xetex pdfkeywords={ASN.1,asn1c,compiler},
bookmarksopen,bookmarksopenlevel=1,
pdffitwindow,
xetex
]{hyperref} ]{hyperref}
%\fancyhf{}
%\fancyhead[LE,RO]{\thepage}
%\fancyhead[LO]{\rightmark}
%\fancyhead[RE]{\leftmark}
%\fancyfoot[R]{\lastxmark}
\makeatother \makeatother
...@@ -63,20 +93,15 @@ xetex ...@@ -63,20 +93,15 @@ xetex
\begin{document} \begin{document}
\title{Using the Open Source ASN.1 Compiler} \title{Using the Open Source ASN.1 Compiler}
\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>} \author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>}
\pagestyle{fancy}
\fancyhead[L]{\leftmark}
\fancyhead[R]{\href{http://lionet.info/asn1c}{asn1c-0.9.25}}
\maketitle \maketitle
\lhead{This document describes \href{http://lionet.info/asn1c}{asn1c-0.9.21}}
\rhead{$Revision$}
\tableofcontents{} \tableofcontents{}
\pagestyle{headings}
\part{Using the ASN.1 Compiler} \part{Using the ASN.1 Compiler}
...@@ -96,40 +121,24 @@ standardized encoding rules (BER, DER, XER, PER). ...@@ -96,40 +121,24 @@ standardized encoding rules (BER, DER, XER, PER).
For example, suppose the following ASN.1 module is given% For example, suppose the following ASN.1 module is given%
\footnote{Part \vref{par:ASN.1-Basics} provides a quick reference \footnote{Part \vref{par:ASN.1-Basics} provides a quick reference
on the ASN.1 notation.}: on the ASN.1 notation.}:
\begin{lyxcode} \begin{asn}
RectangleTest~DEFINITIONS~::= RectangleTest DEFINITIONS ::= BEGIN
BEGIN Rectangle ::= SEQUENCE {
height INTEGER, -- Height of the rectangle
~ width INTEGER -- Width of the rectangle
}
Rectangle~::=~SEQUENCE~\{
~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
\}
~
END END
\end{lyxcode} \end{asn}
The compiler would read this ASN.1 definition and produce the following The compiler would read this ASN.1 definition and produce the following
C type% C type:
\footnote{\emph{-fnative-types} compiler option is used to produce basic C \emph{int} \begin{codesample}
types instead of infinite width INTEGER\_t structures. See Section typedef struct Rectangle_s {
\vref{sec:Command-line-options}.% long height;
}: long width;
\begin{lyxcode} } Rectangle_t;
typedef~struct~Rectangle\_s~\{ \end{codesample}
~~~~int~height;
~~~~int~width;
\}~Rectangle\_t;
\end{lyxcode}
It would also create the code for converting this structure into platform-independent It would also create the code for converting this structure into platform-independent
wire representation (a serializer API) and the decoder of such wire wire representation (a serializer API) and the decoder of such wire
representation back into local, machine-specific type (a deserializer representation back into local, machine-specific type (a deserializer
...@@ -138,29 +147,34 @@ API). ...@@ -138,29 +147,34 @@ API).
\section{Quick start with asn1c} \section{Quick start with asn1c}
After building and installing the compiler, the \emph{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 modules%
} 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} \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.% to find out about \textbf{-P} and \textbf{-R} options.%
}: }:
\begin{lyxcode} \begin{bash}
asn1c~\emph{<module.asn1>} asn1c %\emph{<modules.asn1>}%
\end{lyxcode} \end{bash}
The asn1c takes a number of command line options,
such as an option to produce native long types
for integers instead of infinite width INTEGER\_t structures:
\begin{bash}
asn1c %\textbf{-fnative-types} \emph{<modules.asn1>}%
\end{bash}
If several ASN.1 modules contain interdependencies, all of the files If several ASN.1 modules contain interdependencies, all of the files
must be specified altogether: must be specified altogether:
\begin{lyxcode} \begin{bash}
asn1c~\emph{<module1.asn1>~<module2.asn1>~...} asn1c %\emph{<module1.asn1> <module2.asn1> ...}%
\end{lyxcode} \end{bash}
The compiler \textbf{-E} and \textbf{-EF} options are used for testing The compiler \textbf{-E} and \textbf{-EF} options are used for testing
the parser and the semantic fixer, respectively. These options will the parser and the semantic fixer, respectively. These options will
instruct the compiler to dump out the parsed (and fixed, if \textbf{-F} instruct the compiler to dump out the parsed (and fixed, if \textbf{-F}
is involved) ASN.1 specification as it was ``understood'' is involved) ASN.1 specification as it was ``understood''
by the compiler. It might be useful to check whether a particular by the compiler. It might be useful to check whether a particular
syntactic construction is properly supported by the compiler. syntactic construct is properly supported by the compiler.
\begin{lyxcode} \begin{bash}
asn1c~\textbf{-EF}~\emph{<module-to-test.asn1>} asn1c %\textbf{-EF} \emph{<module-to-test.asn1>}%
\end{lyxcode} \end{bash}
The \textbf{-P} option is used to dump the compiled output on the 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 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} current directory. You would probably want to start with \textbf{-P}
...@@ -170,109 +184,102 @@ need to be generated, and supress linking in the numerous support ...@@ -170,109 +184,102 @@ need to be generated, and supress linking in the numerous support
files. files.
Print the compiled output instead of creating multiple source files: Print the compiled output instead of creating multiple source files:
\begin{lyxcode} \begin{bash}
asn1c~\textbf{-P}~\emph{<module-to-compile-and-print.asn1>} asn1c %\textbf{-P} \emph{<module-to-compile-and-print.asn1>}%
\end{lyxcode} \end{bash}
\section{Recognizing compiler output} \section{Recognizing compiler output}
After compiling, the following entities will be created in your current The asn1c compiler produces a number of files:
directory:
\begin{itemize} \begin{itemize}
\item A set of .c and .h files, generally a single pair for each type defined \item A set of .c and .h files for each type defined
in the ASN.1 specifications. These files will be named similarly to in the ASN.1 specification. These files will be named similarly to
the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the
RectangleTest ASN.1 module defined in the beginning of this document). 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 \item A set of helper .c and .h files which contain the generic encoders,
and other useful routines. There will be quite a few of them, some 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 of them are not even always necessary, but the overall amount of code
after compilation will be rather small anyway. after compilation will be rather small anyway.
\item A \emph{converter-sample.c} file containing the \emph{int main()} function with a fully functioning decoder. It can convert a given PDU between BER, XER and possibly PER (if -gen-PER option to asn1c was in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function.
\item A \emph{Makefile.am.sample} file mentioning all the files created \item A \emph{Makefile.am.sample} file mentioning all the files created
at the earlier steps. This file is suitable for either automake suite at the earlier steps. This file is suitable for either automake suite
or the plain `make` utility. or the plain `make` utility. Just rename it into \emph{Makefile}.
\end{itemize} \end{itemize}
It is your responsibility to create .c file with the \emph{int main()} It is possible to compile everything with just a couple of instructions:
routine. \begin{bash}
asn1c -fnative-types -pdu=%\emph{Rectangle}% *.asn1
In other words, after compiling the Rectangle module, you have the make -f Makefile.am.sample # If you use `make`
following set of files: \{~Makefile.am.sample, Rectangle.c, Rectangle.h, \end{bash}
\textbf{\ldots{}} \}, where ``\textbf{\ldots{}}'' stands for the or
set of additional ``helper'' files created by the compiler. If you \begin{bash}
add a simple file with the \emph{int main()} routine, it would even asn1c -fnative-types *.asn1
be possible to compile everything with the single instruction: cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this
\begin{lyxcode} \end{bash}
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 Refer to the Chapter \vref{cha:Step-by-step-examples} for a sample
\emph{int main()} routine. \emph{int main()} function if you want some custom logic and not satisfied
with the supplied \emph{converter-sample.c}.
\clearpage{}
\section{\label{sec:Command-line-options}Command line options} \section{\label{sec:Command-line-options}Command line options}
The following table summarizes the asn1c command line options. The following table summarizes the asn1c command line options.
\renewcommand{\arraystretch}{1.33} \renewcommand{\arraystretch}{1.33}
\begin{longtable}{lp{4in}} \begin{longtable}{lp{4in}}
\toprule \textbf{Overall Options} & \textbf{Description}\\
\textbf{\small Overall Options} & \textbf{\small Description}\tabularnewline
\midrule \midrule
{\small -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1 {-E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
specification code to the standard output.}\tabularnewline specification code to the standard output.}\\
{\small -F} & {\small Used together with -E, instructs the compiler to stop after {-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 the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1
specification to the standard output.}\tabularnewline specification to the standard output.}\\
{\small -P} & {\small Dump the compiled output to the standard output instead of {-P} & {\small Dump the compiled output to the standard output instead of
creating the target language files on disk.}\tabularnewline creating the target language files on disk.}\\
{\small -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\tabularnewline {-R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\
{\small -S }\emph{\small <directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\tabularnewline {-S}~\emph{<directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\\
{\small -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\tabularnewline {-X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\
\midrule\tabularnewline \textbf{Warning Options} & \textbf{Description}\\
\textbf{\small Warning Options} & \textbf{\small Description}\tabularnewline
\midrule \midrule
{\small -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\tabularnewline {-Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\
{\small -Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\tabularnewline {-Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\\
{\small -Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the {-Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the
fixing stage.}\tabularnewline fixing stage.}\\
{\small -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\tabularnewline {-Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\
\midrule\tabularnewline \textbf{Language Options} & \textbf{Description}\\
\textbf{\small Language Options} & \textbf{\small Description}\tabularnewline
\midrule \midrule
{\small -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other {-fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other
types for which this constraint is normally prohibited by the standard. 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 This is a violation of an ASN.1 standard and compiler may fail to
produce the meaningful code.}\tabularnewline produce the meaningful code.}\\
{\small -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents {-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 name clashes in case the module reuses the same identifiers in multiple
contexts.}\tabularnewline contexts.}\\
{\small -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE {-findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
members as indirect pointers instead of declaring them inline. Consider members as indirect pointers instead of declaring them inline. Consider
using this option together with }\textbf{\small -fno-include-deps}{\small{} using this option together with \textbf{-fno-include-deps}
to prevent circular references. }\tabularnewline to prevent circular references. }\\
{\small -fknown-extern-type=}\emph{\small <name>} & {\small Pretend the specified type is known. The compiler will assume {-fknown-extern-type=}\emph{<name>} & {\small Pretend the specified type is known. The compiler will assume
the target language source files for the given type have been provided the target language source files for the given type have been provided
manually. }\tabularnewline manually. }\\
{\small -fnative-types} & {\small Use the native machine's data types (int, double) whenever {-fnative-types} & {\small Use the native machine's data types (long, double) whenever
possible, instead of the compound INTEGER\_t, ENUMERATED\_t and REAL\_t possible, instead of the compound INTEGER\_t, ENUMERATED\_t and REAL\_t
types. }\tabularnewline types. }\\
{\small -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This {-fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
may produce a shorter executable.}\tabularnewline may produce a shorter executable.}\\
{\small -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical {-fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical
dependencies.}\tabularnewline dependencies.}\\
{\small -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's {-funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's
structures.}\tabularnewline structures.}\\\\
\midrule\tabularnewline \textbf{Codecs Generation Options} & \textbf{Description}\\
\textbf{\small Codecs Generation Options} & \textbf{\small Description}\tabularnewline
\midrule \midrule
{\small -gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\tabularnewline {-gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\\
{\small -pdu=}\emph{\small auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically.}\tabularnewline {-pdu=}\emph{auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically. Also accepts a special keyword \emph{all} or a particular type to be used as a PDU.}\\ \\
\midrule\tabularnewline \textbf{Output Options} & \textbf{Description}\\
\textbf{\small Output Options} & \textbf{\small Description}\tabularnewline
\midrule \midrule
{\small -print-constraints} & {\small When -EF are also specified, this option forces the compiler {-print-constraints} & {\small When -EF are also specified, this option forces the compiler
to explain its internal understanding of subtype constraints.}\tabularnewline to explain its internal understanding of subtype constraints.}\\
{\small -print-lines} & {\small Generate ``-{}- \#line'' comments {-print-lines} & {\small Generate ``-{}- \#line'' comments
in -E output.}\tabularnewline in -E output.}\\
\bottomrule
\end{longtable} \end{longtable}
\renewcommand{\arraystretch}{1} \renewcommand{\arraystretch}{1}
...@@ -286,21 +293,19 @@ First of all, you should include one or more header files into your ...@@ -286,21 +293,19 @@ First of all, you should include one or more header files into your
application. Typically, it is enough to include the header file of application. Typically, it is enough to include the header file of
the main PDU type. For our Rectangle module, including the Rectangle.h the main PDU type. For our Rectangle module, including the Rectangle.h
file is sufficient: file is sufficient:
\begin{lyxcode} \begin{codesample}
\#include~<Rectangle.h> #include <Rectangle.h>
\end{lyxcode} \end{codesample}
The header files defines the C structure corresponding to the ASN.1 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, 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 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 the ASN.1 module. For example, here is the code which frees the Rectangle\_t
structure: structure:
\begin{lyxcode} \begin{codesample}
Rectangle\_t~{*}rect~=~...; Rectangle_t *rect = ...;
~ asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
\end{codesample}
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 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 structure which needs to be freed. The second line invokes the generic
\emph{free\_struct()} routine created specifically for this Rectangle\_t \emph{free\_struct()} routine created specifically for this Rectangle\_t
...@@ -356,7 +361,7 @@ versions of BER, so the generic BER parser is also capable of decoding ...@@ -356,7 +361,7 @@ 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. 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 \emph{The ASN.1 compiler provides the generic BER decoder which is
implicitly capable of decoding BER, CER and DER encoded data.} capable of decoding BER, CER and DER encoded data.}
The decoder is restartable (stream-oriented), which means that in The decoder is restartable (stream-oriented), which means that in
case the buffer has less data than it is expected, the decoder will case the buffer has less data than it is expected, the decoder will
...@@ -367,59 +372,42 @@ the next buffer contain the unprocessed part of the previous buffer. ...@@ -367,59 +372,42 @@ the next buffer contain the unprocessed part of the previous buffer.
Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes. Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
\begin{itemize} \begin{itemize}
\item You may concatenate these buffers and feed the BER decoder with 300 \item You can concatenate these buffers and feed the BER decoder with 300
bytes of data, or bytes of data, or
\item You may feed it the first buffer of 100 bytes of data, realize that \item You can 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 the ber\_decoder consumed only 95 bytes from it and later feed the
decoder with 205 bytes buffer which consists of 5 unprocessed bytes decoder with 205 bytes buffer which consists of 5 unprocessed bytes
from the first buffer and the additional 200 bytes from the second from the first buffer and the additional 200 bytes from the second
buffer. buffer.
\end{itemize} \end{itemize}
This is not as convenient as it could be (like, the BER encoder could This is not as convenient as it could be (the BER encoder could
consume the whole 100 bytes and keep these 5 bytes in some temporary consume the whole 100 bytes and keep these 5 bytes in some temporary
storage), but in case of existing stream based processing it might storage), but in case of existing stream based processing it might
actually fit well into existing algorithm. Suggestions are welcome. actually fit well into existing algorithm. Suggestions are welcome.
Here is the simplest example of BER decoding. Here is the simplest example of BER decoding:
\begin{lyxcode}
Rectangle\_t~{*} \begin{codesample}
Rectangle_t *
simple\_deserializer(const~void~{*}buffer,~size\_t~buf\_size)~\{ simple_deserializer(const void *buffer, size_t buf_size) {
Rectangle_t *rect = 0; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
~~~~Rectangle\_t~{*}rect~=~0;~~~~/{*}~Note~this~0!~{*}/ asn_dec_rval_t rval;
~~~~asn\_dec\_rval\_t~rval; rval = %\textbf{asn\_DEF\_Rectangle.ber\_decoder}%(0,
&asn_DEF_Rectangle,
~ (void **)&rect, /* Decoder %\emph{moves}% the pointer */
buffer, buf_size,
~~~~rval~=~\textbf{asn\_DEF\_Rectangle.ber\_decoder}(0, 0);
~~~~~~~~~~\&asn\_DEF\_Rectangle, if(rval%\textbf{.code}% == RC_OK) {
return rect; /* Decoding succeeded */
~~~~~~~~~~(void~{*}{*})\&rect, } else {
/* Free partially decoded rect */
~~~~~~~~~~buffer,~buf\_size, asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
return 0;
~~~~~~~~~~0); }
}
~ \end{codesample}
~~~~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 The code above defines a function, \emph{simple\_deserializer}, which
takes a buffer and its length and is expected to return a pointer 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 to the Rectangle\_t structure. Inside, it tries to convert the bytes
...@@ -436,11 +424,9 @@ be decoded into the structure by the time something goes wrong. ...@@ -436,11 +424,9 @@ 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()} A little less wordy would be to invoke a globally available \emph{ber\_decode()}
function instead of dereferencing the asn\_DEF\_Rectangle type descriptor: function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
\begin{lyxcode} \begin{codesample}
rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect, rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
\end{codesample}
~~~~buffer,~buf\_size);
\end{lyxcode}
Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference
is gone, and also the last argument (0) is no longer necessary. is gone, and also the last argument (0) is no longer necessary.
...@@ -479,55 +465,30 @@ to encode X.509 certificates. ...@@ -479,55 +465,30 @@ to encode X.509 certificates.
As with BER decoder, the DER encoder may be invoked either directly 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 from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
function, which is somewhat simpler: function, which is somewhat simpler:
\begin{lyxcode} \begin{codesample}
~ /*
* This is the serializer itself.
/{*} * It supplies the DER encoder with the
* pointer to the custom output function.
~{*}~This~is~the~serializer~itself, */
ssize_t
~{*}~it~supplies~the~DER~encoder~with~the simple_serializer(FILE *ostream, Rectangle_t *rect) {
asn_enc_rval_t er; /* Encoder return value */
~{*}~pointer~to~the~custom~output~function.
er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream);
~{*}/ if(er%\textbf{.encoded}% == -1) {
/*
ssize\_t * Failed to encode the rectangle data.
*/
simple\_serializer(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{ fprintf(stderr, "Cannot encode %\%%s: %\%%s\n",
er%\textbf{.failed\_type}%->name, strerror(errno));
~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/ return -1;
} else {
~ /* Return the number of bytes */
return er.encoded;
~~~~er~=~der\_encode(\&asn\_DEF\_Rect,~rect, }
}
~~~~~~~~write\_stream,~ostream); \end{codesample}
~~~~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 As you see, the DER encoder does not write into some sort of buffer
or something. It just invokes the custom function (possible, multiple or something. It just invokes the custom function (possible, multiple
times) which would save the data into appropriate storage. The optional times) which would save the data into appropriate storage. The optional
...@@ -536,7 +497,7 @@ used by \emph{\_write\_stream()} as the pointer to the appropriate ...@@ -536,7 +497,7 @@ used by \emph{\_write\_stream()} as the pointer to the appropriate
output stream to be used. output stream to be used.
If the custom write function is not given (passed as 0), then the 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) 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 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 prove useful to determine the size of the structure's encoding before
actually doing the encoding% actually doing the encoding%
...@@ -556,43 +517,26 @@ encoder routine API comes in two flavors: stdio-based and callback-based. ...@@ -556,43 +517,26 @@ encoder routine API comes in two flavors: stdio-based and callback-based.
With the callback-based encoder, the encoding process is very similar With the callback-based encoder, the encoding process is very similar
to the DER one, described in Section \vref{sub:Encoding-DER}. The to the DER one, described in Section \vref{sub:Encoding-DER}. The
following example uses the definition of write\_stream() from up there. following example uses the definition of write\_stream() from up there.
\begin{lyxcode} \begin{codesample}
/{*} /*
* This procedure generates the XML document
~{*}~This~procedure~generates~the~XML~document * by invoking the XER encoder.
* NOTE: Do not copy this code verbatim!
~{*}~by~invoking~the~XER~encoder. * If the stdio output is necessary,
* use the xer_fprint() procedure instead.
~{*}~NOTE:~Do~not~copy~this~code~verbatim! * See Section%\vref{sub:Printing-the-target}%.
*/
~{*}~~~~~~~If~the~stdio~output~is~necessary,
~{*}~~~~~~~use~the~xer\_fprint()~procedure~instead.
~{*}~~~~~~~See~Section~\vref{sub:Printing-the-target}.
~{*}/
int int
print_as_XML(FILE *ostream, Rectangle_t *rect) {
asn_enc_rval_t er; /* Encoder return value */
print\_as\_XML(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{ er = xer_encode(&asn_DEF_Rectangle, rect,
XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */
~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/ write_stream, ostream);
~
~~~~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{codesample}
~~~~return~(er.encoded~==~-1)~?~-1~:~0;
\}
\end{lyxcode}
Look into xer\_encoder.h for the precise definition of xer\_encode() Look into xer\_encoder.h for the precise definition of xer\_encode()
and related types. and related types.
...@@ -604,37 +548,23 @@ XML encoder and other pretty-printing suggestions. ...@@ -604,37 +548,23 @@ XML encoder and other pretty-printing suggestions.
The data encoded using the XER rules can be subsequently decoded using The data encoded using the XER rules can be subsequently decoded using
the xer\_decode() API call: the xer\_decode() API call:
\begin{lyxcode} \begin{codesample}
Rectangle\_t~{*} Rectangle_t *
XML_to_Rectangle(const void *buffer, size_t buf_size) {
XML\_to\_Rectangle(const~void~{*}buffer,~size\_t~buf\_size)~\{ Rectangle_t *rect = 0; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
asn_dec_rval_t rval;
~~~~Rectangle\_t~{*}rect~=~0;~/{*}~Note~this~0!~{*}/
rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
~~~~asn\_dec\_rval\_t~rval;
if(rval%\textbf{.code}% == RC_OK) {
~~ return rect; /* Decoding succeeded */
} else {
~~~~rval~=~xer\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect, /* Free partially decoded rect */
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
~~~~~~~~buffer,~buf\_size); return 0;
}
~~~~if(rval\textbf{.code}~==~RC\_OK)~\{ }
\end{codesample}
~~~~~~~~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 takes both BASIC-XER and CANONICAL-XER encodings.
The decoder shares its data consumption properties with BER decoder; The decoder shares its data consumption properties with BER decoder;
...@@ -671,9 +601,9 @@ and related types. ...@@ -671,9 +601,9 @@ and related types.
There are two ways to print the target structure: either invoke the 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() print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint()
function, which is a simpler wrapper of the former: function, which is a simpler wrapper of the former:
\begin{lyxcode} \begin{codesample}
asn\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect); asn_fprint(stdout, &asn_DEF_Rectangle, rect);
\end{lyxcode} \end{codesample}
Look into constr\_TYPE.h for the precise definition of asn\_fprint() Look into constr\_TYPE.h for the precise definition of asn\_fprint()
and related types. and related types.
...@@ -682,9 +612,9 @@ be to invoke XER encoder. The default BASIC-XER encoder performs reasonable ...@@ -682,9 +612,9 @@ be to invoke XER encoder. The default BASIC-XER encoder performs reasonable
formatting for the output to be useful and human readable. To invoke 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() the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint()
call: call:
\begin{lyxcode} \begin{codesample}
xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect); xer_fprint(stdout, &asn_DEF_Rectangle, rect);
\end{lyxcode} \end{codesample}
See Section \vref{sub:Encoding-XER} for XML-related details. See Section \vref{sub:Encoding-XER} for XML-related details.
...@@ -694,19 +624,14 @@ Freeing the structure is slightly more complex than it may seem to. ...@@ -694,19 +624,14 @@ 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 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 and their submembers are recursively freed as well. But it might not
be feasible to free the structure itself. Consider the following case: be feasible to free the structure itself. Consider the following case:
\begin{lyxcode} \begin{codesample}
struct~my\_figure~\{~~~~~~~/{*}~The~custom~structure~{*}/ struct my_figure { /* The custom structure */
int flags; /* <some custom member> */
~~~~int~flags;~~~~~~~~~~~/{*}~<some~custom~member>~{*}/ /* The type is generated by the ASN.1 compiler */
Rectangle_t rect;
~~~~/{*}~The~type~is~generated~by~the~ASN.1~compiler~{*}/ /* other members of the structure */
};
~~~~\emph{Rectangle\_t~rect;} \end{codesample}
~~~~/{*}~other~members~of~the~structure~{*}/
\};
\end{lyxcode}
In this example, the application programmer defined a custom structure In this example, the application programmer defined a custom structure
with one ASN.1-derived member (rect). This member is not a reference 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 to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t
...@@ -721,56 +646,35 @@ argument (besides the obvious type descriptor and target structure ...@@ -721,56 +646,35 @@ argument (besides the obvious type descriptor and target structure
pointers), which is the flag specifying whether the outer pointer pointers), which is the flag specifying whether the outer pointer
itself must be freed (0, default) or it should be left intact (non-zero itself must be freed (0, default) or it should be left intact (non-zero
value). value).
\begin{lyxcode} \begin{codesample}
\textbf{/{*}~1.~Rectangle\_t~is~defined~within~my\_figure~{*}/} /* %\textbf{1. Rectangle\_t is defined within my\_figure}% */
struct my_figure {
struct~my\_figure~\{ Rectangle_t rect;
} *mf = ...;
~~~~Rectangle\_t~rect; /*
* Freeing the Rectangle_t
\}~{*}mf~=~\textbf{...}; * without freeing the mf->rect area.
*/
/{*} asn_DEF_Rectangle.free_struct(
&asn_DEF_Rectangle, &mf->rect, %\textbf{1 /* !free */}%);
~{*}~Freeing~the~Rectangle\_t
/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */
~{*}~without~freeing~the~mf->rect~area Rectangle_t *rect = ...;
/*
~{*}/ * Freeing the Rectangle_t
* and freeing the rect pointer.
asn\_DEF\_Rectangle.free\_struct( */
asn_DEF_Rectangle.free_struct(
~~~~\&asn\_DEF\_Rectangle,~\&mf->rect,~\textbf{1}~\textbf{/{*}~!free~{*}/}); &asn_DEF_Rectangle, rect, %\textbf{0 /* free the pointer too */}%);
\end{codesample}
~~~~
~~
\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 It is safe to invoke the \emph{free\_struct} function with the target
structure pointer set to 0 (NULL), the function will do nothing. structure pointer set to 0 (NULL), the function will do nothing.
For the programmer's convenience, the following macros are available: For the programmer's convenience, the following macros are available:
\begin{lyxcode} \begin{codesample}
ASN\_STRUCT\_FREE(asn\_DEF,~ptr); ASN_STRUCT_FREE(asn_DEF, ptr);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr);
ASN\_STRUCT\_FREE\_CONTENTS\_ONLY(asn\_DEF,~ptr); \end{codesample}
\end{lyxcode}
These macros bear the same semantics as the \emph{free\_struct} function These macros bear the same semantics as the \emph{free\_struct} function
invocation, discussed above. invocation, discussed above.
...@@ -785,30 +689,21 @@ a ``Rectangle'' type used throughout this document. ...@@ -785,30 +689,21 @@ a ``Rectangle'' type used throughout this document.
\begin{enumerate} \begin{enumerate}
\item Create a file named \textbf{rectangle.asn1} with the following contents: \item Create a file named \textbf{rectangle.asn1} with the following contents:
\begin{lyxcode} \begin{asn}
RectangleModule1~DEFINITIONS~::= RectangleModule1 DEFINITIONS ::= BEGIN
BEGIN
~
Rectangle~::=~SEQUENCE~\{
~~~~height~~INTEGER,
~~~~width~~~INTEGER Rectangle ::= SEQUENCE {
height INTEGER,
\} width INTEGER
}
~
END END
\end{lyxcode} \end{asn}
\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: \item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
\begin{lyxcode} \begin{bash}
\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1} asn1c -fnative-types %\textbf{rectangle.asn1}%
\end{lyxcode} \end{bash}
\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading \item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
the \textbf{rectangle.asn1} file into the Web form and unpacking the the \textbf{rectangle.asn1} file into the Web form and unpacking the
produced archive on your computer. produced archive on your computer.
...@@ -816,149 +711,73 @@ produced archive on your computer. ...@@ -816,149 +711,73 @@ produced archive on your computer.
directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
\item Create a main() routine which creates the Rectangle\_t structure in \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 memory and encodes it using BER and XER encoding rules. Let's name
the file \textbf{main.c}:\clearpage{} the file \textbf{main.c}:
\begin{lyxcode} \begin{codesample}[basicstyle=\scriptsize\listingfont]
{\small \#include~<stdio.h>}{\small \par} #include <stdio.h>
#include <sys/types.h>
{\small \#include~<sys/types.h>}{\small \par} #include <Rectangle.h> /* Rectangle ASN.1 type */
{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par} /* Write the encoded output into some FILE stream. */
static int write_out(const void *buffer, size_t size, void *app_key) {
~ FILE *out_fp = app_key;
size_t wrote = fwrite(buffer, 1, size, out_fp);
{\small /{*}}{\small \par} return (wrote == size) ? 0 : -1;
}
{\small{}~{*}~This~is~a~custom~function~which~writes~the}{\small \par}
int main(int ac, char **av) {
{\small{}~{*}~encoded~output~into~some~FILE~stream.}{\small \par} Rectangle_t *rectangle; /* Type to encode */
asn_enc_rval_t ec; /* Encoder return value */
{\small{}~{*}/}{\small \par}
/* Allocate the Rectangle_t */
{\small static~int}{\small \par} rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */
if(!rectangle) {
{\small write\_out(const~void~{*}buffer,~size\_t~size,~void~{*}app\_key)~\{}{\small \par} perror("calloc() failed");
exit(1);
{\small{}~~~~FILE~{*}out\_fp~=~app\_key;}{\small \par} }
{\small{}~~~~size\_t~wrote;}{\small \par} /* Initialize the Rectangle members */
rectangle->height = 42; /* any random value */
{\small{}~}{\small \par} rectangle->width = 23; /* any random value */
{\small{}~~~~wrote~=~fwrite(buffer,~1,~size,~out\_fp);}{\small \par} /* BER encode the data if filename is given */
if(ac < 2) {
{\small{}~}{\small \par} fprintf(stderr, "Specify filename for BER output\n");
} else {
{\small{}~~~~return~(wrote~==~size)~?~0~:~-1;}{\small \par} const char *filename = av[1];
FILE *fp = fopen(filename, "wb"); /* for BER output */
{\small \}}{\small \par}
if(!fp) {
~ perror(filename);
exit(1);
{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par} }
{\small{}~~~~Rectangle\_t~{*}rectangle;~/{*}~Type~to~encode~~~~~~~~{*}/}{\small \par} /* Encode the Rectangle type as BER (DER) */
ec = der_encode(&asn_DEF_Rectangle, rectangle, write_out, fp);
{\small{}~~~~asn\_enc\_rval\_t~ec;~~~~~~/{*}~Encoder~return~value~~{*}/}{\small \par} fclose(fp);
if(ec.encoded == -1) {
{\small{}~}{\small \par} fprintf(stderr, "Could not encode Rectangle (at %\%%s)\n",
ec.failed_type ? ec.failed_type->name : "unknown");
{\small{}~~~~/{*}~Allocate~the~Rectangle\_t~{*}/}{\small \par} exit(1);
} else {
{\small{}~~~~rectangle~=~calloc(1,~sizeof(Rectangle\_t));~/{*}~not~malloc!~{*}/}{\small \par} fprintf(stderr, "Created %\%%s with BER encoded Rectangle\n", filename);
}
{\small{}~~~~if(!rectangle)~\{}{\small \par} }
{\small{}~~~~~~perror(''calloc()~failed'');}{\small \par} /* Also print the constructed Rectangle XER encoded (XML) */
xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
{\small{}~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par}
return 0; /* Encoding finished successfully */
{\small{}~~~~\}}{\small \par} }
\end{codesample}
{\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): \item Compile all files together using C compiler (varies by platform):
\begin{lyxcode} \begin{bash}
\emph{cc~-I.~-o}~\textbf{\emph{rencode}}~\emph{{*}.c} cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}%
\end{lyxcode} \end{bash}
\item Voila! You have just created the BER and XER encoder of a Rectangle \item Voila! You have just created the BER and XER encoder of a Rectangle
type, named \textbf{rencode}! type, named \textbf{rencode}!
\end{enumerate} \end{enumerate}
\clearpage{}
\section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder} \section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder}
...@@ -967,30 +786,21 @@ This example will help you to create a simple BER decoder of a simple ...@@ -967,30 +786,21 @@ This example will help you to create a simple BER decoder of a simple
\begin{enumerate} \begin{enumerate}
\item Create a file named \textbf{rectangle.asn1} with the following contents: \item Create a file named \textbf{rectangle.asn1} with the following contents:
\begin{lyxcode} \begin{asn}
RectangleModule1~DEFINITIONS~::= RectangleModule1 DEFINITIONS ::= BEGIN
BEGIN
~
Rectangle~::=~SEQUENCE~\{
~~~~height~~INTEGER,
~~~~width~~~INTEGER Rectangle ::= SEQUENCE {
height INTEGER,
\} width INTEGER
}
~
END END
\end{lyxcode} \end{asn}
\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}: \item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
\begin{lyxcode} \begin{bash}
\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1} asn1c -fnative-types %\textbf{rectangle.asn1}%
\end{lyxcode} \end{bash}
\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading \item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
the \textbf{rectangle.asn1} file into the Web form and unpacking the the \textbf{rectangle.asn1} file into the Web form and unpacking the
produced archive on your computer. produced archive on your computer.
...@@ -998,114 +808,61 @@ produced archive on your computer. ...@@ -998,114 +808,61 @@ produced archive on your computer.
directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}. directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
\item Create a main() routine which takes the binary input file, decodes \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 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{} (XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:
\begin{lyxcode} \begin{codesample}[basicstyle=\scriptsize\listingfont]
{\small \#include~<stdio.h>}{\small \par} #include <stdio.h>
#include <sys/types.h>
{\small \#include~<sys/types.h>}{\small \par} #include <Rectangle.h> /* Rectangle ASN.1 type */
{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par} int main(int ac, char **av) {
char buf[1024]; /* Temporary buffer */
{\small{}~}{\small \par} Rectangle_t *rectangle = 0; /* Type to decode. %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
asn_dec_rval_t rval; /* Decoder return value */
{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par} FILE *fp; /* Input file handler */
size_t size; /* Number of bytes read */
{\small{}~~~~char~buf{[}1024{]};~~~~~~/{*}~Temporary~buffer~~~~~~{*}/}{\small \par} char *filename; /* Input file name */
{\small{}~~~~Rectangle\_t~{*}rectangle~=~0;~/{*}~Type~to~decode~{*}/}{\small \par} /* Require a single filename argument */
if(ac != 2) {
{\small{}~~~~asn\_dec\_rval\_t~rval;~/{*}~Decoder~return~value~~{*}/}{\small \par} fprintf(stderr, "Usage: %\%%s <file.ber>\n", av[0]);
exit(1);
{\small{}~~~~FILE~{*}fp;~~~~~~~~~~~~/{*}~Input~file~handler~~~~{*}/}{\small \par} } else {
filename = av[1];
{\small{}~~~~size\_t~size;~~~~~~~~~/{*}~Number~of~bytes~read~~{*}/}{\small \par} }
{\small{}~~~~char~{*}filename;~~~~~~/{*}~Input~file~name~{*}/}{\small \par} /* Open input file as read-only binary */
fp = fopen(filename, "rb");
{\small{}~}{\small \par} if(!fp) {
perror(filename);
{\small{}~~~~/{*}~Require~a~single~filename~argument~{*}/}{\small \par} exit(1);
}
{\small{}~~~~if(ac~!=~2)~\{}{\small \par}
/* Read up to the buffer size */
{\small{}~~~~~~fprintf(stderr,~''Usage:~\%s~<file.ber>\textbackslash{}n'',~av{[}0{]});}{\small \par} size = fread(buf, 1, sizeof(buf), fp);
fclose(fp);
{\small{}~~~~~~exit(64);~/{*}~better,~EX\_USAGE~{*}/}{\small \par} if(!size) {
fprintf(stderr, "%\%%s: Empty or broken\n", filename);
{\small{}~~~~\}~else~\{}{\small \par} exit(1);
}
{\small{}~~~~~~filename~=~av{[}1{]};}{\small \par}
/* Decode the input buffer as Rectangle type */
{\small{}~~~~\}}{\small \par} rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rectangle, buf, size);
if(rval.code != RC_OK) {
{\small{}~}{\small \par} fprintf(stderr, "%\%%s: Broken Rectangle encoding at byte %\%%ld\n", filename, (long)rval.consumed);
exit(1);
{\small{}~~~~/{*}~Open~input~file~as~read-only~binary~{*}/}{\small \par} }
{\small{}~~~~fp~=~fopen(filename,~''rb'');}{\small \par} /* Print the decoded Rectangle type as XML */
xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
{\small{}~~~~if(!fp)~\{}{\small \par}
return 0; /* Decoding finished successfully */
{\small{}~~~~~~perror(filename);}{\small \par} \end{codesample}
{\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): \item Compile all files together using C compiler (varies by platform):
\begin{lyxcode} \begin{bash}
\emph{cc~-I.~-o}~\textbf{\emph{rdecode}}~\emph{{*}.c} cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}%
\end{lyxcode} \end{bash}
\item Voila! You have just created the BER decoder of a Rectangle type, \item Voila! You have just created the BER decoder of a Rectangle type,
named \textbf{rdecode}! named \textbf{rdecode}!
\end{enumerate} \end{enumerate}
...@@ -1123,25 +880,16 @@ and how to invoke the constraints validation code in your application. ...@@ -1123,25 +880,16 @@ and how to invoke the constraints validation code in your application.
\begin{enumerate} \begin{enumerate}
\item Create a file named \textbf{rectangle.asn1} with the following contents: \item Create a file named \textbf{rectangle.asn1} with the following contents:
\begin{lyxcode} \begin{asn}
RectangleModuleWithConstraints~DEFINITIONS~::= RectangleModuleWithConstraints DEFINITIONS ::= BEGIN
BEGIN Rectangle ::= SEQUENCE {
height INTEGER (0..100), -- Value range constraint
~ width INTEGER (0..MAX) -- Makes width non-negative
}
Rectangle~::=~SEQUENCE~\{
~~~~height~~INTEGER~(0..100),~-{}-~Value~range~constraint
~~~~width~~~INTEGER~(0..MAX)~~-{}-~Makes~width~non-negative~
\}
~
END END
\end{lyxcode} \end{asn}
\item Compile the file according to procedures shown in the previous chapter. \item Compile the file according to procedures shown in the previous chapter.
\item Modify the Rectangle type processing routine (you can start with the \item Modify the Rectangle type processing routine (you can start with the
main() routine shown in the Section \vref{sec:A-Rectangle-Decoder}) main() routine shown in the Section \vref{sec:A-Rectangle-Decoder})
...@@ -1154,49 +902,32 @@ sharing the data with anyone else. ...@@ -1154,49 +902,32 @@ sharing the data with anyone else.
Placing the constraint checking code \emph{after} decoding, but before Placing the constraint checking code \emph{after} decoding, but before
any further action depending on the decoded data, helps to make sure any further action depending on the decoded data, helps to make sure
the application got the valid contents before making use of it.% 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} \begin{codesample}
int ret; /* Return value */
char errbuf[128]; /* Buffer for error message */
size_t errlen = sizeof(errbuf); /* Size of the buffer */
{\small \}}{\small \par} /* ... here may go Rectangle %\emph{decoding}% code ... */
{\small{}~}{\small \par} ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen);
/* assert(errlen < sizeof(errbuf)); // you may rely on that */
if(ret) {
fprintf(stderr, "Constraint validation failed: %\%%s\n",
errbuf /* errbuf is properly nul-terminated */
);
/* exit(...); // Replace with appropriate action */
}
{\small /{*}~...~here~may~go~Rectangle~encoding~code~...~{*}/}{\small \par} /* ... here may go Rectangle %\emph{encoding}% code ... */
\end{lyxcode} \end{codesample}
\item Compile the resulting C code as shown in the previous chapters. \item Compile the resulting C code as shown in the previous chapters.
\item Try to test the constraints checking code by assigning integer value \item Try to test the constraints checking code by assigning integer value
101 to the \textbf{.height} member of the Rectangle structure, or 101 to the \textbf{.height} member of the Rectangle structure, or
a negative value to the \textbf{.width} member. In either case, the a negative value to the \textbf{.width} member. In either case, the
program should print ``Constraint validation failed'' message, followed program should print ``Constraint validation failed'' message, followed
by the short explanation why validation did not succeed. by a short explanation why validation did not succeed.
\item Done. \item Done.
\end{enumerate} \end{enumerate}
...@@ -1213,7 +944,7 @@ of standards itself \cite{ITU-T/ASN.1}.} ...@@ -1213,7 +944,7 @@ of standards itself \cite{ITU-T/ASN.1}.}
The Abstract Syntax Notation One is used to formally describe the The Abstract Syntax Notation One is used to formally describe the
semantics of data transmitted across the network. Two communicating semantics of data transmitted across the network. Two communicating
parties may have different formats of their native data types (i.e. 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 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 a way to describe the data in a manner which is independent from the
particular machine's representation. The ASN.1 specifications are particular machine's representation. The ASN.1 specifications are
...@@ -1227,15 +958,12 @@ to encode and decode the data according to some encoding rules (which ...@@ -1227,15 +958,12 @@ to encode and decode the data according to some encoding rules (which
are also defined by the ASN.1 standard). are also defined by the ASN.1 standard).
\end{itemize} \end{itemize}
Consider the following example: Consider the following example:
\begin{lyxcode} \begin{asn}
Rectangle~::=~SEQUENCE~\{ Rectangle ::= SEQUENCE {
height INTEGER,
~~~~height~~INTEGER, width INTEGER
}
~~~~width~~~INTEGER \end{asn}
\}
\end{lyxcode}
This ASN.1 specification describes a constructed type, \emph{Rectangle}, This ASN.1 specification describes a constructed type, \emph{Rectangle},
containing two integer fields. This specification may tell the reader containing two integer fields. This specification may tell the reader
that there exists this kind of data structure and that some entity that there exists this kind of data structure and that some entity
...@@ -1249,35 +977,22 @@ and others, including CER and DER derivatives from BER. ...@@ -1249,35 +977,22 @@ and others, including CER and DER derivatives from BER.
The complete specification must be wrapped in a module, which looks The complete specification must be wrapped in a module, which looks
like this: like this:
\begin{lyxcode} \begin{asn}
RectangleModule1 RectangleModule1
{ iso org(3) dod(6) internet(1) private(4)
~~~~\{~iso~org(3)~dod(6)~internet(1)~private(4) enterprise(1) spelio(9363) software(1)
asn1c(5) docs(2) rectangle(1) 1 }
~~~~~~enterprise(1)~spelio(9363)~software(1) DEFINITIONS AUTOMATIC TAGS ::=
~~~~~~asn1c(5)~docs(2)~rectangle(1)~1~\}~
~~~~DEFINITIONS~AUTOMATIC~TAGS~::=
BEGIN BEGIN
~ -- This is a comment which describes nothing.
Rectangle ::= SEQUENCE {
-{}-~This~is~a~comment~which~describes~nothing. height INTEGER, -- Height of the rectangle
width INTEGER -- Width of the rectangle
Rectangle~::=~SEQUENCE~\{ }
~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
\}
~
END END
\end{lyxcode} \end{asn}
The module header consists of module name (RectangleModule1), the The module header consists of module name (RectangleModule1), the
module object identifier (\{...\}), a keyword ``DEFINITIONS'', a module object identifier (\{...\}), a keyword ``DEFINITIONS'', a
set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module
...@@ -1298,58 +1013,40 @@ or a similar kind of two-way choice. ...@@ -1298,58 +1013,40 @@ or a similar kind of two-way choice.
The INTEGER type is a signed natural number type without any restrictions The INTEGER type is a signed natural number type without any restrictions
on its size. If the automatic checking on INTEGER value bounds are on its size. If the automatic checking on INTEGER value bounds are
necessary, the subtype constraints must be used. necessary, the subtype constraints must be used.
\begin{lyxcode} \begin{asn}
SimpleInteger~::=~INTEGER SimpleInteger ::= INTEGER
~
-{}-~An~integer~with~a~very~limited~range
SmallPositiveInt~::=~INTEGER~(0..127) -- An integer with a very limited range
SmallPositiveInt ::= INTEGER (0..127)
~ -- Integer, negative
NegativeInt ::= INTEGER (MIN..0)
-{}-~Integer,~negative \end{asn}
NegativeInt~::=~INTEGER~(MIN..0)
\end{lyxcode}
\subsection{The ENUMERATED type} \subsection{The ENUMERATED type}
The ENUMERATED type is semantically equivalent to the INTEGER type The ENUMERATED type is semantically equivalent to the INTEGER type
with some integer values explicitly named. with some integer values explicitly named.
\begin{lyxcode} \begin{asn}
FruitId~::=~ENUMERATED~\{~apple(1),~orange(2)~\} FruitId ::= ENUMERATED { apple(1), orange(2) }
~ -- The numbers in braces are optional,
-- the enumeration can be performed
-{}-~The~numbers~in~braces~are~optional, -- automatically by the compiler
ComputerOSType ::= ENUMERATED {
-{}-~the~enumeration~can~be~performed FreeBSD, -- acquires value 0
Windows, -- acquires value 1
-{}-~automatically~by~the~compiler Solaris(5), -- remains 5
Linux, -- becomes 6
ComputerOSType~::=~ENUMERATED~\{ MacOS -- becomes 7
}
~~~~FreeBSD,~~~~~~~~~~-{}-~acquires~value~0 \end{asn}
~~~~Windows,~~~~~~~~~~-{}-~acquires~value~1
~~~~Solaris(5),~~~~~~~-{}-~remains~5
~~~~Linux,~~~~~~~~~~~~-{}-~becomes~6
~~~~MacOS~~~~~~~~~~~~~-{}-~becomes~7
\}
\end{lyxcode}
\subsection{The OCTET STRING type} \subsection{The OCTET STRING type}
This type models the sequence of 8-bit bytes. This may be used to 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 transmit some opaque data or data serialized by other types of encoders
(i.e. video file, photo picture, etc). (i.~e., video file, photo picture, etc).
\subsection{The OBJECT IDENTIFIER type} \subsection{The OBJECT IDENTIFIER type}
...@@ -1361,25 +1058,17 @@ get your own identification subtree at \url{http://www.iana.org/protocols/forms. ...@@ -1361,25 +1058,17 @@ get your own identification subtree at \url{http://www.iana.org/protocols/forms.
For example, the very first ASN.1 module in this Chapter (RectangleModule1) 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. has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
\begin{lyxcode} \begin{asn}
ExampleOID~::=~OBJECT~IDENTIFIER ExampleOID ::= OBJECT IDENTIFIER
~
rectangleModule1-oid~ExampleOID
~~::=~\{~1~3~6~1~4~1~9363~1~5~2~1~1~\} rectangleModule1-oid ExampleOID
::= { 1 3 6 1 4 1 9363 1 5 2 1 1 }
~ -- An identifier of the Internet.
internet-id OBJECT IDENTIFIER
-{}-~An~identifier~of~the~Internet. ::= { iso(1) identified-organization(3)
dod(6) internet(1) }
internet-id~OBJECT~IDENTIFIER \end{asn}
~~::=~\{~iso(1)~identified-organization(3)
~~~~~~~~dod(6)~internet(1)~\}
\end{lyxcode}
As you see, names are optional. As you see, names are optional.
...@@ -1389,15 +1078,12 @@ The RELATIVE-OID type has the semantics of a subtree of an OBJECT ...@@ -1389,15 +1078,12 @@ 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 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 from the root of the registration tree where the only thing of interest
is some of the tree's subsequence. is some of the tree's subsequence.
\begin{lyxcode} \begin{asn}
this-document~RELATIVE-OID~::=~\{~docs(2)~usage(1)~\} this-document RELATIVE-OID ::= { docs(2) usage(1) }
~
this-example~RELATIVE-OID~::=~\{ this-example RELATIVE-OID ::= {
this-document assorted-examples(0) this-example(1) }
~~~~this-document~assorted-examples(0)~this-example(1)~\} \end{asn}
\end{lyxcode}
\section{Some of the ASN.1 String Types} \section{Some of the ASN.1 String Types}
...@@ -1439,7 +1125,7 @@ symbol (tilde). ...@@ -1439,7 +1125,7 @@ symbol (tilde).
Alternatively, the alphabet may be described as the PrintableString Alternatively, the alphabet may be described as the PrintableString
alphabet presented earlier, plus the following characters: ``\textbf{!}'', alphabet presented earlier, plus the following characters: ``\textbf{!}'',
``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'', ``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'',
``\textbf{\&}'', ``\textbf{{*}}'', ``\textbf{;}'', ``\textbf{<}'', ``\textbf{\&}'', ``\textbf{*}'', ``\textbf{;}'', ``\textbf{<}'',
``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'', ``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'',
``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'', ``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'',
``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'', ``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'',
...@@ -1453,25 +1139,17 @@ alphabet presented earlier, plus the following characters: ``\textbf{!}'', ...@@ -1453,25 +1139,17 @@ alphabet presented earlier, plus the following characters: ``\textbf{!}'',
This is an ordered collection of other simple or constructed types. This is an ordered collection of other simple or constructed types.
The SEQUENCE constructed type resembles the C ``struct'' statement. The SEQUENCE constructed type resembles the C ``struct'' statement.
\begin{lyxcode} \begin{asn}
Address~::=~SEQUENCE~\{ Address ::= SEQUENCE {
-- The apartment number may be omitted
~~~~-{}-~The~apartment~number~may~be~omitted apartmentNumber NumericString OPTIONAL,
streetName PrintableString,
~~~~apartmentNumber~~~~~~NumericString~OPTIONAL, cityName PrintableString,
stateName PrintableString,
~~~~streetName~~~~~~~~~~~PrintableString, -- This one may be omitted too
zipNo NumericString OPTIONAL
~~~~cityName~~~~~~~~~~~~~PrintableString, }
\end{asn}
~~~~stateName~~~~~~~~~~~~PrintableString,
~~~~-{}-~This~one~may~be~omitted~too
~~~~zipNo~~~~~~~~~~~~~~~~NumericString~OPTIONAL
\}
\end{lyxcode}
\subsection{The SET type} \subsection{The SET type}
...@@ -1490,68 +1168,50 @@ This one resembles the C ``union'' statement. ...@@ -1490,68 +1168,50 @@ This one resembles the C ``union'' statement.
The following type defines a response code, which may be either an The following type defines a response code, which may be either an
integer code or a boolean ``true''/``false'' code. integer code or a boolean ``true''/``false'' code.
\begin{lyxcode} \begin{asn}
ResponseCode~::=~CHOICE~\{ ResponseCode ::= CHOICE {
intCode INTEGER,
~~~~intCode~~~~INTEGER, boolCode BOOLEAN
}
~~~~boolCode~~~BOOLEAN \end{asn}
\}
\end{lyxcode}
\subsection{The SEQUENCE OF type} \subsection{The SEQUENCE OF type}
This one is the list (array) of simple or constructed types: This one is the list (array) of simple or constructed types:
\begin{lyxcode} \begin{asn}
-{}-~Example~1 -- Example 1
ManyIntegers ::= SEQUENCE OF INTEGER
ManyIntegers~::=~SEQUENCE~OF~INTEGER
~ -- Example 2
ManyRectangles ::= SEQUENCE OF Rectangle
-{}-~Example~2 -- More complex example:
-- an array of structures defined in place.
ManyRectangles~::=~SEQUENCE~OF~Rectangle ManyCircles ::= SEQUENCE OF SEQUENCE {
radius INTEGER
~ }
\end{asn}
-{}-~More~complex~example:
-{}-~an~array~of~structures~defined~in~place.
ManyCircles~::=~SEQUENCE~OF~SEQUENCE~\{
~~~~~~~~~~~~~~~~~~~~~~~~~~~~radius~INTEGER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~\}
\end{lyxcode}
\subsection{The SET OF type} \subsection{The SET OF type}
The SET OF type models the bag of structures. It resembles the SEQUENCE 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 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 in the order which is not necessarily the same as the in-memory order
on the remote machines. on the remote machines.
\begin{lyxcode} \begin{asn}
-{}-~A~set~of~structures~defined~elsewhere -- A set of structures defined elsewhere
SetOfApples :: SET OF Apple
SetOfApples~::~SET~OF~Apple
~
-{}-~Set~of~integers~encoding~the~kind~of~a~fruit
FruitBag~::=~SET~OF~ENUMERATED~\{~apple,~orange~\}\end{lyxcode} -- Set of integers encoding the kind of a fruit
FruitBag ::= SET OF ENUMERATED { apple, orange }
\end{asn}
\begin{thebibliography}{ITU-T/ASN.1} \begin{thebibliography}{ITU-T/ASN.1}
\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c} \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[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi}
\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication \bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication
between heterogeneous systems}~---~Morgan Kaufmann Publishers, 2000. between heterogeneous systems} --- Morgan Kaufmann Publishers, 2000.
\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0. \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 \bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 --- Languages
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment