III ASN.1 Tool |
Latest update : Aug 31, 2002
I. | Introduction |
II. | History |
III. | Download |
IV. | Building III ASN.1 Tool |
V. | Using III ASN.1 Compiler |
VI. | Configuration |
VII. | How to use the C++ Interfaces |
VIII. | Common Problems |
IX. | Latest News |
The III ASN.1 Tool includes two parts : an
ASN.1 compiler "asnparser" which compiles the Abstract Syntax to c++ files, and a runtime library
which is used to link with the c++ files generated by
asnparser. Based on the works of Open H.323 projects, it is developed
for the needs of H.450 series protocol. Hence, it supports the
information object class defined in X.681. Below are the summary of
its features.
The Institute for Information Industry (III) have been implementing H.323 protocol stack since 1997. The Encoding/Decoding of ASN.1 types in the H.245 and H.225.0 protocols are the fundamental elements of any H.323 implementation. In 1999, we decided to adopt the ASN.1 compiler from Open H.323 project because it provided the source code that gave us more control. However, when we started to develop H.450 series protocols. The lack of information object support in the OpenH.323 compiler made us to choose between the commercial products or develop our own based on the OpenH.323 ASN.1 compiler. After some discussions, we decided to develop our own. After months of development, we are glad to release our works back to the open source community.
Although we began our development from the works of Open H.323
ASN.1 compiler. We did not want the generated code and library to
depend on their Pwlib. Therefore we replaced the containers in the
ASN.1 library by their counterparts from STL. In the mean
time, we also found the existence of ASN.1/C++ standard
interface from the TeleManagement Forum and The Open Group
Ltd. After finishing the development of parsing of Information
Objects, we started to rewrite the library based on the
specification. As the result, the C++ interface is quite different
from that in Pwlib. This also save us from the work of
documenting the interface and usage of the ASN.1 library.
Below are the dependent libraries/tools and
their download sites.
Dependent Libraries/Tools | Download Sites | |
asnparser | ||
flex & bison | http://www.openh323.org/bin/flexbison.zip | |
BOOST library | http://www.boost.org | |
C++ Standard Library | Compiler build-in or http://www.stlport.org | |
Runtime library | BOOST library | http://www.boost.org |
C++ Standard Library | Compiler build-in or http://www.stlport.org | |
MS Netmonitor H.323 parser | Microsoft Platform SDK | http://www.microsoft.com/msdownload/platformsdk/sdkupdate |
sed | http://www.cornerstonemag.com/sed |
Note :
$ export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$HOME/boost_1_28_0
$ cd iiiasn1-2_12
$ mkdir build && cd build
$ ../configure
$ make
If you want to build test programs, use "make check" instead of "make".
The following are the options you may specify by setting the corresponding flags on C++ compiler command-line.
Controlling Macro | Description |
ASN1_HAS_IOSTREAM | This switch is used to enable IOSTREAM and AVN support. However, it requires the ANSI compliant IOSTREAM library. |
ASN1_ALLOCATOR | Enables custom memory manager. |
ASN1_STATIC | Define it when linking against the static ASN.1 library in MSVC. |
BOOST_NO_MT | This switch is used for BOOST pool library to disable multithread support, required only if ASN1_ALLOCATOR is set. |
When building the ASN.1 run time library in UNIX environment, you should run the configure script with the following options.
conifigure options | Description |
--enable-avn, --diable-avn | Enables or disables IOSTREAM and AVN support |
--enable-allocator, --disable-allocator | Enables or disables custom memory manager |
--enable-thread, --disable-thread | Enables or disable multi-threading |
The following describes how to compile the ASN.1 files.
-v | --verbose | Verbose output (multiple times for more verbose) |
-e | --echo | Echo input file |
-d | --debug | Debug output (copious!) |
-c | --c++ | Generate C++ files |
-s[n] | --split[n] | Split output if it has more than n (default 50) classes |
-o | --output | dir Output directory |
For example, if you have 4 files "h2250v4.asn h235v2.asn h245v7.asn h248.asn" to be
compiled,
you enter the following command : (you can find the mentioned
files in asnh323 directory)
asnparser -c h245v7.asn h235v2.asn
h2250v4.asn
Notice that you have to be careful about
the order of the input files if they have dependencies.
In the above case, "h2250v4.asn" imports
modules from "h235v2.asn" and "h245v7.asn",
so they should proceed "h2250v4.asn".
Below are the list of generated files:
h323_messages.h | h323_message.inl | h323_messages.cxx |   |
h235_security_messages.h | h235_security_messages.inl | h235_security_messages.cxx | h235_security_messages_t.cxx |
multimedia_system_constrol.h | multimedia_system_constrol.inl | multimedia_system_constrol.cxx |   |
msc_faxprofile.h | msc_faxprofile.inl | msc_faxprofile.cxx |   |
The output files are named after their module
names rather than their input file names. The *.h files are the
header files which contain the declarations of c++ class; the *.inl
files contain the definitions of inline member functions; the
*.cxx files contain the definitions of non-inline member functions;
and the *_t.cxx contain the template definition of template
classes. However, there're only 3 modules in these files, where do
the msc_faxprofile.* come from? That's because the H323-MESSAGES
imported FaxProfile from MULTIMEDIA-SYSTEM-CONTROL. In order
to minimize the dependency between
different translation unit and reduce compile
time, the declarations and definitions of FaxProfile are extracted
to a separate file.
The extracting types from imported module feature is very useful.
For instance, if you need only the definition of
MULTIMEDIA-SYSTEM-CONTROL.OpenLogicalChannel in some source files
of your application. You can manually define a
module as follows :
LGC DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
IMPORTS OpenLogicalChannel FROM MULTIMEDIA-SYSTEM-CONTROL;
Olc ::= OpenLogicalChannel
END
Save the file, and compile it using asnparser with other modules.
You will get separate files which contains the definitions of
"OpenLogicalChannel".
If you need to remove some types from a module, use the compiler
directive "Remove". The file "lgc.asn" contains an example.
However, you should be aware that if you remove a type that appears
in a type's extension root (that is, the component which
appears before the extension mark "..." of "SEQUENCE", "SET" or
"CHOICE", the PER decoder cannot ignore a message which
contains such component, even though it is marked as OPTIONAL (You
cannot remove non-OPTIONAL component of a "SEQUENCE" or "SET" type
anyway).
The C++ Interfaces is similar to those specified by TeleManagement Forum, you can download
the document TMF040-1
here.
However, not all interfaces in this document are implemented or
strictly followed. Below are some of the differences between our
implementation and TMF040-1.
You can find some practical examples about the usage of the ASN.1
C++ interface in the testsuite project
file. Here is an example of H.4502 CTInitiate.invoke usage
excerpted from h450Test.cpp file.
namespace H4501 = H4501_Supplementary_ServiceAPDU_Structure ;
namespace HGEL = H4501_General_Error_List;
namespace H4502 = Call_Transfer_Operations;
namespace ROA = Remote_Operations_Apdus;
namespace H225 = H323_MESSAGES;
H4501::Module h4501Module;
HGEL::Module hgelModule;
H4502::Module h4502Module(&hgelModule); // The objects in H4501-General-Error-List
// is referenced by Module Call-Transfer-Operations
const H4501::OPERATION& callTransferOperations = h4502Module.get_H323CallTransferOperations();
// Insert all objects in H323CallTranferOperation to OperationSet
h4501Module.get_OperationSet().insert(callTransferOperations.begin(),
callTransferOperations.end());
ASN1::CoderEnv env;
// set encoding rule
env.set_per_Basic_Aligned();
// only OperationSet in H4501_Supplementary_ServiceAPDU_Structure is needed by decoder
env.insert(&h4501Module);
// CTInitiate.invoke
H4501::H4501SupplementaryService pdu1, pdu2;
pdu1.set_serviceApdu().select_rosApdus().resize(1);
ROA::ROS<H4501::InvokeIdSet, H4501::OperationSet, H4501::OperationSet>& ros = pdu1.ref_serviceApdu().ref_rosApdus()[0];
ROA::Invoke<H4501::InvokeIdSet, H4501::OperationSet>& invoke = ros.select_invoke();
invoke.set_invokeId(1);
invoke.set_opcode(h4502Module.get_callTransferInitiate().operationCode);
std::auto_ptr< H4502::CTInitiateArg> arg(new H4502::CTInitiateArg); // use std::auto_ptr to preserve exception safty
arg->set_callIdentity("1111");
arg->set_reroutingNumber().set_destinationAddress().resize(1);
arg->ref_reroutingNumber().ref_destinationAddress()[0].select_h323_ID(L"Huang-Ming Huang");
invoke.set_argument().grab(arg.release());
std::vector<char> buf;
ASN1::encode(pdu1, &env, std::back_inserter(buf));
if (ASN1::decode(buf.begin(), buf.end(), &env, pdu2) &&
pdu1 == pdu2 )
std::cout << "decode success!\n";
else
std::cout << "decode error!\n";
Here are some of the common problems you might encounter in MSVC.
Huang-Ming Huang
Network Communication Lab
Institute for Information Industry
Taiwan, Republic of China