SIP-аккаунты в MySQL 28.04.2011

Как вы помните, мы вносили SIP клиентов через файл sip.conf. И все было хорошо, но раз уж мы решили пойти по пути MySQL – то почему бы не перенести и клиентов в MySQL.

На мой взгляд, это влечет за собой как минимум два полюса:

  • более легко делать выборки, автоматизировано заносить и блокировать клиентов и тд;
  • будет легко манипулировать sip-клиентами через внешние программы (ниже я покажу один пример).

Если у вас немного телефонов, их список нечасто меняется и не нужно к ним подключаться через скрипты, то можете смело пропустить эту статью.

Немного теории

Применительно к астериску, существует достаточно прикольный по звучанию термин – ARA (Asterisk Realtime Architecture – архитектура реального времени астериск).

Суть ее в том, что некоторые файлы конфигурации из папки /etc/asterisk можно хранить в базе данных.

Существует два типа ARA – статическая и динамическая:

  • Статическая ARA – ничем не отличается от конфигурационных файлов, за исключением, что данные берутся из БД. Т.е., данные считываются при загрузке астериска (или перезагрузке модулей) и дальше астериск не реагирует на их изменения. На мой взгляд, если вам, к примеру, просто нужно сформировать список SIP клиентов и периодически его изменять – это ваш выбор. Вы формируете список и, к примеру, раз в сутки перезагружаете список из MySQL.
  • Динамическая ARA – позволяет читать данные во время работы системы, плюс для некоторых объектов (например, SIP user) обновляет информацию в MySQL. Это, разумеется, менее безопасно, но намного более функционально. Именно этот вариант я и выбрал.

Настройка динамической ARA для sip.conf

Первым делом – нужно создать таблицу конфигурации sip в базе данных. Честно говоря, у меня это вышло не с первого раза. В итоге я взял таблицу по этой ссылке и обрезал поля, которые астериск не стал заполнять.

В результате у меня получилось:

CREATE TABLE tbl_sip_conf (
  id int(11) NOT NULL auto_increment,
  name varchar(80) NOT NULL default '',
  callingpres enum('allowed_not_screened', 'allowed_passed_screen', 'allowed_failed_screen', 'allowed','prohib_not_screened', 'prohib_passed_screen', 'prohib_failed_screen', 'prohib', 'unavailable') default 'allowed_not_screened',
  secret varchar(80) default NULL,
  host varchar(31) NOT NULL default 'dynamic',
  nat varchar(5) NOT NULL default 'no',
  type enum('user','peer','friend') NOT NULL default 'friend',
  disallow varchar(100) default 'all',
  allow varchar(100) default 'ulaw;alaw;gsm;',
  fullcontact varchar(80) NOT NULL default '',
  ipaddr varchar(15) NOT NULL default '',
  port mediumint(5) unsigned NOT NULL default '0',
  username varchar(80) NOT NULL default '',
  defaultuser varchar(80) NOT NULL default '',
  allowoverlap enum('yes','no') default 'no',
  allowsubscribe enum('yes','no') default 'yes',
  allowtransfer enum('yes','no') default 'yes',
  ignoresdpversion enum('yes','no') default 'no',
  videosupport enum('yes','no','always') default 'no',
  rfc2833compensate enum('yes','no') default 'yes',
  session-timers enum('originate','accept','refuse') default 'accept',
  session-expires int(5) unsigned default '1800',
  session-minse int(5) unsigned default '90',
  session-refresher enum('uac','uas') default 'uas',
  registertrying enum('yes','no') default 'yes',
  timert1 int(5) unsigned default '500',
  timerb int(8) unsigned default NULL,
  qualifyfreq int(5) unsigned default '120',
  lastms int(11) NOT NULL,
  regserver varchar(100) NOT NULL default '',
  regseconds int(11) NOT NULL default '0',
  useragent varchar(50) NOT NULL default '',
  PRIMARY KEY  (id),
  UNIQUE KEY name (name),
  KEY name_2 (name)
)

В этой таблице (пока что) я заполнил только secret и name, все остальное – по дефолту.

Дальше вносим изменения в /etc/asterisk/modules.conf, чтобы позволить сначала загружаться ODBC модулю.

[modules]
autoload=yes
preload => res_odbc.so
preload => res_config_odbc.so

В /etc/asterisk/sip.conf я заккоментировал все кроме раздела [general] и добавил в него параметр rtcachefriends=yes.

Последнее, что необходимо сделать - создать /etc/asterisk/extconfig.conf и внести в него

[settings]
sippeers => odbc,asterisk,tbl_sip_conf
sipusers => odbc,asterisk,tbl_sip_conf
sipregs => odbc,asterisk,tbl_sip_conf

После этого перезагружаем астериск и наслаждаемся регистрацией клиентов.

Администрирование номеров через WEB

В качестве первой задачи, я сделал администрирование номеров через WEB-интерфейс. Весь код я приводить не буду, покажу только основную часть.

Для начала, я создал единую таблицу номеров:

CREATE TABLE tbl_global_list (
  short_number varchar(3) NOT NULL,
  user_name varchar(100) NOT NULL default '',
  user_mail varchar(255) NOT NULL default '',
  main_number_type tinyint(4) NOT NULL default '0',
  redirect_number_main varchar(45) NOT NULL default '',
  redirect_number_ext varchar(45) NOT NULL default '',
  last_sip_status enum('ok','disconnected') NOT NULL default 'disconnected',
  PRIMARY KEY  (short_number)
)

Она будет основной для всех наших дальнейших экспериментов, поэтому, распишу поля поподробнее:

  • short_number – 3-х-значный номер-база. Если к нему «прибавить» в начале единичку, получим внутренний номер, если 6-ку – номер переадресации;
  • user_name, user_mail – сделано на будущее, текстовые поля;
  • main_number_type – если 1, то номер [1+short_number] используется как sip-телефон;
  • redirect_number_main – если main_number_type не единица и значение поля не пустое, то при наборе [1+short_number] будет набран redirect_number_main. В дальнейшем, количество типов возрастет;
  • redirect_number_ext – если значение не пустое, то при наборе [6+short_number] будет набран redirect_number_ext;
  • last_sip_status – статус подключения SIP телефона.

Как вносить в нее данные – думаю, каждый разберется сам. Если вам интересен мой способ – напишите мне.

Из нее мы будем заполнять tbl_sip_conf и tbl_short_numbers (об этой таблице я писал здесь). Для этого, после модификаций таблицы, запускаются следующие скрипты:

1. удаляем номера из sip.conf

DELETE FROM tbl_sip_conf
WHERE name NOT IN
(
    SELECT CONCAT('1',short_number)
    FROM tbl_global_list
    WHERE main_number_type=1
)

2. добавляем пользователей в sip.conf (в моем случае, пароль у всех одинаковый)

INSERT IGNORE INTO tbl_sip_conf
(name,secret)
SELECT CONCAT('1',short_number),'*******'
FROM tbl_global_list
WHERE main_number_type=1

После этого желательно перегрузить все же sip.conf, дабы сразу отключить удаленные телефоны. Из PHP я это сделал так:

shell_exec('sudo /usr/sbin/asterisk -rx "sip reload"');

при этом, необходимо прописать в /etc/sudoers разрешение на запуск консоли asterisk от apache под рутом.

apache ALL=(ALL) NOPASSWD: /usr/sbin/asterisk