#!/usr/bin/perl use strict; use warnings; use Proc::Daemon; use File::Basename; use DBI; use Config::IniFiles; use POSIX qw(strftime); use Time::HiRes; use Cwd; use Switch; use IO::Socket; my $daemon = Proc::Daemon->new(pid_file => '/var/run/goip_daemon.pid', work_dir => getcwd()); my $PID = $daemon->Status(); if(!$PID){ $daemon->Init; } $PID = $daemon->Status(); my $continue = 1; $SIG{TERM} = sub { $continue = 0 }; my $LOGFILE = '/var/log/goip_daemon.log'; my $hostname = '127.0.0.1'; my $port = 3306; my $database = 'nextbilling'; my $user = 'root'; my $pass1 = 'senha'; my $has_conn = 0; my $conn = DBI->connect("DBI:mysql:database=$database;host=$hostname;port=$port",$user,$pass1, {AutoCommit =>1, mysql_auto_reconnect=>1}); if($conn){ $has_conn = 1; } open (LOG, ">","$LOGFILE") || die "Não foi possível abrir o arquivo de Logs!!!"; LOG->autoflush(1); logger("\r\n"); logger("=============== INICIANDO DAEMON PARA GW GOIP $PID =============","INFO"); logline(); sub db_reconnect { $conn ||= DBI->connect("DBI:mysql:database=$database;host=$hostname;port=$port",$user,$pass1); } sub logline { logger("--------------------------------------------------------------"); } sub logger { my $date = strftime "%F %H:%M:%S", localtime; my ($txt,$level) = @_; $level = 'INFO' unless ($level); print LOG "[$date] [$level] $txt\r\n"; } sub finalize { logger("============== DESLIGANDO GOIP DAEMON =============",'INFO'); } sub main { my($sock, $newmsg,$client_name, $MAXLEN, $PORTNO); $MAXLEN = 1024; $PORTNO = 44444; $sock = IO::Socket::INET->new( LocalPort => $PORTNO, Proto => 'udp') or die("SOCKET LISTEN: $@"); logger("Waiting UDP messages on port $PORTNO"); while($sock->recv($newmsg, $MAXLEN)){ my($port, $ipaddr) = sockaddr_in($sock->peername); my $client_ip = $sock->peerhost(); my $client_port = $sock->peerport(); my ($TYPE, $req_id, $gsm_id, $response, $pass, $gsm_status, $is_alive, $gsm_signal, $gsm_num, $gsm_imei, $gsm_imsi, $gsm_iccid); my @request = split(';',$newmsg); $client_name = gethostbyaddr($ipaddr, AF_INET); logger("\[$client_ip:$client_port\] Client $client_name requests: @request"); $TYPE = "KEEPALIVE"; $req_id = 0; $gsm_id = 0; $gsm_num = 0; $gsm_imei = 0; $gsm_imsi = 0; $gsm_iccid = 0; $gsm_signal = 0; $gsm_status = "LOGOUT"; $is_alive = 0; if(@request <= 1){ logger("INVALID REQUEST: @request"); $sock->send("OK"); next; } #TIPO: #KEEPALIVE: GOIP KEEPALIVE #STATE: GOIP CHANNEL STATE CHANGES | RETURNS: STATE XXXX OK #RECORD: GOIP STARTS A CALL | RETURNS: RECORD XXXX OK #REMAIN: AFTER EACH CALL, GOIP SEND REMAIN TIME TO SERVER | RETURNS: REMAIN XXXX OK foreach (@request) { my ($param, $value) = split(':',$_); switch($param){ case "req" { $req_id = $value; $TYPE = "KEEPALIVE"; } case "EXPIRY" { $req_id = $value; $TYPE = "EXPIRY"; } case "STATE" { $req_id = $value; $TYPE = "STATE"; } case "RECORD" { $req_id = $value; $TYPE = "RECORD"; } case "RECEIVE" { $req_id = $value; $TYPE = "RECEIVE"; } case "REMAIN" { $req_id = $value; $TYPE = "REMAIN"; } case "CELLS" { $req_id = $value; $TYPE = "CELLS"; } case "CELLINFO" { $req_id = $value; $TYPE = "CELLINFO"; } case "CGATT" { $req_id = $value; $TYPE = "CGATT"; } case "id" { $gsm_id = $value; } case "pass" { $pass = $value; } case "password" { $pass = $value; } case "gsm_status" { $gsm_status = $value; } case "num" { $gsm_num = $value; } case "imei" { $gsm_imei = $value; } case "imsi" { $gsm_imsi = $value; } case "iccid" { $gsm_iccid = $value; } case "signal" { $gsm_signal = $value; } } } switch($TYPE){ case "KEEPALIVE" { $response = "reg:$req_id;status:0;"; db_reconnect(); my $id_provedor = 0; my $sth = $conn->prepare(q { SELECT id FROM goip_gw WHERE password = ? LIMIT 1 }); $sth->execute("$pass"); my $res = $sth->fetchrow_hashref(); $id_provedor = (defined $res->{id}?$res->{id}:0); if($gsm_status eq "LOGOUT"){ $is_alive = 0; }else{ $is_alive = 1; } if($id_provedor > 0){ $sth = $conn->prepare(q { INSERT INTO goip_gw_ports (name, provider, host, port, password, alive, num, last_update, imei, imsi, iccid, `signal`) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), ?, ?, ?, ?) ON DUPLICATE KEY UPDATE host = VALUES(host), port = VALUES(port), alive = VALUES(alive), last_update = NOW(), imei = VALUES(imei), imsi = VALUES(imsi), iccid = VALUES(iccid), `signal` = VALUES(`signal`); }); $sth->execute("$gsm_id",$id_provedor,"$client_ip","$client_port","$pass","$is_alive","$gsm_num","$gsm_imei","$gsm_imsi","$gsm_iccid",$gsm_signal); } } case "STATE" { $response = "STATE $req_id OK"; } case "EXPIRY" { $response = "EXPIRY $req_id OK"; db_reconnect(); my $sth = $conn->prepare(q { DELETE FROM goip_gw_ports WHERE name = ? AND password = ? LIMIT 1 }); $sth->execute("$gsm_id","$pass"); } case "RECEIVE" { $response = "RECEIVE $req_id OK"; } case "REMAIN" { $response = "REMAIN $req_id OK"; } case "CELLS" { $response = "CELLS $req_id OK"; } case "CELLINFO" { $response = "CELLINFO $req_id OK"; } case "CGATT" { $response = "CGATT $req_id OK"; } else { $response = "reg:0;status:0;"; } } logger("SENDING RESPONSE: $response"); $sock->send($response); } goto FINAL; } while($continue){ main(); } FINAL: logline(); if($has_conn){ $conn->disconnect(); } finalize(); close (LOG);