Erlang ASN.1 编译器生成错误的 erlang 代码

Erlang ASN.1 compiler generate wrong erlang code

也许我发现了ASN.1编译错误。 编译器生成 Sorm.erl 文件(此集合中的主文件)并且不会产生错误。

编译命令: erlc -bber +der *.asn

但文件内容有问题。 我想 encode/decode 这样的消息:

ConnReq = #'ConnectRequest'{
        'session-timeout' = 60, 
        'max-data-length' = 10, 
        'data-packet-window-size' = 4, 
        'data-load-timeout' = 3, 
        'request-response-timeout' = 2, 
        'data-packet-response-timeout' = 1
    },
SormMsg = #'Message'{
    version = ?vers, 
    'message-id' = 1234, 
    'message-time' = "161010112000", 
    'operator-name' = asn1_NOVALUE,
    id = "Sessions",
    data = {connect, ConnReq}
},
io:format("SormMsg: ~p~n", [SormMsg]),

{ok, Res} = 'Sorm':encode('Message', SormMsg),
io:format("Connect (bin): ~p~n", [Res]),

DecRes = 'Sorm':decode('Message', Res),
io:format("Decoded: ~p~n", [DecRes]).

但是出现运行时错误。 现在让我们看看编译器生成的代码。

'enc_Message'(Val, TagIn) ->
{_,Cindex1, Cindex2, Cindex3, Cindex4, Cindex5, Cindex6} = Val,
Objid = 'Sorm':'getenc_SormPDUs'(Cindex5),

%%-------------------------------------------------
%% attribute version(1) with type PrintableString DEFAULT = [50,46,50,53,46,48]
%%-------------------------------------------------
   {EncBytes1,EncLen1} =  case is_default_1(Cindex1) of
true -> {[],0};
false ->
encode_restricted_string(Cindex1, [<<19>>])
       end,

%%-------------------------------------------------
%% attribute message-id(2) with type INTEGER
%%-------------------------------------------------
   {EncBytes2,EncLen2} = encode_integer(Cindex2, [<<2>>]),

%%-------------------------------------------------
%% attribute message-time(3) with type UTCTime
%%-------------------------------------------------
   {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<23>>]),

%%-------------------------------------------------
%% attribute operator-name(4) with type PrintableString OPTIONAL
%%-------------------------------------------------
   {EncBytes4,EncLen4} =  case Cindex4 of
         asn1_NOVALUE -> {<<>>,0};
         _ ->
            encode_restricted_string(Cindex4, [<<19>>])
       end,

%%-------------------------------------------------
%% attribute id(5) with type ObjectDescriptor
%%-------------------------------------------------
   {EncBytes5,EncLen5} = encode_restricted_string(Cindex5, [<<7>>]),

%%-------------------------------------------------
%% attribute data(6) with type typefieldData
%%-------------------------------------------------
   {TmpBytes6,_} = Objid('Data', Cindex6, []),
   {EncBytes6,EncLen6} = encode_open_type(TmpBytes6, [])
,

   BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5, EncBytes6],
LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5 + EncLen6,
encode_tags(TagIn, BytesSoFar, LenSoFar).

我们可以看到上线:

'Sorm': 'getenc_SormPDUs' (Cindex5),

该函数必须采用如下所述的值:

%%================================
%%  SormPDUs
%%================================
'getenc_SormPDUs'([{'Externalvaluereference',11,'Management','sorm-message-management'}]) ->
   fun(T,V,O) -> 'Management':'enc_managementMessage'(T,V,O) end;
'getenc_SormPDUs'([{'Externalvaluereference',11,'Sessions','sorm-message-session'}]) ->
   fun(T,V,O) -> 'Sessions':'enc_sessionMessage'(T,V,O) end;
'getenc_SormPDUs'([{'Externalvaluereference',16,'Traps','sorm-message-trap'}]) ->
   fun(T,V,O) -> 'Traps':'enc_trapMessage'(T,V,O) end;
'getenc_SormPDUs'([{'Externalvaluereference',25,'Unformatted','sorm-message-unformatted'}]) ->
   fun(T,V,O) -> 'Unformatted':'enc_unformattedMessage'(T,V,O) end;
'getenc_SormPDUs'([{'Externalvaluereference',42,'Reports','sorm-message-report'}]) ->
   fun(T,V,O) -> 'Reports':'enc_reportMessage'(T,V,O) end;
'getenc_SormPDUs'([{'Externalvaluereference',46,'Tasks','sorm-message-task'}]) ->
   fun(T,V,O) -> 'Tasks':'enc_taskMessage'(T,V,O) end;
'getenc_SormPDUs'(ErrV) ->
   fun(C,V,_) -> exit({'Type not compatible with table constraint',{component,C},{value,V}, {unique_name_and_value,id, ErrV}}) end.

