Last active
March 31, 2023 15:27
-
-
Save pc-m/39fd8c16b77b47fe5684a64a803f6f95 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/wazo_calld/controller.py b/wazo_calld/controller.py | |
| index 276283ac..54f8074b 100644 | |
| --- a/wazo_calld/controller.py | |
| +++ b/wazo_calld/controller.py | |
| @@ -20,6 +20,8 @@ from .bus import CoreBusConsumer, CoreBusPublisher | |
| from .collectd import CollectdPublisher | |
| from .http_server import api, HTTPServer | |
| from .service_discovery import self_check | |
| +from .helpers.channel_proxy import ChannelProxy | |
| + | |
| logger = logging.getLogger(__name__) | |
| @@ -49,6 +51,7 @@ class Controller: | |
| ] | |
| self._pubsub = pubsub.Pubsub() | |
| + self._channel_proxy = ChannelProxy(self.ari.client) | |
| plugin_helpers.load( | |
| namespace='wazo_calld.plugins', | |
| names=config['enabled_plugins'], | |
| @@ -58,6 +61,7 @@ class Controller: | |
| 'asyncio': self.asyncio, | |
| 'bus_publisher': self.bus_publisher, | |
| 'bus_consumer': self.bus_consumer, | |
| + 'channel_proxy': self._channel_proxy, | |
| 'collectd': self.collectd, | |
| 'config': config, | |
| 'status_aggregator': self.status_aggregator, | |
| diff --git a/wazo_calld/helpers/__init__.py b/wazo_calld/helpers/__init__.py | |
| new file mode 100644 | |
| index 00000000..e69de29b | |
| diff --git a/wazo_calld/helpers/channel_proxy.py b/wazo_calld/helpers/channel_proxy.py | |
| new file mode 100644 | |
| index 00000000..1e7546da | |
| --- /dev/null | |
| +++ b/wazo_calld/helpers/channel_proxy.py | |
| @@ -0,0 +1,80 @@ | |
| +# Copyright 2023 The Wazo Authors (see the AUTHORS file) | |
| +# SPDX-License-Identifier: GPL-3.0-or-later | |
| + | |
| +import logging | |
| + | |
| +from time import time | |
| + | |
| +logger = logging.getLogger(__name__) | |
| + | |
| +CHANNEL_CACHE_EXPIRATION = 60 * 60 | |
| + | |
| + | |
| +class ChannelProxy: | |
| + def __init__(self, ari): | |
| + self._ari = ari | |
| + self._channel_variable_cache = {} | |
| + self._channel_json_cache = {} | |
| + self._last_cache_cleanup = time() | |
| + | |
| + def get_variable(self, channel_id, name): | |
| + response = self._ari.channels.getChannelVar(channelId=channel_id, variable=name) | |
| + return response['value'] | |
| + | |
| + def get_constant(self, channel_id, name): | |
| + try: | |
| + result = self._get_cached_value(channel_id, name) | |
| + except KeyError: | |
| + result = self.get_variable(channel_id, name) | |
| + self._insert_value(channel_id, name, result) | |
| + return result | |
| + | |
| + def get_constant_json(self, channel_id): | |
| + try: | |
| + result = self._channel_json_cache[channel_id] | |
| + except KeyError: | |
| + channel = self._ari.channels.get(channelId=channel_id) | |
| + result = channel.json | |
| + self._channel_json_cache[channel_id] = result | |
| + return result | |
| + | |
| + def on_hang_up(self, channel, event): | |
| + self._remove_cached_channel(channel.id) | |
| + self._remove_old_calls_from_cache() | |
| + | |
| + def _remove_old_calls_from_cache(self): | |
| + # To avoid leaking channel variables if an event ever gets missed | |
| + # we are going to clean the cache every once in a while | |
| + now = time() | |
| + threshold = now - CHANNEL_CACHE_EXPIRATION | |
| + if self._last_cache_cleanup > threshold: | |
| + return | |
| + | |
| + to_remove = set() | |
| + for call_id in self._channel_variable_cache.keys(): | |
| + if float(call_id) < threshold: | |
| + to_remove.add(call_id) | |
| + | |
| + for call_id in self._channel_json_cache.keys(): | |
| + if float(call_id) < threshold: | |
| + to_remove.add(call_id) | |
| + | |
| + logger.debug('Removing %s calls from the cache', len(to_remove)) | |
| + for call_id in to_remove: | |
| + self._remove_cached_channel(call_id) | |
| + | |
| + self._last_cache_cleanup = now | |
| + | |
| + def _remove_cached_channel(self, channel_id): | |
| + logger.debug('removing %s from channel proxy', channel_id) | |
| + self._channel_variable_cache.pop(channel_id, None) | |
| + self._channel_json_cache.pop(channel_id, None) | |
| + | |
| + def _insert_value(self, channel_id, name, value): | |
| + if channel_id not in self._channel_variable_cache: | |
| + self._channel_variable_cache[channel_id] = {name: value} | |
| + else: | |
| + self._channel_variable_cache[channel_id][name] = value | |
| + | |
| + def _get_cached_value(self, channel_id, name): | |
| + return self._channel_variable_cache[channel_id][name] | |
| diff --git a/wazo_calld/plugin_helpers/ari_.py b/wazo_calld/plugin_helpers/ari_.py | |
| index 59ad5ec3..0ecef980 100644 | |
| --- a/wazo_calld/plugin_helpers/ari_.py | |
| +++ b/wazo_calld/plugin_helpers/ari_.py | |
| @@ -145,20 +145,21 @@ class GlobalVariableConstantNameAdapter: | |
| class Channel: | |
| - def __init__(self, channel_id, ari): | |
| + def __init__(self, channel_id, ari, channel_proxy): | |
| self.id = channel_id | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| def __str__(self): | |
| return self.id | |
| def asterisk_name(self): | |
| try: | |
| - channel = self._ari.channels.get(channelId=self.id) | |
| + json = self._channel_proxy.get_constant_json(self.id) | |
| except ARINotFound: | |
| return False | |
| - return channel.json['name'] | |
| + return json['name'] | |
| def connected_channels(self): | |
| channel_ids = set( | |
| @@ -175,11 +176,14 @@ class Channel: | |
| channel_ids.remove(self.id) | |
| except KeyError: | |
| pass | |
| - return {Channel(channel_id, self._ari) for channel_id in channel_ids} | |
| + return { | |
| + Channel(channel_id, self._ari, self._channel_proxy) | |
| + for channel_id in channel_ids | |
| + } | |
| def conversation_id(self): | |
| try: | |
| - linkedid = self._get_var('CHANNEL(linkedid)') | |
| + linkedid = self._get_constant('CHANNEL(linkedid)') | |
| except ARINotFound: | |
| return None | |
| return linkedid | |
| @@ -192,25 +196,25 @@ class Channel: | |
| channel_id = connected_channels.pop().id | |
| except KeyError: | |
| raise NotEnoughChannels() | |
| - return Channel(channel_id, self._ari) | |
| + return Channel(channel_id, self._ari, self._channel_proxy) | |
| def user(self, default=None): | |
| if self.is_local(): | |
| try: | |
| - uuid = self._get_var('WAZO_DEREFERENCED_USERUUID') | |
| + uuid = self._get_constant('WAZO_DEREFERENCED_USERUUID') | |
| except ARINotFound: | |
| return default | |
| return uuid | |
| try: | |
| - uuid = self._get_var('XIVO_USERUUID') | |
| + uuid = self._get_constant('XIVO_USERUUID') | |
| return uuid | |
| except ARINotFound: | |
| return default | |
| def tenant_uuid(self, default=None): | |
| try: | |
| - tenant_uuid = self._get_var('WAZO_TENANT_UUID') | |
| + tenant_uuid = self._get_constant('WAZO_TENANT_UUID') | |
| except ARINotFound: | |
| return default | |
| return tenant_uuid | |
| @@ -224,11 +228,11 @@ class Channel: | |
| def is_local(self): | |
| try: | |
| - channel = self._ari.channels.get(channelId=self.id) | |
| + json = self._channel_proxy.get_constant_json(self.id) | |
| except ARINotFound: | |
| return False | |
| - return channel.json['name'].startswith('Local/') | |
| + return json['name'].startswith('Local/') | |
| def is_caller(self): | |
| try: | |
| @@ -238,7 +242,7 @@ class Channel: | |
| pass | |
| try: | |
| - direction = self._get_var('WAZO_CHANNEL_DIRECTION') | |
| + direction = self._get_constant('WAZO_CHANNEL_DIRECTION') | |
| return direction == 'to-wazo' | |
| except ARINotFound: | |
| pass | |
| @@ -256,15 +260,13 @@ class Channel: | |
| def is_sip(self): | |
| try: | |
| - return self._get_var('CHANNEL(channeltype)') == 'PJSIP' | |
| + return self._get_constant('CHANNEL(channeltype)') == 'PJSIP' | |
| except ARINotFound: | |
| return False | |
| def dialed_extension(self): | |
| try: | |
| - return self._ari.channels.getChannelVar( | |
| - channelId=self.id, variable='WAZO_ENTRY_EXTEN' | |
| - )['value'] | |
| + return self._channel_proxy.get_constant(self.id, 'WAZO_ENTRY_EXTEN') | |
| except ARINotFound: | |
| try: | |
| channel = self._ari.channels.get(channelId=self.id) | |
| @@ -301,13 +303,13 @@ class Channel: | |
| def sip_call_id_unsafe(self): | |
| '''This method expects a SIP channel''' | |
| try: | |
| - return self._get_var('CHANNEL(pjsip,call-id)') | |
| + return self._get_constant('CHANNEL(pjsip,call-id)') | |
| except ARINotFound: | |
| return | |
| def line_id(self): | |
| try: | |
| - return int(self._get_var('WAZO_LINE_ID')) | |
| + return int(self._get_constant('WAZO_LINE_ID')) | |
| except ARINotFound: | |
| return | |
| except ValueError: | |
| @@ -345,16 +347,18 @@ class Channel: | |
| except ARINotFound: | |
| return | |
| + def _get_constant(self, var): | |
| + return self._channel_proxy.get_constant(self.id, var) | |
| + | |
| def _get_var(self, var): | |
| - return self._ari.channels.getChannelVar(channelId=self.id, variable=var)[ | |
| - 'value' | |
| - ] | |
| + return self._channel_proxy.get_variable(self.id, var) | |
| class Bridge: | |
| - def __init__(self, bridge_id, ari): | |
| + def __init__(self, bridge_id, ari, channel_proxy): | |
| self.id = bridge_id | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| self.global_variables = GlobalVariableNameDecorator( | |
| GlobalVariableAdapter(self._ari), | |
| 'WAZO_BRIDGE_{bridge_id}_VARIABLE_{{}}'.format(bridge_id=self.id), | |
| @@ -395,7 +399,7 @@ class Bridge: | |
| return set() | |
| return set( | |
| - Channel(channel_id, self._ari).user() | |
| + Channel(channel_id, self._ari, self._channel_proxy).user() | |
| for channel_id in bridge.json['channels'] | |
| ) | |
| @@ -408,12 +412,13 @@ class Bridge: | |
| class BridgeSnapshot(Bridge): | |
| - def __init__(self, snapshot, ari): | |
| + def __init__(self, snapshot, ari, channel_proxy): | |
| self._snapshot = snapshot | |
| - super().__init__(snapshot['id'], ari) | |
| + self._channel_proxy = channel_proxy | |
| + super().__init__(snapshot['id'], ari, channel_proxy) | |
| def valid_user_uuids(self): | |
| return set( | |
| - Channel(channel_id, self._ari).user() | |
| + Channel(channel_id, self._ari, self._channel_proxy).user() | |
| for channel_id in self._snapshot['channels'] | |
| ) | |
| diff --git a/wazo_calld/plugin_helpers/tests/test_ari_helpers.py b/wazo_calld/plugin_helpers/tests/test_ari_helpers.py | |
| index 634fc489..03948581 100644 | |
| --- a/wazo_calld/plugin_helpers/tests/test_ari_helpers.py | |
| +++ b/wazo_calld/plugin_helpers/tests/test_ari_helpers.py | |
| @@ -13,12 +13,14 @@ from hamcrest import ( | |
| from ari.exceptions import ARINotFound | |
| +from wazo_calld.helpers.channel_proxy import ChannelProxy | |
| from ..ari_ import Channel | |
| class TestChannelHelper(TestCase): | |
| def setUp(self): | |
| self.ari = Mock() | |
| + self.channel_proxy = ChannelProxy(self.ari) | |
| def test_dialed_extension_when_no_channel_exist(self): | |
| self.ari.channels.getChannelVar.side_effect = ARINotFound( | |
| @@ -30,7 +32,7 @@ class TestChannelHelper(TestCase): | |
| ari_client=self.ari, | |
| ) | |
| - channel = Channel(s.channel_id, self.ari) | |
| + channel = Channel(s.channel_id, self.ari, self.channel_proxy) | |
| result = channel.dialed_extension() | |
| assert_that(result, equal_to(None)) | |
| @@ -40,7 +42,7 @@ class TestChannelHelper(TestCase): | |
| mocked_channel = self.ari.channels.get.return_value = Mock() | |
| mocked_channel.json = {'dialplan': {'exten': 's'}} | |
| - channel = Channel(s.channel_id, self.ari) | |
| + channel = Channel(s.channel_id, self.ari, self.channel_proxy) | |
| result = channel.dialed_extension() | |
| assert_that(result, equal_to(s.exten)) | |
| @@ -53,7 +55,7 @@ class TestChannelHelper(TestCase): | |
| self.ari.channels.get.return_value = mocked_channel = Mock() | |
| mocked_channel.json = {'dialplan': {'exten': s.exten}} | |
| - channel = Channel(s.channel_id, self.ari) | |
| + channel = Channel(s.channel_id, self.ari, self.channel_proxy) | |
| result = channel.dialed_extension() | |
| assert_that(result, equal_to(s.exten)) | |
| diff --git a/wazo_calld/plugins/adhoc_conferences/plugin.py b/wazo_calld/plugins/adhoc_conferences/plugin.py | |
| index 11bd03cc..0fbdac5b 100644 | |
| --- a/wazo_calld/plugins/adhoc_conferences/plugin.py | |
| +++ b/wazo_calld/plugins/adhoc_conferences/plugin.py | |
| @@ -20,6 +20,7 @@ class Plugin: | |
| ari = dependencies['ari'] | |
| bus_publisher = dependencies['bus_publisher'] | |
| config = dependencies['config'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| amid_client = AmidClient(**config['amid']) | |
| @@ -28,11 +29,14 @@ class Plugin: | |
| notifier = AdhocConferencesNotifier(bus_publisher) | |
| adhoc_conferences_service = AdhocConferencesService( | |
| - amid_client, ari.client, notifier | |
| + amid_client, | |
| + ari.client, | |
| + notifier, | |
| + channel_proxy, | |
| ) | |
| startup_callback_collector = CallbackCollector() | |
| - adhoc_conferences_stasis = AdhocConferencesStasis(ari, notifier) | |
| + adhoc_conferences_stasis = AdhocConferencesStasis(ari, notifier, channel_proxy) | |
| ari.client_initialized_subscribe(startup_callback_collector.new_source()) | |
| startup_callback_collector.subscribe(adhoc_conferences_stasis.initialize) | |
| diff --git a/wazo_calld/plugins/adhoc_conferences/services.py b/wazo_calld/plugins/adhoc_conferences/services.py | |
| index 38bae499..4b2bac6c 100644 | |
| --- a/wazo_calld/plugins/adhoc_conferences/services.py | |
| +++ b/wazo_calld/plugins/adhoc_conferences/services.py | |
| @@ -24,10 +24,11 @@ logger = logging.getLogger(__name__) | |
| class AdhocConferencesService: | |
| - def __init__(self, amid_client, ari, notifier): | |
| + def __init__(self, amid_client, ari, notifier, channel_proxy): | |
| self._amid_client = amid_client | |
| self._ari = ari | |
| self._notifier = notifier | |
| + self._channel_proxy = channel_proxy | |
| def create_from_user(self, host_call_id, participant_call_ids, user_uuid): | |
| logger.debug( | |
| @@ -36,7 +37,7 @@ class AdhocConferencesService: | |
| host_call_id, | |
| participant_call_ids, | |
| ) | |
| - host_channel = Channel(host_call_id, self._ari) | |
| + host_channel = Channel(host_call_id, self._ari, self._channel_proxy) | |
| if not host_channel.exists(): | |
| raise HostCallNotFound(host_call_id) | |
| @@ -54,7 +55,9 @@ class AdhocConferencesService: | |
| raise HostCallAlreadyInConference(host_call_id) | |
| for participant_call_id in participant_call_ids: | |
| - if not Channel(participant_call_id, self._ari).exists(): | |
| + if not Channel( | |
| + participant_call_id, self._ari, self._channel_proxy | |
| + ).exists(): | |
| raise ParticipantCallNotFound(participant_call_id) | |
| try: | |
| @@ -116,7 +119,7 @@ class AdhocConferencesService: | |
| } | |
| def _find_peer_channel(self, call_id): | |
| - return Channel(call_id, self._ari).only_connected_channel() | |
| + return Channel(call_id, self._ari, self._channel_proxy).only_connected_channel() | |
| def _redirect_host(self, host_call_id, host_peer_channel_id, adhoc_conference_id): | |
| try: | |
| @@ -215,7 +218,7 @@ class AdhocConferencesService: | |
| ) | |
| def delete_from_user(self, adhoc_conference_id, user_uuid): | |
| - bridge_helper = Bridge(adhoc_conference_id, self._ari) | |
| + bridge_helper = Bridge(adhoc_conference_id, self._ari, self._channel_proxy) | |
| if not bridge_helper.exists(): | |
| raise AdhocConferenceNotFound(adhoc_conference_id) | |
| @@ -230,11 +233,11 @@ class AdhocConferencesService: | |
| def add_participant_from_user( | |
| self, adhoc_conference_id, participant_call_id, user_uuid | |
| ): | |
| - bridge_helper = Bridge(adhoc_conference_id, self._ari) | |
| + bridge_helper = Bridge(adhoc_conference_id, self._ari, self._channel_proxy) | |
| if not bridge_helper.exists(): | |
| raise AdhocConferenceNotFound(adhoc_conference_id) | |
| - if not Channel(participant_call_id, self._ari).exists(): | |
| + if not Channel(participant_call_id, self._ari, self._channel_proxy).exists(): | |
| raise ParticipantCallNotFound(participant_call_id) | |
| if ( | |
| @@ -277,7 +280,7 @@ class AdhocConferencesService: | |
| def remove_participant_from_user( | |
| self, adhoc_conference_id, participant_call_id, user_uuid | |
| ): | |
| - bridge_helper = Bridge(adhoc_conference_id, self._ari) | |
| + bridge_helper = Bridge(adhoc_conference_id, self._ari, self._channel_proxy) | |
| if not bridge_helper.exists(): | |
| raise AdhocConferenceNotFound(adhoc_conference_id) | |
| @@ -287,7 +290,7 @@ class AdhocConferencesService: | |
| ): | |
| raise AdhocConferenceNotFound(adhoc_conference_id) | |
| - if not Channel(participant_call_id, self._ari).exists(): | |
| + if not Channel(participant_call_id, self._ari, self._channel_proxy).exists(): | |
| raise ParticipantCallNotFound(participant_call_id) | |
| participants = self._ari.bridges.get(bridgeId=adhoc_conference_id).json[ | |
| diff --git a/wazo_calld/plugins/adhoc_conferences/stasis.py b/wazo_calld/plugins/adhoc_conferences/stasis.py | |
| index d3c6b84e..24b52d6c 100644 | |
| --- a/wazo_calld/plugins/adhoc_conferences/stasis.py | |
| +++ b/wazo_calld/plugins/adhoc_conferences/stasis.py | |
| @@ -15,10 +15,11 @@ ADHOC_CONFERENCE_STASIS_APP = 'adhoc_conference' | |
| class AdhocConferencesStasis: | |
| - def __init__(self, ari, notifier): | |
| + def __init__(self, ari, notifier, channel_proxy): | |
| self._ari = ari.client | |
| self._core_ari = ari | |
| self._notifier = notifier | |
| + self._channel_proxy = channel_proxy | |
| self._adhoc_conference_creation_lock = threading.Lock() | |
| def _subscribe(self): | |
| @@ -97,10 +98,10 @@ class AdhocConferencesStasis: | |
| ) | |
| return | |
| - bridge_helper = BridgeSnapshot(event['bridge'], self._ari) | |
| + bridge_helper = BridgeSnapshot(event['bridge'], self._ari, self._channel_proxy) | |
| if is_adhoc_conference_host: | |
| - host_channel = Channel(channel_id, self._ari) | |
| + host_channel = Channel(channel_id, self._ari, self._channel_proxy) | |
| host_user_uuid = host_channel.user() | |
| host_tenant_uuid = host_channel.tenant_uuid() | |
| bridge_helper.global_variables.set('WAZO_HOST_CHANNEL_ID', channel_id) | |
| @@ -118,7 +119,9 @@ class AdhocConferencesStasis: | |
| ) | |
| self._set_host_connectedline(channel_id, adhoc_conference_id) | |
| - participant_call = CallsService.make_call_from_channel(self._ari, channel) | |
| + participant_call = CallsService.make_call_from_channel( | |
| + self._ari, self._channel_proxy, channel | |
| + ) | |
| other_participant_uuids = bridge_helper.valid_user_uuids() | |
| self._notifier.participant_joined( | |
| adhoc_conference_id, other_participant_uuids, participant_call | |
| @@ -138,7 +141,7 @@ class AdhocConferencesStasis: | |
| ) | |
| continue | |
| other_participant_call = CallsService.make_call_from_channel( | |
| - self._ari, other_participant_channel | |
| + self._ari, self._channel_proxy, other_participant_channel | |
| ) | |
| self._notifier.participant_joined( | |
| adhoc_conference_id, [host_user_uuid], other_participant_call | |
| @@ -173,7 +176,7 @@ class AdhocConferencesStasis: | |
| 'adhoc conference %s: channel %s left', adhoc_conference_id, channel_id | |
| ) | |
| - bridge_helper = Bridge(adhoc_conference_id, self._ari) | |
| + bridge_helper = Bridge(adhoc_conference_id, self._ari, self._channel_proxy) | |
| try: | |
| host_user_uuid = bridge_helper.global_variables.get('WAZO_HOST_USER_UUID') | |
| except KeyError: | |
| @@ -256,7 +259,7 @@ class AdhocConferencesStasis: | |
| return | |
| logger.debug('adhoc conference %s: bridge was destroyed', bridge.id) | |
| - bridge_helper = Bridge(bridge.id, self._ari) | |
| + bridge_helper = Bridge(bridge.id, self._ari, self._channel_proxy) | |
| try: | |
| host_user_uuid = bridge_helper.global_variables.get('WAZO_HOST_USER_UUID') | |
| diff --git a/wazo_calld/plugins/applications/models.py b/wazo_calld/plugins/applications/models.py | |
| index 319d916e..a8d7720a 100644 | |
| --- a/wazo_calld/plugins/applications/models.py | |
| +++ b/wazo_calld/plugins/applications/models.py | |
| @@ -41,9 +41,10 @@ class ApplicationNode: | |
| class CallFormatter: | |
| - def __init__(self, application, ari=None): | |
| + def __init__(self, application, ari=None, channel_proxy=None): | |
| self._application = application | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| self._snoop_list = None | |
| def from_channel(self, channel, variables=None, node_uuid=None): | |
| @@ -58,7 +59,7 @@ class CallFormatter: | |
| call.node_uuid = node_uuid | |
| if self._ari is not None: | |
| - channel_helper = _ChannelHelper(channel.id, self._ari) | |
| + channel_helper = _ChannelHelper(channel.id, self._ari, self._channel_proxy) | |
| call.on_hold = channel_helper.on_hold() | |
| call.is_caller = channel_helper.is_caller() | |
| call.dialed_extension = channel_helper.dialed_extension() | |
| @@ -110,7 +111,7 @@ class CallFormatter: | |
| if not self._ari: | |
| return {} | |
| - snoop_helper = SnoopHelper(self._ari) | |
| + snoop_helper = SnoopHelper(self._ari, self._channel_proxy) | |
| self._snoop_list = snoop_helper.list_(self._application) | |
| result = {} | |
| @@ -197,7 +198,7 @@ class _Snoop: | |
| if old_snoop_channel: | |
| old_snoop_channel.hangup() | |
| - def new_snoop_channel(self, ari, whisper_mode): | |
| + def new_snoop_channel(self, ari, channel_proxy, whisper_mode): | |
| logger.debug('Creating new snoop channel') | |
| try: | |
| snoop_channel = ari.channels.snoopChannel( | |
| @@ -209,7 +210,7 @@ class _Snoop: | |
| except ARINotFound: | |
| raise NoSuchCall(self.snooped_call_id) | |
| - _ChannelHelper(snoop_channel.id, ari).wait_until_in_stasis() | |
| + _ChannelHelper(snoop_channel.id, ari, channel_proxy).wait_until_in_stasis() | |
| snoop_channel.setChannelVar( | |
| variable=self._whisper_mode_chan_var, | |
| @@ -278,8 +279,9 @@ class _Snoop: | |
| class SnoopHelper: | |
| - def __init__(self, ari): | |
| + def __init__(self, ari, channel_proxy): | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| def create(self, application, snooped_call_id, snooping_call_id, whisper_mode): | |
| self.validate_ownership(application, snooped_call_id, snooping_call_id) | |
| @@ -287,7 +289,9 @@ class SnoopHelper: | |
| snoop = _Snoop(application, snooped_call_id, snooping_call_id) | |
| try: | |
| snoop.create_bridge(self._ari) | |
| - snoop_channel = snoop.new_snoop_channel(self._ari, whisper_mode) | |
| + snoop_channel = snoop.new_snoop_channel( | |
| + self._ari, self._channel_proxy, whisper_mode | |
| + ) | |
| snoop.update_snoop_channel(snoop_channel) | |
| except Exception as e: | |
| logger.debug('Error while creating the snoop bridge, destroying it. %s', e) | |
| @@ -303,7 +307,9 @@ class SnoopHelper: | |
| snoop = self.get(application, snoop_uuid) | |
| self.validate_ownership(application, snoop.snooped_call_id) | |
| - snoop_channel = snoop.new_snoop_channel(self._ari, whisper_mode) | |
| + snoop_channel = snoop.new_snoop_channel( | |
| + self._ari, self._channel_proxy, whisper_mode | |
| + ) | |
| snoop.update_snoop_channel(snoop_channel) | |
| return snoop | |
| diff --git a/wazo_calld/plugins/applications/plugin.py b/wazo_calld/plugins/applications/plugin.py | |
| index 2e25537b..d4036d9d 100644 | |
| --- a/wazo_calld/plugins/applications/plugin.py | |
| +++ b/wazo_calld/plugins/applications/plugin.py | |
| @@ -48,6 +48,7 @@ class Plugin: | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| next_token_changed_subscribe = dependencies['next_token_changed_subscribe'] | |
| pubsub = dependencies['pubsub'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| auth_client = AuthClient(**config['auth']) | |
| confd_client = ConfdClient(**config['confd']) | |
| @@ -70,10 +71,12 @@ class Plugin: | |
| notifier, | |
| confd_apps_cache, | |
| moh_cache, | |
| + channel_proxy, | |
| ) | |
| stasis = ApplicationStasis( | |
| ari, | |
| + channel_proxy, | |
| service, | |
| notifier, | |
| confd_apps_cache, | |
| diff --git a/wazo_calld/plugins/applications/services.py b/wazo_calld/plugins/applications/services.py | |
| index 4f3c294a..958ac6b5 100644 | |
| --- a/wazo_calld/plugins/applications/services.py | |
| +++ b/wazo_calld/plugins/applications/services.py | |
| @@ -29,14 +29,15 @@ logger = logging.getLogger(__name__) | |
| class ApplicationService: | |
| - def __init__(self, ari, confd, amid, notifier, confd_apps, moh): | |
| + def __init__(self, ari, confd, amid, notifier, confd_apps, moh, channel_proxy): | |
| self._ari = ari | |
| self._amid = amid | |
| self._notifier = notifier | |
| self._confd = confd | |
| self._confd_apps = confd_apps | |
| self._moh = moh | |
| - self._snoop_helper = SnoopHelper(self._ari) | |
| + self._channel_proxy = channel_proxy | |
| + self._snoop_helper = SnoopHelper(self._ari, self._channel_proxy) | |
| def call_mute(self, application, call_id): | |
| try: | |
| @@ -46,7 +47,7 @@ class ApplicationService: | |
| except ARINotFound: | |
| raise NoSuchCall(call_id) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_updated(application, call) | |
| @@ -58,7 +59,7 @@ class ApplicationService: | |
| except ARINotFound: | |
| raise NoSuchCall(call_id) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_updated(application, call) | |
| @@ -73,7 +74,7 @@ class ApplicationService: | |
| def start_user_outgoing_call(self, application, channel): | |
| set_channel_var_sync(channel, 'WAZO_USER_OUTGOING_CALL', 'true') | |
| variables = self.get_channel_variables(channel) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel, variables=variables) | |
| self._notifier.user_outgoing_call_created(application, call) | |
| @@ -274,7 +275,7 @@ class ApplicationService: | |
| name = channel.json['name'] | |
| return name.startswith('Local/') and name.endswith(';2') | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| for channel_id in application['channel_ids']: | |
| try: | |
| channel = self._ari.channels.get(channelId=channel_id) | |
| @@ -341,7 +342,7 @@ class ApplicationService: | |
| channel = self._ari.channels.originate(**originate_kwargs) | |
| variables = self.get_channel_variables(channel) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| return formatter.from_channel(channel, variables=variables, node_uuid=node_uuid) | |
| def originate_user( | |
| @@ -374,17 +375,17 @@ class ApplicationService: | |
| def originate_answered(self, application, channel): | |
| channel.answer() | |
| variables = self.get_channel_variables(channel) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel, variables=variables) | |
| self._notifier.call_initiated(application, call) | |
| def snoop_create( | |
| self, application, snooped_call_id, snooping_call_id, whisper_mode | |
| ): | |
| - if not Channel(snooping_call_id, self._ari).is_in_stasis(): | |
| + if not Channel(snooping_call_id, self._ari, self._channel_proxy).is_in_stasis(): | |
| raise CallNotInApplication(application['uuid'], snooping_call_id) | |
| - if not Channel(snooped_call_id, self._ari).is_in_stasis(): | |
| + if not Channel(snooped_call_id, self._ari, self._channel_proxy).is_in_stasis(): | |
| raise CallNotInApplication(application['uuid'], snooped_call_id) | |
| snoop = self._snoop_helper.create( | |
| diff --git a/wazo_calld/plugins/applications/stasis.py b/wazo_calld/plugins/applications/stasis.py | |
| index a0bf3d46..0999c140 100644 | |
| --- a/wazo_calld/plugins/applications/stasis.py | |
| +++ b/wazo_calld/plugins/applications/stasis.py | |
| @@ -32,8 +32,9 @@ class AppNameHelper: | |
| class ApplicationStasis: | |
| - def __init__(self, ari, service, notifier, confd_apps, moh): | |
| + def __init__(self, ari, channel_proxy, service, notifier, confd_apps, moh): | |
| self._ari = ari.client | |
| + self._channel_proxy = channel_proxy | |
| self._confd_apps = confd_apps | |
| self._moh = moh | |
| self._core_ari = ari | |
| @@ -77,7 +78,7 @@ class ApplicationStasis: | |
| node = make_node_from_bridge_event(event.get('bridge')) | |
| self._notifier.node_updated(application, node) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_updated(application, call) | |
| @@ -128,7 +129,7 @@ class ApplicationStasis: | |
| return | |
| application = self._service.get_application(application_uuid) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_deleted(application, call) | |
| @@ -152,7 +153,7 @@ class ApplicationStasis: | |
| if moh: | |
| set_channel_var_sync(channel, 'WAZO_MOH_UUID', str(moh['uuid'])) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_updated(application, call) | |
| @@ -164,7 +165,7 @@ class ApplicationStasis: | |
| application = self._service.get_application(application_uuid) | |
| set_channel_var_sync(channel, 'WAZO_MOH_UUID', '') | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| self._notifier.call_updated(application, call) | |
| @@ -175,7 +176,7 @@ class ApplicationStasis: | |
| application = self._service.get_application(application_uuid) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| if channel.json['state'] == 'Up': | |
| @@ -189,7 +190,7 @@ class ApplicationStasis: | |
| application = self._service.get_application(application_uuid) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel) | |
| if event['value'] == '1': | |
| @@ -247,7 +248,7 @@ class ApplicationStasis: | |
| application = self._service.get_application(application_uuid) | |
| variables = self._service.get_channel_variables(channel) | |
| - formatter = CallFormatter(application, self._ari) | |
| + formatter = CallFormatter(application, self._ari, self._channel_proxy) | |
| call = formatter.from_channel(channel, variables=variables) | |
| self._notifier.call_entered(application, call) | |
| diff --git a/wazo_calld/plugins/applications/tests/test_stasis.py b/wazo_calld/plugins/applications/tests/test_stasis.py | |
| index 4086d275..ddcb3a7f 100644 | |
| --- a/wazo_calld/plugins/applications/tests/test_stasis.py | |
| +++ b/wazo_calld/plugins/applications/tests/test_stasis.py | |
| @@ -15,6 +15,7 @@ from unittest.mock import ( | |
| ) | |
| from wazo_test_helpers.hamcrest.raises import raises | |
| +from wazo_calld.helpers.channel_proxy import ChannelProxy | |
| from ..stasis import ApplicationStasis | |
| @@ -28,6 +29,7 @@ class TestApplicationStasisStartHandler(TestCase): | |
| self.app = ApplicationStasis( | |
| self.ari, | |
| + ChannelProxy(self.ari), | |
| self.service, | |
| self.notifier, | |
| self.confd_apps_cache, | |
| diff --git a/wazo_calld/plugins/calls/bus_consume.py b/wazo_calld/plugins/calls/bus_consume.py | |
| index 665cd928..376ba93e 100644 | |
| --- a/wazo_calld/plugins/calls/bus_consume.py | |
| +++ b/wazo_calld/plugins/calls/bus_consume.py | |
| @@ -27,6 +27,7 @@ class CallsBusEventHandler: | |
| xivo_uuid, | |
| dial_echo_manager, | |
| notifier, | |
| + channel_proxy, | |
| ): | |
| self.ami = ami | |
| self.ari = ari | |
| @@ -36,6 +37,7 @@ class CallsBusEventHandler: | |
| self.xivo_uuid = xivo_uuid | |
| self.dial_echo_manager = dial_echo_manager | |
| self.notifier = notifier | |
| + self._channel_proxy = channel_proxy | |
| def subscribe(self, bus_consumer): | |
| bus_consumer.subscribe('Newchannel', self._add_sip_call_id) | |
| @@ -62,7 +64,7 @@ class CallsBusEventHandler: | |
| if not event['Channel'].startswith('PJSIP/'): | |
| return | |
| channel_id = event['Uniqueid'] | |
| - channel = Channel(channel_id, self.ari) | |
| + channel = Channel(channel_id, self.ari, self._channel_proxy) | |
| sip_call_id = channel.sip_call_id_unsafe() | |
| if not sip_call_id: | |
| return | |
| @@ -89,7 +91,9 @@ class CallsBusEventHandler: | |
| logger.debug('channel %s not found', channel_id) | |
| return | |
| - call = self.services.make_call_from_channel(self.ari, channel) | |
| + call = self.services.make_call_from_channel( | |
| + self.ari, self._channel_proxy, channel | |
| + ) | |
| if self._call_direction_unknown(call): | |
| call.direction = self.services.conversation_direction_from_channels( | |
| self.ari, [channel.id] | |
| @@ -113,7 +117,9 @@ class CallsBusEventHandler: | |
| except ARINotFound: | |
| logger.debug('channel %s not found', channel_id) | |
| return | |
| - call = self.services.make_call_from_channel(self.ari, channel) | |
| + call = self.services.make_call_from_channel( | |
| + self.ari, self._channel_proxy, channel | |
| + ) | |
| self.notifier.call_updated(call) | |
| def _relay_channel_answered(self, event): | |
| @@ -135,7 +141,9 @@ class CallsBusEventHandler: | |
| except ARINotFound: | |
| logger.debug('channel %s not found', channel_id) | |
| return | |
| - call = self.services.make_call_from_channel(self.ari, channel) | |
| + call = self.services.make_call_from_channel( | |
| + self.ari, self._channel_proxy, channel | |
| + ) | |
| if self._call_direction_unknown(call): | |
| call.direction = self.services.conversation_direction_from_channels( | |
| self.ari, [channel.id] | |
| @@ -149,7 +157,7 @@ class CallsBusEventHandler: | |
| self.collectd.publish(ChannelEndedCollectdEvent()) | |
| def _partial_call_from_channel_id(self, channel_id): | |
| - channel = Channel(channel_id, self.ari) | |
| + channel = Channel(channel_id, self.ari, self._channel_proxy) | |
| call = Call(channel.id) | |
| call.user_uuid = channel.user() | |
| call.tenant_uuid = channel.tenant_uuid() | |
| @@ -261,7 +269,9 @@ class CallsBusEventHandler: | |
| self.ari, [channel.id for channel in participant_channels] | |
| ) | |
| for channel in participant_channels: | |
| - call = self.services.make_call_from_channel(self.ari, channel) | |
| + call = self.services.make_call_from_channel( | |
| + self.ari, self._channel_proxy, channel | |
| + ) | |
| if call.direction != call_direction: | |
| self._set_conversation_direction_cache(channel.id, call_direction) | |
| call.direction = call_direction | |
| @@ -305,7 +315,9 @@ class CallsBusEventHandler: | |
| self.ari, [channel.id for channel in participant_channels] | |
| ) | |
| for channel in participant_channels: | |
| - call = self.services.make_call_from_channel(self.ari, channel) | |
| + call = self.services.make_call_from_channel( | |
| + self.ari, self._channel_proxy, channel | |
| + ) | |
| if call.direction != call_direction: | |
| self._set_conversation_direction_cache(channel.id, call_direction) | |
| call.direction = call_direction | |
| diff --git a/wazo_calld/plugins/calls/plugin.py b/wazo_calld/plugins/calls/plugin.py | |
| index 0f344964..361278db 100644 | |
| --- a/wazo_calld/plugins/calls/plugin.py | |
| +++ b/wazo_calld/plugins/calls/plugin.py | |
| @@ -45,6 +45,7 @@ class Plugin: | |
| collectd = dependencies['collectd'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| config = dependencies['config'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| token_changed_subscribe(amid_client.set_token) | |
| @@ -66,6 +67,7 @@ class Plugin: | |
| dial_echo_manager, | |
| phoned_client, | |
| notifier, | |
| + channel_proxy, | |
| ) | |
| calls_stasis = CallsStasis( | |
| @@ -76,6 +78,7 @@ class Plugin: | |
| notifier, | |
| config['uuid'], | |
| amid_client, | |
| + channel_proxy, | |
| ) | |
| startup_callback_collector = CallbackCollector() | |
| @@ -91,6 +94,7 @@ class Plugin: | |
| config['uuid'], | |
| dial_echo_manager, | |
| notifier, | |
| + channel_proxy, | |
| ) | |
| calls_bus_event_handler.subscribe(bus_consumer) | |
| diff --git a/wazo_calld/plugins/calls/services.py b/wazo_calld/plugins/calls/services.py | |
| index 844634ab..a2f4c6bb 100644 | |
| --- a/wazo_calld/plugins/calls/services.py | |
| +++ b/wazo_calld/plugins/calls/services.py | |
| @@ -46,6 +46,7 @@ class CallsService: | |
| dial_echo_manager, | |
| phoned_client, | |
| notifier, | |
| + channel_proxy, | |
| ): | |
| self._ami = amid_client | |
| self._ari_config = ari_config | |
| @@ -55,6 +56,7 @@ class CallsService: | |
| self._phoned_client = phoned_client | |
| self._notifier = notifier | |
| self._state_persistor = ReadOnlyStatePersistor(self._ari) | |
| + self._channel_proxy = channel_proxy | |
| def list_calls(self, application_filter=None, application_instance_filter=None): | |
| channels = self._ari.channels.list() | |
| @@ -87,7 +89,10 @@ class CallsService: | |
| app_instance_channels.append(channel) | |
| channels = app_instance_channels | |
| - return [self.make_call_from_channel(self._ari, channel) for channel in channels] | |
| + return [ | |
| + self.make_call_from_channel(self._ari, self._channel_proxy, channel) | |
| + for channel in channels | |
| + ] | |
| def list_calls_user( | |
| self, user_uuid, application_filter=None, application_instance_filter=None | |
| @@ -97,7 +102,7 @@ class CallsService: | |
| call | |
| for call in calls | |
| if call.user_uuid == user_uuid | |
| - and not Channel(call.id_, self._ari).is_local() | |
| + and not Channel(call.id_, self._ari, self._channel_proxy).is_local() | |
| ] | |
| def originate(self, request): | |
| @@ -221,7 +226,7 @@ class CallsService: | |
| variables={'variables': variables}, | |
| ) | |
| - call = self.make_call_from_channel(self._ari, channel) | |
| + call = self.make_call_from_channel(self._ari, self._channel_proxy, channel) | |
| call.dialed_extension = request['destination']['extension'] | |
| return call | |
| @@ -257,7 +262,7 @@ class CallsService: | |
| except ARINotFound: | |
| raise NoSuchCall(channel_id) | |
| - return self.make_call_from_channel(self._ari, channel) | |
| + return self.make_call_from_channel(self._ari, self._channel_proxy, channel) | |
| def hangup(self, call_id): | |
| channel_id = call_id | |
| @@ -279,7 +284,7 @@ class CallsService: | |
| # NOTE(fblackburn): asterisk should send back an event | |
| # instead of falsy pretend that channel is muted | |
| - call = self.make_call_from_channel(self._ari, channel) | |
| + call = self.make_call_from_channel(self._ari, self._channel_proxy, channel) | |
| self._notifier.call_updated(call) | |
| def unmute(self, call_id): | |
| @@ -293,7 +298,7 @@ class CallsService: | |
| # NOTE(fblackburn): asterisk should send back an event | |
| # instead of falsy pretend that channel is unmuted | |
| - call = self.make_call_from_channel(self._ari, channel) | |
| + call = self.make_call_from_channel(self._ari, self._channel_proxy, channel) | |
| self._notifier.call_updated(call) | |
| def mute_user(self, call_id, user_uuid): | |
| @@ -340,9 +345,9 @@ class CallsService: | |
| return new_channel.id | |
| @staticmethod | |
| - def make_call_from_channel(ari, channel): | |
| + def make_call_from_channel(ari, channel_proxy, channel): | |
| channel_variables = channel.json.get('channelvars', {}) | |
| - channel_helper = Channel(channel.id, ari) | |
| + channel_helper = Channel(channel.id, ari, channel_proxy) | |
| call = Call(channel.id) | |
| call.conversation_id = channel_helper.conversation_id() | |
| call.creation_time = channel.json['creationtime'] | |
| @@ -391,10 +396,10 @@ class CallsService: | |
| return call | |
| @staticmethod | |
| - def channel_destroyed_event(ari, event): | |
| + def channel_destroyed_event(ari, channel_proxy, event): | |
| channel = event['channel'] | |
| channel_id = channel.get('id') | |
| - channel_helper = Channel(channel_id, ari) | |
| + channel_helper = Channel(channel_id, ari, channel_proxy) | |
| channel_variables = event['channel']['channelvars'] | |
| conversation_id = channel_variables.get('CHANNEL(linkedid)') | |
| connected = channel.get('connected') | |
| @@ -664,7 +669,7 @@ class CallsService: | |
| ] | |
| def _verify_user(self, call_id, user_uuid): | |
| - channel = Channel(call_id, self._ari) | |
| + channel = Channel(call_id, self._ari, self._channel_proxy) | |
| if not channel.exists() or channel.is_local(): | |
| raise NoSuchCall(call_id) | |
| diff --git a/wazo_calld/plugins/calls/stasis.py b/wazo_calld/plugins/calls/stasis.py | |
| index 5f4d6656..bc8a6ce6 100644 | |
| --- a/wazo_calld/plugins/calls/stasis.py | |
| +++ b/wazo_calld/plugins/calls/stasis.py | |
| @@ -26,7 +26,15 @@ logger = logging.getLogger(__name__) | |
| class CallsStasis: | |
| def __init__( | |
| - self, ari, collectd, bus_publisher, services, notifier, xivo_uuid, amid_client | |
| + self, | |
| + ari, | |
| + collectd, | |
| + bus_publisher, | |
| + services, | |
| + notifier, | |
| + xivo_uuid, | |
| + amid_client, | |
| + channel_proxy, | |
| ): | |
| self.ari = ari.client | |
| self._core_ari = ari | |
| @@ -40,6 +48,7 @@ class CallsStasis: | |
| self.state_persistor = StatePersistor(self.ari) | |
| self.xivo_uuid = xivo_uuid | |
| self.ami = amid_client | |
| + self._channel_proxy = channel_proxy | |
| def initialize(self): | |
| self._subscribe() | |
| @@ -49,6 +58,7 @@ class CallsStasis: | |
| self.ari.on_channel_event('StasisStart', self.stasis_start) | |
| self.ari.on_channel_event('ChannelDestroyed', self.channel_destroyed) | |
| self.ari.on_channel_event('ChannelDestroyed', self.relay_channel_hung_up) | |
| + self.ari.on_channel_event('ChannelDestroyed', self._channel_proxy.on_hang_up) | |
| self.ari.on_application_registered( | |
| DEFAULT_APPLICATION_NAME, self.subscribe_to_all_channel_events | |
| ) | |
| @@ -126,5 +136,7 @@ class CallsStasis: | |
| logger.debug('Ignoring local channel hangup: %s', channel_id) | |
| return | |
| logger.debug('Relaying to bus: channel %s ended', channel_id) | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self._channel_proxy, event | |
| + ) | |
| self.notifier.call_ended(call, event['cause']) | |
| diff --git a/wazo_calld/plugins/calls/tests/test_bus_consume.py b/wazo_calld/plugins/calls/tests/test_bus_consume.py | |
| index 9cd91705..4feab6bf 100644 | |
| --- a/wazo_calld/plugins/calls/tests/test_bus_consume.py | |
| +++ b/wazo_calld/plugins/calls/tests/test_bus_consume.py | |
| @@ -6,6 +6,8 @@ from unittest.mock import Mock | |
| from hamcrest import assert_that, calling, not_, raises | |
| +from wazo_calld.helpers.channel_proxy import ChannelProxy | |
| + | |
| from ..bus_consume import CallsBusEventHandler | |
| from ..exceptions import NoSuchCall | |
| @@ -29,6 +31,7 @@ class TestCallsBusEventHandler(TestCase): | |
| xivo_uuid, | |
| dial_echo_manager, | |
| notifier, | |
| + ChannelProxy(ari), | |
| ) | |
| def test_relay_channel_answered_channel_is_gone(self): | |
| diff --git a/wazo_calld/plugins/calls/tests/test_services.py b/wazo_calld/plugins/calls/tests/test_services.py | |
| index fd6d53c1..ff6357ff 100644 | |
| --- a/wazo_calld/plugins/calls/tests/test_services.py | |
| +++ b/wazo_calld/plugins/calls/tests/test_services.py | |
| @@ -5,14 +5,24 @@ from hamcrest import assert_that, equal_to | |
| from unittest.mock import Mock, patch | |
| from unittest import TestCase | |
| +from wazo_calld.helpers.channel_proxy import ChannelProxy | |
| + | |
| from ..services import CallsService | |
| class TestServices(TestCase): | |
| def setUp(self): | |
| self.ari = Mock() | |
| + self.channel_proxy = ChannelProxy(self.ari) | |
| self.services = CallsService( | |
| - Mock(), Mock(), self.ari, Mock(), Mock(), Mock(), Mock() | |
| + Mock(), | |
| + Mock(), | |
| + self.ari, | |
| + Mock(), | |
| + Mock(), | |
| + Mock(), | |
| + Mock(), | |
| + self.channel_proxy, | |
| ) | |
| self.example_to_fit = { | |
| @@ -69,7 +79,9 @@ class TestServices(TestCase): | |
| event = self.example_to_fit | |
| event['channel']['channelvars'] = {} | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self.channel_proxy, event | |
| + ) | |
| assert_that(call.user_uuid, equal_to(None)) | |
| assert_that(call.dialed_extension, equal_to(None)) | |
| @@ -84,7 +96,9 @@ class TestServices(TestCase): | |
| event = self.example_to_fit | |
| event['channel']['channelvars'] = {'XIVO_USERUUID': 'new_useruuid'} | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self.channel_proxy, event | |
| + ) | |
| assert_that(call.user_uuid, equal_to('new_useruuid')) | |
| @@ -101,7 +115,9 @@ class TestServices(TestCase): | |
| 'WAZO_DEREFERENCED_USERUUID': 'new-user-uuid', | |
| } | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self.channel_proxy, event | |
| + ) | |
| assert_that(call.user_uuid, equal_to('new-user-uuid')) | |
| @@ -112,7 +128,9 @@ class TestServices(TestCase): | |
| channel_ids.return_value = [] | |
| event = self.example_to_fit | |
| creation_time = event['channel']['creationtime'] | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self.channel_proxy, event | |
| + ) | |
| assert_that(call.creation_time, equal_to(creation_time)) | |
| @@ -122,7 +140,9 @@ class TestServices(TestCase): | |
| def test_direction_of_call_to_who_is_caller(self, channel_ids): | |
| channel_ids.return_value = [] | |
| event = self.example_to_fit | |
| - call = self.services.channel_destroyed_event(self.ari, event) | |
| + call = self.services.channel_destroyed_event( | |
| + self.ari, self.channel_proxy, event | |
| + ) | |
| assert_that(call.is_caller, equal_to(True)) | |
| diff --git a/wazo_calld/plugins/conferences/plugin.py b/wazo_calld/plugins/conferences/plugin.py | |
| index 746c436a..2f9f0a5c 100644 | |
| --- a/wazo_calld/plugins/conferences/plugin.py | |
| +++ b/wazo_calld/plugins/conferences/plugin.py | |
| @@ -25,6 +25,7 @@ class Plugin: | |
| bus_publisher = dependencies['bus_publisher'] | |
| config = dependencies['config'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| confd_client = ConfdClient(**config['confd']) | |
| @@ -32,7 +33,12 @@ class Plugin: | |
| token_changed_subscribe(amid_client.set_token) | |
| token_changed_subscribe(confd_client.set_token) | |
| - conferences_service = ConferencesService(amid_client, ari.client, confd_client) | |
| + conferences_service = ConferencesService( | |
| + amid_client, | |
| + ari.client, | |
| + channel_proxy, | |
| + confd_client, | |
| + ) | |
| notifier = ConferencesNotifier(bus_publisher) | |
| bus_event_handler = ConferencesBusEventHandler( | |
| confd_client, notifier, conferences_service | |
| diff --git a/wazo_calld/plugins/conferences/services.py b/wazo_calld/plugins/conferences/services.py | |
| index 4803da4f..9eb0e4a2 100644 | |
| --- a/wazo_calld/plugins/conferences/services.py | |
| +++ b/wazo_calld/plugins/conferences/services.py | |
| @@ -29,10 +29,11 @@ logger = logging.getLogger(__name__) | |
| class ConferencesService: | |
| - def __init__(self, amid, ari, confd): | |
| + def __init__(self, amid, ari, channel_proxy, confd): | |
| self._amid = amid | |
| self._ari = ari | |
| self._confd = confd | |
| + self._channel_proxy = channel_proxy | |
| def list_participants(self, tenant_uuid, conference_id): | |
| if not Conference(tenant_uuid, conference_id, self._confd).exists(): | |
| @@ -74,7 +75,9 @@ class ConferencesService: | |
| 'language': participant_list_item['Language'], | |
| 'call_id': participant_list_item['Uniqueid'], | |
| 'user_uuid': Channel( | |
| - participant_list_item['Uniqueid'], self._ari | |
| + participant_list_item['Uniqueid'], | |
| + self._ari, | |
| + self._channel_proxy, | |
| ).user(), | |
| } | |
| try: | |
| diff --git a/wazo_calld/plugins/dial_mobile/plugin.py b/wazo_calld/plugins/dial_mobile/plugin.py | |
| index a6bba164..8904b7ec 100644 | |
| --- a/wazo_calld/plugins/dial_mobile/plugin.py | |
| +++ b/wazo_calld/plugins/dial_mobile/plugin.py | |
| @@ -19,6 +19,7 @@ class Plugin: | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| config = dependencies['config'] | |
| bus_publisher = dependencies['bus_publisher'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| token_changed_subscribe(amid_client.set_token) | |
| @@ -27,7 +28,7 @@ class Plugin: | |
| token_changed_subscribe(auth_client.set_token) | |
| notifier = Notifier(bus_publisher) | |
| - service = DialMobileService(ari, notifier, amid_client, auth_client) | |
| + service = DialMobileService(ari, channel_proxy, notifier, amid_client, auth_client) | |
| stasis = DialMobileStasis(ari, service) | |
| event_handler = EventHandler(service) | |
| diff --git a/wazo_calld/plugins/dial_mobile/services.py b/wazo_calld/plugins/dial_mobile/services.py | |
| index 55a6ca78..7ba0b2a1 100644 | |
| --- a/wazo_calld/plugins/dial_mobile/services.py | |
| +++ b/wazo_calld/plugins/dial_mobile/services.py | |
| @@ -147,8 +147,9 @@ class _PollingContactDialer: | |
| class DialMobileService: | |
| - def __init__(self, ari, notifier, amid_client, auth_client): | |
| + def __init__(self, ari, channel_proxy, notifier, amid_client, auth_client): | |
| self._ari = ari.client | |
| + self._channel_proxy = channel_proxy | |
| self._auth_client = auth_client | |
| self._amid_client = amid_client | |
| self._contact_dialers = {} | |
| @@ -221,7 +222,7 @@ class DialMobileService: | |
| del self._contact_dialers[key] | |
| def clean_bridge(self, bridge_id): | |
| - bridge_helper = Bridge(bridge_id, self._ari) | |
| + bridge_helper = Bridge(bridge_id, self._ari, self._channel_proxy) | |
| if bridge_helper.has_lone_channel(): | |
| logger.debug( | |
| 'dial_mobile: bridge %s: only one participant left, hanging up', | |
| diff --git a/wazo_calld/plugins/meetings/plugin.py b/wazo_calld/plugins/meetings/plugin.py | |
| index afdb673d..9469c4b0 100644 | |
| --- a/wazo_calld/plugins/meetings/plugin.py | |
| +++ b/wazo_calld/plugins/meetings/plugin.py | |
| @@ -24,6 +24,7 @@ class Plugin: | |
| bus_publisher = dependencies['bus_publisher'] | |
| config = dependencies['config'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| confd_client = ConfdClient(**config['confd']) | |
| @@ -32,7 +33,11 @@ class Plugin: | |
| token_changed_subscribe(confd_client.set_token) | |
| meetings_service = MeetingsService( | |
| - amid_client, ari.client, confd_client, config | |
| + amid_client, | |
| + ari.client, | |
| + confd_client, | |
| + config, | |
| + channel_proxy, | |
| ) | |
| notifier = MeetingsNotifier(bus_publisher) | |
| bus_event_handler = MeetingsBusEventHandler( | |
| diff --git a/wazo_calld/plugins/meetings/services.py b/wazo_calld/plugins/meetings/services.py | |
| index 759091f0..830b4ef6 100644 | |
| --- a/wazo_calld/plugins/meetings/services.py | |
| +++ b/wazo_calld/plugins/meetings/services.py | |
| @@ -24,11 +24,12 @@ logger = logging.getLogger(__name__) | |
| class MeetingsService: | |
| - def __init__(self, amid, ari, confd, config): | |
| + def __init__(self, amid, ari, confd, config, channel_proxy): | |
| self._amid = amid | |
| self._ari = ari | |
| self._confd = confd | |
| self._max_participants = config['max_meeting_participants'] | |
| + self._channel_proxy = channel_proxy | |
| def get_status(self, meeting_uuid): | |
| tenant_uuid = None | |
| @@ -101,7 +102,9 @@ class MeetingsService: | |
| 'caller_id_number': participant_list_item['CallerIDNum'], | |
| 'call_id': participant_list_item['Uniqueid'], | |
| 'user_uuid': Channel( | |
| - participant_list_item['Uniqueid'], self._ari | |
| + participant_list_item['Uniqueid'], | |
| + self._ari, | |
| + self._channel_proxy, | |
| ).user(), | |
| } | |
| try: | |
| @@ -149,7 +152,7 @@ class MeetingsService: | |
| if not meeting.exists(): | |
| raise NoSuchMeeting(tenant_uuid, meeting_uuid) | |
| - channel = Channel(participant_id, self._ari) | |
| + channel = Channel(participant_id, self._ari, self._channel_proxy) | |
| try: | |
| self._amid.action( | |
| 'ConfbridgeKick', | |
| diff --git a/wazo_calld/plugins/relocates/plugin.py b/wazo_calld/plugins/relocates/plugin.py | |
| index 61d573e9..2ef398b0 100644 | |
| --- a/wazo_calld/plugins/relocates/plugin.py | |
| +++ b/wazo_calld/plugins/relocates/plugin.py | |
| @@ -25,6 +25,7 @@ class Plugin: | |
| bus_publisher = dependencies['bus_publisher'] | |
| config = dependencies['config'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| confd_client = ConfdClient(**config['confd']) | |
| @@ -33,11 +34,19 @@ class Plugin: | |
| token_changed_subscribe(confd_client.set_token) | |
| relocates = RelocateCollection() | |
| - state_factory = StateFactory(state_index, amid_client, ari.client) | |
| + state_factory = StateFactory( | |
| + state_index, amid_client, ari.client, channel_proxy | |
| + ) | |
| notifier = RelocatesNotifier(bus_publisher) | |
| relocates_service = RelocatesService( | |
| - amid_client, ari.client, confd_client, notifier, relocates, state_factory | |
| + amid_client, | |
| + ari.client, | |
| + confd_client, | |
| + notifier, | |
| + relocates, | |
| + state_factory, | |
| + channel_proxy, | |
| ) | |
| relocates_stasis = RelocatesStasis(ari, relocates) | |
| diff --git a/wazo_calld/plugins/relocates/services.py b/wazo_calld/plugins/relocates/services.py | |
| index e73cab31..8f250a6f 100644 | |
| --- a/wazo_calld/plugins/relocates/services.py | |
| +++ b/wazo_calld/plugins/relocates/services.py | |
| @@ -132,7 +132,9 @@ class ExtensionDestination(Destination): | |
| class RelocatesService: | |
| - def __init__(self, amid, ari, confd_client, notifier, relocates, state_factory): | |
| + def __init__( | |
| + self, amid, ari, confd_client, notifier, relocates, state_factory, channel_proxy | |
| + ): | |
| self.ari = ari | |
| self.confd_client = confd_client | |
| self.notifier = notifier | |
| @@ -140,6 +142,7 @@ class RelocatesService: | |
| self.destination_factory = DestinationFactory(amid, ari) | |
| self.relocates = relocates | |
| self.duplicate_relocate_lock = threading.Lock() | |
| + self._channel_proxy = channel_proxy | |
| def list_from_user(self, user_uuid): | |
| return [ | |
| @@ -159,14 +162,16 @@ class RelocatesService: | |
| ): | |
| try: | |
| relocated_channel = Channel( | |
| - initiator_call, self.ari | |
| + initiator_call, | |
| + self.ari, | |
| + self._channel_proxy, | |
| ).only_connected_channel() | |
| except TooManyChannels as e: | |
| raise TooManyChannelCandidates(e.channels) | |
| except NotEnoughChannels: | |
| raise RelocateCreationError('relocated channel not found') | |
| - initiator_channel = Channel(initiator_call, self.ari) | |
| + initiator_channel = Channel(initiator_call, self.ari, self._channel_proxy) | |
| if not initiator_channel.exists(): | |
| details = {'initiator_call': initiator_call} | |
| raise RelocateCreationError('initiator call not found', details) | |
| @@ -210,7 +215,7 @@ class RelocatesService: | |
| auto_answer, | |
| user_uuid, | |
| ): | |
| - initiator_channel = Channel(initiator_call, self.ari) | |
| + initiator_channel = Channel(initiator_call, self.ari, self._channel_proxy) | |
| user = User(user_uuid, self.confd_client) | |
| variables = {} | |
| diff --git a/wazo_calld/plugins/relocates/state.py b/wazo_calld/plugins/relocates/state.py | |
| index 2ac46eb0..5d472380 100644 | |
| --- a/wazo_calld/plugins/relocates/state.py | |
| +++ b/wazo_calld/plugins/relocates/state.py | |
| @@ -71,18 +71,19 @@ class RelocateCompleter: | |
| class StateFactory: | |
| - def __init__(self, index, amid, ari): | |
| + def __init__(self, index, amid, ari, channel_proxy): | |
| self._index = index | |
| - self._state_args = [amid, ari] | |
| + self._state_args = [amid, ari, channel_proxy] | |
| def make(self, name): | |
| return self._index[name](*self._state_args) | |
| class RelocateState: | |
| - def __init__(self, amid, ari): | |
| + def __init__(self, amid, ari, channel_proxy): | |
| self._amid = amid | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| @state | |
| @@ -128,7 +129,9 @@ class RelocateStateRecipientRing(RelocateState): | |
| relocate.events.publish('answered', relocate) | |
| if 'answer' in relocate.completions: | |
| completer = RelocateCompleter(self._amid, self._ari) | |
| - if Channel(relocate.relocated_channel, self._ari).is_in_stasis(): | |
| + if Channel( | |
| + relocate.relocated_channel, self._ari, self._channel_proxy | |
| + ).is_in_stasis(): | |
| completer.bridge(relocate) | |
| try: | |
| self._ari.channels.hangup(channelId=relocate.initiator_channel) | |
| @@ -171,7 +174,9 @@ class RelocateStateWaitingForCompletion(RelocateState): | |
| def complete(self, relocate): | |
| completer = RelocateCompleter(self._amid, self._ari) | |
| - if Channel(relocate.relocated_channel, self._ari).is_in_stasis(): | |
| + if Channel( | |
| + relocate.relocated_channel, self._ari, self._channel_proxy | |
| + ).is_in_stasis(): | |
| completer.bridge(relocate) | |
| try: | |
| self._ari.channels.hangup(channelId=relocate.initiator_channel) | |
| diff --git a/wazo_calld/plugins/switchboards/ari_helpers.py b/wazo_calld/plugins/switchboards/ari_helpers.py | |
| index d7930321..9ea5069e 100644 | |
| --- a/wazo_calld/plugins/switchboards/ari_helpers.py | |
| +++ b/wazo_calld/plugins/switchboards/ari_helpers.py | |
| @@ -1,4 +1,4 @@ | |
| -# Copyright 2021-2023 The Wazo Authors (see the AUTHORS file) | |
| +# Copyright 2021 The Wazo Authors (see the AUTHORS file) | |
| # SPDX-License-Identifier: GPL-3.0-or-later | |
| from ari.exceptions import ARINotFound | |
| @@ -10,11 +10,11 @@ class Switchboard: | |
| def __init__(self, switchboard_uuid, ari): | |
| self.uuid = switchboard_uuid | |
| self._ari = ari | |
| - self.bridge_queue_id = BRIDGE_QUEUE_ID.format(uuid=self.uuid) | |
| def queued_call_ids(self): | |
| + bridge_id = BRIDGE_QUEUE_ID.format(uuid=self.uuid) | |
| try: | |
| - bridge = self._ari.bridges.get(bridgeId=self.bridge_queue_id) | |
| + bridge = self._ari.bridges.get(bridgeId=bridge_id) | |
| except ARINotFound: | |
| return [] | |
| @@ -23,6 +23,3 @@ class Switchboard: | |
| def has_queued_call(self, call_id): | |
| return call_id in self.queued_call_ids() | |
| - | |
| - def get_bridge_queue(self): | |
| - return self._ari.bridges.get(bridgeId=self.bridge_queue_id) | |
| diff --git a/wazo_calld/plugins/switchboards/plugin.py b/wazo_calld/plugins/switchboards/plugin.py | |
| index 08177c54..c5b5bbae 100644 | |
| --- a/wazo_calld/plugins/switchboards/plugin.py | |
| +++ b/wazo_calld/plugins/switchboards/plugin.py | |
| @@ -1,4 +1,4 @@ | |
| -# Copyright 2017-2021 The Wazo Authors (see the AUTHORS file) | |
| +# Copyright 2017-2023 The Wazo Authors (see the AUTHORS file) | |
| # SPDX-License-Identifier: GPL-3.0-or-later | |
| from wazo_confd_client import Client as ConfdClient | |
| @@ -32,6 +32,7 @@ class Plugin: | |
| config = dependencies['config'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| next_token_changed_subscribe = dependencies['next_token_changed_subscribe'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| confd_client = ConfdClient(**config['confd']) | |
| switchboard_get_cache = ConfdClientGetUUIDCacheDecorator( | |
| @@ -51,7 +52,11 @@ class Plugin: | |
| switchboards_notifier = SwitchboardsNotifier(bus_publisher) | |
| switchboards_service = SwitchboardsService( | |
| - ari.client, asyncio, confd_client, switchboards_notifier | |
| + ari.client, | |
| + asyncio, | |
| + confd_client, | |
| + switchboards_notifier, | |
| + channel_proxy, | |
| ) | |
| switchboards_stasis = SwitchboardsStasis( | |
| diff --git a/wazo_calld/plugins/switchboards/services.py b/wazo_calld/plugins/switchboards/services.py | |
| index f71c9651..3145d4ea 100644 | |
| --- a/wazo_calld/plugins/switchboards/services.py | |
| +++ b/wazo_calld/plugins/switchboards/services.py | |
| @@ -2,7 +2,6 @@ | |
| # SPDX-License-Identifier: GPL-3.0-or-later | |
| import logging | |
| -import threading | |
| from ari.exceptions import ARINotFound | |
| @@ -35,12 +34,12 @@ logger = logging.getLogger(__name__) | |
| class SwitchboardsService: | |
| - def __init__(self, ari, asyncio, confd, notifier): | |
| + def __init__(self, ari, asyncio, confd, notifier, channel_proxy): | |
| self._ari = ari | |
| self._asyncio = asyncio | |
| self._confd = confd | |
| self._notifier = notifier | |
| - self.duplicate_queued_call_answer_lock = threading.Lock() | |
| + self._channel_proxy = channel_proxy | |
| def queued_calls(self, tenant_uuid, switchboard_uuid): | |
| logger.debug( | |
| @@ -92,7 +91,9 @@ class SwitchboardsService: | |
| calls = self.queued_calls(tenant_uuid, switchboard_uuid) | |
| self._notifier.queued_calls(tenant_uuid, switchboard_uuid, calls) | |
| - noanswer_timeout = Channel(channel_id, self._ari).switchboard_timeout() | |
| + noanswer_timeout = Channel( | |
| + channel_id, self._ari, self._channel_proxy | |
| + ).switchboard_timeout() | |
| if not noanswer_timeout: | |
| logger.debug( | |
| 'Switchboard %s: ignoring no answer timeout = %s', | |
| @@ -102,7 +103,9 @@ class SwitchboardsService: | |
| return | |
| noanswer_fallback_action = Channel( | |
| - channel_id, self._ari | |
| + channel_id, | |
| + self._ari, | |
| + self._channel_proxy, | |
| ).switchboard_noanswer_fallback_action() | |
| if not noanswer_fallback_action: | |
| logger.debug( | |
| @@ -171,64 +174,45 @@ class SwitchboardsService: | |
| user_uuid, | |
| line_id, | |
| ) | |
| - with self.duplicate_queued_call_answer_lock: | |
| - if not SwitchboardConfd( | |
| - tenant_uuid, switchboard_uuid, self._confd | |
| - ).exists(): | |
| - raise NoSuchSwitchboard(switchboard_uuid) | |
| + if not SwitchboardConfd(tenant_uuid, switchboard_uuid, self._confd).exists(): | |
| + raise NoSuchSwitchboard(switchboard_uuid) | |
| - if not SwitchboardARI(switchboard_uuid, self._ari).has_queued_call( | |
| - queued_call_id | |
| - ): | |
| - logger.debug( | |
| - 'Switchboard %s: call %s is not queued', | |
| - switchboard_uuid, | |
| - queued_call_id, | |
| - ) | |
| - raise NoSuchCall(queued_call_id) | |
| + try: | |
| + queued_channel = self._ari.channels.get(channelId=queued_call_id) | |
| + except ARINotFound: | |
| + raise NoSuchCall(queued_call_id) | |
| - try: | |
| - queued_channel = self._ari.channels.get(channelId=queued_call_id) | |
| - except ARINotFound: | |
| - raise NoSuchCall(queued_call_id) | |
| + try: | |
| + user = User(user_uuid, self._confd, tenant_uuid=tenant_uuid) | |
| + if line_id: | |
| + line = user.line(line_id) | |
| + else: | |
| + line = user.main_line() | |
| + endpoint = line.interface_autoanswer() | |
| + except InvalidUserUUID as e: | |
| + raise NoSuchConfdUser(e.details['user_uuid']) | |
| - try: | |
| - user = User(user_uuid, self._confd, tenant_uuid=tenant_uuid) | |
| - if line_id: | |
| - line = user.line(line_id) | |
| - else: | |
| - line = user.main_line() | |
| - endpoint = line.interface_autoanswer() | |
| - except InvalidUserUUID as e: | |
| - raise NoSuchConfdUser(e.details['user_uuid']) | |
| - | |
| - caller_id = assemble_caller_id( | |
| - queued_channel.json['caller']['name'], | |
| - queued_channel.json['caller']['number'], | |
| - ).encode('utf-8') | |
| - | |
| - channel = self._ari.channels.originate( | |
| - endpoint=endpoint, | |
| - app=DEFAULT_APPLICATION_NAME, | |
| - appArgs=[ | |
| - 'switchboard', | |
| - 'switchboard_answer', | |
| - tenant_uuid, | |
| - switchboard_uuid, | |
| - queued_call_id, | |
| - ], | |
| - callerId=caller_id, | |
| - originator=queued_call_id, | |
| - variables={'variables': AUTO_ANSWER_VARIABLES}, | |
| - ) | |
| + caller_id = assemble_caller_id( | |
| + queued_channel.json['caller']['name'], | |
| + queued_channel.json['caller']['number'], | |
| + ).encode('utf-8') | |
| - try: | |
| - bridge = SwitchboardARI(switchboard_uuid, self._ari).get_bridge_queue() | |
| - bridge.removeChannel(channel=queued_call_id) | |
| - except ARINotFound: | |
| - pass | |
| + channel = self._ari.channels.originate( | |
| + endpoint=endpoint, | |
| + app=DEFAULT_APPLICATION_NAME, | |
| + appArgs=[ | |
| + 'switchboard', | |
| + 'switchboard_answer', | |
| + tenant_uuid, | |
| + switchboard_uuid, | |
| + queued_call_id, | |
| + ], | |
| + callerId=caller_id, | |
| + originator=queued_call_id, | |
| + variables={'variables': AUTO_ANSWER_VARIABLES}, | |
| + ) | |
| - return channel.id | |
| + return channel.id | |
| def hold_call(self, tenant_uuid, switchboard_uuid, call_id): | |
| logger.debug( | |
| diff --git a/wazo_calld/plugins/switchboards/tests/test_services.py b/wazo_calld/plugins/switchboards/tests/test_services.py | |
| index 3b3ac31f..7e4f43b6 100644 | |
| --- a/wazo_calld/plugins/switchboards/tests/test_services.py | |
| +++ b/wazo_calld/plugins/switchboards/tests/test_services.py | |
| @@ -5,6 +5,7 @@ from unittest import TestCase | |
| from unittest.mock import Mock, sentinel as s | |
| from wazo_calld.plugins.switchboards.services import SwitchboardsService | |
| +from wazo_calld.helpers.channel_proxy import ChannelProxy | |
| class TestSwitchboardService(TestCase): | |
| @@ -13,9 +14,14 @@ class TestSwitchboardService(TestCase): | |
| self.asyncio = Mock() | |
| self.confd = Mock() | |
| self.notifier = Mock() | |
| + self.channel_proxy = ChannelProxy(self.ari) | |
| self.service = SwitchboardsService( | |
| - self.ari, self.asyncio, self.confd, self.notifier | |
| + self.ari, | |
| + self.asyncio, | |
| + self.confd, | |
| + self.notifier, | |
| + self.channel_proxy, | |
| ) | |
| def test_moh_on_new_queued_call_when_defined(self): | |
| diff --git a/wazo_calld/plugins/transfers/plugin.py b/wazo_calld/plugins/transfers/plugin.py | |
| index 6030de55..10911c7d 100644 | |
| --- a/wazo_calld/plugins/transfers/plugin.py | |
| +++ b/wazo_calld/plugins/transfers/plugin.py | |
| @@ -29,6 +29,7 @@ class Plugin: | |
| bus_publisher = dependencies['bus_publisher'] | |
| config = dependencies['config'] | |
| token_changed_subscribe = dependencies['token_changed_subscribe'] | |
| + channel_proxy = dependencies['channel_proxy'] | |
| amid_client = AmidClient(**config['amid']) | |
| confd_client = ConfdClient(**config['confd']) | |
| @@ -46,6 +47,7 @@ class Plugin: | |
| state_factory, | |
| state_persistor, | |
| transfer_lock, | |
| + channel_proxy, | |
| ) | |
| transfers_stasis = TransfersStasis( | |
| @@ -55,6 +57,7 @@ class Plugin: | |
| state_factory, | |
| state_persistor, | |
| config['uuid'], | |
| + channel_proxy, | |
| ) | |
| startup_callback_collector = CallbackCollector() | |
| @@ -66,6 +69,7 @@ class Plugin: | |
| state_factory.set_dependencies( | |
| amid_client, | |
| ari.client, | |
| + channel_proxy, | |
| notifier, | |
| transfers_service, | |
| state_persistor, | |
| diff --git a/wazo_calld/plugins/transfers/services.py b/wazo_calld/plugins/transfers/services.py | |
| index b74bad3d..bc869e83 100644 | |
| --- a/wazo_calld/plugins/transfers/services.py | |
| +++ b/wazo_calld/plugins/transfers/services.py | |
| @@ -36,6 +36,7 @@ class TransfersService: | |
| state_factory, | |
| state_persistor, | |
| transfer_lock, | |
| + channel_proxy, | |
| ): | |
| self.amid_client = amid_client | |
| self.ari = ari | |
| @@ -43,6 +44,7 @@ class TransfersService: | |
| self.state_persistor = state_persistor | |
| self.state_factory = state_factory | |
| self.transfer_lock = transfer_lock | |
| + self._channel_proxy = channel_proxy | |
| def list_from_user(self, user_uuid): | |
| transfers = self.state_persistor.list() | |
| @@ -66,8 +68,8 @@ class TransfersService: | |
| raise TransferAlreadyStarted(initiator_call) | |
| if not ( | |
| - Channel(transferred_call, self.ari).is_in_stasis() | |
| - and Channel(initiator_call, self.ari).is_in_stasis() | |
| + Channel(transferred_call, self.ari, self._channel_proxy).is_in_stasis() | |
| + and Channel(initiator_call, self.ari, self._channel_proxy).is_in_stasis() | |
| ): | |
| transfer_state = self.state_factory.make_from_class( | |
| TransferStateReadyNonStasis | |
| @@ -94,15 +96,17 @@ class TransfersService: | |
| return new_state.transfer | |
| def create_from_user(self, initiator_call, exten, flow, timeout, user_uuid): | |
| - if not Channel(initiator_call, self.ari).exists(): | |
| + if not Channel(initiator_call, self.ari, self._channel_proxy).exists(): | |
| raise TransferCreationError('initiator channel not found') | |
| - if Channel(initiator_call, self.ari).user() != user_uuid: | |
| + if Channel(initiator_call, self.ari, self._channel_proxy).user() != user_uuid: | |
| raise UserPermissionDenied(user_uuid, {'call': initiator_call}) | |
| try: | |
| transferred_call = ( | |
| - Channel(initiator_call, self.ari).only_connected_channel().id | |
| + Channel(initiator_call, self.ari, self._channel_proxy) | |
| + .only_connected_channel() | |
| + .id | |
| ) | |
| except TooManyChannels as e: | |
| raise TooManyTransferredCandidates(e.channels) | |
| diff --git a/wazo_calld/plugins/transfers/stasis.py b/wazo_calld/plugins/transfers/stasis.py | |
| index 6271c750..a9509e31 100644 | |
| --- a/wazo_calld/plugins/transfers/stasis.py | |
| +++ b/wazo_calld/plugins/transfers/stasis.py | |
| @@ -27,7 +27,14 @@ logger = logging.getLogger(__name__) | |
| class TransfersStasis: | |
| def __init__( | |
| - self, amid_client, ari, services, state_factory, state_persistor, xivo_uuid | |
| + self, | |
| + amid_client, | |
| + ari, | |
| + services, | |
| + state_factory, | |
| + state_persistor, | |
| + xivo_uuid, | |
| + channel_proxy, | |
| ): | |
| self.ari = ari.client | |
| self._core_ari = ari | |
| @@ -40,6 +47,7 @@ class TransfersStasis: | |
| self.hangup_pubsub.set_exception_handler(self.invalid_event) | |
| self.state_factory = state_factory | |
| self.state_persistor = state_persistor | |
| + self._channel_proxy = channel_proxy | |
| def initialize(self): | |
| self._subscribe() | |
| @@ -123,13 +131,19 @@ class TransfersStasis: | |
| logger.debug('Processing lost hangups since last stop...') | |
| for transfer in transfers: | |
| transfer_state = self.state_factory.make(transfer) | |
| - if not Channel(transfer.transferred_call, self.ari).exists(): | |
| + if not Channel( | |
| + transfer.transferred_call, self.ari, self._channel_proxy | |
| + ).exists(): | |
| logger.debug('Transferred hangup from transfer %s', transfer.id) | |
| transfer_state = transfer_state.transferred_hangup() | |
| - if not Channel(transfer.initiator_call, self.ari).exists(): | |
| + if not Channel( | |
| + transfer.initiator_call, self.ari, self._channel_proxy | |
| + ).exists(): | |
| logger.debug('Initiator hangup from transfer %s', transfer.id) | |
| transfer_state = transfer_state.initiator_hangup() | |
| - if not Channel(transfer.recipient_call, self.ari).exists(): | |
| + if not Channel( | |
| + transfer.recipient_call, self.ari, self._channel_proxy | |
| + ).exists(): | |
| logger.debug('Recipient hangup from transfer %s', transfer.id) | |
| transfer_state = transfer_state.recipient_hangup() | |
| logger.debug('Done.') | |
| @@ -142,7 +156,9 @@ class TransfersStasis: | |
| transfer_state = self.state_factory.make(transfer) | |
| if ( | |
| transfer_state.name == TransferStatus.ringback | |
| - and Channel(transfer.recipient_call, self.ari).exists() | |
| + and Channel( | |
| + transfer.recipient_call, self.ari, self._channel_proxy | |
| + ).exists() | |
| ): | |
| channel = self.ari.channels.get(channelId=transfer.recipient_call) | |
| if channel.json['state'] != 'Up': | |
| diff --git a/wazo_calld/plugins/transfers/state.py b/wazo_calld/plugins/transfers/state.py | |
| index ae703d27..30f220ef 100644 | |
| --- a/wazo_calld/plugins/transfers/state.py | |
| +++ b/wazo_calld/plugins/transfers/state.py | |
| @@ -18,9 +18,10 @@ logger = logging.getLogger(__name__) | |
| class StateFactory: | |
| - def __init__(self, ari=None): | |
| + def __init__(self, ari=None, channel_proxy=None): | |
| self._state_constructors = {} | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| self._configured = False | |
| def set_dependencies(self, *dependencies): | |
| @@ -69,6 +70,7 @@ class TransferState: | |
| self, | |
| amid, | |
| ari, | |
| + channel_proxy, | |
| notifier, | |
| services, | |
| state_persistor, | |
| @@ -77,6 +79,7 @@ class TransferState: | |
| ): | |
| self._amid = amid | |
| self._ari = ari | |
| + self._channel_proxy = channel_proxy | |
| self._notifier = notifier | |
| self._services = services | |
| self._state_persistor = state_persistor | |
| @@ -88,6 +91,7 @@ class TransferState: | |
| new_state = cls( | |
| other_state._amid, | |
| other_state._ari, | |
| + other_state._channel_proxy, | |
| other_state._notifier, | |
| other_state._services, | |
| other_state._state_persistor, | |
| @@ -208,7 +212,7 @@ class TransferStateReady(TransferState): | |
| variables, | |
| timeout, | |
| ): | |
| - channel = Channel(initiator_channel.id, self._ari) | |
| + channel = Channel(initiator_channel.id, self._ari, self._channel_proxy) | |
| initiator_uuid = channel.user() | |
| initiator_tenant_uuid = channel.tenant_uuid() | |
| if initiator_uuid is None: | |
| @@ -279,7 +283,7 @@ class TransferStateReadyNonStasis(TransferState): | |
| variables, | |
| timeout, | |
| ): | |
| - channel = Channel(initiator_channel.id, self._ari) | |
| + channel = Channel(initiator_channel.id, self._ari, self._channel_proxy) | |
| initiator_uuid = channel.user() | |
| initiator_tenant_uuid = channel.tenant_uuid() | |
| if initiator_uuid is None: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment