diff options
-rw-r--r-- | db/migrate/20130116145500_set_routing_variables.rb | 12 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/gateway.lua | 1 | ||||
-rw-r--r-- | misc/freeswitch/scripts/configuration.lua | 2 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/dialplan.lua | 87 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/router.lua | 203 |
5 files changed, 67 insertions, 238 deletions
diff --git a/db/migrate/20130116145500_set_routing_variables.rb b/db/migrate/20130116145500_set_routing_variables.rb new file mode 100644 index 0000000..abd8fa6 --- /dev/null +++ b/db/migrate/20130116145500_set_routing_variables.rb @@ -0,0 +1,12 @@ +class SetRoutingVariables < ActiveRecord::Migration + def up + GsParameter.create(:entity => 'call_route', :section => 'failover', :name => '603', :value => 'true', :class_type => 'Boolean') + GsParameter.create(:entity => 'call_route', :section => 'failover', :name => '480', :value => 'true', :class_type => 'Boolean') + GsParameter.create(:entity => 'call_route', :section => 'failover', :name => 'UNALLOCATED_NUMBER', :value => 'true', :class_type => 'Boolean') + GsParameter.create(:entity => 'call_route', :section => 'failover', :name => 'NORMAL_TEMPORARY_FAILURE', :value => 'true', :class_type => 'Boolean') + end + + def down + GsParameter.where(:entity => 'call_route', :section => 'failover').destroy_all + end +end diff --git a/misc/freeswitch/scripts/common/gateway.lua b/misc/freeswitch/scripts/common/gateway.lua index 6e9fbfb..5c76aba 100644 --- a/misc/freeswitch/scripts/common/gateway.lua +++ b/misc/freeswitch/scripts/common/gateway.lua @@ -16,6 +16,7 @@ function Gateway.new(self, arg) self.log = arg.log; self.database = arg.database; self.record = arg.record; + self.GATEWAY_PREFIX = 'gateway'; return object; end diff --git a/misc/freeswitch/scripts/configuration.lua b/misc/freeswitch/scripts/configuration.lua index b4dc0f6..1162e97 100644 --- a/misc/freeswitch/scripts/configuration.lua +++ b/misc/freeswitch/scripts/configuration.lua @@ -49,7 +49,7 @@ function gateways(database, profile_name) gateways_xml = gateways_xml .. xml:element{ 'gateway', - name = gateway.name, + name = gateway_class.GATEWAY_PREFIX .. gateway.id, xml:from_hash('param', parameters, 'name', 'value'), }; end diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua index 88670ca..32f59c2 100644 --- a/misc/freeswitch/scripts/dialplan/dialplan.lua +++ b/misc/freeswitch/scripts/dialplan/dialplan.lua @@ -343,12 +343,6 @@ function Dialplan.destination_new(self, arg) end -function Dialplan.routes_get(self, destination) - require 'dialplan.route' - return dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = self.routes }:outbound(self.caller, destination.number); -end - - function Dialplan.set_caller_picture(self, entry_id, entry_type, image) entry_type = entry_type:lower(); if entry_type == 'user' then @@ -629,9 +623,11 @@ function Dialplan.callthrough(self, destination) return { continue = false, code = 404, phrase = 'No destination' } end - local route = dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = self.routes }:prerouting(self.caller, destination_number); - if route and route.value then - destination_number = route.value; + require 'dialplan.router' + local route = dialplan.router.Router:new{ log = self.log, database = self.database, caller = self.caller }:route_run('prerouting', destination_number, true); + + if route and route.destination_number then + destination_number = route.destination_number; end if not callthrough:whitelist(destination_number) then @@ -760,7 +756,9 @@ function Dialplan.switch(self, destination) return self:dialplanfunction(destination); elseif not common.str.blank(destination.number) then local result = { continue = false, code = 404, phrase = 'No route' } - local routes = self:routes_get(destination); + + require 'dialplan.router' + local routes = dialplan.router.Router:new{ log = self.log, database = self.database, caller = self.caller }:route_run('outbound', destination.number); if not routes or #routes == 0 then self.log:notice('SWITCH - no route - number: ', destination.number); @@ -802,26 +800,26 @@ function Dialplan.switch(self, destination) self.caller:set_callee_id(destination.callee_id_number, destination.callee_id_name); for index, route in ipairs(routes) do - if route.class == 'hangup' then + if route.endpoint_type == 'hangup' then return { continue = false, code = route.endpoint, phrase = route.phrase, cause = route.value } end - if route.class == 'forward' then + if route.endpoint_type == 'forward' then return { continue = true, call_forwarding = { number = route.value, service = 'route', type = 'phonenumber' }} end - destination.gateway = route.endpoint; - destination.type = route.class; - destination.number = route.value; - destination.caller_id_number = route.caller_id_number; - destination.caller_id_name = route.caller_id_name; + + for key, value in pairs(route) do + destination[key] = value; + end + result = self:dial(destination); if result.continue == false then break; end - if common.str.to_b(self.routes.failover[tostring(result.code)]) == true then + if common.str.to_b(self.route_failover[tostring(result.code)]) == true then self.log:info('SWITCH - failover - code: ', result.code); - elseif common.str.to_b(self.routes.failover[tostring(result.cause)]) == true then + elseif common.str.to_b(self.route_failover[tostring(result.cause)]) == true then self.log:info('SWITCH - failover - cause: ', result.cause); else self.log:info('SWITCH - no failover - cause: ', result.cause, ', code: ', result.code); @@ -839,7 +837,8 @@ end function Dialplan.run(self, destination) require 'common.str'; - + require 'dialplan.router'; + self.caller:set_variable('hangup_after_bridge', false); self.caller:set_variable('bridge_early_media', 'true'); self.caller:set_variable('default_language', self.default_language); @@ -855,35 +854,55 @@ function Dialplan.run(self, destination) end end - self.routes = common.configuration_file.get('/opt/freeswitch/scripts/ini/routes.ini'); self.caller.domain_local = self.domain; self:retrieve_caller_data(); + self.route_failover = common.configuration_table.get(self.database, 'call_route', 'failover'); if not destination or destination.type == 'unknown' then - require 'dialplan.route' local route = nil; - if self.caller.gateway then if not common.str.blank(self.caller.gateway.settings.number_source) then self.log:debug('INBOUND_NUMBER: number_source: ', self.caller.gateway.settings.number_source, ', number: ', self.caller:to_s(self.caller.gateway.settings.number_source)); self.caller.destination_number = self.caller:to_s(self.caller.gateway.settings.number_source); end - local route_object = dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = self.routes }; - route = route_object:inbound(self.caller, self.caller.destination_number); - local inbound_caller_id_number = route_object:inbound_cid_number(self.caller, self.caller.gateway_name, 'gateway'); - route_object.expandable.caller_id_number = inbound_caller_id_number; - local inbound_caller_id_name = route_object:inbound_cid_name(self.caller, self.caller.gateway_name, 'gateway'); - self.log:info('INBOUND_CALLER_ID_REWRITE - number: ', inbound_caller_id_number, ', name: ', inbound_caller_id_name); - self.caller.caller_id_number = inbound_caller_id_number or self.caller.caller_id_number; - self.caller.caller_id_name = inbound_caller_id_name or self.caller.caller_id_name; - self.caller.caller_phone_numbers[1] = self.caller.caller_id_number; + route = dialplan.router.Router:new{ log = self.log, database = self.database, caller = self.caller }:route_run('inbound', self.caller.destination_number, true); + if route then + + local ignore_keys = { + gateway = true, + ['type'] = true, + actions = true, + }; + + for key, value in pairs(route) do + if not ignore_keys[key] then + self.caller[key] = value; + end + end + + self.caller.caller_phone_numbers[1] = self.caller.caller_id_number; + else + self.log:notice('INBOUND - no route'); + end + + if false then + local route_object = dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = self.routes }; + route = route_object:inbound(self.caller, self.caller.destination_number); + local inbound_caller_id_number = route_object:inbound_cid_number(self.caller, self.caller.gateway_name, 'gateway'); + route_object.expandable.caller_id_number = inbound_caller_id_number; + local inbound_caller_id_name = route_object:inbound_cid_name(self.caller, self.caller.gateway_name, 'gateway'); + self.log:info('INBOUND_CALLER_ID_REWRITE - number: ', inbound_caller_id_number, ', name: ', inbound_caller_id_name); + self.caller.caller_id_number = inbound_caller_id_number or self.caller.caller_id_number; + self.caller.caller_id_name = inbound_caller_id_name or self.caller.caller_id_name; + self.caller.caller_phone_numbers[1] = self.caller.caller_id_number; + end else - route = dialplan.route.Route:new{ log = self.log, database = self.database, routing_table = self.routes }:prerouting(self.caller, self.caller.destination_number); + route = dialplan.router.Router:new{ log = self.log, database = self.database, caller = self.caller }:route_run('prerouting', self.caller.destination_number, true); end if route then - destination = self:destination_new{ number = route.value } + destination = self:destination_new{ ['type'] = route.type, id = route.id, number = route.destination_number } self.caller.destination_number = destination.number; self.caller.destination = destination; elseif not destination or destination.type == 'unknown' then diff --git a/misc/freeswitch/scripts/dialplan/router.lua b/misc/freeswitch/scripts/dialplan/router.lua deleted file mode 100644 index 76d7ada..0000000 --- a/misc/freeswitch/scripts/dialplan/router.lua +++ /dev/null @@ -1,203 +0,0 @@ --- Gemeinschaft 5 module: call router class --- (c) AMOOMA GmbH 2013 --- - -module(...,package.seeall) - -Router = {} - --- create route object -function Router.new(self, arg) - arg = arg or {} - object = arg.object or {} - setmetatable(object, self); - self.__index = self; - self.class = 'router'; - self.log = arg.log; - self.database = arg.database; - self.routes = arg.routes or {}; - self.caller = arg.caller; - self.variables = arg.variables or {}; - return object; -end - -function Router.build_tables(self) - local elements = { - { var_in = 'group', var_out = '', pattern = '^users$', replacement = '', action = 'not_match', mandatory = true }, - { var_in = 'destination_number', var_out = 'destination_number', pattern = '^1$', replacement = '+123456', action = 'not_match', mandatory = true }, - { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^100$', replacement = '+4930100', action = 'set_route_var', mandatory = false }, - } - - local elements2 = { - { var_in = 'group', var_out = '', pattern = '^users$', replacement = '', action = 'match', mandatory = true }, - { var_in = 'destination_number', var_out = 'destination_number', pattern = '^1$', replacement = '+123456', action = 'not_match', mandatory = true }, - { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^100$', replacement = '+4930100', action = 'set_route_var', mandatory = false }, - } - - local elements3 = { - { var_in = 'destination_number', var_out = 'destination_number', pattern = '^#31#(%d+)$', replacement = 'f-dcliron-%1', action = 'set_route_var', mandatory = false }, - } - - local elements4 = { - { var_in = 'destination_number', var_out = 'destination_number', pattern = '^(%d+)$', replacement = '%1', action = 'set_route_var', mandatory = true }, - { var_in = 'caller_id_number', var_out = 'caller_id_number', pattern = '^(.+)$', replacement = '+49%1', action = 'set_route_var', mandatory = false }, - } - - local routes = { - prerouting = { - { id = 10, name = 'feature codes', elements = elements3, endpoint_type = 'dialplanfunction', endpoint_id = 0 }, - }, - outbound = { - { id = 1, name = 'no users', elements = elements, endpoint_type = 'gateway', endpoint_id = 1, }, - { id = 2, name = 'all users', elements = elements2, endpoint_type = 'gateway', endpoint_id = 1, }, - { id = 3, name = 'all users', elements = elements2, endpoint_type = 'gateway', endpoint_id = 1, }, - }, - inbound = { - { id = 20, name = 'haeron', elements = elements4, endpoint_type = 'phonenumber', endpoint_id = 1, }, - }, - - }; - - return routes; -end - - -function Router.failover_table(self) - return { - ['603'] = true, - ['480'] = true, - UNALLOCATED_NUMBER = true, - NORMAL_TEMPORARY_FAILURE = true, - } -end - - -function Router.expand_variables(self, line) - return (line:gsub('{([%a%d_]+)}', function(captured) - return variables[captured] or ''; - end)) -end - - -function Router.set_parameter(self, action, name, value) - if action == 'set_session_var' then - self.log:debug('ROUTER_SET_SESSION_VARIABLE - ', name, ' = ', value); - self.caller[name] = value; - elseif action == 'set_channel_var' then - self.log:debug('ROUTER_SET_VARIABLE - ', name, ' = ', value); - self.caller:set_variable(name, value); - elseif action == 'export_channel_var' then - self.log:debug('ROUTER_EXPORT_VARIABLE - ', name, ' = ', value); - self.caller:export_variable(name, value); - elseif action == 'set_header' then - self.log:debug('ROUTER_SIP_HEADER - ', name, ': ', value); - self.caller:export_variable('sip_h_' .. name, value); - else - self.log:error('ROUTER_SET_PARAMERER - unknown action: ', action, ', ', name, ' = ', value); - end -end - - -function Router.element_match(self, pattern, search_string, replacement) - local variables_list = {}; - local success, result = pcall(string.find, search_string, pattern); - - if not success then - self.log:error('ELEMENT_MATCH - table error - pattern: ', pattern, ', search_string: ', search_string); - elseif result then - return true, search_string:gsub(pattern, self:expand_variables(replacement, variables_list)); - end - - return false; -end - - -function Router.route_match(self, route) - local destination = { - gateway = 'gateway' .. route.endpoint_id, - ['type'] = route.endpoint_type, - id = route.endpoint_id, - actions = {} - }; - - local route_matches = false; - - for index=1, #route.elements do - local result = false; - local replacement = nil; - - local element = route.elements[index]; - if element.var_in == 'group' then - local groups = common.str.try(self.caller, 'auth_account.owner.groups'); - if not groups or type(groups) ~= 'table' then - if element.mandatory then - return false; - end - end - - for group_name, value in pairs(groups) do - result, replacement = self:element_match(tostring(element.pattern), tostring(group_name), tostring(element.replacement)); - if result then - break; - end - end - - else - local search_string = tostring(common.str.try(self.caller, element.var_in)) - result, replacement = self:element_match(tostring(element.pattern), tostring(search_string), tostring(element.replacement)); - end - - if element.action == 'not_match' then - result = not result; - end - - if not result then - if element.mandatory then - return false; - end - elseif element.action ~= 'match' and element.action ~= 'not_match' then - if element.action == 'set_route_var' then - destination[element.var_out] = replacement; - else - table.insert(destination.actions, {action = element.action, name = element.var_out, value = replacement}); - end - end - - if result then - route_matches = true; - end - end - - if route_matches then - return destination; - end; - - return nil; -end - - -function Router.route_run(self, table_name, phone_number, find_first) - local routing_tables = self:build_tables(); - local routing_table = routing_tables[table_name]; - - local routes = {}; - - if type(routing_table) == 'table' then - for index=1, #routing_table do - local route = self:route_match(routing_table[index], phone_number); - if route then - table.insert(routes, route); - self.log:info('ROUTE ', #routes,' - ', table_name,'=', routing_table[index].id, '/', routing_table[index].name, ', destination: ', route.type, '=', route.id); - if find_first then - return route; - end - else - self.log:debug('ROUTE_NO_MATCH - ', table_name, '=', routing_table[index].id, '/', routing_table[index].name); - end - end - end - - if not find_first then - return routes; - end -end |