diff options
Diffstat (limited to '_misc/monitorCallerID2.pl')
-rw-r--r-- | _misc/monitorCallerID2.pl | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/_misc/monitorCallerID2.pl b/_misc/monitorCallerID2.pl new file mode 100644 index 0000000..d39c38f --- /dev/null +++ b/_misc/monitorCallerID2.pl @@ -0,0 +1,261 @@ +#ver 0.02 (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; +my @devices; +sub deviceNumber{ + my $deviceNumber = shift; + my $deviceType = $deviceNumber & 0xFFFF0000; + if ($deviceType==0x1310000) { + $deviceType='CO' + } elsif ($deviceType==0x1210000) { + $deviceType='PS' + } elsif ($deviceType==0x1110000) { + $deviceType='EXT' + } elsif ($deviceType==0x1550000) { + $deviceType='DISA' + } + $deviceNumber = $deviceNumber & 0x0000FFFF; + return $deviceType.sprintf("%03s",$deviceNumber); +} +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 GetSystemData{ + my $DeviceCategory = shift; + #EXT=5 + #CO =2 + my $pdu = $CSTAapdu->encode({svcRequest=>{ + invokeID=>4, + serviceID=>51, + serviceArgs=>{ + privateData=>{ + private=>{ + kmeSystemData=>{ + getSystemData=>{ + request=>{ + deviceList=>{ + category=>{ + standardDevice=>$DeviceCategory + } + } + } + } + } + } + } + } + } + }); + #my $pdu = "A11602020602020133300DA40BA009A407A105A0030A010".$DeviceCategory; + #$pdu = pack('H*', $pdu); + send_pdu($pdu); + # getSystemDataPosAck + $pdu = receive_stuff(); + my $out = $CSTAapdu->decode($pdu); + my $crossRefID = $out->{svcResult}->{result}->{serviceResult}->{extensions}->{privateData}[0]->{private}->{kmeSystemData}->{getSystemDataPosAck}; + my $lastSegment=0; + # systemDataLinkedReply + while (!$lastSegment) { + $pdu = receive_stuff(); + my $out = $CSTAapdu->decode($pdu); + my $systemDataLinkedReply = $out->{svcRequest}->{serviceArgs}->{privateData}->{private}->{kmeSystemData}->{systemDataLinkedReply}; + if (defined $systemDataLinkedReply) { + if ($systemDataLinkedReply->{crossRefID} cmp $crossRefID) {next} + $lastSegment = $systemDataLinkedReply->{lastSegment}; + foreach my $KmeDeviceStateEntry (@{$systemDataLinkedReply->{sysData}->{deviceList}}) { + if ($KmeDeviceStateEntry->{status}==0) { +# print "device:",$KmeDeviceStateEntry->{number},"\n"; + push @devices, ($KmeDeviceStateEntry->{device}->{deviceIdentifier}->{deviceNumber}); + } + } + } + } +} +sub MonitorStartArgument{ +my $device = shift; +my $pdu = $CSTAapdu->encode({svcRequest=>{ + invokeID=>9, + serviceID=>71, + serviceArgs=>{ + monitorObject=>{ + deviceObject=>{ + deviceIdentifier=>{ + deviceNumber=>$device + } + } + }, + requestedMonitorFilter=>{} + } + } + }); +send_pdu($pdu); +#$pdu = receive_stuff(); +} +sub CSTAEventReportArgument{ +my $refeventSpecificInfo = shift; +if (defined $refeventSpecificInfo->{eventSpecificInfo}->{callControlEvents}) { + my $refcallControlEvents = $refeventSpecificInfo->{eventSpecificInfo}->{callControlEvents}; + my $callControlEvents = (keys %{$refcallControlEvents})[0]; + my $Event = $refcallControlEvents->{$callControlEvents}; + #print Dumper($refcallControlEvents); + if ((($Event->{localConnectionInfo}==2) & (($Event->{cause}==22) | ($Event->{cause}==38))) | + (($Event->{localConnectionInfo}==3) & ($Event->{cause}==74))) { + #localConnectionInfo = allerting and cause=newCall|distributed + my $CalledID = deviceID($Event->{alertingDevice}->{deviceIdentifier}); + my $CallerID; + if (defined $Event->{callingDevice}->{notKnown}) { + $CallerID = deviceID($Event->{associatedCallingDevice}->{deviceIdentifier}) + } else { + $CallerID = deviceID($Event->{callingDevice}->{deviceIdentifier}) + } + print strftime("%H:%M:%S ", localtime); + print("Call to:$CalledID from:$CallerID\n"); + } + } +} +sub deviceID{ + my $deviceIdentifier = shift; + $deviceIdentifier = $deviceIdentifier->{deviceIdentifier}; + if (defined $deviceIdentifier->{dialingNumber}) { + return $deviceIdentifier->{dialingNumber} + } elsif (defined $deviceIdentifier->{deviceNumber}) { + return deviceNumber($deviceIdentifier->{deviceNumber}) + } elsif (defined $deviceIdentifier->{other}) { + return $deviceIdentifier->{other} + } +} +sub SystemStatusResult{ + my $invokeID = shift; + my $pdu = $CSTAapdu->encode({svcResult=>{invokeID=>$invokeID,result=>{serviceID=>211,serviceResult=>{noData=>1}}}}); + send_pdu($pdu); # send SystemStatus Result +} +$Data::Dumper::Indent=1; +$Data::Dumper::Pair=' '; +$Data::Dumper::Quotekeys=0; +$Data::Dumper::Varname='calls'; +# parse ASN.1 desciptions +my $asn = Convert::ASN1->new; +#$asn->configure(tagdefault=>'EXPLICIT'); +$asn->prepare_file('d:\111\asn_perl\kxtde.asn') or die "prepare: ", $asn->error; +my %serviceArgs = ( 21=> 'CSTAEventReportArgument', + 51=> 'EscapeArgument', + 71=> 'MonitorStartArgument', + 211=> 'SystemStatusArg'); +foreach (keys %serviceArgs) { + $asn->registertype('serviceArgs',$_,$asn->find($serviceArgs{$_})); +} +my %serviceResults = ( 51=> 'EscapeResult', + 71=> 'MonitorStartResult', + 211=> 'SystemStatusRes'); +foreach (keys %serviceResults) { + $asn->registertype('serviceResult',$_,$asn->find($serviceResults{$_})); +} +$CSTAapdu = $asn->find('CSTAapdu'); +csta_connect({'host'=>'192.168.0.101', 'port'=>33333}); +GetSystemData(2); +GetSystemData(5); +foreach my $number (@devices) { + MonitorStartArgument($number); +} +while (1) { + my $pdu = receive_stuff(); + my $out = $CSTAapdu->decode($pdu); + if (defined $out->{svcRequest}) { + my $serviceID = $out->{svcRequest}->{serviceID}; + my $invokeID = $out->{svcRequest}->{invokeID}; + my $serviceArgs = $out->{svcRequest}->{serviceArgs}; + if ($serviceID==21) { + CSTAEventReportArgument($serviceArgs); + } elsif ($serviceID==211) { # if SystemStatus Request + SystemStatusResult($invokeID); + } + } +} |