diff options
Diffstat (limited to 'misc/freeswitch/scripts/dialplan')
-rw-r--r-- | misc/freeswitch/scripts/dialplan/acd.lua | 2 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/dialplan.lua | 18 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/dtmf.lua | 69 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/functions.lua | 20 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/hunt_group.lua | 13 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/router.lua | 12 | ||||
-rw-r--r-- | misc/freeswitch/scripts/dialplan/sip_call.lua | 71 |
7 files changed, 163 insertions, 42 deletions
diff --git a/misc/freeswitch/scripts/dialplan/acd.lua b/misc/freeswitch/scripts/dialplan/acd.lua index f4b298e..5ed8979 100644 --- a/misc/freeswitch/scripts/dialplan/acd.lua +++ b/misc/freeswitch/scripts/dialplan/acd.lua @@ -194,7 +194,7 @@ function AutomaticCallDistributor.agents_available(self, strategy) local accounts = {} self.database:query(sql_query, function(entry) - if not entry.callstate then + if common.str.blank(entry.callstate) then table.insert(accounts, entry); end end); diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua index ff4adc6..72503e5 100644 --- a/misc/freeswitch/scripts/dialplan/dialplan.lua +++ b/misc/freeswitch/scripts/dialplan/dialplan.lua @@ -350,10 +350,10 @@ function Dialplan.set_caller_picture(self, entry_id, entry_type, image) require 'dialplan.user' local user = dialplan.user.User:new{ log = self.log, database = self.database }:find_by_id(entry_id); if user then - self.caller:set_variable('sip_h_Call-Info', '<' .. self.user_image_url .. '/' .. tonumber(entry_id) .. '/snom_caller_picture_' .. tostring(user.record.image) .. '>;purpose=icon'); + self.caller:export_variable('sip_h_Call-Info', '<' .. self.user_image_url .. '/' .. tonumber(entry_id) .. '/snom_caller_picture_' .. tostring(user.record.image) .. '>;purpose=icon'); end elseif entry_type == 'phonebookentry' and image then - self.caller:set_variable('sip_h_Call-Info', '<' .. self.phone_book_entry_image_url .. '/' .. tonumber(entry_id) .. '/snom_caller_picture_' .. tostring(image) .. '>;purpose=icon'); + self.caller:export_variable('sip_h_Call-Info', '<' .. self.phone_book_entry_image_url .. '/' .. tonumber(entry_id) .. '/snom_caller_picture_' .. tostring(image) .. '>;purpose=icon'); end end @@ -445,6 +445,8 @@ function Dialplan.dial(self, destination) send_ringing = ( self.send_ringing_to_gateways and self.caller.from_gateway ), bypass_media_network = self.config.parameters.bypass_media_network, update_callee_display = self.config.parameters.update_callee_display, + detect_dtmf_after_bridge_caller = self.detect_dtmf_after_bridge_caller, + detect_dtmf_after_bridge_callee = self.detect_dtmf_after_bridge_callee, } ); end @@ -759,7 +761,7 @@ function Dialplan.switch(self, destination) elseif not common.str.blank(destination.number) then local result = { continue = false, code = 404, phrase = 'No route' } - local clip_no_screening = common.str.try(caller, 'account.record.clip_no_screening'); + local clip_no_screening = common.str.try(self.caller, 'account.record.clip_no_screening'); self.caller.caller_id_numbers = {} if not common.str.blank(clip_no_screening) then for index, number in ipairs(common.str.strip_to_a(clip_no_screening, ',')) do @@ -814,11 +816,13 @@ 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.endpoint_type == 'hangup' then - return { continue = false, code = route.endpoint, phrase = route.phrase, cause = route.value } + if route.type == 'hangup' then + self.log:notice('SWITCH_HANGUP - code: ', route.code, ', phrase: ', route.phrase, ', cause: ', route.cause); + return { continue = false, code = route.code or '404', phrase = route.phrase, cause = route.cause } end - if route.endpoint_type == 'forward' then - return { continue = true, call_forwarding = { number = route.value, service = 'route', type = 'phonenumber' }} + if route.type == 'forward' then + self.log:notice('SWITCH_CALL_FORWARDING - number: ', route.number); + return { continue = true, call_forwarding = { number = route.number, service = 'route', type = 'phonenumber' }} end for key, value in pairs(route) do diff --git a/misc/freeswitch/scripts/dialplan/dtmf.lua b/misc/freeswitch/scripts/dialplan/dtmf.lua new file mode 100644 index 0000000..4dbd35f --- /dev/null +++ b/misc/freeswitch/scripts/dialplan/dtmf.lua @@ -0,0 +1,69 @@ +-- Gemeinschaft 5 module: dtmf class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Dtmf = {} + +-- create dtmf object +function Dtmf.new(self, arg) + arg = arg or {} + object = arg.object or {} + setmetatable(object, self); + self.__index = self; + self.class = 'Dtmf'; + self.log = arg.log; + self.bleg = arg.bleg + self.digit_timeout = arg.digit_timeout or 5; + self.router = arg.router; + + return object; +end + + +function Dtmf.detect(self, caller, sequence, digit, duration, calee) + local timestamp = os.time(); + if timestamp - sequence.updated > self.digit_timeout then + sequence.digits = digit; + else + sequence.digits = sequence.digits .. digit; + end + + caller.dtmf_digits = sequence.digits; + + if calee then + self.log:debug('DTMF_RECEIVER callee - digit: [', digit, '][', duration, '], sequence: ', sequence.digits); + else + self.log:debug('DTMF_RECEIVER caller - digit: [', digit, '][', duration, '], sequence: ', sequence.digits); + end + + local route = self.router:route_run('dtmf', true); + sequence.updated = timestamp; + + if not route then + return; + end + + if route.type == 'dialplanfunction' or route.type == 'phonenumber' or route.type == 'unknown' then + self:transfer(caller, route.destination_number, calee) + else + self.log:notice('DTMF_RECEIVER - unhandled destination: ', route.type, '=', route.id); + end +end + + +function Dtmf.transfer(self, caller, destination, calee) + require 'common.fapi' + local fapi = common.fapi.FApi:new{ log = log }; + local callee_uuid = caller:to_s('bridge_to'); + + self.log:notice('DTMF_RECEIVER_TRANSFER - destination: ', destination, ', uuid: ', caller.uuid, ', callee_uuid: ', callee_uuid, ', callee_initiated: ', calee); + if calee then + caller:execute('transfer', destination); + fapi:execute('uuid_kill', callee_uuid); + else + fapi:execute('uuid_transfer', callee_uuid .. ' ' .. destination); + caller.session:hangup(); + end +end diff --git a/misc/freeswitch/scripts/dialplan/functions.lua b/misc/freeswitch/scripts/dialplan/functions.lua index 2ca51c8..4430be1 100644 --- a/misc/freeswitch/scripts/dialplan/functions.lua +++ b/misc/freeswitch/scripts/dialplan/functions.lua @@ -111,6 +111,8 @@ function Functions.dialplan_function(self, caller, dialed_number) result = "+" .. tostring(parameters[3]); elseif fid == "hangup" then result = self:hangup(caller, parameters[3], parameters[4]); + elseif fid == "park" then + result = self:park(caller, parameters[3]); end return result; @@ -264,7 +266,7 @@ function Functions.account_node_change(self, caller) -- resync caller phones for index, phone_caller in ipairs(caller_phones) do - local result = phone_caller:resync{ auth_name = caller_sip_account.auth_name, domain = caller.domain }; + local result = phone_caller:resync{ auth_name = caller_sip_account.record.auth_name, domain = caller_sip_account.record.host }; self.log:info('NODE_CHANGE - resync phone - mac: ', phone_caller.record.mac_address, ', ip_address: ', phone_caller.record.ip_address, ', result: ', result); end @@ -302,6 +304,7 @@ function Functions.user_login(self, caller, number, pin) if not caller_phone then self.log:notice('LOGIN - caller phone not found or not hot-deskable'); + local result = phone_class:resync{ auth_name = caller_sip_account.record.auth_name, domain = caller_sip_account.record.host }; return { continue = false, code = 403, phrase = 'Phone not hot-deskable', no_cdr = true } end @@ -374,13 +377,13 @@ function Functions.user_login(self, caller, number, pin) -- resync destination phones for index, phone_destination in ipairs(destination_phones) do - local result = phone_destination:resync{ auth_name = destination_sip_account.auth_name, domain = caller.domain_local }; + local result = phone_destination:resync{ auth_name = destination_sip_account.record.auth_name, domain = destination_sip_account.record.host }; self.log:info('LOGIN - resync destination phone - mac: ', phone_destination.record.mac_address, ', ip_address: ', phone_destination.record.ip_address, ', result: ', result); end -- resync caller phones for index, phone_caller in ipairs(caller_phones) do - local result = phone_caller:resync{ auth_name = caller_sip_account.auth_name, domain = caller.domain }; + local result = phone_caller:resync{ auth_name = caller_sip_account.record.auth_name, domain = caller_sip_account.record.host }; self.log:info('LOGIN - resync caller phone - mac: ', phone_caller.record.mac_address, ', ip_address: ', phone_caller.record.ip_address, ', result: ', result); end @@ -409,8 +412,9 @@ function Functions.user_logout(self, caller) local caller_phones = phone_class:find_all_hot_deskable_by_account(caller_sip_account.id); - if caller_phones == 0 then + if #caller_phones == 0 then self.log:notice('LOGOUT - caller phones not found or not hot-deskable'); + local result = phone_class:resync{ auth_name = caller_sip_account.record.auth_name, domain = caller_sip_account.record.host }; return { continue = false, code = 403, phrase = 'Phone not hot-deskable', no_cdr = true } end @@ -426,7 +430,7 @@ function Functions.user_logout(self, caller) -- resync caller phones for index, phone_caller in ipairs(caller_phones) do - local result = phone_caller:resync{ auth_name = caller_sip_account.auth_name, domain = caller.domain }; + local result = phone_caller:resync{ auth_name = caller_sip_account.record.auth_name, domain = caller_sip_account.record.host }; self.log:info('LOGIN - resync caller phone - mac: ', phone_caller.record.mac_address, ', ip_address: ', phone_caller.record.ip_address, ', result: ', result); end @@ -909,3 +913,9 @@ function Functions.hangup(self, caller, code, phrase) self.log:info("FUNCTION_HANGUP code: ", code, ', phrase: ', phrase); return { continue = false, code = code, phrase = phrase:gsub('_', ' '), no_cdr = true } end + +function Functions.park(self, caller, lot) + self.log:info("FUNCTION_PARK lot: ", lot); + caller:execute("valet_park", 'valet_lot ' .. lot); + return { continue = false, code = 200, phrase = 'OK', no_cdr = true } +end diff --git a/misc/freeswitch/scripts/dialplan/hunt_group.lua b/misc/freeswitch/scripts/dialplan/hunt_group.lua index 2c73bf8..fa3c05b 100644 --- a/misc/freeswitch/scripts/dialplan/hunt_group.lua +++ b/misc/freeswitch/scripts/dialplan/hunt_group.lua @@ -98,6 +98,18 @@ function HuntGroup.run(self, dialplan_object, caller, destination) self.log:info('HUNTGROUP ', self.record.id, ' - name: ', self.record.name, ', strategy: ', self.record.strategy,', members: ', #hunt_group_members); + local clip_no_screening = common.str.try(caller, 'account.record.clip_no_screening'); + caller.caller_id_numbers = {} + if not common.str.blank(clip_no_screening) then + for index, number in ipairs(common.str.strip_to_a(clip_no_screening, ',')) do + table.insert(caller.caller_id_numbers, number); + end + end + for index, number in ipairs(caller.caller_phone_numbers) do + table.insert(caller.caller_id_numbers, number); + end + self.log:info('CALLER_ID_NUMBERS - clir: ', caller.clir, ', numbers: ', table.concat(caller.caller_id_numbers, ',')); + local save_destination = caller.destination; local destinations = {} @@ -172,6 +184,7 @@ function HuntGroup.run(self, dialplan_object, caller, destination) self.log:info('HUNTGROUP ', self.record.id, ' - all members busy'); run_queue = false; end + caller:sleep(500); end else if forwarding_destination then diff --git a/misc/freeswitch/scripts/dialplan/router.lua b/misc/freeswitch/scripts/dialplan/router.lua index cdcb58b..bda80a7 100644 --- a/misc/freeswitch/scripts/dialplan/router.lua +++ b/misc/freeswitch/scripts/dialplan/router.lua @@ -18,11 +18,16 @@ function Router.new(self, arg) self.routes = arg.routes or {}; self.caller = arg.caller; self.variables = arg.variables or {}; + self.routing_tables = {}; return object; end -function Router.read_table(self, table_name) +function Router.read_table(self, table_name, force_reload) + if not force_reload and self.routing_tables[table_name] then + return self.routing_tables[table_name]; + end + local routing_table = {}; local sql_query = 'SELECT * \ @@ -48,6 +53,8 @@ function Router.read_table(self, table_name) }); end); + self.routing_tables[table_name] = routing_table; + return routing_table; end @@ -143,7 +150,7 @@ function Router.route_match(self, route) if not common.str.blank(element.var_out) then local command, variable_name = common.str.partition(element.var_out, ':'); if not command or not variable_name or command == 'var' then - destination[element.var_out] = replacement; + common.str.set(destination, element.var_out, replacement); elseif command == 'chv' then destination.channel_variables[variable_name] = replacement; elseif command == 'hdr' then @@ -159,6 +166,7 @@ function Router.route_match(self, route) end if route_matches then + destination.number = destination.number or destination.destination_number; return destination; end; diff --git a/misc/freeswitch/scripts/dialplan/sip_call.lua b/misc/freeswitch/scripts/dialplan/sip_call.lua index d1557e9..b56f1b2 100644 --- a/misc/freeswitch/scripts/dialplan/sip_call.lua +++ b/misc/freeswitch/scripts/dialplan/sip_call.lua @@ -95,39 +95,50 @@ function SipCall.fork(self, destinations, arg ) table.insert(origination_variables, 'ignore_display_updates=true'); end - if not destination.node_local then + if not destination.node_local or destination.type == 'node' then require 'common.node' - local node = common.node.Node:new{ log = self.log, database = self.database }:find_by_id(destination.node_id); - if node then - table.insert(origination_variables, 'sip_h_X-GS_node_id=' .. self.caller.local_node_id); - table.insert(dial_strings, '[' .. table.concat(origination_variables , ',') .. ']sofia/gateway/' .. node.record.name .. '/' .. destination.number); + local node = nil; + + if not destination.node_local then + node = common.node.Node:new{ log = self.log, database = self.database }:find_by_id(destination.node_id); + else + node = common.node.Node:new{ log = self.log, database = self.database }:find_by_id(destination.id); end - elseif destination.type == 'node' then - local node = common.node.Node:new{ log = self.log, database = self.database }:find_by_id(destination.id); if node then table.insert(origination_variables, 'sip_h_X-GS_node_id=' .. self.caller.local_node_id); + table.insert(origination_variables, 'sip_h_X-GS_account_uuid=' .. tostring(self.caller.account_uuid)); + table.insert(origination_variables, 'sip_h_X-GS_account_type=' .. tostring(self.caller.account_type)); + table.insert(origination_variables, 'sip_h_X-GS_auth_account_type=' .. tostring(self.caller.auth_account_type)); + table.insert(origination_variables, 'sip_h_X-GS_auth_account_uuid=' .. tostring(self.caller.auth_account_uuid)); + table.insert(origination_variables, 'sip_h_X-GS_loop_count=' .. tostring(self.caller.loop_count)); table.insert(dial_strings, '[' .. table.concat(origination_variables , ',') .. ']sofia/gateway/' .. node.record.name .. '/' .. destination.number); end elseif destination.type == 'sipaccount' then local callee_id_params = ''; local sip_account = sip_account_class:find_by_id(destination.id); - local call_waiting = self:call_waiting_busy(sip_account); - if not call_waiting then - destinations[index].numbers = sip_account:phone_numbers(); + if not sip_account then + self.log:notice('FORK - sip_account not found - sip_account=', destination.id); + elseif common.str.blank(sip_account.record.profile_name) or common.str.blank(sip_account.record.sip_host) then + call_result = { code = 480, phrase = 'User offline', disposition = 'USER_NOT_REGISTERED' }; + else + local call_waiting = self:call_waiting_busy(sip_account); + if not call_waiting then + destinations[index].numbers = sip_account:phone_numbers(); - if not arg.callee_id_name then - table.insert(origination_variables, "effective_callee_id_name='" .. sip_account.record.caller_name .. "'"); - end - if not arg.callee_id_number then - table.insert(origination_variables, "effective_callee_id_number='" .. destination.number .. "'"); - end - if destination.alert_info then - table.insert(origination_variables, "alert_info='" .. destination.alert_info .. "'"); + if not arg.callee_id_name then + table.insert(origination_variables, "effective_callee_id_name='" .. sip_account.record.caller_name .. "'"); + end + if not arg.callee_id_number then + table.insert(origination_variables, "effective_callee_id_number='" .. destination.number .. "'"); + end + if destination.alert_info then + table.insert(origination_variables, "alert_info='" .. destination.alert_info .. "'"); + end + table.insert(dial_strings, '[' .. table.concat(origination_variables , ',') .. ']sofia/' .. sip_account.record.profile_name .. '/' .. sip_account.record.auth_name .. '%' .. sip_account.record.sip_host); + else + some_destinations_busy = true; + call_result = { code = 486, phrase = 'User busy', disposition = 'USER_BUSY' }; end - table.insert(dial_strings, '[' .. table.concat(origination_variables , ',') .. ']user/' .. sip_account.record.auth_name); - else - some_destinations_busy = true; - call_result = { code = 486, phrase = 'User busy', disposition = 'USER_BUSY' }; end elseif destination.type == 'gateway' then require 'common.gateway' @@ -169,11 +180,6 @@ function SipCall.fork(self, destinations, arg ) end self.caller:set_callee_id(arg.callee_id_number, arg.callee_id_name); - self.caller:set_header('X-GS_account_uuid', self.caller.account_uuid); - self.caller:set_header('X-GS_account_type', self.caller.account_type); - self.caller:set_header('X-GS_auth_account_type', self.caller.auth_account_type); - self.caller:set_header('X-GS_auth_account_uuid', self.caller.auth_account_uuid); - self.caller:set_header('X-GS_loop_count', self.caller.loop_count); self.caller:set_variable('call_timeout', arg.timeout ); self.log:info('FORK DIAL - destinations: ', #dial_strings, ', timeout: ', arg.timeout); @@ -195,6 +201,12 @@ function SipCall.fork(self, destinations, arg ) fork_index = tonumber(session_callee:getVariable('gs_fork_index')) or 0; local destination = destinations[fork_index]; + if arg.detect_dtmf_after_bridge_caller then + session:execute('start_dtmf'); + end + if arg.detect_dtmf_after_bridge_callee then + session_callee:execute('start_dtmf'); + end if arg.bypass_media_network then local callee_uuid = session_callee:get_uuid(); @@ -226,10 +238,15 @@ function SipCall.fork(self, destinations, arg ) self.caller:set_variable('gs_destination_id', destination.id); self.caller:set_variable('gs_destination_uuid', destination.uuid); + if arg.detect_dtmf_after_bridge_callee then + session_callee:setInputCallback('input_call_back_callee', 'session_callee'); + end + self.log:info('FORK ', fork_index, ' BRIDGE - destination: ', destination.type, '=', destination.id, '/', destination.uuid,'@', destination.node_id, ', number: ', destination.number, ', dial_time: ', os.time() - start_time); + freeswitch.bridge(self.caller.session, session_callee); self:wait_hangup(self.caller.session, session_callee); end |