Update directory.lua

moteus changes to directory.lua in pull request 1129.
This commit is contained in:
FusionPBX 2016-10-23 12:46:35 -06:00 committed by GitHub
parent 10f1c42509
commit b807c7e15f
1 changed files with 163 additions and 53 deletions

View File

@ -1,6 +1,6 @@
-- xml_handler.lua
-- Part of FusionPBX
-- Copyright (C) 2013 - 2015 Mark J Crane <markjcrane@fusionpbx.com>
-- Copyright (C) 2013 - 2016 Mark J Crane <markjcrane@fusionpbx.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
@ -70,26 +70,63 @@
--all other directory actions: sip_auth, user_call
--except for the action: group_call
-- Do we need use proxy to make call to ext. reged on different FS
-- true - send call to FS where ext reged
-- false - send call directly to ext
local USE_FS_PATH = xml_handler and xml_handler["fs_path"]
-- Make sance only for extensions with number_alias
-- false - you should register with AuthID=UserID=Extension (default)
-- true - you should register with AuthID=Extension and UserID=Number Alias
-- also in this case you need 2 records in memcache for one extension
local DIAL_STRING_BASED_ON_USERID = xml_handler and xml_handler["reg_as_number_alias"]
-- Use number as presence_id
-- When you have e.g. extension like `user-100` with number-alias `100`
-- by default presence_id is `user-100`. This option allow use `100` as presence_id
local NUMBER_AS_PRESENCE_ID = xml_handler and xml_handler["number_as_presence_id"]
local sip_auth_method = params:getHeader("sip_auth_method")
if sip_auth_method then
sip_auth_method = sip_auth_method:upper();
end
-- Get UserID. If used UserID ~= AuthID then we have to disable `inbound-reg-force-matching-username`
-- on sofia profile and check UserID=Number-Alias and AuthID=Extension on register manually.
-- But in load balancing mode in proxy INVITE we have UserID equal to origin UserID but
-- AuthID equal to callee AuthID. (e.g. 105 call to 100 and one FS forward call to other FS
-- then we have UserID=105 but AuthID=100).
-- Because we do not verify source of INVITE (FS or user device) we have to accept any UserID
-- for INVITE in such mode. So we just substitute correct UserID for check.
-- !!! NOTE !!! do not change USE_FS_PATH before this check.
local from_user = params:getHeader("sip_from_user")
if USE_FS_PATH and sip_auth_method == 'INVITE' then
from_user = user
end
-- Check eather we need build dial-string. Before request dial-string FusionPBX set `dialed_extension`
-- variable. So if we have no such variable we do not need build dial-string.
dialed_extension = params:getHeader("dialed_extension");
if (dialed_extension == nil) then
-- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is null\n");
USE_FS_PATH = false;
else
-- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is " .. dialed_extension .. "\n");
end
-- verify from_user and number alias for this methods
local METHODS = {
-- _ANY_ = true,
REGISTER = true,
-- INVITE = true,
}
if (user == nil) then
user = "";
end
--get the cache
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
if (domain_name) then
XML_STRING = trim(api:execute("memcache", "get directory:" .. user .. "@" .. domain_name));
end
if (XML_STRING == "-ERR NOT FOUND") or (XML_STRING == "-ERR CONNECTION FAILURE") then
source = "database";
continue = true;
else
source = "cache";
continue = true;
end
else
XML_STRING = "";
source = "database";
continue = true;
if (from_user == "") or (from_user == nil) then
from_user = user
end
--prevent processing for invalid user
@ -98,22 +135,50 @@
continue = false;
end
-- cleanup
XML_STRING = nil;
-- get the cache. We can use cache only if we do not use `fs_path`
-- or we do not need dial-string. In other way we have to use database.
if (continue) and (not USE_FS_PATH) then
if (trim(api:execute("module_exists", "mod_memcache")) == "true") then
if (domain_name) then
local key = "directory:" .. (from_user or user) .. "@" .. domain_name
XML_STRING = trim(api:execute("memcache", "get " .. key));
if debug['cache'] then
if XML_STRING:sub(1, 4) == '-ERR' then
freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] get key: " .. key .. " fail: " .. XML_STRING .. "\n")
else
freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] get key: " .. key .. " pass!" .. "\n")
end
end
else
XML_STRING = "-ERR NOT FOUND"
end
if (XML_STRING == "-ERR NOT FOUND") or (XML_STRING == "-ERR CONNECTION FAILURE") then
source = "database";
continue = true;
else
source = "cache";
continue = true;
end
else
XML_STRING = "";
source = "database";
continue = true;
end
end
--show the params in the console
--if (params:serialize() ~= nil) then
-- freeswitch.consoleLog("notice", "[xml_handler-directory.lua] Params:\n" .. params:serialize() .. "\n");
--end
--set the variable from the params
dialed_extension = params:getHeader("dialed_extension");
if (dialed_extension == nil) then
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is null\n");
xml_handler["fs_path"] = false;
else
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dialed_extension is " .. dialed_extension .. "\n");
end
local loaded_from_db = false
--build the XML string from the database
if (source == "database") or (xml_handler["fs_path"]) then
if (source == "database") or (USE_FS_PATH) then
loaded_from_db = true
--database connection
if (continue) then
--connect to the database
@ -146,7 +211,7 @@
--if load balancing is set to true then get the hostname
if (continue) then
if (xml_handler["fs_path"]) then
if (USE_FS_PATH) then
--get the domain_name from domains
if (domain_name == nil) then
@ -173,9 +238,15 @@
dbh_switch = database_handle('switch');
end
--get register name
local reg_user = dialed_extension
if not DIAL_STRING_BASED_ON_USERID then
reg_user = trim(api:execute("user_data", dialed_extension .. "@" .. domain_name .. " attr id"));
end
--get the destination hostname from the registration
sql = "SELECT hostname FROM registrations ";
sql = sql .. "WHERE reg_user = '"..dialed_extension.."' ";
sql = sql .. "WHERE reg_user = '"..reg_user.."' ";
sql = sql .. "AND realm = '"..domain_name.."' ";
if (database["type"] == "mysql") then
now = os.time();
@ -189,9 +260,9 @@
--freeswitch.consoleLog("notice", "[xml_handler] sql: " .. sql .. "\n");
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] database_hostname is " .. database_hostname .. "\n");
--hostname was not found set xml_handler["fs_path"] to false to prevent a database_hostname concatenation error
--hostname was not found set USE_FS_PATH to false to prevent a database_hostname concatenation error
if (database_hostname == nil) then
xml_handler["fs_path"] = false;
USE_FS_PATH = false;
end
--close the database connection
@ -253,7 +324,6 @@
nibble_account = row.nibble_account;
sip_bypass_media = row.sip_bypass_media;
absolute_codec_string = row.absolute_codec_string;
force_ping = row.force_ping;
forward_all_enabled = row.forward_all_enabled;
forward_all_destination = row.forward_all_destination;
forward_busy_enabled = row.forward_busy_enabled;
@ -265,30 +335,48 @@
do_not_disturb = row.do_not_disturb;
-- check matching UserID and AuthName
if sip_auth_method then
local check_from_number = METHODS[sip_auth_method] or METHODS._ANY_
if DIAL_STRING_BASED_ON_USERID then
continue = (sip_from_user == user) and ((not check_from_number) or (from_user == sip_from_number))
else
continue = (sip_from_user == user) and ((not check_from_number) or (from_user == user))
end
if not continue then
XML_STRING = nil;
return 1;
end
end
--set the presence_id
presence_id = (NUMBER_AS_PRESENCE_ID and sip_from_number or sip_from_user) .. "@" .. domain_name;
--set the dial_string
if (string.len(row.dial_string) > 0) then
dial_string = row.dial_string;
else
local destination = (DIAL_STRING_BASED_ON_USERID and sip_from_number or sip_from_user) .. "@" .. domain_name;
--set a default dial string
if (dial_string == null) then
dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. user .. "@" .. domain_name .. "}${sofia_contact(" .. extension .. "@" .. domain_name .. ")}";
dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. presence_id .. "}${sofia_contact(" .. destination .. ")}";
end
--set the an alternative dial string if the hostnames don't match
if (xml_handler["fs_path"]) then
if (USE_FS_PATH) then
if (local_hostname == database_hostname) then
freeswitch.consoleLog("notice", "[xml_handler-directory.lua] local_host and database_host are the same\n");
else
--sofia/internal/${user_data(${destination_number}@${domain_name} attr id)}@${domain_name};fs_path=sip:server
user_id = trim(api:execute("user_data", user .. "@" .. domain_name .. " attr id"));
dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. user .. "@" .. domain_name .. "}sofia/internal/" .. user_id .. "@" .. domain_name .. ";fs_path=sip:" .. database_hostname;
local profile, proxy = "internal", database_hostname;
dial_string = "{sip_invite_domain=" .. domain_name .. ",presence_id=" .. presence_id .."}sofia/" .. profile .. "/" .. destination .. ";fs_path=sip:" .. proxy;
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] dial_string " .. dial_string .. "\n");
end
else
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] seems balancing is false??" .. tostring(xml_handler["fs_path"]) .. "\n");
--freeswitch.consoleLog("notice", "[xml_handler-directory.lua] seems balancing is false??" .. tostring(USE_FS_PATH) .. "\n");
end
--show debug informationa
if (xml_handler["fs_path"]) then
if (USE_FS_PATH) then
freeswitch.consoleLog("notice", "[xml_handler] local_hostname: " .. local_hostname.. " database_hostname: " .. database_hostname .. " dial_string: " .. dial_string .. "\n");
end
end
@ -298,8 +386,8 @@
--get the voicemail from the database
if (continue) then
vm_enabled = "true";
if tonumber(user) == nil then
sql = "SELECT * FROM v_voicemails WHERE domain_uuid = '" .. domain_uuid .. "' and voicemail_id = '" .. number_alias .. "' ";
if number_alias and #number_alias > 0 then
sql = "SELECT * FROM v_voicemails WHERE domain_uuid = '" .. domain_uuid .. "' and voicemail_id = '" .. number_alias .. "' ";
else
sql = "SELECT * FROM v_voicemails WHERE domain_uuid = '" .. domain_uuid .. "' and voicemail_id = '" .. user .. "' ";
end
@ -389,6 +477,7 @@
table.insert(xml, [[ <variable name="call_timeout" value="]] .. call_timeout .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_name" value="]] .. sip_from_user .. [["/>]]);
table.insert(xml, [[ <variable name="caller_id_number" value="]] .. sip_from_number .. [["/>]]);
table.insert(xml, [[ <variable name="presence_id" value="]] .. presence_id .. [["/>]]);
if (string.len(call_group) > 0) then
table.insert(xml, [[ <variable name="call_group" value="]] .. call_group .. [["/>]]);
end
@ -461,9 +550,6 @@
if (string.len(absolute_codec_string) > 0) then
table.insert(xml, [[ <variable name="absolute_codec_string" value="]] .. absolute_codec_string .. [["/>]]);
end
if (string.len(force_ping) > 0) then
table.insert(xml, [[ <variable name="force_ping" value="]] .. force_ping .. [["/>]]);
end
if (sip_bypass_media == "bypass-media") then
table.insert(xml, [[ <variable name="bypass_media" value="true"/>]]);
end
@ -517,14 +603,26 @@
dbh:release();
--set the cache
if (user and domain_name) then
result = trim(api:execute("memcache", "set directory:" .. user .. "@" .. domain_name .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
local key = "directory:" .. (DIAL_STRING_BASED_ON_USERID and sip_from_number or sip_from_user) .. "@" .. domain_name
if debug['cache'] then
freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] set key: " .. key .. "\n")
end
result = trim(api:execute("memcache", "set " .. key .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
if sip_from_number ~= sip_from_user then
key = "directory:" .. sip_from_user .. "@" .. domain_name
if debug['cache'] then
freeswitch.consoleLog("notice", "[xml_handler-directory][memcache] set key: " .. key .. "\n")
end
result = trim(api:execute("memcache", "set " .. key .. " '"..XML_STRING:gsub("'", "&#39;").."' "..expire["directory"]));
end
--save to the conf directory
--local file = assert(io.open(conf_dir .. "/directory/" .. user .. "@" .. domain_name .. ".xml.cache", "w"));
--file:write(XML_STRING);
--file:close();
--send the xml to the console
if (debug["xml_string"]) then
local file = assert(io.open(temp_dir .. "/" .. user .. "@" .. domain_name .. ".xml", "w"));
file:write(XML_STRING);
file:close();
end
--send to the console
if (debug["cache"]) then
@ -533,10 +631,22 @@
end
end
--disable registration for number-alias
if (params:getHeader("sip_auth_method") == "REGISTER") then
if (api:execute("user_data", user .. "@" .. domain_name .." attr id") ~= user) then
if XML_STRING and (not loaded_from_db) and sip_auth_method then
local user_id = api:execute("user_data", from_user .. "@" .. domain_name .." attr id")
if user_id ~= user then
XML_STRING = nil;
elseif METHODS[sip_auth_method] or METHODS._ANY_ then
local alias
if DIAL_STRING_BASED_ON_USERID then
alias = api:execute("user_data", from_user .. "@" .. domain_name .." attr number-alias")
end
if alias and #alias > 0 then
if from_user ~= alias then
XML_STRING = nil
end
elseif from_user ~= user_id then
XML_STRING = nil;
end
end
end