use POSIX; use Carp; #use Data::Dumper; use IO::Socket; sub decode_msg_header { my $bin = shift; my $len = unpack( 'n', $bin ); return $len; } sub encode_msg_header { my $len = shift; # print("len: [$len]\n"); 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); $headerdata = convert_to_hex($header); # print("SENT HEADER: [$headerdata]\n"); $socket->write($pdu); $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 receive_stuff(); } sub open_csta_socket { my $host = shift; my $port = shift; # print("trying to open a connection to $host on port $port\n"); $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 ) { # фрагмент пакета # print("RECEIVED fragment".chr(7)."\n"); $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 ); # print("Received 2 bytes, assuming it's a data length\n"); my $len = decode_msg_header($header); # print("Waiting for [$len] bytes of ASN1 data now\n"); $nbytes = $socket->sysread( $pdu, $len ); if ( $nbytes < $len ) { # фрагмент пакета # print("RECEIVED fragment".chr(7)."\n"); $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 main_loop { while (1) { my $pdu = receive_stuff(); my $hexdata = convert_to_hex($pdu); # If SystemStatus Request if ( $hexdata =~ /A1 0C 02 01 .. 02 02 00 D3 30 03 0A 01 02/ ) { # SystemStatus Response my $pdu = "A20B0201" . substr( $hexdata, 12, 2 ) . "3006020200D30500"; $pdu = pack( 'H*', $pdu ); send_pdu($pdu); } # If SystemStatus Request 2 elsif ( $hexdata =~ /A1 0D 02 02 .. .. 02 02 00 D3 30 03 0A 01 02/ ) { # SystemStatus Response 2 my $pdu = "A20C0202" . substr( $hexdata, 12, 2 ) . substr( $hexdata, 15, 2 ) . "3006020200D30500"; $pdu = pack( 'H*', $pdu ); send_pdu($pdu); } # if localConnectionInfo=alerting and cause=newCall|distributed elsif ( $hexdata =~ m/4E 01 02 0A 01 [12]6/ ) { # звонок от if ( $hexdata =~ m/61 .. 30 .. 80 / ) { $num = hex( substr( $', 0, 2 ) ); $str = substr( $', 3, $num * 3 ); $str =~ s/\s//g; $CallerID = pack( "H*", $str ); } else { $CallerID = "CO" . substr( $hexdata, length($hexdata) - 2, 2 ); } # звонок кому if ( $hexdata =~ m/63 .. 30 .. 80 / ) { $num = hex( substr( $', 0, 2 ) ); $str = substr( $', 3, $num * 3 ); $str =~ s/\s//g; $CalledID = pack( "H*", $str ); } print strftime( "%H:%M:%S ", localtime ); print("Call to:$CalledID from:$CallerID\n"); } } } sub MonitorStart { my $ext = shift; $ext =~ s/(.)/sprintf("%02x",ord($1))/eg; my $pdu = "A111020178020147300930058003" . $ext . "A000"; $pdu = pack( 'H*', $pdu ); send_pdu($pdu); $pdu = receive_stuff(); } csta_connect( { 'host' => '192.168.0.101', 'port' => 33333 } ); for ( $ext_num = 101 ; $ext_num <= 156 ; $ext_num++ ) { MonitorStart($ext_num); } main_loop();