ASN1 基础知识3

基础知识

&  注释:

本章的内容主要翻译自《ASN.1 Communication between Heterogeneous Systems》。

2.8  基本类型

Table 2-4 基本类型汇总表

类型

UNIVERSAL Tag

取值

BOOLEAN

1

TRUEFALSE

NULL

5

NULL

INTEGER

2

整数

ENUMERATED

10

类型定义中列出的成员

REAL

9

实数

BIT STRING

3

比特串

OCTET STRING

4

八位组串,字节流

OBJECT IDENTIFIER

6

 

RELATIVE-OID

13

 

 

2.8.2  BOOLEAN类型

是两个值的集合:TRUEFALSE。如下:

                RoundResult ::= BOOLEAN

                ok RoundResult ::= TRUE

                ko RoundResult ::= FALSE

UNIVERSALTag值为1

2.8.3  NULL类型

空类型,只有一个值NULL。作为一种结果,空类型是传输报告和响应的典型情况。

Ack ::= NULL

它也在时间信息中使用,表示传送时间没有赋值,如:

                Clock ::= CHOICE

                {

                              time                      UTCTime,

                              out-of-order            NULL

                }

当时钟电池没有电时,值为:

                battery-down Clock ::= out-of-order:NULL

NULL也可以用在表示链表结束的空接点,如:

Figure 2-3 链表结构示意图

LinkedList ::= SEQUENCE

{

              data                      Data,

              next        CHOICE

              {

                     linked-list              LinkedList,

                     end                NULL

              }

}

当然,可以使用SEQUENCE OF来达到类似目的:

                LinkedList ::= SEQUENCE OF Data

 

UNIVERSALTag值为5

2.8.4  INTEGER类型

整数,可以是正整数也可以是负整数,取值范围在协议中没有界定。所以必须由编解码器提前确定好整数的范围,分配必要的内存空间来处理。可以通过在描述中增加一个值声明来判断:

                Interval ::= INTEGER(123456789..123456790)

在使用PER编解码规则时,会按照本地整数范围进行截断;相比之下BER编码规则中因为有明确的长度,所以不会出现截断的情况。

虽然在数学可以有“-0”,但在ASN.1描述中不能这样描述。

 

一些情况下,比如为了定义错误码,需要给一些数值特定的名字,可以使协议更易于理解,也改善了应用层和编解码器之间的接口。这些信息当然可以用注释给出,但是ASN.1编译器不会使用这些信息,在词法分析开始,这些就都被忽略了。ASN.1INTEGER类型提供了一种特殊语法来解决这个问题。以软盘驱动器的错误码为例:

                ErrorCode ::= INTEGER

{

disk-full(1),

no-disk(-1),

disk-not-formatted(2)

                }

stupid-error ErrorCode ::= disk-full

这些名字只能被用于定义ErrorCode类型的值,不能用于其它类型值的定义。

命名的整数不需要排序。对于没有命名的整数,还是可以使用的;已经命名的整数,也可以直接使用数字:

                ok ErrorCode ::= 0

                stupid-error ErrorCode ::= 1

注意:这种命名使用的使花括号,不是约束(使用圆括号)。

 

这种方式和ENUMERATED类型相比,区别在于:

l           必须指定数值,不能像ENUMERATED中那样缺省;

l           不能使用扩展标记“”。当然这实际上不是个问题,和ENUMERATED不同,没有命名的整数还可以使用。

此外,这种方式如果使用不当,会造成混乱,要特别小心。如:

alpha INTEGER ::= 1

Type1 ::= INTEGER { alpha(2) }

Type2 ::= INTEGER { alpha(3), beta(alpha) }

gamma Type2 ::= beta

delta Type2 ::= alpha

实际上gamma的值为1delta的值为3

 

注意:在ASN.1中,INTEGERREAL类型之间没有兼容性,就是说不能将INTEGER的值赋给一个REAL类型的值。同样的,INTEGERENUMERATED类型间也不存在兼容性。

 

UNIVERSALTag值为2

2.8.5  ENUMERATED类型

ENUMERATED类型与INTEGER类型相比, 区别在于:

