aboutsummaryrefslogtreecommitdiff
path: root/_misc/makecall.pl
diff options
context:
space:
mode:
Diffstat (limited to '_misc/makecall.pl')
-rw-r--r--_misc/makecall.pl358
1 files changed, 358 insertions, 0 deletions
diff --git a/_misc/makecall.pl b/_misc/makecall.pl
new file mode 100644
index 0000000..dff02ef
--- /dev/null
+++ b/_misc/makecall.pl
@@ -0,0 +1,358 @@
+#ver 0.03 (C)Cyr
+use strict;
+use warnings;
+use diagnostics;
+use IO::Socket;
+use Convert::ASN1;
+
+#use Data::Dumper;
+use Carp;
+use POSIX;
+my $CSTAapdu;
+my $socket;
+
+sub decode_msg_header {
+ my $bin = shift;
+ my $len = unpack( 'n', $bin );
+ return $len;
+}
+
+sub encode_msg_header {
+ my $len = shift;
+ die "Message larger than allowed!" unless ( $len <= 240 );
+ my $bin = pack( 'n', $len );
+ return $bin;
+}
+
+sub convert_to_hex {
+ my $pdu = $_[0];
+ my $hexdata = unpack( 'H*', $pdu );
+ $hexdata =~ tr/a-z/A-Z/;
+ $hexdata =~ s/(..)/$1 /g;
+ $hexdata =~ s/ $//g;
+ return $hexdata;
+}
+
+sub send_pdu {
+ my $pdu = $_[0];
+ my $header = encode_msg_header( length($pdu) );
+ $socket->write($header);
+ $socket->write($pdu);
+
+ # my $hexdata = convert_to_hex($pdu);
+ # print("SENT: [$hexdata]\n");
+}
+
+sub csta_connect {
+ my %args = %{ $_[0] };
+ open_csta_socket( $args{host}, $args{port} );
+
+ # A-ASSOCIATE Request
+ my $pdu =
+"602380020780A10706052B0C00815ABE14281206072B0C00821D8148A007A0050303000800";
+ $pdu = pack( 'H*', $pdu );
+ send_pdu($pdu);
+
+ # A-ASSOCIATE Result
+ $pdu = receive_stuff();
+ my $hexdata = convert_to_hex($pdu);
+ if ( $hexdata =~ /A2 03 02 01 01/ ) {
+ print "rejected-permanent\n";
+ exit 0;
+ }
+
+ #SystemStatus Request
+ $pdu = receive_stuff();
+ my $out = $CSTAapdu->decode($pdu);
+ my $invokeID = $out->{svcRequest}->{invokeID};
+ SystemStatusResult($invokeID);
+}
+
+sub open_csta_socket {
+ my $host = shift;
+ my $port = shift;
+ $socket = new IO::Socket::INET(
+ PeerAddr => $host,
+ PeerPort => $port,
+ Blocking => 1,
+ Proto => 'tcp'
+ ) || die "Error creating socket: $!\n";
+ $socket->autoflush(1);
+ print("opened a connection to $host on port $port\n");
+}
+
+sub receive_stuff {
+ my $header = '';
+ my $pdu = '';
+ my $nbytes = $socket->sysread( $header, 2 );
+ if ( $nbytes == 1 ) { # фрагмент пакета
+ my $header2;
+ my $nbytes2 = $socket->sysread( $header2, 1 );
+ $header = $header . $header2;
+ $nbytes = 2;
+ }
+ croak "Didn't receive the specified amount of data (2 bytes)!\n" . chr(7)
+ unless ( $nbytes == 2 );
+ my $len = decode_msg_header($header);
+ $nbytes = $socket->sysread( $pdu, $len );
+ if ( $nbytes < $len ) { # фрагмент пакета
+ my $pdu2;
+ my $nbytes2 = $socket->sysread( $pdu2, $len - $nbytes );
+ $pdu = $pdu . $pdu2;
+ $nbytes = $nbytes + $nbytes2;
+ }
+ croak "Didn't receive the specified amount of data ($len bytes)!\n" . chr(7)
+ unless ( $nbytes == $len );
+
+ # my $hexdata = convert_to_hex($pdu);
+ # print("RECEIVED:[$hexdata]\n");
+ return $pdu;
+}
+
+sub SystemStatusResult {
+ my $invokeID = shift;
+ my $pdu = $CSTAapdu->encode(
+ {
+ svcResult => {
+ invokeID => $invokeID,
+ result => { serviceID => 211, serviceResult => { noData => 1 } }
+ }
+ }
+ );
+ send_pdu($pdu); # send SystemStatus Result
+}
+
+sub makeCall {
+ my $dialingNumber = shift;
+ my $pdu = $CSTAapdu->encode(
+ {
+ svcRequest => {
+ invokeID => 9,
+ serviceID => 10,
+ serviceArgs => {
+ callingDevice => {
+ deviceIdentifier => {
+ dialingNumber =>
+ $dialingNumber # номер абонента
+ }
+ },
+ calledDirectoryNumber => {
+ deviceIdentifier => {
+ dialingNumber =>
+ 178 # номер ICD автоинформатора
+ }
+ }
+ }
+ }
+ }
+ );
+ send_pdu($pdu);
+ $pdu = receive_stuff();
+
+ #Convert::ASN1::asn_dump($pdu);
+ my $out = $CSTAapdu->decode($pdu);
+
+ #$Data::Dumper::Indent=1;
+ #$Data::Dumper::Pair=' ';
+ #$Data::Dumper::Quotekeys=0;
+ #$Data::Dumper::Varname='CSTAapdu';
+ #print Dumper($out);
+ if ( defined $out->{svcResult}->{result}->{serviceResult}->{callingDevice} )
+ {
+ print $out->{svcResult}->{result}->{serviceResult}->{callingDevice}
+ ->{both}->{deviceID}->{staticID}->{deviceIdentifier}->{dialingNumber},
+ "\n";
+ }
+ elsif ( defined $out->{svcError}->{parameter} ) {
+
+ #my $error_parameter = (keys %{$out->{svcError}->{parameter}})[0];
+ #print $error_parameter,"\n";
+ if ( defined $out->{svcError}->{parameter}->{operation} ) {
+ my $OperationErrors = $out->{svcError}->{parameter}->{operation};
+ if ( $OperationErrors == 12 ) {
+ print $dialingNumber, " - invalidDeviceID\n";
+ }
+ elsif ( $OperationErrors == 6 ) {
+ print $dialingNumber, " - invalidCalledDeviceID\n";
+ }
+ elsif ( $OperationErrors == 31 ) {
+ print $dialingNumber, " - invalidParameterValue\n";
+ }
+ elsif ( $OperationErrors == 2 ) {
+ print $dialingNumber, " - requestIncompatibleWithObject\n";
+ }
+ else {
+ print "OperationErrors:", $OperationErrors, "\n";
+ }
+ }
+ elsif ( defined $out->{svcError}->{parameter}->{stateIncompatibility} )
+ {
+ my $StateIncompatibilityErrors =
+ $out->{svcError}->{parameter}->{stateIncompatibility};
+ if ( $StateIncompatibilityErrors == 2 ) {
+ print $dialingNumber, " - invalidObjectState\n";
+ }
+ else {
+ print "StateIncompatibilityErrors:",
+ $StateIncompatibilityErrors;
+ }
+ }
+ elsif (
+ defined $out->{svcError}->{parameter}
+ ->{systemResourceAvailability} )
+ {
+ my $SystemResourceAvailabilityErrors =
+ $out->{svcError}->{parameter}->{systemResourceAvailability};
+ if ( $SystemResourceAvailabilityErrors == 15 ) {
+ print $dialingNumber, " - deviceOutOfService\n";
+ }
+ else {
+ print "SystemResourceAvailabilityErrors:",
+ $SystemResourceAvailabilityErrors;
+ }
+ }
+ else {
+ print Dumper($out);
+ }
+ }
+ else {
+ print Dumper($out);
+ }
+}
+
+# parse ASN.1 desciptions
+my $asn = Convert::ASN1->new;
+
+#$asn->configure(tagdefault=>'EXPLICIT');
+$asn->prepare(<<ASN1) or die "prepare: ", $asn->error;
+CSTAapdu ::= CHOICE {
+ svcRequest ROIVapdu,
+ svcResult RORSapdu,
+ svcError ROERapdu
+-- svcReject RORJapdu
+}
+ROIVapdu ::= [1] IMPLICIT SEQUENCE {
+ invokeID INTEGER,
+ serviceID INTEGER,
+ serviceArgs ANY DEFINED BY serviceID
+}
+RORSapdu ::= [2] IMPLICIT SEQUENCE {
+ invokeID INTEGER,
+ result SEQUENCE {
+ serviceID INTEGER,
+ serviceResult ANY DEFINED BY serviceID OPTIONAL
+ }
+}
+ROERapdu ::= [3] IMPLICIT SEQUENCE {
+ invokeID INTEGER,
+ code INTEGER, -- local:1
+ parameter UniversalFailure
+}
+UniversalFailure ::= CHOICE
+{ operation [0] EXPLICIT OperationErrors,
+ stateIncompatibility [2] EXPLICIT StateIncompatibilityErrors,
+ systemResourceAvailability [3] EXPLICIT SystemResourceAvailabilityErrors,
+ unspecified [7] UnspecifiedErrors
+}
+OperationErrors ::= ENUMERATED
+{
+ invalidDeviceID (12),
+ invalidCalledDeviceID (6),
+ invalidParameterValue (31),
+ requestIncompatibleWithObject (2)
+}
+StateIncompatibilityErrors ::= ENUMERATED
+{
+ invalidObjectState (2)
+}
+SystemResourceAvailabilityErrors ::= ENUMERATED
+{
+ deviceOutOfService (15)
+}
+UnspecifiedErrors ::= NULL
+
+--makeCall OPERATION ::=
+--{ ARGUMENT MakeCallArgument
+-- RESULT MakeCallResult
+-- ERRORS {universalFailure}
+-- CODE local: 10
+--}
+
+MakeCallArgument ::= SEQUENCE
+{ callingDevice DeviceID,
+ calledDirectoryNumber DeviceID
+}
+MakeCallResult ::= SEQUENCE
+{ callingDevice ConnectionID}
+
+ConnectionID ::= [APPLICATION 11] CHOICE
+{
+ deviceID [1] LocalDeviceID,
+ both SEQUENCE
+ { callID [0] IMPLICIT CallID,
+ deviceID [1] LocalDeviceID
+ }
+}
+
+CallID ::= OCTET STRING
+
+LocalDeviceID ::= CHOICE
+{ staticID DeviceID}
+
+DeviceID ::= SEQUENCE
+{ deviceIdentifier CHOICE
+ { dialingNumber [0] IMPLICIT NumberDigits,
+ deviceNumber [1] IMPLICIT DeviceNumber,
+ other [6] IMPLICIT OtherPlan
+ }
+}
+OtherPlan ::= OCTET STRING
+
+NumberDigits ::= IA5String
+
+DeviceNumber ::= INTEGER
+
+systemStatus ::= CHOICE
+{ ARGUMENT SystemStatusArg,
+ RESULT SystemStatusRes
+-- ERRORS {universalFailure}
+-- CODE local: 211
+}
+SystemStatusArg ::= SEQUENCE
+{ systemStatus SystemStatus}
+
+SystemStatusRes ::= CHOICE
+{ noData NULL}
+
+SystemStatus ::= ENUMERATED
+{ normal (2),
+ messageLost (3),
+ overloadReached (6)
+}
+ASN1
+my %serviceArgs = ( #51=> 'EscapeArgument',
+ 10 => 'MakeCallArgument',
+ 211 => 'SystemStatusArg'
+);
+foreach ( keys %serviceArgs ) {
+ $asn->registertype( 'serviceArgs', $_, $asn->find( $serviceArgs{$_} ) );
+}
+my %serviceResults = ( #51=> 'EscapeResult',
+ 10 => 'MakeCallResult',
+ 211 => 'SystemStatusRes'
+);
+foreach ( keys %serviceResults ) {
+ $asn->registertype( 'serviceResult', $_,
+ $asn->find( $serviceResults{$_} ) );
+}
+$CSTAapdu = $asn->find('CSTAapdu');
+csta_connect( { 'host' => '192.168.0.66', 'port' => 33333 } );
+print "makeCall:\n";
+my @devices = ( 106, 111, 155, 156 ); # список номеров
+my $i = 0;
+for (@devices) {
+ makeCall($_);
+ if ( $i++ % 2 ) { # 2 - количество каналов SVM
+ sleep 3 # задержка на сообщение
+ }
+}