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

Introduction

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.


History

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. 


Download

III ASN.1 Tool can be download from the CVS repository.


Building III ASN.1 Tool

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 :

Build ASN.1 Tools in MSVC.

  1. If you are using MSVC 6.0, download and install the patch of build-in C++ standard library from
    http://www.dinkumware.com/vc_fixes.htm
    l; in addition, you should replace the definition of auto_ptr in C:\Program Files\Microsoft Visual Studio\VC98\include\memory with the contents  in the file.
  2.  open iiiasn1.dsw with MSVC
  3. If you want to build III H.323 Packet analyzer for Microsoft Network Monitor, install Microsoft Platform SDK.
  4. Start MSVC, Go into the Tools menu, Options item, Directories tab and add  to the Include files path with the BOOST. In addition, add the path of iiiasn1-2_12/Lib to the executable files path. If you want to build III H.323 Packet analyzer for Microsoft Network Monitor, add the path of sed to the executable files path.
  5. Select Build All.
  6. Copy the IIIH323Parser.dll to the subdirectory parsers of your netmon directory when needed. (network monitor is a bundled program of Windows 2000 Server Edition, it also available from Microsoft Server Management Server)

Build Runtime Library in Unix Environment

  1. Unpack iiiasn1.tar.gz.
  2. Specify the path of BOOST Library in the environment variable CPLUS_INCLUDE_PATH as follows:

     $ export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$HOME/boost_1_28_0

  3. configure iiiasn1 and build it.

    $ cd iiiasn1-2_12
    $ mkdir build && cd build
    $ ../configure
    $ make

    If you want to build test programs, use "make check" instead of "make".


Configuration

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

Using III ASN.1 Compiler

The following describes how to compile the ASN.1 files.

ansparser [options] asnfile...

-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). 



How to use the C++ Interfaces

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.

  1. The III ASN.1 runtime library doesn't use C++ exception as its error handling mechanism. Errors can be checked by the return code of (member) function call instead of exception catching.
  2. The only compiler directive supported is "Remove". Furthermore, only typereferences can be removed. 
  3. std::vector is used by SEQUENCE_OF instead std::deque. 
  4. SET_OF is implemented the same way as SEQUENCE_OF.
  5. INTEGER is not a template class, which means no 64 bit or big integer support. 
  6. BIT_STRING interface does not follow the interface of std::vector<bool>.
  7. OCTET_STRING inherits std::vector<char> rather than std::string.
  8. No AbstractType.
  9. isValid() and isStrictlyValid() only checks some basic PER visible constraint. Table constraint is not checked.
  10. The Abstract Value Notation of OpenTypeFieldVal is  not correct. The correct semantic should be "Type ':' Value". However, only "Value" is outputted by asValueNotation() and  use setAsValueNotation() for open type does not work.
  11. CoderEnv does not follow std::set<Module*>  interface, it only provides basic insert/erase functions; on the other hand, find(const char*moduleName) is added.
  12. Information Object and Information Object Set do not have abstract base classes; in addition, no code is generated for ValueSetField in Information Object Class.
  13. For the components in CHOICE, there are no enumerations of the component names because not all the C++ compilers we have tested support this syntax. Use the component_name::id_ instead. Furthermore, the TMF040-1 specification uses component_name::id instead of component_name::id_. However, without the underscore, it may cause name conflicts. As a result, we added an underscore for all the generated CHOICE component id.


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";


Common Problems

Here are some of the common problems you might encounter in MSVC.


Latest News

Aug 31, 2002 - version 2.12
Oct 6, 2001 - version 2.11
July 9, 2001 -Version 2.1
May 4, 2001
May 2, 2001
April 26, 2001  - Version 2.0

Huang-Ming Huang
Network Communication Lab
Institute for Information Industry
Taiwan, Republic of China