l           取值是受限制的,没有列出的数值不能使用;

l           数值是不能操作的,只能用于编码;

l           不用明确指定数值,ASN.1可以自动计算相应的数值(从0开始);

l           可以使用扩展,保证和新版本的编码兼容;

l           是数值关联(显式或者隐式)到标识符,而INTEGER中则是标识符显式关联到数值。

 

ABRT-diagnostic ::= ENUMERATED

{

no-reason-given(1),

protocol-error(2),

authentication-mechanism-name-not-recognized(3),

authentication-mechanism-name-required(4),

authentication-failure(5),

authentication-required(6),

...

}

不能直接使用数字,如:

                abert-diagnostic ABERT-diagnostic ::= 4   -- 错误的

在使用扩展标记“...”时,需要额外注意的是,在扩展标记后的成员,其数值必须是升序排列的。

A ::= ENUMERATED {a, b, ..., c(0)}

-- 错误: a c 都是0

B ::= ENUMERATED {a, b, ..., c, d(2)}

-- 错误: c d 都是2

C ::= ENUMERATED {a, b(3), ..., c(1)}

-- Correct: c = 1

CHOICESEQUENCESET不同在使用扩展标记...增加新成员时ENUMERATED类型中不需要使用版本标识[[ ]]”,并且只能有一个扩展标记。

 

注意事项:

l           按照ASN.1的语义模型,任意两个ENUMERATED类型都是不兼容的。

l           当一个ENUMERATED类型被IMPORTS到另一个模块中,则其列表中的标识符也被导入,但只能用于该类型值的赋值。

l           基本列表(在扩展标识符之前)中的值不需要连续,也不需要排序。

l           扩展列表(在扩展标识符之后)中的值不需要连续,但需要升序排列。

l           扩展列表中的值不能和基本列表中的值重复,不论该值是明确指定的,还是缺省计算的。

l           扩展列表中成员的值必须该列表中前一个成员的值大。

l           表示成员值的必须是数字,不能是标识符。

 

UNIVERSALTag值为10

2.8.6  REAL类型

从语义上等效于:

SEQUENCE

{

mantissa            INTEGER (ALL EXCEPT 0),

base                  INTEGER (2|10),

exponent            INTEGER

}

但是REAL类型有自己特定的UNIVERSAL Tag值。

 

pi REAL ::= {314159, 10, -5}

e REAL ::= {271828128459045235360287, 10, -23}

zero REAL ::= 0

注意:实数0不能用三元组的方式给出。

我们用PLUS-INFINITYMINUS-INFINITY分别表示“正无穷大”和“负无穷大”,这两个也不能用三元组表示。

此外,我们也要主要到ASN.1中的实数只能以2或者10为底(base的约束)。

 

UNIVERSALTag值为9

2.8.7  BIT STRING类型

按照ASN.1的定义,BIT STRING可以长度为0,也可以非常长。它可以是原始的比特流形式,也可以是布尔向量模型。

比特流形式:

                pi-decimals BIT STRING ::=

'00100100001111110110101010001000100001

01101000110000100011010011000100110001

100110001010001011100000001101110000'B

pi-decimals BIT STRING ::=

'243F6A8885A308D313198A2E0370'H

注意:这种形式下,要考虑大小端的影响。

 

布尔向量模型:

Figure 2-4 权限示意图

Figure 2-4所示的权限示意图,当使用不同的比特表示权限时,在ASN.1中可以这样描述:

Rights ::= BIT STRING

{

user-read(0),

user-write(1),

group-read(2),

group-write(3),

other-read(4),

other-write(5)

}

group1 Rights ::= { group-read, group-write }

当然,也可以之间用码字来赋值:

                group2 Rights ::= '0011'B

group2 Rights ::= '3'H

group3 Rights ::= '001100'B

weird-rights Rights ::= '0000001'B

注意

l           命名的比特列表不影响值的声明;

l           命名的比特列表没有限制,位置也不必连续,也不对类型的长度产生影响。如weird-rights

l           以码字赋值时,起始的比特是必须的(最左面的比特),用来定位。后续的0比特无意义。group2group3 group1的结果是一样的。