'getdec_SormPDUs'([{'Externalvaluereference',11,'Management','sorm-message-management'}]) ->
   fun(T,V,O) -> 'Management':'dec_managementMessage'(T,V,O) end;
'getdec_SormPDUs'([{'Externalvaluereference',11,'Sessions','sorm-message-session'}]) ->
   fun(T,V,O) -> 'Sessions':'dec_sessionMessage'(T,V,O) end;
'getdec_SormPDUs'([{'Externalvaluereference',16,'Traps','sorm-message-trap'}]) ->
   fun(T,V,O) -> 'Traps':'dec_trapMessage'(T,V,O) end;
'getdec_SormPDUs'([{'Externalvaluereference',25,'Unformatted','sorm-message-unformatted'}]) ->
   fun(T,V,O) -> 'Unformatted':'dec_unformattedMessage'(T,V,O) end;
'getdec_SormPDUs'([{'Externalvaluereference',42,'Reports','sorm-message-report'}]) ->
   fun(T,V,O) -> 'Reports':'dec_reportMessage'(T,V,O) end;
'getdec_SormPDUs'([{'Externalvaluereference',46,'Tasks','sorm-message-task'}]) ->
   fun(T,V,O) -> 'Tasks':'dec_taskMessage'(T,V,O) end;
'getdec_SormPDUs'(ErrV) ->
  fun(C,V,_) -> exit({{component,C},{value,V},{unique_name_and_value,id, ErrV}}) end.

但是如果您查看函数代码 'enc_Message' (Val, TagIn),您会看到变量 Cindex5 将用作字符串:

{EncBytes5, EncLen5} = encode_restricted_string (Cindex5, [<< 7 >>]),

这里和那里有错误。

encode_restricted_string(OctetList, TagIn) when is_binary(OctetList) ->
    encode_tags(TagIn, OctetList, byte_size(OctetList));
encode_restricted_string(OctetList, TagIn) when is_list(OctetList) ->
    encode_tags(TagIn, OctetList, length(OctetList)).

但是,如果您将我的代码更改为:

%%================================
%%  SormPDUs
%%================================
'getenc_SormPDUs'("Management") ->
   fun(T,V,O) -> 'Management':'enc_managementMessage'(T,V,O) end;
'getenc_SormPDUs'("Sessions") ->
   fun(T,V,O) -> 'Sessions':'enc_sessionMessage'(T,V,O) end;
'getenc_SormPDUs'("Traps") ->
   fun(T,V,O) -> 'Traps':'enc_trapMessage'(T,V,O) end;
'getenc_SormPDUs'("Unformatted") ->
   fun(T,V,O) -> 'Unformatted':'enc_unformattedMessage'(T,V,O) end;
'getenc_SormPDUs'("Reports") ->
   fun(T,V,O) -> 'Reports':'enc_reportMessage'(T,V,O) end;
'getenc_SormPDUs'("Tasks") ->
   fun(T,V,O) -> 'Tasks':'enc_taskMessage'(T,V,O) end;
'getenc_SormPDUs'(ErrV) ->
   fun(C,V,_) -> exit({'Type not compatible with table constraint',{component,C},{value,V}, {unique_name_and_value,id, ErrV}}) end.

'getdec_SormPDUs'("Management") ->
   fun(T,V,O) -> 'Management':'dec_managementMessage'(T,V,O) end;
'getdec_SormPDUs'("Sessions") ->
   fun(T,V,O) -> 'Sessions':'dec_sessionMessage'(T,V,O) end;
'getdec_SormPDUs'("Traps") ->
   fun(T,V,O) -> 'Traps':'dec_trapMessage'(T,V,O) end;
'getdec_SormPDUs'("Unformatted") ->
   fun(T,V,O) -> 'Unformatted':'dec_unformattedMessage'(T,V,O) end;
'getdec_SormPDUs'("Reports") ->
   fun(T,V,O) -> 'Reports':'dec_reportMessage'(T,V,O) end;
'getdec_SormPDUs'("Tasks") ->
   fun(T,V,O) -> 'Tasks':'dec_taskMessage'(T,V,O) end;
'getdec_SormPDUs'(ErrV) ->
  fun(C,V,_) -> exit({{component,C},{value,V},{unique_name_and_value,id, ErrV}}) end.

编译执行成功

问:ASN.1 文件或编译器或我自己的代码有错误吗?

Required ASN files

Erlang issue ERL-281

  1. Erlang ASN.1 编译器在处理信息对象 (X.681) 时出错。 Comment for this problem

  2. 有一个解决方法comment: 使用此 OID sorm-message-session 而不是 OID { sorm-message-session }