# Prepared by # Muhammad Faheem # faheem_imt@yahoo.com # This scripts captures AMI Event and parses Registration Events and stores latest IP/Ports using Filing. #!/usr/bin/perl use strict; use IO::Socket; use Time::HiRes; # this moudule will be used to time difference... in future.. use DBI; my $sec; my $min; my %hash = (); my %user_hash = (); # this hash table will maintain user Clone Line enable/disable status... my $socket = new IO::Socket::INET ( PeerAddr => '127.0.0.1', PeerPort => 5038, Proto => 'tcp', ) or die "Couldn't connect to Server\n"; my $tmp; # login string... $tmp="Action: Login\r\nUsername: admin\r\nSecret: secret5\r\nActionID: 1\r\n\r\n"; my $recv_data; if($socket->send($tmp) == 0){ print "could not connect to Asterisk server"; exit(1); } my $base_time = Time::HiRes::time(); my $current_time; my $diff; &UpdateUserStatusHash(); while(1){ $current_time = Time::HiRes::time(); $diff = $current_time - $base_time; if($diff >= 20 ){ print "\nUpdating Cloneline Status form DB to Local Hash...\n"; &UpdateUserStatusHash(); $base_time = Time::HiRes::time(); } $socket->recv($recv_data,1024); &tokenizepackets($recv_data); } sub tokenizepackets(){ my $recv_data = shift; #print $recv_data; my @lines = split(/\n/,$recv_data); #split the lines... my @tmp = split(/:/,$lines[0]); #split each lines : #print "@tmp[0]\n"; my $type = $tmp[1]; $type = trim($type); if($type eq "PeerStatus"){ @tmp = split(/:/,$lines[6]); my $status = $tmp[1]; $status = trim($status); #print "My Status is: $status\n"; @tmp = split(/:/,$lines[2]); #line3 hold username @tmp = split(/\//,$tmp[1]); #Since username= SIP/username so split the string on "/" basis. my $USER = $tmp[1]; # arr[0] is SIP arr[1] is username; $USER = trim($USER); # Remove forward or trailing whitespaces.. if( ($status eq "Registered") and ($user_hash{$USER} eq "enabled") ){ @tmp = split(/:/,$lines[3]); my $IP = $tmp[1]; $IP = trim($IP); @tmp = split(/:/,$lines[4]); my $PORT = $tmp[1]; $PORT= trim($PORT); &ProcessQueue($USER,$IP,$PORT); } } else{ return 0; } } sub UpdateUserStatusHash(){ my $dsn = "DBI:mysql:dbname:localhost:3306"; my $dbh = DBI->connect($dsn,'usrname','pass') or die "Couldn't connect to database: " . DBI->errstr;#connect to DB my $sth = $dbh->prepare("SELECT username , cloneline FROM did where cloneline ='enabled'") or die "Couldn't prepare statement: " . $dbh->errstr; $sth->execute() or die "Couldn't execute statement: " .$sth->errstr; my @data; my %user_hash_tmp = ""; while(@data = $sth->fetchrow_array){ #print "$data[0] : @data[1] \n"; $user_hash_tmp{$data[0]} = $data[1]; } $sth->finish(); $dbh->disconnect(); # if any user disabled the clone line then remove the file... foreach my $key ( keys %user_hash ){ #print "key: $key, value: $hash{$key}\n"; if( ($user_hash{$key}) ne ($user_hash_tmp{$key})) { my $path = "/var/lib/asterisk/users/".$key; delete $hash{$key}; print $path."\n"; my $command = "rm -rf $path"; system($command); } } %user_hash = ""; %user_hash = %user_hash_tmp; %user_hash_tmp = ""; } #============================================================ sub ProcessQueue(){ my $USER= shift; #USERNAME, IP, Port <------ my $IP= shift; my $PORT= shift; my $ip1 = $hash{$USER}{0}{0}; # first IP:port my $ip2 = $hash{$USER}{1}{0}; # second IP:port # print "IP1:$ip1\n"; # print "IP2:$ip2\n"; if($hash{$USER}{0}{0} eq ""){ print "+++++++++ Case First Registration++++++++++++\n"; $hash{$USER}{0}{0} ="$IP:$PORT"; $hash{$USER}{0}{1} = Time::HiRes::time(); print "First Registration for User: $USER\n"; print "IP1:Port ".$hash{$USER}{0}{0}."\n"; print "Time $hash{$USER}{0}{1} \n"; #&DBPut($USER,$IP,$PORT); &PutFile($USER,$IP,$PORT); } elsif($ip1 eq "$IP:$PORT"){ print "+++++++++++ Case - 1 ++++++++++++++\n"; print "User:$USER : Alread Registered @ $IP\n"; print "Updating Time Stamp\n"; $hash{$USER}{0}{1} = Time::HiRes::time(); print "IP1:".$hash{$USER}{0}{0}."\n"; my $tmp = $hash{$USER}{0}{1}; print "Time $tmp \n"; print "IP2:".$hash{$USER}{1}{0}."\n"; $tmp = $hash{$USER}{1}{1}; print "Time $tmp \n"; } elsif( $ip2 eq "$IP:$PORT"){ # skip the packet processing.... print "++++++++++++ Case - 2 +++++++++++++++\n"; print "User:$USER : Alread Registered @ $IP:$PORT\n"; print "Updating Time Stamp\n"; # print "loocha comes here\n"; # print "ip2: $ip2 \n"; # print "IP:PORT $IP:$PORT\n"; # print "Before\n"; my $tmp1 = $hash{$USER}{0}{0}; my $tmp2 = $hash{$USER}{0}{1}; $hash{$USER}{0}{0} = "$IP:$PORT"; $hash{$USER}{0}{1} = Time::HiRes::time(); $hash{$USER}{1}{0} = $tmp1; $hash{$USER}{1}{1} = $tmp2; print "IP1:".$hash{$USER}{0}{0}."\n"; my $tmp = $hash{$USER}{0}{1}; print "Time $tmp \n"; print "IP2:".$hash{$USER}{1}{0}."\n"; $tmp = $hash{$USER}{1}{1}; print "Time $tmp \n"; print "++++++++++++++++++++++++++++++++++++++++++\n"; } else{ print "+++++++++ Case New User++++++++++++++\n"; print "New User:$USER found IP:Port@ $IP:$PORT\n"; $hash{$USER}{1}{0} = $hash{$USER}{0}{0}; $hash{$USER}{1}{1} = $hash{$USER}{0}{1}; $hash{$USER}{0}{0} = "$IP:$PORT"; $hash{$USER}{0}{1} = Time::HiRes::time(); print "IP1:".$hash{$USER}{0}{0}."\n"; my $tmp = $hash{$USER}{0}{1}; print "Time $tmp \n"; print "IP2:".$hash{$USER}{1}{0}."\n"; $tmp = $hash{$USER}{1}{1}; print "Time $tmp \n"; #&DBUpdate_1($USER,$IP,$PORT); my @tmp1 = split(/:/,$hash{$USER}{0}{0}); my @tmp2 = split(/:/,$hash{$USER}{1}{0}); #&DBUpdate_3($USER,$IP,$PORT,$tmp[0],$tmp[1]); &UpdateFile($USER,$tmp1[0],$tmp1[1],$tmp2[0],$tmp2[1]); print "++++++++++++++++++++++++++++++++++++++++++\n"; } } sub trim() { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } sub PutFile(){ my $USER = shift; my $IP = shift; my $PORT = shift; my $str = "SIP/$USER@"."$IP:$PORT"; my $path = ">/var/lib/asterisk/users/".$USER; open(FH,$path) or die "FAILED:: $!"; print FH $str; print FH "\n"; close(FH); } sub UpdateFile(){ my $USER = shift; my $IP = shift; my $PORT = shift; my $IP2 = shift; my $PORT2 = shift; my $str = "SIP/$USER@"."$IP:$PORT\n"."SIP/$USER@"."$IP2:$PORT2"; #print "I am writing file \n".$str; my $path = ">/var/lib/asterisk/users/".$USER; open(FH,$path) or die "FAILED:: $!"; print FH $str; print FH "\n"; close(FH); } #$manager_sock->send("Action: command\r\ncommand: reload\r\n\r\n"); #$manager_sock->close();