Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Как распарсить CSTA ASN.1


Автор: Cyr 7.4.2014, 12:41
Научите парсить CSTA сообщения.
Нашёл библиотеку http://search.cpan.org/~leifj/Net-CSTA-0.04/lib/Net/CSTA.pm.
С помощью такого:  
Код

use Convert::ASN1;
my $pdu ="A1 34 02 01 03 02 01 15 30 2C 55 04 01 11 00 12 A0 24 B0 22 
    6B 11 30 0F 80 04 30 30 37 35 A1 07 30 05 80 03 31 31 31 63 
    07 30 05 80 03 31 31 31 4E 01 01 0A 01 16";
$pdu =~s/\s//g; # убираем пробелы
$pdu =pack ("H*", $pdu); # превращаем строку в бинарник
Convert::ASN1::asn_dump($pdu);

Смог получить голую ASN.1 структуру:
Код

0000   52: [CONTEXT 1] {
0002    1:   INTEGER = 3
0005    1:   INTEGER = 21
0008   44:   SEQUENCE {
000A    4:     [APPLICATION 21]
000C     :       01 11 00 12 __ __ __ __ __ __ __ __ __ __ __ __ ....
0010   36:     [CONTEXT 0] {
0012   34:       [CONTEXT 16] {
0014   17:         [APPLICATION 11] {
0016   15:           SEQUENCE {
0018    4:             [CONTEXT 0]
001A     :               30 30 37 35 __ __ __ __ __ __ __ __ __ __ __ __ 0075
001E    7:             [CONTEXT 1] {
0020    5:               SEQUENCE {
0022    3:                 [CONTEXT 0]
0024     :                   31 31 31 __ __ __ __ __ __ __ __ __ __ __ __ __ 111
0027     :               }
0027     :             }
0027     :           }
0027     :         }
0027    7:         [APPLICATION 3] {
0029    5:           SEQUENCE {
002B    3:             [CONTEXT 0]
002D     :               31 31 31 __ __ __ __ __ __ __ __ __ __ __ __ __ 111
0030     :           }
0030     :         }
0030    1:         [APPLICATION 14]
0032     :           01 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ .
0033    1:         ENUM = 22
0036     :       }
0036     :     }
0036     :   }
0036     : }

Как её заполнить CSTA директивами? Чтобы получить это:
Код

   CSTAEventReportArgument {
      crossRefIdentifier = 01110012
      eventSpecificInfo {
         callControlEvents {
            serviceInitiated {
               initiatedConnection {
                  both {
                     callID = 0075
                     deviceID {
                        staticID {
                           deviceIdentifier {
                              dialingNumber = 111
                           }
                        }
                     }
                  }
               }
               initiatingDevice {
                  deviceIdentifier {
                     deviceIdentifier {
                        dialingNumber = 111
                     }
                  }
               }
               localConnectionInfo = initiated
               cause = newCall
            }
         }
      }
   }


Автор: arto 7.4.2014, 13:59
похоже, вы в $pdu длину потеряли

Автор: Cyr 7.4.2014, 14:01
arto,  нет. с чего вы так решили?

Автор: arto 7.4.2014, 15:41
длина вашего pdu 55 байтов, а первые октеты у вас A1 34.
Или я ошибаюсь?

Автор: Cyr 7.4.2014, 15:46
длина pdu - 54 байта, а длина сообщения после первого октета равна 52 (34h).
так что там всё нормал. 

Автор: arto 8.4.2014, 12:44
# print A1 34 02 01 03 02 01 15 30 2C 55 04 01 11 00 12 A0 24 B0 22 6B 11 30 0F 80 04 30 30 37 35 A1 07 30 05 80 03 31 31 31 63 07 30 05 80 03 31 31 31 4E 01 01 0A 01 16 | perl -0777 -MData::Dumper -MNet::CSTA::ASN=CSTAapdu -lne 'print Dumper($CSTAapdu->decode(pack"H*",s#\s+##gsr))' 
$VAR1 = {
          'svcRequest' => {
                            'serviceArgs' => undef,
                            'serviceID' => 21,
                            'invokeID' => 3
                          }
        };
#

попытайтесь найти нормальную asn.1 грамматику для csta

Автор: Cyr 8.4.2014, 14:02
Цитата(arto @ 8.4.2014,  13:44)
попытайтесь найти нормальную asn.1 грамматику для csta

нашёл, 274 файла... все части CSTA. около 700 килобайт.
Видимо надо использовать только Convert::ASN1 и подсовывать туда эти файлы?

Автор: arto 9.4.2014, 07:53
Посмотрите как сделано в Net::CSTA::ASN, там неполохой пример.

Автор: Cyr 11.4.2014, 10:39
Цитата(arto @ 9.4.2014,  08:53)
Посмотрите как сделано в Net::CSTA::ASN, там неполохой пример.

arto, в принципе в Net::CSTA::ASN практически тоже самое что и в полном CSTA. Почему же оно полностью не парсится?
Как определить, где конкретно (в каком месте) затык?