需要对BIT STRING长度进行约束时,可以使用SIZE,如:

                RIGHTS ::= BIT STRING (SIZE(6))

 

和命名INTEGER类型相似,在命名BIT STRING中也不能使用扩展标记“”。

 

OCTET STRING类型一样,可以使用CONTAINING ENCODED BY来约束。

 

UNIVERSALTag值为3

2.8.8  OCTET STRING类型

BIT STRING类型类似,但是单位不是比特而是8个比特的八位组。

 

UNIVERSALTag值为4

2.8.9  OBJECT IDENTIFIER类型

OBJECT IDENTIFIER类型是对象的唯一标识的集合,这里对象可以是(但不限于):

l           一种抽象语法,一定是在表示层无歧义的注册过(ISO8822);

l           一种传输语法,一定是注册过,在表示层可以被抽象语法使用(ISO8823-1);

l           一种应用实体(ISO7498-3);

l           一个ASN.1模块;

l           一种ROSE操作(ISO9072-2);

l           等等。

我们用注册树来表征所有注册的标识:

Figure 2-5 注册树

OBJECT IDENTIFIER类型就是该注册树所有叶子的路径集合。一个OBJECT IDENTIFIER类型的值可以是:

internet-id OBJECT IDENTIFIER ::=

{ iso(1) identified-organization(3) dod(6) internet(1) }

francetelecom-id OBJECT IDENTIFIER ::=

{ iso member-body f(250) type-org(1) ft(16) }

ber-id OBJECT IDENTIFIER ::= { 2 1 1 }

即可以用各叶子的名字,可以用编号,也可以混合使用。

此外,对于多个有相同根名字的值,可以如下定义:

ID ::= OBJECT IDENTIFIER

id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) }

id-bp ID ::= { id-edims 11 }

id-bp-edifact-ISO646 ID ::= { id-bp 1 }

id-bp-edifact-T61 ID ::= { id-bp 2 }

id-bp-edifact-octet ID ::= { id-bp 3 }

id-bp-ansiX12-ISO646 ID ::= { id-bp 4 }

id-bp-ansiX12-T61 ID ::= { id-bp 5 }

id-bp-ansiX12-ebcdic ID ::= { id-bp 6 }

 

每当一个对象注册到注册树中时,ISO标准ISO9834-1都会对它增加一个相应的文本描述,称之为ObjectDescriptor。如对上面ber-idObjectDescriptor为:

                ber-descriptor ObjectDescriptor ::=

"Basic Encoding of a single ASN.1 type"

2.8.10  RELATIVE-OID类型

前面OBJECT IDENTIFIER类型可以看作是对象在注册树中的绝对路径,而RELATIVE-OID类型则是相对路径。其参考基准节点可以是一个OBJECT IDENTIFIER类型的值(动态的),或者是收发双方默认的(静态的)。

RELATIVE-OID可以使用CONSTRAINED BY进行约束。

2.9  字符串类型

Known-multiple Character String Type指字符串中每个字符编码所占字节数都一样。

Table 2-5 字符串类型一览表

类型名字

Tag

字符表

ESC

Multi

NumericString

18

字符“0”到“9”,空格

 

PrintableString

19

