Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a park timeout #49

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ See the docs_ for the deats!

.. _inbound ESL: https://freeswitch.org/confluence/display/FREESWITCH/mod_event_socket#mod_event_socket-Configuration
.. _park-only: https://freeswitch.org/confluence/display/FREESWITCH/mod_dptools%3A+park
.. _here: https://github.com/friends-of-freeswitch/switchio/blob/master/conf/switchiodp.xml
.. _here: https://github.com/friends-of-freeswitch/switchio/blob/park_timeout/conf/ci-minimal/dialplan/switchydp.xml


What's included?
Expand Down
3 changes: 2 additions & 1 deletion conf/ci-minimal/dialplan/switchydp.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- A context for relinquishing control of all calls to switchio, the inbound ESL client -->
<context name="switchio">
<!-- Park call and transfer control to esl -->
<extension name="switchiopark">
<condition field="destination_number" expression="^(.*)$">
<!-- Park call and transfer control to switchio over ESL -->
<action application="set" data="park_timeout=3:NETWORK_OUT_OF_ORDER"/>
<action application="park"/>
</condition>
</extension>
Expand Down
10 changes: 0 additions & 10 deletions conf/switchiodp.xml

This file was deleted.

3 changes: 0 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
]
},
install_requires=['click', 'colorlog'],
package_data={
'switchio': ['../conf/switchiodp.xml']
},
extras_require={
'metrics': ['pandas>=0.18'],
'hdf5': ['tables==3.2.1.1'],
Expand Down
5 changes: 4 additions & 1 deletion switchio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@
'Service',
]

PARK_DP = path.join(path.dirname(__file__), '../conf', 'switchiodp.xml')
PARK_DP = path.join(
path.dirname(__file__),
'../conf/ci-minimal/dialplan', 'switchiodp.xml'
)
15 changes: 15 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,21 @@ def el(fshost):
assert not el.is_alive()


@pytest.fixture
def ael(el):
"""An event listener (el) with active event loop
Unsubscribe the listener from verbose updates.
"""
assert not el.connected()
# avoid latency caused by update events
el.unsubscribe("CALL_UPDATE")
el.connect()
el.start()
assert el.connected()
yield el
el.disconnect()


@pytest.yield_fixture
def client(fshost):
"""Deliver a core.Client connected to fshost
Expand Down
15 changes: 0 additions & 15 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,6 @@
import asyncio


@pytest.fixture
def ael(el):
"""An event listener (el) with active event loop
Unsubscribe the listener from verbose updates.
"""
assert not el.connected()
# avoid latency caused by update events
el.unsubscribe("CALL_UPDATE")
el.connect()
el.start()
assert el.connected()
yield el
el.disconnect()


def bridge2dest_callback(sess):
if sess['Call-Direction'] == 'inbound':
sess.bridge(dest_url=sess['variable_sip_req_uri'])
Expand Down
48 changes: 48 additions & 0 deletions tests/test_coroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,51 @@ async def timeout_on_hangup(self, sess):
assert task.done()
with pytest.raises(asyncio.TimeoutError):
task.result()


@pytest.mark.parametrize('sleep', [2, 5])
def test_simplest_flow(fssock, scenario, client, ael, sleep):
"""Verify that a coroutine can satisfy SIPp's simplest call flow.

Additionally, verify that when calls are not answered and left in the park
state they time out and are rejected after 3 seconds (according to the CI
dialplan).
"""
class MyApp:
@coroutine(
"CHANNEL_PARK",
subscribe=('PLAYBACK_STOP', 'PLAYBACK_START')
)
async def answer_play_hangup(self, sess):
await asyncio.sleep(sleep)
await sess.answer()
# non-blocking
sess.playback(
'en/us/callie/ivr/8000/ivr-founder_of_freesource.wav')
await sess.recv("PLAYBACK_START")
await sess.recv("CHANNEL_HANGUP")
# XXX: seems the playback isn't stopping on its own? - the
# hangup does it though...
# sess.breakmedia()
await sess.recv("PLAYBACK_STOP")
await sess.recv("CHANNEL_HANGUP_COMPLETE")

client.connect()
client.listener = ael
# assigning a listener overrides it's call lookup var so restore it
client.listener.call_tracking_header = 'variable_call_uuid'
assert 'default' == client.load_app(MyApp, on_value="default")

uac = scenario.prepare()[1]
uac.proxyaddr = None
uac.destaddr = fssock
uac.pause_duration = 6000

# make the call
if sleep > 3:
# XML dialplan's `park_timeout` should reject the call
with pytest.raises(RuntimeError):
uac()
else:
# call should be hung up by this UAC
uac()