Всем известно, что FreeSWITCH (FS) работает на конфигах XML. Все настройки пользователей (directory), dialplan и прочие, настраиваются именно в этих XML конфигах. Но, зачастую, очень хочется управлять пользователями и диалпланом "на лету", то есть, не перезагружая вручную модули и не касаясь FS в принципе. Кроме этого все будет настраиваться через веб-интерфейс, что в общем-то, достаточно удобно.
Для того, чтобы такую возможность воплотить в жизнь, в FS есть модуль mod_xml_curl. Также нужна будет база MySQL или PgSQL и веб сервер, на котором будет лежать PHP скрипт для формирования XML конфига.
Описывать как поднимать и настраивать Apache и MySQL я не стану. Уверен, что вы можете без труда сделать это самостоятельно. Опишу лишь основной алгоритм действий, который необходимо провести.
НАСТРОЙКА
Сначала, нам нужно в базу добавить базу и таблицу, например, в MySQL. Для этого выполняем:
create database freeswitch;
use freeswitch;
CREATE TABLE
`extensions` ( `userid` varchar(5) NOT NULL DEFAULT '',
`password` varchar(30) NOT NULL DEFAULT '',
`displayname` varchar(14) NOT NULL DEFAULT '',
`vmpasswd` varchar(10) DEFAULT NULL,
`accountcode` varchar(10) DEFAULT NULL,
`outbound_caller_id_name` varchar(14) DEFAULT NULL,
`outbound_caller_id_number` varchar(14) DEFAULT NULL );
Далее заполняем таблицу данными:
insert into extensions (userid,password,displayname,vmpasswd,accountcode,outbound_caller_id_name,outbound_caller_id_number) values
("1001","12345","Ivan Ivanov","12345","1001","Manager","+79261234567"),
("1002","12345","Vasya Pupkin","12345","1002","Boss","+79051234567");
select * from extensions;
После того, как у нас есть данные в базе пишем PHP скрипт, который будет эти данные выдергивать и формировать XML:
xml_handler.php
<?php=
function not_found()
{
Header("Content-type: text/xml");
$xmlw = new XMLWriter();
$xmlw -> openMemory();
$xmlw -> setIndent(true);
$xmlw -> setIndentString('');
$xmlw -> startDocument('1.0', 'UTF-8', 'no');
$xmlw -> startElement('document');
$xmlw -> writeAttribute('type', 'freeswitch/xml');
$xmlw -> startElement('section');
$xmlw -> writeAttribute('name', 'result');
$xmlw -> startElement('result');
$xmlw -> writeAttribute('status', 'not found');
$xmlw -> endElement(); //end result
$xmlw -> endElement(); //end section
$xmlw -> endDocument(); //end document
echo $xmlw -> outputMemory();
return TRUE;
}
function directory()
{
global $_SERVER;
global $_POST;
# connect to mysql
$connect = ($GLOBALS["___mysqli_ston"] = mysqli_connect("localhost", "root", "superPASS"));
mysqli_select_db( $connect, 'freeswitch') or die(mysqli_error($GLOBALS["___mysqli_ston"]));
# Query
$query = "SELECT * FROM extensions WHERE userid='" . $_POST['user'] . "'";
# perform the query
$result = mysqli_query( $connect, $query) or die(mysqli_error($GLOBALS["___mysqli_ston"]));
$num_rows = mysqli_num_rows($result);
if($num_rows==0){
# if no database row, fallback to filesystem, no FS error
not_found();
return TRUE;
}
Header("Content-type: text/xml");
$xmlw = new XMLWriter();
$xmlw -> openMemory();
$xmlw -> setIndent(true);
$xmlw -> setIndentString('');
$xmlw -> startDocument('1.0', 'UTF-8', 'no');
$xmlw -> startElement('document');
$xmlw -> writeAttribute('type', 'freeswitch/xml');
$xmlw -> startElement('section');
$xmlw -> writeAttribute('name', 'directory');
$xmlw -> startElement('domain');
$xmlw -> writeAttribute('name','$${domain}');
$xmlw -> startElement('params');
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'dial-string');
$xmlw -> writeAttribute('value', '{^^:sip_invite_domain=${dialed_domain}:presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(*/${dialed_user}@${dialed_domain})}');
$xmlw -> endElement(); //end param
$xmlw -> endElement(); //end param
while( $row = mysqli_fetch_array($result, MYSQLI_ASSOC) ) {
$xmlw -> startElement('user');
$xmlw -> writeAttribute('id', $row['userid']);
// Params
$xmlw -> startElement('params');
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'password');
$xmlw -> writeAttribute('value', $row['password']);
$xmlw -> endElement();
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'vm-password');
$xmlw -> writeAttribute('value', $row['vmpasswd']);
$xmlw -> endElement();
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'max-registrations-per-extension');
$xmlw -> writeAttribute('value', $row['maxregistrationsperextension']);
$xmlw -> endElement();
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'sip-force-expires');
$xmlw -> writeAttribute('value', $row['sipforceexpires']);
$xmlw -> endElement();
$xmlw -> startElement('param');
$xmlw -> writeAttribute('name', 'sip-expires-max-deviation');
$xmlw -> writeAttribute('value', $row['sipexpiresmaxdeviation']);
$xmlw -> endElement();
$xmlw -> endElement(); //end params
// Variables
$xmlw -> startElement('variables');
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'accountcode');
$xmlw -> writeAttribute('value', $row['accountcode']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'user_context');
$xmlw -> writeAttribute('value', $row['user_context']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'effective_caller_id_name');
$xmlw -> writeAttribute('value', $row['displayname']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'effective_caller_id_number');
$xmlw -> writeAttribute('value', $row['userid']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'outbound_caller_id_name');
$xmlw -> writeAttribute('value', $row['outbound_caller_id_name']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'outbound_caller_id_number');
$xmlw -> writeAttribute('value', $row['outbound_caller_id_number']);
$xmlw -> endElement();
$xmlw -> startElement('variable');
$xmlw -> writeAttribute('name', 'callgroup');
$xmlw -> writeAttribute('value', $row['callgroup']);
$xmlw -> endElement();
$xmlw -> endElement(); //end variables
$xmlw -> endElement(); //end user
} // end while
$xmlw -> endElement(); //end domain
$xmlw -> endElement(); //end section
$xmlw -> endDocument(); //end document
echo $xmlw -> outputMemory();
return TRUE;
}
if (isset($_POST['section'])) {
if($_POST['section']=='directory') {
directory();
} else {
# if section is not directory, fallback to filesystem, no FS error
not_found();
}
}
?>
Выкладываем этот скрипт в папку веб сервера, для того чтобы к нему можно было обратиться.
И настраиваем в FS модуль по адресу ../freeswitch/conf/autoload_configs/xml_curl.conf.xml, в котором указываем путь до вашего php-скрипта. Например, так:
..
<binding name="localhostweb">
<param name="gateway-url" value="http://192.168.0.199/xml_handler.php" bindings="directory"/>
</binding>
..
Перезагружаем мод в FS и если все сделали правильно, то теперь данные о пользователе будут браться из базы.
Проверить можно так: в CLI FS пишем xml_curl debug_on и пробуем зарегистрировать пользователя. Если все правильно, то в папке /tmp будет создан XML файл с конфигом зарегистрированного пользователя. Если что то пошло не так - анализируем ошибки.
После того как все заработало, можно написать для себя веб-морду с помощью которой вы будете заводить/изменять/удалять пользователя.
Выглядит это так: