OSS ASN.1 Tools for C#
Example: Building an Application
The following sample application illustrates the use of the OSS ASN.1/C# Compiler to compile a simple ASN.1 module, and the use of the OSS API to invoke the encoder/decoder. By following these steps you can produce and run an executable program that encodes and then decodes a message.
The C# application program in this example is tbcas.cs and the associated ASN.1 source file is bcas.asn .
Step 1: Invoking
the OSS ASN.1 Compiler
The following describes how to compile the abstract syntax defined
in bcas.asn:
INPUT
-- Baseball Card Abstract Syntax (BCAS)
BCAS DEFINITIONS ::= BEGIN
BBCard ::= SEQUENCE {
name IA5String (SIZE (1..60)),
team IA5String (SIZE (1..60)),
age INTEGER (1..100),
position IA5String (SIZE (1..60)),
handedness ENUMERATED
{left-handed(0), right-handed(1), ambidextrous(2)},
batting-average REAL
}
myCard BBCard ::= {
name "Casey",
team "Mudville Nine",
age 32,
position "left field",
handedness ambidextrous,
batting-average {mantissa 250, base 10, exponent -3}
}
END
COMMAND
You enter the following command:
asn1 bcas.asn
or equivalently:
asn1 bcas
The above command informs the OSS ASN.1/C# Compiler that we
want to convert the ASN.1 file bcas.asn to C#. This is implied
by default when no command line option is specified.
The OSS ASN.1/C# Compiler will emit the following files and C#
classes:
| bcas\ |
|
// project class set directory |
| bcas\AssemblyInfo.cs |
|
// administrative information for bcas assembly |
| bcas\bcas |
|
// main namespace directory |
| bcas\bcas\BCAS |
|
// BCAS module namespace directory |
| bcas\bcas\BCAS\BBCard.cs |
|
// BBCard type class |
| bcas\bcas\BCAS\BCAS_values.cs |
|
// BCAS module types values class |
| bcas\bcas\BCAS\NamespaceDoc.cs |
|
// NamespaceDoc class |
| bcas\bcas\BcasFactory.cs |
|
// Factory class |
| bcas\bcas\files |
|
// generated cs files list |
| bcas\bcas\namespace-list |
|
// generated namespaces list |
| bcas\bcas\overview.html |
|
// overview |
OUTPUT
The following class represents the BBCard PDU.
Accessor and mutator methods are generated for each
component of the PDU. Some internal information has
been omitted.
BBCard.cs:
namespace bcas.BCAS
{
using System;
using BcasFactory = bcas.BcasFactory;
using IBerAsn1Writer = OSS.Asn1rt.Writer.Ber.IBerAsn1Writer;
using IBerAsn1Reader = OSS.Asn1rt.Reader.Ber.IBerAsn1Reader;
using Asn1Factory = OSS.Asn1rt.Util.Asn1Factory;
using Asn1RuntimeProperties = OSS.Asn1rt.Util.Asn1RuntimeProperties;
using IEncoder = OSS.Asn1rt.IEncoder;
using IDecoder = OSS.Asn1rt.IDecoder;
using Asn1Exception = OSS.Asn1rt.Asn1Exception;
using Asn1Type = OSS.Asn1rt.Type.Asn1Type;
using OSS.Asn1rt.Util;
/// Runtime class for 'BBCard' type.
///
[Serializable()]
public class BBCard : OSS.Asn1rt.Type.Asn1SequenceType
{
/// Runtime class for 'name' member.
///
[Serializable()]
public class _name : OSS.Asn1rt.Type.Asn1IA5StringType
{
/// The default constructor for _name.
///
public _name() : base()
{
}
/// The constructor for _name.
///
/// The value to initialize this instance.
public _name(string val) : base(val)
{
}
/// Sets the value of this type using an already
/// valued appropriate Asn1Type.
///
public void SetValue(
OSS.Asn1rt.Type.Asn1IA5StringType typeInstance)
{
base.__setTypeValue(typeInstance);
}
/// Returns the lower size for this type.
///
public override long GetLowerSize()
{
return 1L;
}
/// Returns the upper size for this type.
///
public override long GetUpperSize()
{
return 60L;
}
}
/// Runtime class for 'team' member.
///
[Serializable()]
public class _team : OSS.Asn1rt.Type.Asn1IA5StringType
{
/// The default constructor for _team.
///
public _team() : base()
{
}
/// The constructor for _team.
///
/// The value to initialize this instance.
public _team(string val) : base(val)
{
}
/// Sets the value of this type using an already
/// valued appropriate Asn1Type.
///
public void SetValue(
OSS.Asn1rt.Type.Asn1IA5StringType typeInstance)
{
base.__setTypeValue(typeInstance);
}
/// Returns the lower size for this type.
///
public override long GetLowerSize()
{
return 1L;
}
/// Returns the upper size for this type.
///
public override long GetUpperSize()
{
return 60L;
}
}
/// Runtime class for 'age' member.
///
[Serializable()]
public class _age : OSS.Asn1rt.Type.Asn1IntegerType
{
/// The constructor for _age.
///
public _age() : base(0)
{
}
/// The constructor for _age.
///
/// The value to initialize this instance.
public _age(long val) : base(val)
{
}
/// Sets the value of this type using an already valued
/// appropriate Asn1Type.
///
public void SetValue(
OSS.Asn1rt.Type.Asn1IntegerType typeInstance)
{
base.__setTypeValue(typeInstance);
}
/// Returns the lower bound for this type.
///
public override long GetLowerBound()
{
return 1L;
}
/// Returns the upper bound for this type.
///
public override long GetUpperBound()
{
return 100L;
}
}
/// Runtime class for 'position' member.
///
[Serializable()]
public class _position : OSS.Asn1rt.Type.Asn1IA5StringType
{
/// The default constructor for _position.
///
public _position() : base()
{
}
/// The constructor for _position.
///
/// The value to initialize this instance.
public _position(string val) : base(val)
{
}
/// Sets the value of this type using an already
/// valued appropriate Asn1Type.
///
public void SetValue(
OSS.Asn1rt.Type.Asn1IA5StringType typeInstance)
{
base.__setTypeValue(typeInstance);
}
/// Returns the lower size for this type.
///
public override long GetLowerSize()
{
return 1L;
}
/// Returns the upper size for this type.
///
public override long GetUpperSize()
{
return 60L;
}
}
/// Runtime class for 'handedness' member.
///
[Serializable()]
public class _handedness : OSS.Asn1rt.Type.Asn1EnumeratedType
{
/// The constant for 'left-handed' state.
///
public const int left_handed = 0;
/// The constant for 'right-handed' state.
///
public const int right_handed = 1;
/// The constant for 'ambidextrous' state.
///
public const int ambidextrous = 2;
/// The default constructor for _handedness.
///
public _handedness() : base(0)
{
}
/// The constructor for _handedness.
///
/// The value to initialize this instance.
public _handedness(long val) : base(val)
{
}
/// Sets the value of this type using an already
/// valued appropriate Asn1Type.
///
public void SetValue(
OSS.Asn1rt.Type.Asn1EnumeratedType typeInstance)
{
base.__setTypeValue(typeInstance);
}
}
/// Constructor for BBCard.
///
public BBCard() : base()
{
}
/// Sets the value of this type using an already valued
/// appropriate Asn1Type.
///
public void SetValue(BBCard typeInstance)
{
base.__setTypeValue(typeInstance);
}
/// The instance accessor for 'name' giving access to
/// internal values.
///
/// the instance of '_name'.
///
public _name name()
{
__setComponentIsDefined(0);
return (_name)__instantiateTypeByIndex(0);
}
/// Property to set and get value of 'name' member
/// using a string.
/// WARNING : documentation may not link to the right item,
/// trust the above comment!
///
///
public string Name
{
get
{
return name().StringValue;
}
set
{
name().SetValue(value);
}
}
/// The instance accessor for 'team' giving access
/// to internal values.
///
/// the instance of '_team'.
///
public _team team()
{
__setComponentIsDefined(1);
return (_team)__instantiateTypeByIndex(1);
}
/// Property to set and get value of 'team' member using
/// a string.
/// WARNING : documentation may not link to the right item,
/// trust the above comment!
///
///
public string Team
{
get
{
return team().StringValue;
}
set
{
team().SetValue(value);
}
}
/// The instance accessor for 'age' giving access to
/// internal values.
///
/// the instance of '_age'.
///
public _age age()
{
__setComponentIsDefined(2);
return (_age)__instantiateTypeByIndex(2);
}
/// Property to set and get value of 'age' member using a int.
/// WARNING : documentation may not link to the right item,
/// trust the above comment!
///
///
public int Age
{
get
{
return age().IntValue;
}
set
{
age().SetValue(value);
}
}
/// The instance accessor for 'position' giving access
/// to internal values.
///
/// the instance of '_position'.
///
public _position position()
{
__setComponentIsDefined(3);
return (_position)__instantiateTypeByIndex(3);
}
/// Property to set and get value of 'position' member
/// using a string.
/// WARNING : documentation may not link to the right item,
/// trust the above comment!
///
///
public string Position
{
get
{
return position().StringValue;
}
set
{
position().SetValue(value);
}
}
/// The instance accessor for 'handedness' giving access
/// to internal values.
///
/// the instance of '_handedness'.
///
public _handedness handedness()
{
__setComponentIsDefined(4);
return (_handedness)__instantiateTypeByIndex(4);
}
/// Property to set and get value of 'handedness'
/// member using a int.
/// WARNING : documentation may not link to the right item,
/// trust the above comment!
///
///
public int Handedness
{
get
{
return handedness().IntValue;
}
set
{
handedness().SetValue(value);
}
}
/// Tests for equality this BBCard with the specified object.
///
/// the object to test against.
///
/// The result is true if the argument is not null and
/// is an BBCard
/// instance that holds an internal value that is equal to the one
/// held by this instance.
///
public override bool Equals(object anObject)
{
if ( !(anObject is BBCard))
return false;
return base.Equals(anObject);
}
/// Returns a hash code for this type instance.
///
/// a hash code for this type instance.
///
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
The following class provides all initialized values of the BCAS module. Some internal information has been omitted.
BCAS_values.cs:
namespace bcas.BCAS
{
using System;
using Asn1Type = OSS.Asn1rt.Type.Asn1Type;
/// Convenient class holding ASN.1 values defined in BCAS module.
///
///
/// Each ASN.1 value is defined as a static variable, the type of which
/// is the appropriate Asn1Type
/// and the value of which is set with the value from the ASN.1 module.
///
public class BCAS_values
{
/// Runtime variable for myCard.
///
public static bcas.BCAS.BBCard myCard = new bcas.BCAS.BBCard();
static BCAS_values()
{
/* myCard */ myCard.name().SetValue("Casey");
/* myCard */ myCard.team().SetValue("Mudville Nine");
/* myCard */ myCard.age().SetValue(32);
/* myCard */ myCard.position().SetValue("left field");
/* myCard */ myCard.handedness().SetValue(
bcas.BCAS.BBCard._handedness.ambidextrous);
}
}
}
The following class provides a C# class holding information for decoder and encoder creation. Some internal information has been omitted.
BcasFactory.cs:
namespace bcas
{
using System;
using Asn1Factory = OSS.Asn1rt.Util.Asn1Factory;
using Asn1RuntimeProperties = OSS.Asn1rt.Util.Asn1RuntimeProperties;
using IEncoder = OSS.Asn1rt.IEncoder;
using IDecoder = OSS.Asn1rt.IDecoder;
using Asn1Exception = OSS.Asn1rt.Asn1Exception;
/// Specific class for runtime information for bcas Asn1CsAPI.
/// This class holds information for decoder and encoder creation.
///
public class BcasFactory
{
// encoding rules
private static string _encodingRules = "BER";
// pre-encoding / post-decoding properties for direct access
private static bool _isPreEncodingForConstructedOf = false;
private static bool _isPostDecodingForConstructedOf = false;
// properties static initialization
static BcasFactory()
{
_encoderProperties["validating"] = "true";
_decoderProperties["resolvingContent"] = "true";
_decoderProperties["validating"] = "true";
}
/// returns the encoding rules family to be used with
/// this generated API.
///
/// Trying to use encoding rules that are not part
/// of this family may
/// result in encoding/decoding problems. The encoding rules
/// family : "Basic" (BER/DER),
/// "Packed" (PER), "XML" (XER) or "*" (standing for all encoding
/// rules family).
///
/// This API is built for "Basic" encoding rules family.
///
///
public static string GetGeneratedAPIEncodingRulesFamily()
{
return "Basic";
}
/// sets the encoding rules. Default value is "BER".
///
/// Thrown if the given
/// encodingRules are not part of the encoding
/// rules family defined for this generated API or if they are not
/// supported.
///
/// "BER", "DER", "AlignedBasicPER",
/// "UnalignedBasicPER", "AlignedCanonicalPER",
/// "UnalignedCanonicalPER",
/// "BasicXER", "CanonicalXER" (ignoring case)
///
public static void SetEncodingRules(string encodingRules)
{
Asn1RuntimeProperties.checkEncodingRulesFamily(
"Basic", encodingRules);
_encodingRules = encodingRules;
}
/// sets an encoder property.
///
/// Thrown if the given
/// property is not supported
/// The property name.
/// The value for property.
public static void SetEncoderProperty(string property, string val)
{
Asn1RuntimeProperties.checkEncoderProperty(property,
_encodingRules);
_encoderProperties[property] = val;
}
/// gets an encoder property as a string.
///
/// Thrown if the given
/// property is not supported
/// The property name.
/// The encoder property value as a string.
///
public static string GetEncoderProperty(string property)
{
Asn1RuntimeProperties.checkEncoderProperty(property,
_encodingRules);
return (string)_encoderProperties[property];
}
/// sets a decoder property as a string.
///
/// Thrown if the given
/// property is not supported
/// The property name.
/// The value for property.
public static void SetDecoderProperty(string property, string val)
{
Asn1RuntimeProperties.checkDecoderProperty(property,
_encodingRules);
_decoderProperties[property] = val;
}
/// gets a decoder property as a string.
///
/// Thrown if the
/// given property is not supported
/// The property name.
/// the decoder property value as a string.
///
public static string GetDecoderProperty(string property)
{
Asn1RuntimeProperties.checkDecoderProperty(property,
_encodingRules);
return (string)_decoderProperties[property];
}
/// sets a generic type property.
///
/// Thrown if the given
/// property is not supported
/// The property name.
/// The value for property.
public static void SetTypeProperty(string property, string val)
{
Asn1RuntimeProperties.checkTypeProperty(property,
_encodingRules);
_typeProperties[property] = val;
// for direct access
if ("postDecodingForConstructedOf".Equals(property))
_isPostDecodingForConstructedOf = true;
if ("preEncodingForConstructedOf".Equals(property))
_isPreEncodingForConstructedOf = true;
}
/// gets a generic type property.
///
/// Thrown if the given
/// property is not supported
/// The property name.
/// the type property value as a string.
///
public static string GetTypeProperty(string property)
{
Asn1RuntimeProperties.checkTypeProperty(property,
_encodingRules);
return (string)_typeProperties[property];
}
/// Creates an instance of an appropriate decoder.
/// Initial specified decoder is a BER decoder.
///
/// The inital specified properties are :
///
/// - "resolvingContent" with value "true"
///
///
/// - "validating" with value "true"
///
///
/// a IDecoder interface.
///
public static IDecoder CreateDecoder()
{
IDecoder decoder = Asn1Factory.createDecoder(_encodingRules);
decoder.SetProperties(_decoderProperties);
return decoder;
}
/// Creates an instance of an appropriate encoder.
/// Initial specified encoder is a BER encoder.
///
/// The inital specified properties are :
///
/// - "validating" with value "true"
///
///
/// a IEncoder interface.
///
public static IEncoder CreateEncoder()
{
IEncoder encoder = Asn1Factory.createEncoder(_encodingRules);
encoder.SetProperties(_encoderProperties);
return encoder;
}
/// Says whether pre-encoding is to be used for SEQUENCE OF /
/// SET OF types.
///
/// True if pre-encoding is used.
public static bool IsPreEncodingForConstructedOf()
{
return _isPreEncodingForConstructedOf;
}
/// Says whether post-decoding is to be used for SEQUENCE OF /
/// SET OF types.
///
/// True if post-decoding is used.
public static bool IsPostDecodingForConstructedOf()
{
return _isPostDecodingForConstructedOf;
}
}
}
Step 2: Compiling and linking the sample application
The following is a copy of the C# program in tbcas.cs.
This program validates the myCard value of the BBCard PDU described
by the bcas.asn abstract syntax, encodes the PDU (using BER),
decodes it, and compares the unencoded and decoded PDUs. Note that
the bcas C# classes (generated by the compiler) have been used by
the application program. (The function calls to the Encoder/Decoder
methods are in bold font.)
INPUT
C#File, tbcas.cs:
using bcas;
using bcas.BCAS;
/* Universal classes from the OSS runtime library */
using OSS.Asn1rt;
using OSS.Asn1rt.Util;
/* C# system classes */
using System;
using System.IO;
public class Tbcas {
public static int Main(string[] args)
{
IEncoder encoder = null;
IDecoder decoder = null;
string encodingRule = null;
BBCard decoded = new BBCard();
/*
* Get encoding rules which were specified on the ASN.1 compiler
* command line.
*/
if (BcasFactory.GetGeneratedAPIEncodingRulesFamily() == "Basic")
encodingRule = "BER";
else if (BcasFactory.GetGeneratedAPIEncodingRulesFamily() == "XML")
encodingRule = "XER";
else
encodingRule = "PER";
/*
* Create instance of the encoder
*/
try {
encoder = BcasFactory.CreateEncoder();
}
catch (Asn1Exception ex) {
Console.WriteLine(encodingRule +
"-encoder object failed to create: " + ex.Message);
return 1;
}
/*
* Print the input to the encoder.
*/
Console.WriteLine("Printing the unencoded PDU...\n");
Console.WriteLine(BCAS_values.myCard);
/*
* Validate the input PDU value.
*/
Console.WriteLine("\nValidating the unencoded PDU...");
try {
BCAS_values.myCard.Validate();
Console.WriteLine("Validated successfully.");
}
catch (Asn1Exception ex) {
/*
* An error occurred, print the error message.
*/
Console.WriteLine("Failed to validate: " + ex.Message);
return 1;
}
/*
* Encode the PDU. Return non-zero for failure.
*/
try {
Console.WriteLine("\n{0}-encoding the PDU...", encodingRule);
encoder.Encode(BCAS_values.myCard);
Console.WriteLine("PDU encoded successfully.");
}
catch (Asn1Exception ex) {
/*
* An error occurred, print the error message.
*/
Console.WriteLine("Failed to encode: " + ex.Message);
return 1;
}
/*
* Print the encoder's output.
*/
Console.WriteLine("\nPrinting the {0}-encoded PDU...\n",
encodingRule);
Console.WriteLine(ByteArray.ByteArrayToHexString(encoder.Data,
" ", 20));
/*
* Create instance of the decoder
*/
try {
decoder = BcasFactory.CreateDecoder();
}
catch (Asn1Exception ex) {
Console.WriteLine(encodingRule +
"-decoder object failed to create: " + ex.Message);
return 1;
}
/*
* Decode the encoded PDU whose encoding is in "encodedData".
*/
try {
Console.WriteLine("\n{0}-decoding the PDU...", encodingRule);
decoder.Decode(encoder.Data, decoded);
Console.WriteLine("Decoded successfully.");
}
catch (Asn1Exception ex) {
/*
* An error occurred, print the error message.
*/
Console.WriteLine("Failed to decode: " + ex.Message);
return 1;
}
/*
* Print the decoder's output.
*/
Console.WriteLine("\nPrinting the decoded PDU...\n\n" + decoded);
/*
* Compare the decoded PDU and unencoded one
*/
try {
Console.WriteLine
("\nComparing the unencoded and decoded PDUs...");
if (BCAS_values.myCard.Equals(decoded))
Console.WriteLine("Compared successfully.");
}
catch (Asn1Exception ex) {
/*
* An error occurred, print the error message.
*/
Console.WriteLine("Failed to compare: " + ex.Message);
return 1;
}
return 0;
}
}
COMMAND
Next, generate a public-private key pair for signing the
generated files as follows:
E>
sn -q -k bcas.snk
OUTPUT
The above command generates bcas.snk key file.
COMMAND
Next, build the sample application program as follows:
csc -out:tbcas.exe tbcas.cs -recurse:bcas\*.cs -r:"%OSS_CSHARP_HOME%"\bin\asn1rt.dll
>
OUTPUT
The above command C#-compiles the compiler generated and tbcas.cs .
C# files and builds the resulting application tbcas.exe using the
OSS runtime asn1rt.dll.
Step 3: Invoking the encoder/decoder
INPUT
(None: For this example, the encoder input is generated by the ASN.1
compiler as a C# class instance initialized from the ASN.1 value
notation.)
COMMAND
tbcas
This command simply runs tbcas.
OUTPUT
Printing the unencoded PDU...
BBCard SEQUENCE
{
name IA5String = Casey
team IA5String = Mudville Nine
age INTEGER = 32
position IA5String = left field
handedness ENUMERATED = ambidextrous(2)
}
Validating the unencoded PDU...
Validated successfully.
BER-encoding the PDU...
PDU encoded successfully.
Printing the BER-encoded PDU...
30 28 16 05 43 61 73 65 79 16 0d 4d 75 64 76 69 6c 6c 65 20
4e 69 6e 65 02 01 20 16 0a 6c 65 66 74 20 66 69 65 6c 64 0a
01 02
BER-decoding the PDU...
Decoded successfully.
Printing the decoded PDU...
BBCard SEQUENCE
{
name IA5String = Casey
team IA5String = Mudville Nine
age INTEGER = 32
position IA5String = left field
handedness ENUMERATED = ambidextrous(2)
}
Comparing the unencoded and decoded PDUs...
Compared successfully.
.:. Top
Copyright © 2008 OSS Nokalva, Inc. All Rights Reserved.