# Точка входа
route{
# # Следующий условный оператор осуществляет проверку поля заголовка MaxForwards - счетчик «прыжков» маршрутизации. 
# Если его значение равно нулю, посылается ответ 483 и прекращается обработка данного пакета. 
# Помимо этого, функция mf_process_maxfwd_header() смотрит. а имеется ли вообще такой заголовок в пакете, если нет, 
# то он создается и устанавливается в заданное значение - в данном случае 10.
if (!mf_process_maxfwd_header("70")) {
sl_send_reply("483","Too Many Hops");
exit;
}
# Далее мы проверяем наличие тега у поля To, который показывает, относится ли данный пакет к какому-либо диалогу.
if (has_totag()) {
# Пакет OPTIONS, помимо собственно запроса доступных опций, обычно используется в качестве средства проверки соединения. 
# Следующая проверка служит для того, чтобы удостовериться, действительно ли пакет предназначен именно нашему прокси.
if (is_method("OPTIONS") &&
uri==myself && (! uri=~"sip:.*[@]+.*")) {
options_reply();
exit;
}
# Смотрим, есть ли в пакете указание, куда его маршрутизировать дальше. 
# Функция loose route() сама по себе очень многозначная (как и многие другие функции), и, если таковое указание имеется, 
# она действует в соответствии с секцией 16.12 RFC 3261 за некоторыми исключениями (о них лучше почитать в документации).
if (loose_route()) {
# В серьезных скриптах маршрутизации здесь и спрятана вся логика - например, 
# осуществляется аккаунтинг. Однако, поскольку скрипт у нас исключительно простой, 
# пакет мы просто маршрутизируем по направлению, которое в нем и задано.
route(relay);
} else {
#В случае же, если пакет не содержит маршрута, мы смотрим, не является ли он пакетом ACK, 
# пришедшим в ответ на сообщение об ошибке, и переправляем его куда следует.
if (is_method("ACK")) {
if ( t_check_trans() ) {
t_relay();
exit;
} else {
# Если же данный запрос ACK не принадлежит никакой транзакции, мы просто его игнорируем.
exit;
}
}
#В остальных же случаях мы отправляем сообщение с кодом "404", аналогичное подобному же в HTTP.
sl_send_reply("404","Not here");
}
exit;
}
#Обрабатываем запросы, не относящиеся к заданному диалогу. Запрос CANCEL мы не трогаем и пересылаем дальше.
if (is_method("CANCEL")) {
if (t_check_trans()) {
t_relay();
}
exit;
}
#Функция t check trans() тоже имеет двойное назначение - если запрос не относится ни к ACK, ни к CANCEL, 
# но относится к какой- то транзакции ретрансляции, она его ретранслирует дальше, что следующая строчка и делает. t_check_trans();
# Фильтруем пакеты, у которых есть поле Route, но не задано поле To (за исключением пакета ACK), и логируем о подобных попытках.
t_check_trans();
#Если запрос адресован не нам, добавляем поле Record-Route для принудительной маршрутизации SIP-трафика через наш прокси.
if (loose_route()) {
xlog("L_ERR",
"Attempt to route with preloaded Route's
[$fu/$tu/$ru/$ci]");
if (!is_method("ACK")) {
sl_send_reply("403",
"Preloaded Route denied");
}
}
#Если в запросе не фигурирует URI, который хоть как-то относится к нашему серверу, мы его отправляем в route(relay).
if (!is_method("REGISTER|MESSAGE")) {
record_route();
}
#Поддержку presence (сообщений о статусе присутствия абонента) тоже не реализуем, для чего отключаем методы.
if (!uri==myself) {
route(relay);
}
#Поддержку presence (сообщений о статусе присутствия абонента) тоже не реализуем,
для чего отключаем методы.
PUBLISH и SUBSCRIBE
if (is_method("PUBLISH|SUBSCRIBE")) {
sl_send_reply("503",
"Service Unavailable");
exit;
}
#Обработка запроса REGISTER. Для упрощения скрипта мы даем возможность регистрироваться всем, безо всякой аутентификации. Кроме того, база местоположений по тем же соображениям временная, в настоящую БД ничего не пишется
if (is_method("REGISTER")) {
if (!save("location", "m")) {
sl_reply_error();
}
exit;
}
# Функция lookup() проверяет, есть ли у нас в базе местоположений данный пользователь. Если его нет, мы создаем новую транзакцию и возвращаем "404".
# Опять же в серьезных скриптах здесь еще и проверяются поддерживаемые клиентом методы, чего мы не делаем.
if (!lookup("location")) {
t_newtran();
t_reply("404", "Not Found");
exit;
}
route(relay);
}
#Блок relay, который и обрабатывает все проходящие пакеты.
route[relay] {
#В случае INVITE мы смотрим, есть ли отрицательный результат транзакции, и, если есть, отправляем в соответствующий блок.
if (is_method("INVITE")) {
t_on_failure("fail");
}
#Наконец, пропускаем пакет дальше и, если он почему-либо не проходит,выдаем ошибку "500".
if (!t_relay()) {
send_reply("500",
"Internal Server Error");
}
}
# Блок fail, о котором было упомянуто выше.
failure_route[fail] {
#Если транзакция была отменена, мы просто выходим из блока.
if (t_was_cancelled()) {
exit;
}
}

~~socialite~~

  • opensips.txt
  • Последние изменения: 2016/12/17