diff --git a/library/media_sessions.php b/library/media_sessions.php index a76b334..19c2a38 100644 --- a/library/media_sessions.php +++ b/library/media_sessions.php @@ -1,803 +1,803 @@ dispatcher = $dispatcher; $this->filters = $filters; $this->allowedDomains = $allowedDomains; $this->getUserAgentPictures(); } public function getUserAgentPictures() { global $userAgentImages; global $userAgentImagesFile; if (!isset($userAgentImagesFile)) { $userAgentImagesFile = "phone_images.php"; } require_once "$userAgentImagesFile"; $this->userAgentImages = $userAgentImages; } private function connectSocket() { if (!strlen($this->dispatcher)) { return false; } if (preg_match("/^(tls|tcp):(.*):(.*)$/", $this->dispatcher, $m)) { $hostname = $m[1].'://'.$m[2]; $port = $m[3]; $target = 'tcp://'.$m[2].':'.$m[3]; $transport = $m[1]; $this->mp_tls_cert_file = '/etc/cdrtool/mediaproxy.'.$m[2].'.pem'; if ($m[1] == 'tls') { if (!file_exists($this->mp_tls_cert_file)) { printf( "

Error: mediaproxy certificate file %s does not exist. \n", $this->mp_tls_cert_file ); return false; } $tls_options=array('ssl' => array('local_cert' => $this->mp_tls_cert_file)); $context = stream_context_create($tls_options); } else { $context = stream_context_create(array()); } } else { printf( "

Error: MediaProxy dispatcher '%s' must be in the form: tls:hostname:port or tcp:hostname:port", $this->dispatcher ); return false; } if ($fp = stream_socket_client($target, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context)) { if ($transport == "tls") { if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)) { printf("

Error connecting to %s: (Could not enable crypto) \n", $target); return false; } } return $fp; } else { printf("

Error connecting to %s: %s (%s) \n", $target, $errstr, $errno); return false; } } public function fetchSessionFromNetwork() { // get sessions from MediaProxy2 dispatcher if (!$fp = $this->connectSocket()) { return array(); } fputs($fp, "sessions\r\n"); $line = fgets($fp); return json_decode($line); } public function fetchSummaryFromNetwork() { // get summary from MediaProxy2 dispatcher if (count($this->allowedDomains)) { return array(); } if (!$fp = $this->connectSocket()) { return array(); } fwrite($fp, "summary\r\n"); $line = fgets($fp); fclose($fp); return json_decode($line, true); } public function getSessions() { $_sessions = $this->fetchSessionFromNetwork(); if (count($this->allowedDomains)) { $this->domain_statistics['total'] = array( 'sessions' => 0, 'caller' => 0, 'callee' => 0 ); foreach ($_sessions as $_session) { list($user1, $domain1) = explode("@", $_session->from_uri); list($user2, $domain2) = explode("@", $_session->to_uri); if (preg_match("/^(.*):/", $domain1, $m)) { $domain1 = $m[1]; } $may_display = false; foreach ($this->allowedDomains as $allow_domain) { if ($this->endsWith($domain1, $allow_domain)) { $may_display = true; break; } if ($this->endsWith($domain2, $allow_domain)) { $may_display = true; break; } } if (!$may_display) { continue; } if (!array_key_exists($domain1, $this->domain_statistics)) { $this->domain_statistics[$domain1] = array( 'sessions' => 0, 'caller' => 0, 'callee' => 0 ); } $this->domain_statistics[$domain1]['sessions']++; $this->domain_statistics['total']['sessions']++; foreach ($_session->streams as $streamInfo) { list($relay_ip, $relay_port) = explode(":", $streamInfo->caller_local); $_relay_statistics[$relay_ip]['stream_count'][$streamInfo->media_type]++; if ($_session->duration) { $session_bps = ($streamInfo->caller_bytes + $streamInfo->callee_bytes) / $_session->duration * 8; $_relay_statistics[$relay_ip]['bps_relayed'] = $_relay_statistics[$relay_ip]['bps_relayed'] + $session_bps; } $this->domain_statistics[$domain1]['caller'] = $this->domain_statistics[$domain1]['caller'] + intval($streamInfo->caller_bytes / $_session->duration * 2); $this->domain_statistics['total']['caller'] = $this->domain_statistics['total']['caller'] + intval($streamInfo->caller_bytes / $_session->duration * 2); $this->domain_statistics[$domain1]['callee'] = $this->domain_statistics[$domain1]['callee'] + intval($streamInfo->callee_bytes / $_session->duration * 2); $this->domain_statistics['total']['callee'] = $this->domain_statistics['total']['callee'] + intval($streamInfo->callee_bytes/$_session->duration * 2); } $_relay_statistics[$relay_ip]['session_count']++; $_sessions2[] = $_session; } } else { $this->domain_statistics['total'] = array( 'sessions' => 0, 'caller' => 0, 'callee' => 0 ); foreach ($_sessions as $_session) { list($user1, $domain1) = explode("@", $_session->from_uri); list($user2, $domain2) = explode("@", $_session->to_uri); if (preg_match("/^(.*):/", $domain1, $m)) { $domain1=$m[1]; } if (!array_key_exists($domain1, $this->domain_statistics)) { $this->domain_statistics[$domain1]= array( 'sessions' => 0, 'caller' => 0, 'callee' => 0 ); } $this->domain_statistics[$domain1]['sessions']++; $this->domain_statistics['total']['sessions']++; foreach ($_session->streams as $streamInfo) { if ($_session->duration) { $this->domain_statistics[$domain1]['caller'] = $this->domain_statistics[$domain1]['caller'] + intval($streamInfo->caller_bytes / $_session->duration * 2); $this->domain_statistics['total']['caller'] = $this->domain_statistics['total']['caller'] + intval($streamInfo->caller_bytes / $_session->duration * 2); $this->domain_statistics[$domain1]['callee'] = $this->domain_statistics[$domain1]['callee'] + intval($streamInfo->callee_bytes / $_session->duration * 2); $this->domain_statistics['total']['callee'] = $this->domain_statistics['total']['callee'] + intval($streamInfo->callee_bytes / $_session->duration * 2); } } } $_sessions2 = $_sessions; } if (count($this->allowedDomains)) { foreach (array_keys($_relay_statistics) as $_ip) { $this->relay_statistics[] = array( 'ip' => $_ip, 'bps_relayed' => $_relay_statistics[$_ip]['bps_relayed'], 'session_count' => $_relay_statistics[$_ip]['session_count'], 'stream_count' => $_relay_statistics[$_ip]['stream_count'], 'status' => 'ok', 'uptime' => 'unknown' ); } } if (strlen($this->filters['user'])) { foreach ($_sessions2 as $_session) { $user=$this->filters['user']; if (preg_match("/$user/", $_session->from_uri) || preg_match("/$user/", $_session->to_uri)) { $this->sessions[] = $_session; } } } else { $this->sessions = $_sessions2; } } public function getSummary() { if (count($this->allowedDomains)) { if (is_array($this->relay_statistics)) { $this->summary = $this->relay_statistics; } } else { $this->summary = $this->fetchSummaryFromNetwork(); } } public function showSearch() { printf( "

", $_SERVER['PHP_SELF'], isset($_REQUEST['user']) ? $_REQUEST['user'] : '' ); print ""; } public function showHeader() { print " Media sessions "; } public function showFooter() { } public function showAll() { $this->showHeader(); if (!$this->allowedDomains) { $this->showSummary(); } $this->showSearch(); $this->showSessions(); $this->showFooter(); } public function showSummary() { $this->getSummary(); if (!count($this->summary)) { return; } if (count($this->allowedDomains)) { print "
"; } else { print "
Address Relayed traffic Sessions Streams Status
"; } $i = 1; foreach ($this->summary as $relay) { unset($media_types); unset($streams); $streams = ''; $media_types=count($relay['stream_count']); if ($media_types > 1) { foreach (array_keys($relay['stream_count']) as $key) { $streams .= sprintf("%s %s, ", $key, $relay['stream_count'][$key]); } $streams=chop($streams, ', '); } else { foreach (array_keys($relay['stream_count']) as $key) { $streams=sprintf("%s %s", $key, $relay['stream_count'][$key]); } } $rClass= 'label-success'; if ($relay['status'] == 'halting') { $rClass = 'label-warning'; } $relayStatus = sprintf("%s", $rClass, ucfirst($relay['status'])); if (count($this->allowedDomains)) { printf( " ", $i, $this->ip2host($relay['ip']), $this->normalizeTraffic($relay['bps_relayed']), $relay['session_count'], $streams, $relayStatus ); } else { printf( " ", $i, $this->ip2host($relay['ip']), $relay['version'], $this->normalizeTime($relay['uptime']), $this->normalizeTraffic($relay['bps_relayed']), $relay['session_count'], $streams, $relayStatus ); } $i++; } print "
Address Version Uptime Relayed traffic Sessions Streams Status
%d %s %s %d %s %s
%d %s %s %s %s %d %s %s
"; } public function showSessions() { if (!count($this->sessions)) { print '

Sessions

'; return; } printf('

Sessions (%d)

', count($this->sessions)); print ''; foreach ($this->sessions as $session) { $from = $session->from_uri; $to = $session->to_uri; $sessionId = $session->call_id; # rtrim(base64_encode(hash('md5', $session->call_id, true)), "="); $fromAgent = $session->caller_ua; $toAgent = $session->callee_ua; $fromImage = $this->getImageForUserAgent($fromAgent); $toImage = $this->getImageForUserAgent($toAgent); $streamsRowSpan = count($session->streams) + 1; printf( ' ', $fromImage, $toImage, $from, $sessionId, $to ); // Header row for call sessions printf( ' ', $streamsRowSpan ); $duration = $this->normalizeTime($session->duration); if (count($session->streams) > 0) { foreach ($session->streams as $streamInfo) { $status = $streamInfo->status; $statusClass = ""; if ($status == "idle" || $status == "hold") { $idletime = $this->normalizeTime($streamInfo->timeout_wait); $status = sprintf("%s %s", $status, $idletime); - } else if ($status == "closed") { + } elseif ($status == "closed") { $statusClass = "muted"; } $caller = $streamInfo->caller_remote; $callee = $streamInfo->callee_remote; $relay_caller = $streamInfo->caller_local; $relay_callee = $streamInfo->callee_local; if (substr_count($relay_caller, ":") == 1) { // Probaly ipv4 $relay_caller_data = explode(":", $relay_caller); $relay_caller = $this->ip2host($relay_caller_data[0]).":".$relay_caller_data[1]; } if (substr_count($relay_callee, ":") == 1) { // Probaly ipv4 $relay_callee_data = explode(":", $relay_callee); $relay_callee = $this->ip2host($relay_callee_data[0]).":".$relay_callee_data[1]; } $codec = $streamInfo->caller_codec; $type = $streamInfo->media_type; if ($caller == '?.?.?.?:?') { $caller = '–'; // a dash $align1 = 'center'; } else { $align1 = 'left'; } if ($callee == '?.?.?.?:?') { $callee = '–'; // a dash $align2 = 'center'; } else { $align2 = 'left'; } if ($codec == 'Unknown') { $codec = '–'; // a dash } else { $codec = "$codec"; } if ($type == 'Unknown') { $type = '–'; // a dash } elseif ($type == 'video') { $type = "$type"; } elseif ($type == 'audio') { $type = "$type"; } else { $type = "$type"; } $bytes_in1 = $this->normalizeBytes($streamInfo->caller_bytes); $bytes_in2 = $this->normalizeBytes($streamInfo->callee_bytes); printf( ' ', $statusClass, $type, $codec, $statusClass, $align1, $caller, $statusClass, $relay_caller, $statusClass, $relay_callee, $statusClass, $align2, $callee, $statusClass, $status, $statusClass, $duration, $statusClass, $bytes_in1, $statusClass, $bytes_in2 ); } } else { print ''; } // Spacer row print ''; } print "
%s %s
From: %s
- %s + %s
To: %s
Type/Codec Caller address Relay caller Relay callee Callee address Status Duration Bytes Caller Bytes Called
%s %s %s %s %s %s %s %s %s %s
 
 

"; } private function normalizeBytes($bytes) { $mb = $bytes / 1024 / 1024.0; $kb = $bytes / 1024.0; if ($mb >= 0.95) { return sprintf("%.2fM", $mb); } elseif ($kb >= 1) { return sprintf("%.2fk", $kb); } else { return sprintf("%d", $bytes); } } private function normalizeTime($period) { $sec = $period % 60; $min = floor($period / 60); $h = floor($min / 60); $d = floor($h / 24); $min = $min % 60; $h = $h % 24; if ($d >= 1) { return sprintf('%dd %dh %02d\' %02d"', $d, $h, $min, $sec); } else if ($h >= 1) { return sprintf('%dh %02d\' %02d"', $h, $min, $sec); } else { return sprintf('%d\' %02d"', $min, $sec); } } private function normalizeTraffic($traffic) { // input is in bits/second $mb = $traffic / 1024 / 1024.0; $gb = $traffic / 1024 / 1024 / 1024; $kb = $traffic / 1024.0; if ($gb >= 0.95) { return sprintf("%.2f Gbit/s", $gb); } elseif ($mb >= 0.95) { return sprintf("%.2f Mbit/s", $mb); } elseif ($kb >= 1) { return sprintf("%.2f Kbit/s", $kb); } elseif ($traffic == 0) { return $traffic; } else { return sprintf("%d bit/s", $traffic); } } public function getImageForUserAgent($agent) { foreach ($this->userAgentImages as $agentRegexp => $image) { if (preg_match("/$agentRegexp/i", $agent)) { if ($image == 'asterisk.png') { return sprintf( '', $agent, $agent ); } return sprintf( '%s', $image, $agent, $agent, $agent ); } } return ""; } public function ip2host($ip) { return $ip; } } class MediaSessionsNGNPro extends MediaSessions { private $soapEngineId; private $SOAPlogin; private $SoapAuth; private $SOAPurl; private $soapclient; // get Media session from NGNPro public function __construct($engineId, $allowedDomains = array(), $filters = array()) { if (!strlen($engineId)) { return false; } $this->soapEngineId = $engineId; $this->filters = $filters; $this->allowedDomains = $allowedDomains; $this->getUserAgentPictures(); require "/etc/cdrtool/ngnpro_engines.inc"; require_once "ngnpro_soap_library.php"; if (!strlen($this->soapEngineId)) { return false; } if (!$soapEngines[$this->soapEngineId]) { return false; } $this->SOAPlogin = array( "username" => $soapEngines[$this->soapEngineId]['username'], "password" => $soapEngines[$this->soapEngineId]['password'], "admin" => true ); $this->SOAPurl = $soapEngines[$this->soapEngineId]['url']; $this->SoapAuth = array('auth', $this->SOAPlogin , 'urn:AGProjects:NGNPro', 0, ''); // Instantiate the SOAP client $this->soapclient = new WebService_NGNPro_SipPort($this->SOAPurl); $this->soapclient->setOpt('curl', CURLOPT_TIMEOUT, 5); $this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0); $this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0); if (is_array($soapEngines[$this->soapEngineId]['hostnames'])) { $this->hostnames = $soapEngines[$this->soapEngineId]['hostnames']; } else { $this->hostnames = array(); } } public function fetchSessionFromNetwork() { if (!is_object($this->soapclient)) { return false; } $this->soapclient->addHeader($this->SoapAuth); $result = $this->soapclient->getMediaSessions(); if ((new PEAR)->isError($result)) { $error_msg = $result->getMessage(); $error_fault = $result->getFault(); $error_code = $result->getCode(); printf( "Error from %s: %s: %s", $this->SOAPurl, $error_fault->detail->exception->errorcode, $error_fault->detail->exception->errorstring ); return false; } return json_decode($result); } public function fetchSummaryFromNetwork() { if (!is_object($this->soapclient)) { return array(); } $this->soapclient->addHeader($this->SoapAuth); $result = $this->soapclient->getMediaSummary(); if ((new PEAR)->isError($result)) { $error_msg = $result->getMessage(); $error_fault = $result->getFault(); $error_code = $result->getCode(); printf( "Error from %s: %s: %s", $this->SOAPurl, $error_fault->detail->exception->errorcode, $error_fault->detail->exception->errorstring ); return array(); } return json_decode($result, true); } public function ip2host($ip) { if ($this->hostnames[$ip]) { return $this->hostnames[$ip]; } else { return $ip; } } public function endsWith($string, $endString) { $len = strlen($endString); if ($len == 0) { return true; } return (substr($string, -$len) === $endString); } } ?> diff --git a/library/sip_statistics.php b/library/sip_statistics.php index 596d015..5a90709 100644 --- a/library/sip_statistics.php +++ b/library/sip_statistics.php @@ -1,982 +1,982 @@ isError($result); } private function checkLogSoapError($result, $syslog = false, $print = false) { if (!$this->soapHasError($result)) { return false; } $error_msg = $result->getMessage(); $error_fault= $result->getFault(); $error_code = $result->getCode(); $log = sprintf( "Error from %s: %s: %s", $this->SOAPurl, $error_fault->detail->exception->errorcode, $error_fault->detail->exception->errorstring ); return true; } public function __construct($engineId, $allowedDomains = array()) { if (!strlen($engineId)) { return false; } $this->allowedDomains = $allowedDomains; $this->soapEngineId = $engineId; require "/etc/cdrtool/ngnpro_engines.inc"; require_once "ngnpro_soap_library.php"; $this->SOAPlogin = array( "username" => $soapEngines[$this->soapEngineId]['username'], "password" => $soapEngines[$this->soapEngineId]['password'], "admin" => true ); $this->SOAPurl = $soapEngines[$this->soapEngineId]['url']; $this->SoapAuth = array('auth', $this->SOAPlogin , 'urn:AGProjects:NGNPro', 0, ''); $this->soapclient = new WebService_NGNPro_NetworkPort($this->SOAPurl); $this->soapclient->setOpt('curl', CURLOPT_TIMEOUT, 5); $this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYPEER, 0); $this->soapclient->setOpt('curl', CURLOPT_SSL_VERIFYHOST, 0); if (is_array($soapEngines[$this->soapEngineId]['hostnames'])) { $this->hostnames = $soapEngines[$this->soapEngineId]['hostnames']; } else { $this->hostnames = array(); } } public function getStatistics() { $this->soapclient->addHeader($this->SoapAuth); $result = $this->soapclient->getStatistics(); if ($this->checkLogSoapError($result)) { return false; } $this->statistics = json_decode($result, true); foreach (array_keys($this->statistics) as $_ip) { if ($_ip == 'summary') { foreach (array_keys($this->statistics[$_ip]) as $_role) { if ($_role == 'sip_proxy') { foreach (array_keys($this->statistics[$_ip][$_role]) as $_section) { foreach (array_keys($this->statistics[$_ip][$_role][$_section]) as $_domain) { if (count($this->allowedDomains) && !in_array($_domain, $this->allowedDomains)) { continue; } if (count($this->allowedDomains) && !in_array($_section, $this->allowedSummary)) { continue; } $this->sip_summary[$_section]=$this->sip_summary[$_section]+$this->statistics[$_ip][$_role][$_section][$_domain]; } } } } continue; } foreach (array_keys($this->statistics[$_ip]) as $_role) { if ($_role == 'sip_proxy') { $this->node_statistics[$_ip]['sip_proxy']=true; foreach (array_keys($this->statistics[$_ip][$_role]) as $_section) { foreach (array_keys($this->statistics[$_ip][$_role][$_section]) as $_domain) { if (count($this->allowedDomains) && !in_array($_domain, $this->allowedDomains)) { continue; } $this->domain_statistics[$_domain][$_section] = $this->domain_statistics[$_domain][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain]; $this->domain_statistics['total'][$_section] = $this->domain_statistics['total'][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain]; $this->node_statistics[$_ip][$_section] = $this->node_statistics[$_ip][$_section] + $this->statistics[$_ip][$_role][$_section][$_domain]; } } } } } } public function getStatus() { $this->soapclient->addHeader($this->SoapAuth); $result = $this->soapclient->getStatus(); if ($this->checkLogSoapError($result)) { return false; } $this->status = json_decode($result, true); foreach (array_keys($this->status) as $_id) { foreach ($this->status[$_id]['roles'] as $_role) { if ($_role == 'sip_proxy') { $this->sip_proxies[$this->status[$_id]['ip']]++; } if ($_role == 'thor_dnsmanager') { $this->dns_managers[$this->status[$_id]['ip']]++; } if ($_role == 'thor_manager') { $this->thor_managers[$this->status[$_id]['ip']]++; } if ($_role == 'conference_server') { $this->conference_servers[$this->status[$_id]['ip']]++; } if ($_role == 'voicemail_server') { $this->voicemail_servers[$this->status[$_id]['ip']]++; } $ip=$this->status[$_id]['ip']; $this->roles[$_role][$ip]=array( 'ip' => $ip, 'version' => $this->status[$_id]['version'] ); foreach (array_keys($this->status[$_id]) as $_attr) { if ($_attr == 'ip' || $_attr == 'version' || $_attr == 'roles') { continue; } $this->roles[$_role][$ip]['attributes'][$_attr]=$this->status[$_id][$_attr]; } } } } public function showStatus() { $this->getStatus(); print "
"; print ""; if (count($this->allowedDomains)) { print ""; } else { print ""; } foreach (array_keys($this->roles) as $_role) { if (count($this->allowedDomains)) { if (!in_array($_role, $this->allowedRoles)) { continue; } } foreach ($this->roles[$_role] as $_entity) { if (!$print_role[$_role]) { $_role_print = preg_replace("/_/", " ", $_role); } else { $_role_print = ''; } if (count($this->allowedDomains)) { printf( "", ucfirst($_role_print), $this->ip2host($_entity['ip']), $_entity['version'] ); } else { $a_print = ''; if (is_array($_entity['attributes'])) { foreach (array_keys($_entity['attributes']) as $_a1) { if ($_a1 == 'dburi') { if (preg_match("/^(mysql:\/\/\w*):\w*(@.*)$/", $_entity['attributes'][$_a1], $m)) { $val = $m[1].':xxx'.$m[2]; } else { $val = $_entity['attributes'][$_a1]; } } else { $val=$_entity['attributes'][$_a1]; } $a_print .= sprintf("%s=%s ", $_a1, $val); } } printf( "", ucfirst($_role_print), $this->ip2host($_entity['ip']), $_entity['version'], $a_print ); } $print_role[$_role]++; } } print "
RoleAddressVersion
RoleAddressVersionAttributes
%s%s%s
%s%s%s%s
"; } public function showStatistics() { $this->getStatistics(); print "
"; print ""; foreach (array_keys($this->sip_summary) as $_section) { $_section_print = preg_replace("/_/", " ", $_section); printf("", ucfirst($_section_print)); } print ""; foreach (array_keys($this->sip_summary) as $_section) { printf("", $this->sip_summary[$_section]); } print ""; print "
%s
%s
"; } private function ip2host($ip) { if ($this->hostnames[$ip]) { return $this->hostnames[$ip]; } else { return $ip; } } } class SipThorNetworkImage { // plot graphical SIP Thor network status public $imgsize = 630; public $nodes = array(); public $node_statistics = array(); public $display_options = array(); public $accounts_item = 'online_accounts'; public function __construct($engineId, $allowedDomains = array(), $display_options = array()) { if (!strlen($engineId)) { return false; } if (is_array($display_options)) { $this->display_options = $display_options; } if (array_key_exists('accounts_item', $this->display_options)) { $this->accounts_item=$this->display_options['accounts_item']; } $this->soapEngineId=$engineId; $NetworkStatistics = new NetworkStatistics($engineId, $allowedDomains); $NetworkStatistics->getStatus(); $NetworkStatistics->getStatistics(); $this->sip_proxies = $NetworkStatistics->sip_proxies; $this->conference_servers = $NetworkStatistics->conference_servers; $this->voicemail_servers = $NetworkStatistics->voicemail_servers; $this->dns_managers = $NetworkStatistics->dns_managers; $this->thor_mangers = $NetworkStatistics->thor_managers; $this->node_statistics = $NetworkStatistics->node_statistics; $this->hostnames = $NetworkStatistics->hostnames; if (!$this->display_options['hide_sessions']) { require_once("media_sessions.php"); $MediaSessions = new MediaSessionsNGNPro($engineId); $MediaSessions->getSummary(); foreach ($MediaSessions->summary as $_relay) { $this->node_statistics[$_relay['ip']]['sessions']=$_relay['session_count']; } } } public function returnImageData() { if ($this->display_options['hide_accounts']) { foreach ($this->node_statistics as $key => $value) { if ($value['sip_proxy']) { $this->node_statistics[$key] = array(); $this->node_statistics[$key]['sip_proxy'] = true; } } } return $this; } public function buildImage() { $img = imagecreatetruecolor($this->imgsize, $this->imgsize); $white = imagecolorallocate($img, 255, 255, 255); $black = imagecolorallocate($img, 0, 0, 0); imagefill($img, 0, 0, $white); $c=count($this->sip_proxies); $cx=$this->imgsize/2; $cy=$cx; $radius=0.7*$cx; // Sip Thor node image $sip_thor_node_img = @imagecreatefrompng('SipThorNode.png'); list($nw, $nh) = getimagesize('SipThorNode.png'); // Internet cloud Image $cloud_img = @imagecreatefrompng('InternetCloud.png'); list($cw, $ch) = getimagesize('InternetCloud.png'); // Sip Thor title rectangle image $sip_thor_background_img = @imagecreatefrompng('SipThorNetworkBackground.png'); list($tw, $th) = getimagesize('SipThorNetworkBackground.png'); if (!$this->display_options['hide_frame']) { imagecopy($img, $sip_thor_background_img, $this->imgsize/2-$tw/2, $this->imgsize/2-$th/2, 0, 0, $tw, $th); } imagecopy($img, $cloud_img, $this->imgsize/2-$cw/2, $this->imgsize/2-$ch/2, 0, 0, $cw, $ch); $dash=false; $dashsize=2; for ($angle=0; $angle<=(180+$dashsize); $angle+=$dashsize) { $x = ($radius * cos(deg2rad($angle))); $y = ($radius * sin(deg2rad($angle))); if ($dash) { imageline($img, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $black); imageline($img, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $black); } $dash=!$dash; $px=$x; $py=$y; if ($dash) { imageline($img, $cx+$px, $cy+$py, $cx+$x, $cy+$y, $black); imageline($img, $cx-$px, $cx-$py, $cx-$x, $cy-$y, $black); } } if (count($this->dns_managers)) { $h1=0; $t=count($this->dns_managers); foreach (array_keys($this->dns_managers) as $_ip) { imagecopy($img, $sip_thor_node_img, $this->imgsize - 120 - $h1, 0, 0, 0, $nw - 20, $nh - 20); $text = sprintf("DNS%s", $t--); imagestring($img, 3, $this->imgsize - 65 - $h1, 80, $text, $black); $v1 = $v1+10; $h1 = $h1+50; } $v1=100; foreach (array_keys($this->dns_managers) as $_ip) { imagestring($img, 3, $this->imgsize - 125, $v1, $_ip, $black); $v1=$v1+10; } } if (count($this->node_statistics)) { $dashsize=360/count($this->node_statistics); $j=0; $node_names=array_keys($this->node_statistics); for ($angle=0; $angle<360; $angle+=$dashsize) { $x = ($radius * cos(deg2rad($angle))); $y = ($radius * sin(deg2rad($angle))); if ($this->hostnames[$node_names[$j]]) { $text = $this->hostnames[$node_names[$j]]; // $text = $node_names[$j]; } else { $text = $node_names[$j]; } $px = $x; $py = $y; if (strlen($this->node_statistics[$node_names[$j]]['online_accounts']) && strlen($this->node_statistics[$node_names[$j]]['sessions'])) { if (!$this->display_options['hide_accounts']) { $extra_text1=intval($this->node_statistics[$node_names[$j]][$this->accounts_item]). ' accounts'; } if (!$this->display_options['hide_sessions']) { $extra_text2=intval($this->node_statistics[$node_names[$j]]['sessions']). ' sessions'; } } else if (strlen($this->node_statistics[$node_names[$j]]['online_accounts'])) { if (!$this->display_options['hide_accounts']) { $extra_text1=intval($this->node_statistics[$node_names[$j]][$this->accounts_item]). ' accounts'; } else { $extra_text1=$node_names[$j]; } $extra_text2=""; } else if (strlen($this->node_statistics[$node_names[$j]]['sessions'])) { if (!$this->display_options['hide_sessions']) { $extra_text1=intval($this->node_statistics[$node_names[$j]]['sessions']). ' sessions'; } $extra_text2=""; } if (($angle >= 120 && $angle < 240)) { imagestring($img, 3, $cx+$px-70, $cy+$py-72, $text, $black); imagestring($img, 3, $cx+$px-70, $cy+$py-62, $extra_text1, $black); imagestring($img, 3, $cx+$px-70, $cy+$py-52, $extra_text2, $black); } else { imagestring($img, 3, $cx+$px-110, $cy+$py-30, $text, $black); imagestring($img, 3, $cx+$px-110, $cy+$py-20, $extra_text1, $black); imagestring($img, 3, $cx+$px-110, $cy+$py-10, $extra_text2, $black); } imagecopy($img, $sip_thor_node_img, $cx + $px - $nw / 2 + 7, $cy + $py - $nh / 2 + 5, 0, 0, $nw - 20, $nh - 20); $j++; } } return $img; } } class SIPstatistics { // build graphical statistics with sip registrar and media relay usage private $path; private $harvest_file; private $harvest_script; private $mrtgcfg_dir; private $mrtgcfg_file; private $mrtg_data_script; private $mrtg_config_script; public $domains = array('total'=>'total'); public function __construct() { global $CDRTool; $this->path=$CDRTool['Path']; $this->harvest_file = "/tmp/CDRTool-sip-statistics.txt"; $this->harvest_script = $this->path."/scripts/harvestStatistics.php"; $this->mrtgcfg_dir = $this->path."/status/usage"; $this->mrtgcfg_file = $this->path."/status/usage/sip_statistics.mrtg"; $this->mrtg_data_script = $this->path."/scripts/generateMrtgData.php"; $this->mrtg_config_script = $this->path."/scripts/generateMrtgConfig.php"; $this->getDomains(); } private function getDomains() { global $CDRTool; if (!is_array($CDRTool['statistics']['domains'])) { return; } foreach ($CDRTool['statistics']['domains'] as $_domain) { $this->domains[$_domain]=$_domain; } } public function generateMrtgConfigFile() { if (!$handle = fopen($this->mrtgcfg_file, 'w+')) { echo "Error opening {$this->mrtgcfg_file}.\n"; return 0; } // printing cfg header fwrite($handle, " ### Global Config Options WorkDir: {$this->mrtgcfg_dir} IconDir: {$this->mrtgcfg_dir}/images Refresh: 300 #WriteExpires: Yes "); foreach ($this->domains as $key => $value) { fwrite($handle, "\n\n ## {$key} Target[{$key}_users]: `{$this->mrtg_data_script} {$key} users` Options[{$key}_users]: growright, gauge, nobanner BodyTag[{$key}_users]: #PNGTitle[{$key}_users]:
Online Users for {$key}
MaxBytes[{$key}_users]: 5000000 Title[{$key}_users]: Online Users for {$key} ShortLegend[{$key}_users]: U XSize[{$key}_users]: 300 YSize[{$key}_users]: 75 Ylegend[{$key}_users]: Users Legend1[{$key}_users]: Online Users LegendI[{$key}_users]: Online Users LegendO[{$key}_users]: PageTop[{$key}_users]:

Online Users for {$key}

Target[{$key}_sessions]: `{$this->mrtg_data_script} {$key} sessions` Options[{$key}_sessions]: growright, nobanner, gauge BodyTag[{$key}_sessions]: MaxBytes[{$key}_sessions]: 50000 Title[{$key}_sessions]: Sessions Statistics for {$key} ShortLegend[{$key}_sessions]: Ses XSize[{$key}_sessions]: 300 YSize[{$key}_sessions]: 75 Ylegend[{$key}_sessions]: Sessions Legend1[{$key}_sessions]: Active Sessions LegendI[{$key}_sessions]: Active Sessions LegendO[{$key}_sessions]: PageTop[{$key}_sessions]:

Active Sessions for {$key}

Target[{$key}_traffic]: `{$this->mrtg_data_script} {$key} traffic` Options[{$key}_traffic]: gauge, growright, bits, nobanner BodyTag[{$key}_traffic]: #PNGTitle[{$key}_traffic]: {$key} traffic MaxBytes[{$key}_traffic]: 1250000000 Title[{$key}_traffic]: IP traffic for {$key} XSize[{$key}_traffic]: 300 YSize[{$key}_traffic]: 75 Legend1[{$key}_traffic]: Caller Traffic in Bits per Second Legend2[{$key}_traffic]: Called Traffic in Bits per Second LegendI[{$key}_traffic]: caller LegendO[{$key}_traffic]: called PageTop[{$key}_traffic]:

IP Traffic for {$key}

"); } fclose($handle); } public function generateMrtgData($domain, $dataType) { $value1 = 0; $value2 = 0; $domain = str_replace(".", "\.", $domain); $lines = explode("\n", file_get_contents($this->harvest_file)); foreach ($lines as $line) { if (preg_match("/^$domain\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/", $line, $m)) { if ($dataType == 'sessions') { $value1 = $m[2]; $value2 = $m[2]; } else if ($dataType == 'traffic') { $value1 = $m[3]; $value2 = $m[4]; } else if ($dataType == 'users') { $value1 = $m[1]; $value2 = $m[1]; } } } printf("%d\n%d\n0\n0\n\n", $value1, $value2); } public function getOnlineAccountsFromMySQL($class) { $domains = array(); $online_devices = 0; $online_accounts = 0; if (!class_exists($class)) { return array(); } $db = new $class(); $query="select count(*) as c, domain from location group by domain"; dprint_sql($query); if (!$db->query($query)) { $log=sprintf("Database error for query %s: %s (%s)", $query, $db->Error, $db->Errno); print $log; syslog(LOG_NOTICE, $log); return array(); } if (!$db->num_rows()) { return array(); } while ($db->next_record()) { $domains[$db->f('domain')]['online_devices'] = intval($db->f('c')); $online_devices = $online_devices + intval($db->f('c')); } $query="select count(distinct(concat(username,domain))) as c, domain from location group by domain"; dprint_sql($query); if (!$db->query($query)) { $log = sprintf("Database error for query %s: %s (%s)", $query, $db->Error, $db->Errno); print $log; syslog(LOG_NOTICE, $log); return array(); } if (!$db->num_rows()) { return array(); } while ($db->next_record()) { $domains[$db->f('domain')]['online_accounts'] = intval($db->f('c')); $online_accounts=$online_accounts+intval($db->f('c')); } $domains['total']['online_devices']=$online_devices; $domains['total']['online_accounts']=$online_accounts; return $domains; } private function writeHarvestFile($body) { if (!strlen($body)) { return 0; } if (!$handle = fopen($this->harvest_file, 'w+')) { $log=sprintf("Error opening mrtg harvest file %s\n", $this->harvest_file); print $log; syslog(LOG_NOTICE, $log); return false; } fwrite($handle, $body); fclose($handle); } public function harvestStatistics() { global $DATASOURCES; $datasources = array_keys($DATASOURCES); $totals = array(); foreach ($datasources as $datasource) { if (!$DATASOURCES[$datasource]['skipStatistics']) { if ($DATASOURCES[$datasource]['mediaSessions']) { // MediaProxy 2 via NGNPro require_once("media_sessions.php"); $MediaSessions = new MediaSessionsNGNPro($DATASOURCES[$datasource]['mediaSessions']); $MediaSessions->getSessions(); $totals = array_merge_recursive($totals, $MediaSessions->domain_statistics); - } else if ($DATASOURCES[$datasource]['mediaDispatcher']) { + } elseif ($DATASOURCES[$datasource]['mediaDispatcher']) { // MediaProxy 2 via dispatcher tcp socket require_once("media_sessions.php"); $MediaSessions = new MediaSessions($DATASOURCES[$datasource]['mediaDispatcher']); $MediaSessions->getSessions(); $totals = array_merge_recursive($totals, $MediaSessions->domain_statistics); } if ($DATASOURCES[$datasource]['networkStatus']) { // OpenSIPS via NGNPro $NetworkStatistics = new NetworkStatistics($DATASOURCES[$datasource]['networkStatus']); $NetworkStatistics->getStatistics(); $totals = array_merge_recursive($totals, $NetworkStatistics->domain_statistics); - } else if ($DATASOURCES[$datasource]['db_registrar']) { + } elseif ($DATASOURCES[$datasource]['db_registrar']) { // OpenSIPS via MySQL query $db_registrar_domains=$this->getOnlineAccountsFromMySQL($DATASOURCES[$datasource]['db_registrar']); $totals = array_merge_recursive($totals, $db_registrar_domains); } } } $body="domains\t\t\tonline_accounts\tsessions\tcaller\tcallee\n\n"; foreach (array_keys($totals) as $_domain) { if (!$totals[$_domain]['online_accounts'] && !$totals[$_domain]['sessions']) { continue; } $body .= sprintf( "%s\t\t%d\t\t%d\t\t%s\t%s\n", $_domain, $totals[$_domain]['online_accounts'], $totals[$_domain]['sessions'], intval($totals[$_domain]['caller']), intval($totals[$_domain]['callee']) ); } $this->writeHarvestFile($body); } public function buildStatistics() { system($this->mrtg_config_script); system($this->harvest_script); system("env LANG=C mrtg $this->mrtgcfg_file"); } } /** * MRTGGraphs class sets up the dashboard and creates Entity objects. */ class MRTGGraphs { /** * MRTG entities * * @var array */ public $entities = array(); /** * Server hostname; * * @var type */ public $hostname; /** * Domains; * * @var type */ public $domains = array(); /** * Graphs types; * * @var type */ public $graph_types = array('users','sessions','traffic'); /** * Construct. */ public function __construct() { //require("sip_statistics.php"); $title='Platform usage'; if (is_readable("/etc/cdrtool/local/header.phtml")) { include("/etc/cdrtool/local/header.phtml"); } else { include("header.phtml"); } $layout = new pageLayoutLocal(); $layout->showTopMenu($title); global $CDRTool; $SIPstatistics = new SIPstatistics(); $allowedDomains = ''; if (strlen($CDRTool['filter']['domain'])) { $allowedDomains = explode(' ', $CDRTool['filter']['domain']); } if (is_array($allowedDomains)) { $domains = array_intersect($allowedDomains, array_keys($SIPstatistics->domains)); } else { $domains = array_keys($SIPstatistics->domains); } $this->domains[]= $domains; // read entities in directory for each entry in domain list foreach ($domains as $entity) { $entity = sprintf("status/usage/%s", $entity); foreach ($this->graph_types as $type) { $final_entity = sprintf("%s_%s.log", $entity, $type); $this->entities[] = new MRTGEntity(preg_replace("/.log$/", "", $final_entity)); } } $this->layout = $layout; // determine hostname exec("hostname -f", $hostname); $this->hostname = $hostname[0]; } } /** * Entity class represents each MRTG entity found in the directory. */ class MRTGEntity { /** * Entity name. * * @var string */ public $name; /** * Entity title. * * @var string */ public $title; /** * Entity page link. * * @var string */ public $link; /** * Entity log file. * * @var string */ public $log; /** * Construct. * * @throws Exception */ public function __construct($name) { // check entity exists if (!is_file("{$name}.html")) { throw new Exception("Could not find MRTG files for entity {$name}"); } // add name $this->name = $name; // create nicer-looking title $np = explode('_', $name); $this->title = preg_replace("/status\/usage\//", "", $np[0]); array_shift($np); if (in_array('users', $np) && strstr($this->title, 'total')) { $this->title = ucfirst($this->title)." SIP Accounts online"; } else if (in_array('users', $np)) { $this->title = "Online SIP accounts on $this->title"; } else if (in_array('traffic', $np) && strstr($this->title, 'total')) { $this->title = ucfirst($this->title)." relayed RTP traffic"; } else if (in_array('traffic', $np)) { $this->title = "Relayed RTP traffic for $this->title"; } else if (in_array('sessions', $np) && strstr($this->title, 'total')) { $this->title = ucfirst($this->title)." active RTP media sessions"; } else if (in_array('sessions', $np)) { $this->title = "Active RTP media sessions for $this->title"; } else { $this->title .= " (".implode(" ", $np).")"; } // add HTML and log files $this->link = $name.'.html'; $this->log = $name.'.log'; } /** * Retrieve and process the entity's log file. * * @param boolean $max Set to true to retrieve maximum in/out rather than average. * * @return string JSON encoded data */ public function retrieveLog($max = false) { // arrays for parsed data $in = $out = $stamps = array(); global $start_date,$stop_date; foreach (file("{$this->name}.log") as $line) { // ignore the summary line if (!isset($header)) { $header = $line; continue; } $parts = explode(' ', rtrim($line)); //if ($parts[1] == 0 && $parts[2] == 0 && $parts[3] == 0 && $parts[4] == 0) continue; if ($parts[0] < $start_date->getTimestamp()) { continue; } if ($parts[0] > $stop_date->getTimestamp()) { continue; } array_push($stamps, $parts[0]); if (strstr($this->name, 'traffic')) { if ($max) { $in[] = array($parts[0],round(($parts[3]*8)/1000)); $out[] = array($parts[0]*1000,round(($parts[4]*8)/1000)); } else { $in[] = array(date('Y-m-d H:i:s', $parts[0]), round(($parts[1]*8))); $out[] = array(date('Y-m-d H:i:s', $parts[0]), round(($parts[2]*8))); } } else { if ($max) { $in[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[3])); $out[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[4])); } else { $in[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[1])); $out[] = array(date('Y-m-d H:i:s', $parts[0]),round($parts[2])); } } } // determine earliest and latest timestamps $latest = array_shift($stamps); $earliest = array_pop($stamps); $interval = 300; // encode and return response return json_encode(array( 'earliest' => $earliest, 'latest' => $latest, 'start' => $start_date, 'stop' => $stop_date, 'interval' => $interval, 'intervalMin' => round($interval/60, 0), 'inData' => array_reverse($in), 'outData' => array_reverse($out) )); } } ?>