diff --git a/library/media_sessions.php b/library/media_sessions.php
index fb88cf2..d6c4698 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 (!is_array($this->summary) || !count($this->summary)) {
return;
}
if (count($this->allowedDomains)) {
print "
|
Address
|
Relayed traffic |
Sessions |
Streams |
Status |
";
} else {
print "
|
Address
|
Version
|
Uptime |
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(
"
%d |
%s |
%s |
%d |
%s |
%s |
",
$i,
$this->ip2host($relay['ip']),
$this->normalizeTraffic($relay['bps_relayed']),
$relay['session_count'],
$streams,
$relayStatus
);
} else {
printf(
"
%d |
%s |
%s |
%s |
%s |
%d |
%s |
%s |
",
$i,
$this->ip2host($relay['ip']),
$relay['version'],
$this->normalizeTime($relay['uptime']),
$this->normalizeTraffic($relay['bps_relayed']),
$relay['session_count'],
$streams,
$relayStatus
);
}
$i++;
}
print "
";
}
public function showSessions()
{
- if (!count($this->sessions)) {
+ if (!is_array($this->sessions) || !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(
'
%s |
%s |
|
',
$fromImage,
$toImage,
$from,
$sessionId,
$to
);
// Header row for call sessions
printf(
'
|
Type/Codec |
Caller address |
Relay caller |
Relay callee |
Callee address |
Status |
Duration |
Bytes Caller |
Bytes Called |
',
$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);
} 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(
'
%s %s |
%s |
%s |
%s |
%s |
%s |
%s |
%s |
%s |
',
$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 "
";
}
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(
'',
$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);
}
}
?>