字符“A Z”,“a”到“z”,“0”到“9”,空格,单引号(),圆括号(( )),加号(+),逗号(,),减号(-),点(.),斜杠(/),冒号(:),等号(=),问号(?

 

VisibleString

ISO646String

26

[ISOReg] entry no. 6; space

 

IA5String

22

[ISOReg] entry no. 1 & 6;

space, delete

 

TeletexString

T61String

20

[ISOReg] entry no. 6, 87, 102,

103, 106, 107, 126, 144, 150,

153, 156, 164, 165, 168; space, delete

 

VideotexString

21

[ISOReg] entry no. 1, 13, 72,

73, 87, 89, 102, 108, 126, 128,

129, 144, 150, 153, 164, 165,

168; space, delete

 

GraphicString

25

all the graphical sets (called

`G') of [ISOReg]; space

 

GeneralString

27

all the graphical sets (called

`G') and all the control characters

(called `C') of [ISOReg];

space, delete

 

UniversalString

28

[ISO10646-1]

 

BMPString

30

the basic multilingual plane

[ISO10646-1] (65,536 cells)

 

UTF8String

12

[ISO10646-1]

 

 

 

2.10  组合类型与扩展原则

2.10.1  Tag

传输数据,一定要避免接收方收到数据解码时出现不清楚的地方。具体说,接收方要明确知道每个收到数据的类型,我们就要对各类型进行系统性的编号。在ASN.1的第一种编解码规则BERBasic Encode Rule)中,对数据编码使用的是三元组规则:<type, length, value>或者称为TLV,这里type或者称为tag,它是类型的标识符,在ASN.1中每种类型的tag是唯一的。length是编码数据value的字节数。value是实际数据的编码。

I. TagsTagging Classes

分配给每个类型的tag实际上是一个值对:<tagging class, number>。有四种tagging classUNIVERSALcontext-specificAPPLICATIONPRIVATE。这种方式实际提供了不同的Tag空间。在一个上下文中,如果Tagging Class不同,则相同number的两个Tag也是不同的。

l           UNIVERSALTagASN.1标准定义的,在描述中不能修改。

Table 2-6 ASN.1中定义的UNIVERSALTag

Tag

类型

0

BER保留

1

BOOLEAN

2

INTEGER

3

BIT STRING

4

OCTET STRING

5

NULL

6

OBJECT IDENTIFIER

7

ObjectDescripion

8

EXTERNAL, INSTANCE OF

9

REAL

10

ENUMERATED

11

EMBEDDED PDV

12

UFT8String

13

RELATIVE-OID

14

保留

15

保留

16

SEQUENCE, SEQUENCE OF

17

SET, SET OF

18

NumericString

19

PrintableString

20

TeletexString, T61String

21

VideotexString

22

IA5String

23

UTCTime

24

GeneralizedTime

25

GraphicString

26

VisibleString, ISO646String

27

GeneralString

28

UniversalString

29

CHARACTER STRING

30

BMPString

31

保留

 

l           context-specificTag是对SEQUENCESETCHOICE及其成员使用的,可以在描述中自己定义,只要不产生歧义,相同数值可以在不同结构中反复使用。如:

A-possible-type ::= SET

{

integer                 [0] CHOICE

{

a           [0] INTEGER,

b           [1] INTEGER

},

boolean [1] CHOICE

{

a            [0] BOOLEAN,

b            [1] BOOLEAN

}

                }

l           APPLICATIONTag是为了“to define a data type that finds wide, scattered use within a particular application and that must be distinguishable (by means of its [ abstract syntax]) from all other data types used in the application”。在APPLICATION作用域内,其Tag也是唯一的。如:

Order-number ::= [APPLICATION 0] NumericString (SIZE (12))

但是因为使用IMPORTS等方式下,很难保证唯一性,所以这种Tag类已经不推荐使用了。

 

l           PRIVATETag是为了“use a private-use Tagged [ type] to define a data type that finds use within a particular organization or country and that must be distinguishable (by means of its [ abstract syntax]) from all other data types used by that organization or country”。如一个公司可能这样扩展传输层PDU

RejectTPDU ::= SET

{

destRef                    [0] Reference,

yr-tu-nr                     [1] TPDUnumber,

credit                       [2] Credit,

extended                  [PRIVATE 0] BOOLEAN DEFAULT FALSE

}

PRIVATE类的Tag现在也不推荐使用了。

II. Tagging Mode

使用context-specificTag,如下:

Afters ::= CHOICE

{

cheese [0] IA5String,

dessert [1] IA5String

}

当没有其它更多描述信息,并且使用BER编码时,会将UNIVERSAL类和context-specific类的Tag同时编码出来。这种方式成为EXPLICIT模式。在下面这种情况:

T1 ::= [0] INTEGER

变更为:

T2 ::= [0] CHOICE

{

integer                            INTEGER,

real                          REAL

}

CHOICE取值为integer时不需要变更。

 

与之相对应的时IMPLICIT模式,它将只编码context-specific类的Tag直到另一个UNIVERSALTag出现。如

T ::= [1] IMPLICIT T1

T1 ::= [5] IMPLICIT T2

T2 ::= [APPLICATION 0] IMPLICIT INTEGER

对于类型T,只有Tag 1被编码。

这种模式需要接收方能保证清楚知道抽象语法,能正确解码。

III. Global Tagging Mode

可以在模块定义时,声明模块全局Tag模式。可以是EXPLICIT TAGSIMPLICIT TAGSAUTOMATIC TAGS

l           IMPLICIT TAGS,模块内所有SEQUENCESETCHOICE的成员都是IMPLICIT模式(除非它是CHOICE类型、开放类型或者一个参数类型)。但不影响IMPORTS的内容。

l           AUTOMATIC TAGS,模块内所有SEQUENCESETCHOICE类型ASN.1编译器会自动从0开始,步长为1进行自动编码。而其中的成员则用IMPLICIT模式,除非它是CHOICE类型、开放类型或者一个参数类型。

下面两个定义是等效的:

M DEFINITIONS AUTOMATIC TAGS ::=

BEGIN

T ::= SEQUENCE

{

a                INTEGER,

b                CHOICE

{

i          INTEGER,

n         NULL

},

c                REAL

}

END

 

M DEFINITIONS ::=

BEGIN

T ::= SEQUENCE

{

a                [0] IMPLICIT INTEGER,

b                [1] EXPLICIT CHOICE

{

i          [0] IMPLICIT INTEGER,

n         [1] IMPLICIT NULL

},

c                [2] IMPLICIT REAL

}

END

 

如果使用全局AUTOMATIC TAGS模式时,在描述中给一个类型指定了一个Tag,那么对这个类似的AUTOMATIC TAGS就关闭。如果一个SEQUENCE或者SET类型包含COMPONENTS OF条目,而且这个条目在自动编号前展开;但自动标号又要求在展开前进行,ASN.1编译器要自己检查这种冲突。

 

对新的协议现在都推荐使用AUTOMATIC TAGS

2.10.2  SEQUENCE

SEQUENCE是最常用的ASN.1类型之一,它可以嵌套使用,还可以使用OPTIONALDEFAULTCOMPONENTS OF等对成员进行修饰。

一个常见的SEQUENCE声明如:

Description ::= SEQUENCE

{

surname     IA5String,

first-name   IA5String,

age            INTEGER

}

该类型的一个值为:

johnny Description ::=

{

surname            "Smith",

first-name          "John",

age                   40

}

 

使用OPTIONALDEFAULT时,SEQUENCE类型应该能被明确解码,不存在模棱两可的地方。如下这个类型就有问题

T ::= SEQUENCE

{

x                       INTEGER,

y                       INTEGER OPTIONAL,

z                       INTEGER DEFAULT 0,

t                       INTEGER

}

在使用BER编码规则时,对于值t1 T::={x 1, y 2, t 3}而言,接收方收到的码流如下:

Figure 2-6 OPTIONAL引起的歧义

那么在解码过程中,V2的值无法确定是成员y还是成员z。这种情况下,该类型的定义应该在Tag上做一些补充:

T ::= SEQUENCE

{

x                       INTEGER, -- [UNIVERSAL 2]

y                       [0] INTEGER OPTIONAL,

z                       [1] INTEGER DEFAULT 0,

t                       INTEGER -- [UNIVERSAL 2]

}

注意:对于接收方,没有收到声明DEFAULT的成员和收到DEFAULT的值是等价的。

 

在类型定义中,可以使用COMPONENTS OF将另一个类型的成员插入到当前类型中:

Registration ::= SEQUENCE

{

COMPONENTS OF Description,

marital-status     ENUMERATED

{single, married, divorced,widowed}

}

COMPONENTS的效果使得上面的定义等效于:

 

Registration ::= SEQUENCE

{

surname            IA5String,

first-name          IA5String,

age                   INTEGER,

marital-status     ENUMERATED

{single, married, divorced, widowed}

}

不是

Registration ::= SEQUENCE

{

description         Description,

marital-status     ENUMERATED

{single, married, divorced,widowed}

}

使用COMPONENTS OF的好处在于,如上例中,Description更新升级时,Registration的内容不需要手工修改。

2.10.3  SET

SEQUENCE相比,SET的成员是没有顺序的。同样可以使用OPTIONALDEFAULTCOMPONENTS OF

2.10.4  SEQUENCE OF

SEQUENCE OF相当于某些语言中的动态数组或者列表:所有成员都是一个类型,数目不定。如:

PariTierce DEFINITIONS ::=

BEGIN

SteepleChase ::= SEQUENCE OF INTEGER

         END

相应的典型值为:

winningCombination SteepleChase ::= {5, 2, 12}

no-one-arrived SteepleChase ::= { }

ASN.1提供一种元标记来编写和描述项目的注释、文档,以“@”开头,后接模块名称、类型名字成员序号或者“*”(表示全部),如:

                -- @PariTierce.SteepleChase.* must be distinct

-- @PariTierce.SteepleChase.0 = 5 (horse no. 5 always wins!)

如果是在模块内,则“@”和模块名都可以省略,如:

                -- SteepleChase.* must be distinct

-- SteepleChase.0 = 5 (horse no. 5 always wins!)

2.10.5  SET OF

SEQUENCE OF相比,SET OF的成员是顺序的,其它类似。

2.10.6  CHOICE

CHOICE类型表示一种选择,类似UNION。该提供两个信息:被选择的选项,相应的值。也就是说对于类型:

Afters ::= CHOICE

{

cheese              [0] IA5String,

dessert             [1] IA5String

}

它的一个值而言:

mine Afters ::= dessert:"profiteroles"

(注意:表示方法先是选择的选项dessert,而后是“:”,最后是值

没有必要先定义一个枚举类型来表征具体的选项。

 

SEQUENCESET类型不同,CHOICE没有缺省的UNIVERSAL Tag值,因为它是一些类型的集合,其中被选择项目的Tag会被作为CHOICE相关Tag。在和SEQUENCESET一起使用时,要注意使用AUTOMATIC TAGS或者context-specific Tags。如下面,类型U的定义有问题Tag 0 1都重复了两次):

T ::= CHOICE { a [0] INTEGER,b [1] NULL }

U ::= SET

{

x            [0] REAL,

y            T,

z            CHOICE

{

c     [1] BIT STRING,

d     [2] OCTET STRING

}

}

U的定义应该修改为类似下面:

U ::= SET

{

x            [0] REAL,

y            [1] T,

z            [2] CHOICE

{

c     [1] BIT STRING,

d     [2] OCTET STRING

}

}

 

在协议中,CHOICE类型经常出现。应用层间交换的PDU,通常都是CHOICE结构的,如ROSERemote Operation Service Element ISO13712-1)的简化:

ROS ::= CHOICE

{

invoke                             [1] Invoke,

returnResult              [2] ReturnResult,

returnError                [3] ReturnError,

reject                       [4] Reject

}

 

某些时候,我们想重用CHOICE类型中的某些选项的类型,此时需要使用在ASN.1中被称为选择符(Selection)的 符号“<”。如:

Element ::= CHOICE

{

atomic-no                 INTEGER (1..103),

symbol                     PrintableString

}

 

MendeleievTable ::= SEQUENCE SIZE (103) OF symbol < Element

einsteinium symbol < Element ::= "Es"

2.10.7  类型扩展

可以在定义中插入扩展标记“”来定义一个类型是可扩展的。在ASN.1中可扩展的类型有ENUMERATEDSEQUENCESETCHOICEINTEGERBIT STRING类型,基于前面的介绍,是隐含可扩展类型(对于类似ENUMERATED方式,未命名的数字和比特位置都可以使用)。如:

State ::= ENUMERATED {on, off, out-of-order, ...}

Description ::= SEQUENCE

{

surname                   IA5String,

first-name                 IA5String,

age                          INTEGER,

...

}

Dimensions ::= SET

{

x                                    INTEGER,

y                                    INTEGER,

...

}

Afters ::= CHOICE

{

cheese                     IA5String,

dessert                    IA5String,

...

}

按照标准,扩展标记可以有两个,他们将类型定义分割为两个扩展部分:

T ::= SEQUENCE

{

a                A,

b                B,

...,

...,

c                C

}

 

在扩展时,新增的项目可能有多个,并且其中可能还带有OPTIONALDEFAULT。这种情况下,解码器在解码中就会遇到困难。为了区分不同版本,在扩展部分,可以使用版本符号“[[ ]]”,如:

Afters ::= CHOICE

{

cheese                     IA5String,

dessert                     IA5String,

...!ExtensionPb:greedy,

[[coffee                     NULL ]], -- version 2

[[cognac                   IA5String]] -- version 3

}

Figure 2-7 相同协议不同扩展之间接力示例

如果扩展部分只有一个成员,则版本符号可以省略。如:

State ::= ENUMERATED {on, off, out-of-order, ..., stand-by} -- version 2

Dimensions ::= SET

{

x                              INTEGER,

y                              INTEGER,

...,

z                              INTEGER  -- version 2

}

Afters ::= CHOICE

{

cheese                     IA5String,

dessert                     IA5String,

...,

coffee                       NULL  -- version 2

}

 

 

而类型T的新定义中:

T ::= SEQUENCE

{

a                              A,

b                              B,

...,

[[d                            D,

e                              E]],

...,

c                              C

}

de放在一个版本符号中说明在T类型的一个值中一个出现则另一个必须也出现。

 

当解码扩展类型值时,我们会发现:

l           没有预期的扩展或者

l           出现不期望的扩展

此时,解码器会产生一个协议错误,并且按照应用设计方指定的具体动作来操作:通常是忽略不期望扩展或者为预期的扩展赋缺省值;同时解码器可能还会以事先约定的信号通知应用层。这个约定的信号就是异常Exception,在抽象语法中以“!”开头,后接一个值(可以是数、字符串等),放在扩展标记之后。至于应当如何应对异常,就不是ASN.1关心的内容了。如:

Description ::= SEQUENCE

{

surname                   IA5String,

first-name                 IA5String,

age                          INTEGER,

...!extended-description

}

extended-description INTEGER ::= 1

 

Dimensions ::= SET

{

x                              INTEGER,

y                              INTEGER,

... !IA5String:"dimension error"

}

 

Afters ::= CHOICE

{

cheese                     IA5String,

dessert                     IA5String,

...!ExtensionPb:greedy,

coffee                       NULL,

cognac                     IA5String

}

ExtensionPb::= ENUMERATED {greedy, ...}

 

应用扩展时需要注意的规则:

l           如果模块在头声明中使用了AUTOMATIC TAGS,而且组合类型的根(即类型入口)没有指明Tag,则自动编码过程中,先对根进行自动Tag编码,再对扩展部分进行Tag编码。

l           如果根不是手工Tag编码,则扩展成员也不能手工编码。

l           SET或者CHOICE类型中,扩展部分,要求是按照一定Tag的顺序列出的。Tagging Class的顺序是UNIVERSALAPPLICATIONPRIVATEcontext-specific,每个类中Tag都是升序排列的。

l           当模块定义中使用了EXTENSIBILITY IMPLIED,或者在类型定义结尾只有一个扩展标记,或者在第二个扩展标记前,可以在SEQUENCESETCHOICE类型的扩展插入点,加入一个虚拟成员或者可选项,这样BERCER或者DER解码器必要时可以通过跟踪具体的异常来确认第一个版本的抽象语法是否能接收未知的扩展成员。这个虚拟成员的Tag和其它ASN.1Tag不同,为[IMAGINARY 0]。如下:

Person ::= SET

{

surname                   [0] IA5String,

first-name                 [1] IA5String,

contact                            CHOICE

{

phone-number    [2] NumericString,

e-mail-address   [3] NumericString,

...,

imaginary           [IMAGINARY 0] T

},

info                          CHOICE

{

age                   [4] INTEGER,

...,

imaginary          [IMAGINARY 0] T

}

}

为了避免将来互通问题,对于正在发展的协议,建议在模块定义部分使用EXTENSIBILITY IMPLIED,如:

ModuleName DEFINITIONS AUTOMATIC TAGS

EXTENSIBILITY IMPLIED ::=

BEGIN

-- ...

END

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值