Автор: arto 14.4.2014, 08:49
в модуле написано, что "this module currently implements CSTA phase I - mostly because my PBX (MD110 with 
Application Link 4.0) only supports phase I. Supporting multiple versions will 
require some thought since the versions are largly incompatible."

у вас какая версия csta?

Автор: Cyr 14.4.2014, 08:51
arto, csta phase 3. но я смотрел определения(грамматику) и не смог найти отличия конкретно для моего примера.

Автор: arto 14.4.2014, 11:19
попробуйте вручную распарсить ваш pdu

Автор: Cyr 15.4.2014, 11:09
arto, парсится он нормально.
но видимо заставить делать это на perl для меня - не судьба.
Хочу пойти другим путём.
Как можно в цикле вывести ASN.1 теги и их значения?
Буду обрабатывать их через if ... else

Автор: arto 15.4.2014, 12:34
вам распарсить грамматику?

Автор: Cyr 15.4.2014, 12:42
arto, нет.
Мне просто в цикле надо пройти pdu и получить:
CONTEXT=1
INTEGER = 3
INTEGER = 21
SEQUENCE 
...
И т.д. 
А я уже через if ... else буду выводить, что это за информация и её значение.

Автор: arto 15.4.2014, 14:30
вы хотите написать новый Convert::ASN1 или форкнуть существующий?

btw, у вас данные что собой представляют?

Автор: Cyr 15.4.2014, 14:39
arto, скорее упрощённый вариант под мониторинг сообщений-событий: взяли трубку, набрали номер, соединение, отбой, поступил звонок и т.д.  Различных вариантов сообщений-событий порядка 10-15. Пример в первом посте.
Не осилил я  ASN.1 с грамматикой, поэтому хочу что-нить очень простое и примитивное.
...Я тут нашёл ещё одну либу http://search.cpan.org/~timos/Net-CSTAv3-Client-0.06/lib/Net/CSTAv3/Client.pm. Но там юзается внешняя утилитка unber. Вот если б можно было бы обойтись без неё...

Автор: arto 15.4.2014, 21:59
если посмотреть, что у вас внутри данных, то видно

    0:d=0  hl=2 l=  52 cons: cont [ 1 ]
    2:d=1  hl=2 l=   1 prim: INTEGER           :03
    5:d=1  hl=2 l=   1 prim: INTEGER           :15
    8:d=1  hl=2 l=  44 cons: SEQUENCE
   10:d=2  hl=2 l=   4 prim: appl [ 21 ]
   16:d=2  hl=2 l=  36 cons: cont [ 0 ]
   18:d=3  hl=2 l=  34 cons: cont [ 16 ]
   20:d=4  hl=2 l=  17 cons: appl [ 11 ]
   22:d=5  hl=2 l=  15 cons: SEQUENCE
   24:d=6  hl=2 l=   4 prim: cont [ 0 ]
   30:d=6  hl=2 l=   7 cons: cont [ 1 ]
   32:d=7  hl=2 l=   5 cons: SEQUENCE
   34:d=8  hl=2 l=   3 prim: cont [ 0 ]
   39:d=4  hl=2 l=   7 cons: appl [ 3 ]
   41:d=5  hl=2 l=   5 cons: SEQUENCE
   43:d=6  hl=2 l=   3 prim: cont [ 0 ]
   48:d=4  hl=2 l=   1 prim: appl [ 14 ]
   51:d=4  hl=2 l=   1 prim: ENUMERATED        :16

что первые два поля INTEGER, a третье SEQUENCE, а в грамматике из модуля

ROIVapdu ::=  [1] IMPLICIT SEQUENCE {
        invokeID          INTEGER,  -- no. de sequencia
        serviceID         INTEGER,  -- no. da operacao a ser realizada
        serviceArgs       ANY DEFINED BY serviceID -- Uma das estruturas abaixo
}

ANY. скорее всего парсер не понимает, как конвертировать ANY в SEQUENCE.

а так -- и asn1parser, и asn1c свободные проекты, и из обоих можно взять код либо
бинарник, если у вас не rt.

Автор: Cyr 16.4.2014, 07:52
Цитата

 0:d=0  hl=2 l=  52 cons: cont [ 1 ]
    2:d=1  hl=2 l=   1 prim: INTEGER           :03
    5:d=1  hl=2 l=   1 prim: INTEGER           :15
    8:d=1  hl=2 l=  44 cons: SEQUENCE

arto, а чем вы парсили?
Цитата

что первые два поля INTEGER, a третье SEQUENCE, а в грамматике из модуля

ROIVapdu ::=  [1] IMPLICIT SEQUENCE {
        invokeID          INTEGER,  -- no. de sequencia
        serviceID         INTEGER,  -- no. da operacao a ser realizada
        serviceArgs       ANY DEFINED BY serviceID -- Uma das estruturas abaixo
}

ANY. скорее всего парсер не понимает, как конвертировать ANY в SEQUENCE.

ANY DEFINED BY serviceID - означает, что дальше он должен всё парсить в зависимости от кода serviceID.
serviceID = 15 (21 десятичное) - это второй INTEGER.
my %serviceArgs = ( 
...
21 => 'EventReport',
...
) 

Поэтому дальше он должен  всё парсить как EventReport:

-- Evento generico
EventReport ::= SEQUENCE {
    crossRefIdentifier    MonitorCrossRefID,
    eventType        [0] IMPLICIT INTEGER,
    eventInfo        ANY DEFINED BY eventType
} 

А потом парсить eventInfo в зависимости от кода eventType...

Автор: arto 16.4.2014, 08:17
openssl asn1parse

вот парсеру и надо объяснить, какое правило дальше применять.

Автор: Cyr 16.4.2014, 08:28
arto, дык в начале и конце модуля Net::CSTA::ASN всё же объяснено по идее...
Я не понимаю где там неправильно и как исправить :(
Ведь это по идее должен быть рабочий модуль.

Автор: Cyr 17.4.2014, 14:01
Написал я такой http://pastebin.com/VM5mft4U
И странное дело. Его запускаешь раз 10. И он выдаёт ошибки разные.
А потом вдруг срабатывает и выдаёт результат:
Код

$VAR1 = {
          'crossRefIdentifier' => '☺◄ ↕',
          'eventSpecificInfo' => {
                                   'callControlEvents' => {
                                                            'serviceInitiated' => {
                                                                                    'initiatingDevice' => {
                                                                                                            'deviceIdentifier' => {

            'deviceIdentifier' => {

                                    'dialingNumber' => '111'

                                  }

          }
                                                                                                          },
                                                                                    'localConnectionInfo' => 1,
                                                                                    'initiatedConnection' => {
                                                                                                               'both' =>
 {

   'deviceID' => {

                   'staticID' => {

                                   'deviceIdentifier' => {

                                                           'dialingNumber' => '111'

                                                         }

                                 }

                 },

   'callID' => '0075'

 }
                                                                                                             },
                                                                                    'cause' => 22
                                                                                  }
                                                          }
                                 }
        };

В чём может быть причина?
Причём если вместо use Convert::ASN1 поставить use Convert::ASN1 qw(:io :debug) - то запусков с ошибками гораздо меньше.

Автор: Cyr 21.4.2014, 10:31
Разобрался. Надо было вот так писать:
my $obj = $asn->find('CSTAEventReportArgument');
my $out2= $obj->decode($pdu2) or die $asn->error;

Но теперь столкнулся с такой грамматикой:
Код

ConnectionList ::= SEQUENCE OF SEQUENCE
        {       newConnection [0] ConnectionID                  OPTIONAL,
                oldConnection [1] ConnectionID                  OPTIONAL,
                endpoint [2] CHOICE
                {       deviceID        DeviceID,
                        notKnown        NULL}    OPTIONAL,
                associatedNID [3] CHOICE
                {       deviceID        DeviceID,
                        notKnown        NULL}    OPTIONAL,
                resultingConnectionInfo ConnectionInformation OPTIONAL} 

на таком pdu:
Код

0047   64:       [CONTEXT 1] {
0049   39:         SEQUENCE {
004B   27:           [CONTEXT 0] {
004D   25:             [APPLICATION 11] {
004F   23:               SEQUENCE {
0051    4:                 [CONTEXT 0]
0053     :                   30 30 38 41 __ __ __ __ __ __ __ __ __ __ __ __ 008A
0057   15:                 [CONTEXT 1] {
0059   13:                   SEQUENCE {
005B   11:                     [CONTEXT 0]
005D     :                       38 39 35 31 39 39 39 39 39 39 39 __ __ __ __ __ 89519999999
0068     :                   }
0068     :                 }
0068     :               }
0068     :             }
0068     :           }
0068    8:           [CONTEXT 3] {
006A    6:             SEQUENCE {
006C    4:               [CONTEXT 1]
006E     :                 01 31 00 11 __ __ __ __ __ __ __ __ __ __ __ __ .1..
0072     :             }
0072     :           }
0072     :         }
0072   21:         SEQUENCE {
0074   19:           [CONTEXT 0] {
0076   17:             [APPLICATION 11] {
0078   15:               SEQUENCE {
007A    4:                 [CONTEXT 0]
007C     :                   30 30 38 41 __ __ __ __ __ __ __ __ __ __ __ __ 008A
0080    7:                 [CONTEXT 1] {
0082    5:                   SEQUENCE {
0084    3:                     [CONTEXT 0]
0086     :                       31 32 36 __ __ __ __ __ __ __ __ __ __ __ __ __ 126
0089     :                   }
0089     :                 }
0089     :               }
0089     :             }
0089     :           }
0089     :         }
0089     :       }


asn1 декодер ругается на:

               associatedNID [3] CHOICE
                {       deviceID        DeviceID,
                        notKnown        NULL}    OPTIONAL,

ему не нравится слово optional
но и без него не работает.

Автор: Cyr 27.4.2014, 12:48
заработала такая конструкция:
Код

      ConnectionList ::= [1] SEQUENCE OF SEQUENCE
        {   newConnection [0] EXPLICIT ConnectionID OPTIONAL,
            associatedNID [3] associatedNID_                OPTIONAL
        }
        
        associatedNID_ ::= CHOICE
        {    deviceID    DeviceID,
            notKnown    NULL
        }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)