sippy 2.2.0__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sippy-2.2.2/MANIFEST.in +4 -0
- {sippy-2.2.0/sippy.egg-info → sippy-2.2.2}/PKG-INFO +15 -4
- {sippy-2.2.0 → sippy-2.2.2}/README.md +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/setup.py +4 -5
- sippy-2.2.0/sippy/B2BRoute.py → sippy-2.2.2/sippy/B2B/Route.py +3 -3
- sippy-2.2.2/sippy/B2B/SimpleAPI.py +142 -0
- sippy-2.2.2/sippy/B2B/States.py +36 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/CCEvents.py +32 -19
- {sippy-2.2.0 → sippy-2.2.2}/sippy/CLIManager.py +13 -6
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Core/EventDispatcher.py +33 -7
- sippy-2.2.2/sippy/Exceptions/RtpProxyError.py +30 -0
- sippy-2.2.2/sippy/Exceptions/SdpParseError.py +33 -0
- sippy-2.2.0/sippy/Exceptions/SipParseError.py → sippy-2.2.2/sippy/Exceptions/SipHandlingError.py +6 -16
- sippy-2.2.0/sippy/Exceptions/RtpProxyError.py → sippy-2.2.2/sippy/Exceptions/SipParseError.py +10 -13
- {sippy-2.2.0 → sippy-2.2.2}/sippy/External_command.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Math/recfilter.py +2 -2
- {sippy-2.2.0 → sippy-2.2.2}/sippy/MsgBody.py +2 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/MultipartMixBody.py +33 -7
- {sippy-2.2.0 → sippy-2.2.2}/sippy/MyConfigParser.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/RadiusAccounting.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Radius_client.py +1 -1
- sippy-2.2.2/sippy/Rtp_proxy/Client/Worker/external.py +121 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/Worker/internal.py +95 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/__init__.py +1 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/internal.py +67 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/local.py +41 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/net.py +42 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/stream.py +103 -0
- sippy-2.2.2/sippy/Rtp_proxy/Client/udp.py +214 -0
- sippy-2.2.2/sippy/Rtp_proxy/Cmd/__init__.py +1 -0
- sippy-2.2.2/sippy/Rtp_proxy/Cmd/sequencer.py +63 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/__init__.py +1 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/side.py +263 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/subcommand.py +117 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/subcommand_ice.py +101 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/update.py +122 -0
- sippy-2.2.2/sippy/Rtp_proxy/Session/webrtc.py +42 -0
- sippy-2.2.2/sippy/Rtp_proxy/__init__.py +1 -0
- sippy-2.2.2/sippy/Rtp_proxy/client.py +313 -0
- sippy-2.2.2/sippy/Rtp_proxy/cmd.py +224 -0
- sippy-2.2.2/sippy/Rtp_proxy/session.py +225 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpBody.py +5 -4
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipAddressHF.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipAuthorization.py +0 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipContentType.py +2 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipHeader.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipMsg.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRegistrationAgent.py +4 -2
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRequest.py +11 -2
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipTransactionManager.py +46 -26
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipWWWAuthenticate.py +2 -2
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Time/MonoTime.py +1 -1
- sippy-2.2.2/sippy/Time/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UA.py +79 -46
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UaStateConnected.py +38 -54
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UaStateDead.py +4 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UaStateDisconnected.py +6 -9
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UaStateFailed.py +3 -6
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UacStateCancelling.py +7 -14
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UacStateIdle.py +11 -12
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UacStateRinging.py +29 -24
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UacStateTrying.py +36 -34
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UacStateUpdating.py +30 -32
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UasStateIdle.py +4 -7
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UasStateRinging.py +21 -38
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UasStateTrying.py +18 -39
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UasStateUpdating.py +29 -44
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Udp_server.py +14 -10
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Wss_server.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/sippy/XMPP_server.py +3 -3
- sippy-2.2.0/sippy/b2bua_radius.py → sippy-2.2.2/sippy/b2bua.py +58 -145
- {sippy-2.2.0 → sippy-2.2.2}/sippy/b2bua_simple.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2/sippy.egg-info}/PKG-INFO +15 -4
- {sippy-2.2.0 → sippy-2.2.2}/sippy.egg-info/SOURCES.txt +30 -3
- sippy-2.2.2/sippy.egg-info/entry_points.txt +4 -0
- sippy-2.2.2/tests/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/tests/test_B2BRoute.py +1 -1
- {sippy-2.2.0 → sippy-2.2.2}/tests/test_B2BTransforms.py +1 -1
- sippy-2.2.2/tests/test_Multipart.py +45 -0
- sippy-2.2.0/MANIFEST.in +0 -1
- sippy-2.2.0/sippy.egg-info/entry_points.txt +0 -3
- {sippy-2.2.0 → sippy-2.2.2}/LICENSE +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/pyproject.toml +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/requirements.txt +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/setup.cfg +0 -0
- /sippy-2.2.0/sippy/B2BTransforms.py → /sippy-2.2.2/sippy/B2B/Transforms.py +0 -0
- {sippy-2.2.0/sippy/Core → sippy-2.2.2/sippy/B2B}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Core/Exceptions.py +0 -0
- {sippy-2.2.0/sippy/Exceptions → sippy-2.2.2/sippy/Core}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/ESipHeaderCSV.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/ESipHeaderIgnore.py +0 -0
- {sippy-2.2.0/sippy/Math → sippy-2.2.2/sippy/Exceptions}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/FakeAccounting.py +0 -0
- {sippy-2.2.0/sippy/Security → sippy-2.2.2/sippy/Math}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Network_server.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/RadiusAuthorisation.py +0 -0
- {sippy-2.2.0/sippy/Time → sippy-2.2.2/sippy/Rtp_proxy/Client/Worker}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpConnecton.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpGeneric.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpMedia.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpMediaDescription.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SdpOrigin.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Security/SipNonce.py +0 -0
- {sippy-2.2.0/tests → sippy-2.2.2/sippy/Security}/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Signal.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipAddress.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipAllow.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipAlso.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipCCDiversion.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipCSeq.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipCallId.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipCiscoGUID.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipConf.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipContact.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipContentLength.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipDiversion.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipExpires.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipFrom.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipGenericHF.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipLogger.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipMaxForwards.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipNumericHF.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipPAssertedIdentity.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipPath.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipProxyAuthenticate.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipProxyAuthorization.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRAck.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRSeq.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipReason.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRecordRoute.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipReferTo.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipReferredBy.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipReplaces.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipResponse.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipRoute.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipServer.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipSupported.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipTo.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipURL.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipUserAgent.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipVia.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/SipWarning.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/StatefulProxy.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Time/Timeout.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/Time/clock_dtime.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/UaStateGeneric.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/__init__.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/dictionary +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy/misc.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy.egg-info/dependency_links.txt +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy.egg-info/requires.txt +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/sippy.egg-info/top_level.txt +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/tests/test_SdbBody.py +0 -0
- {sippy-2.2.0 → sippy-2.2.2}/tests/test_Udp_server.py +0 -0
sippy-2.2.2/MANIFEST.in
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sippy
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: RFC3261 SIP Stack and Back-to-Back User Agent (B2BUA)
|
|
5
5
|
Home-page: http://www.b2bua.org/
|
|
6
6
|
Author: Sippy Software, Inc.
|
|
@@ -15,8 +15,19 @@ License-File: LICENSE
|
|
|
15
15
|
Requires-Dist: ElPeriodic>=1.1
|
|
16
16
|
Requires-Dist: pycryptodome
|
|
17
17
|
Requires-Dist: websockets
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: author-email
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: keywords
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: summary
|
|
29
|
+
|
|
30
|
+
[](https://github.com/sippy/b2bua/actions/workflows/python-wheels.yml?query=branch%3Amaster++)
|
|
20
31
|
|
|
21
32
|
# Sippy B2BUA
|
|
22
33
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://github.com/sippy/b2bua/actions/workflows/python-wheels.yml?query=branch%3Amaster++)
|
|
2
2
|
|
|
3
3
|
# Sippy B2BUA
|
|
4
4
|
|
|
@@ -8,19 +8,18 @@ with open("README.md", "r") as fh:
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name = "sippy",
|
|
11
|
-
version = "2.2.
|
|
11
|
+
version = "2.2.2",
|
|
12
12
|
packages = find_packages(),
|
|
13
13
|
|
|
14
14
|
install_requires = requirements,
|
|
15
|
-
|
|
16
|
-
'': ['dictionary', '*.md']
|
|
17
|
-
},
|
|
15
|
+
include_package_data=True,
|
|
18
16
|
test_suite = 'tests',
|
|
19
17
|
|
|
20
18
|
entry_points = {
|
|
21
19
|
'console_scripts': [
|
|
22
20
|
'b2bua_simple = sippy.b2bua_simple:main_func',
|
|
23
|
-
'b2bua_radius = sippy.
|
|
21
|
+
'b2bua_radius = sippy.b2bua:main_func',
|
|
22
|
+
'b2bua = sippy.b2bua:main_func',
|
|
24
23
|
],
|
|
25
24
|
},
|
|
26
25
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
from sippy.SipHeader import SipHeader
|
|
28
28
|
from sippy.SipConf import SipConf
|
|
29
|
-
from sippy.
|
|
29
|
+
from sippy.B2B.Transforms import getTransProc
|
|
30
30
|
|
|
31
31
|
try:
|
|
32
32
|
from urllib import unquote
|
|
@@ -82,7 +82,7 @@ class B2BRoute(object):
|
|
|
82
82
|
self.cli_set = cself.cli_set
|
|
83
83
|
self.params = dict(cself.params)
|
|
84
84
|
self.ainfo = cself.ainfo
|
|
85
|
-
if cself.extra_headers
|
|
85
|
+
if cself.extra_headers is not None:
|
|
86
86
|
self.extra_headers = tuple([x.getCopy() for x in cself.extra_headers])
|
|
87
87
|
return
|
|
88
88
|
route = sroute.split(';')
|
|
@@ -183,7 +183,7 @@ class B2BRoute(object):
|
|
|
183
183
|
if 'gt' in self.params:
|
|
184
184
|
timeout, skip = self.params['gt'].split(',', 1)
|
|
185
185
|
self.params['group_timeout'] = (int(timeout), rnum + int(skip))
|
|
186
|
-
if self.extra_headers
|
|
186
|
+
if self.extra_headers is not None:
|
|
187
187
|
self.extra_headers = self.extra_headers + tuple(pass_headers)
|
|
188
188
|
else:
|
|
189
189
|
self.extra_headers = tuple(pass_headers)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
|
|
2
|
+
# Copyright (c) 2006-2025 Sippy Software, Inc. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
# are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
# list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation and/or
|
|
12
|
+
# other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
17
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
18
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
19
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
20
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
21
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
22
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
23
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
24
|
+
|
|
25
|
+
from ..CLIManager import CLIConnectionManager, CLIManager
|
|
26
|
+
from ..Time.MonoTime import MonoTime
|
|
27
|
+
from .States import CCStateConnected, CCStateARComplete
|
|
28
|
+
|
|
29
|
+
class B2BSimpleAPI(CLIConnectionManager):
|
|
30
|
+
global_config = None
|
|
31
|
+
|
|
32
|
+
def __init__(self, global_config):
|
|
33
|
+
cmdfile = global_config['b2bua_socket']
|
|
34
|
+
self.global_config = global_config
|
|
35
|
+
if cmdfile.startswith('tcp:'):
|
|
36
|
+
parts = cmdfile[4:].split(':', 1)
|
|
37
|
+
if len(parts) == 1:
|
|
38
|
+
address = (parts[0], 12345)
|
|
39
|
+
else:
|
|
40
|
+
address = (parts[0], int(parts[1]))
|
|
41
|
+
super().__init__(self.recvCommand, address, tcp = True)
|
|
42
|
+
else:
|
|
43
|
+
if cmdfile.startswith('unix:'):
|
|
44
|
+
cmdfile = cmdfile[5:]
|
|
45
|
+
super().__init__(self.recvCommand, cmdfile)
|
|
46
|
+
|
|
47
|
+
def recvCommand(self, clim, cmd):
|
|
48
|
+
ccm = self.global_config['_cmap']
|
|
49
|
+
args = cmd.split()
|
|
50
|
+
cmd = args.pop(0).lower()
|
|
51
|
+
if cmd == 'q':
|
|
52
|
+
clim.close()
|
|
53
|
+
return False
|
|
54
|
+
if cmd == 'l':
|
|
55
|
+
res = 'In-memory calls:\n'
|
|
56
|
+
total = 0
|
|
57
|
+
for (cid, sname), uaast, uaost in ccm.listActiveCalls():
|
|
58
|
+
res += f'{cid}: {sname} ('
|
|
59
|
+
if uaast is not None:
|
|
60
|
+
_s, _t, _h, _p, _cld, _cli = uaast
|
|
61
|
+
res += f'{_s} {_t}:{_h}:{_p} {_cld} {_cli} -> '
|
|
62
|
+
else:
|
|
63
|
+
res += 'N/A -> '
|
|
64
|
+
if uaost is not None:
|
|
65
|
+
_s, _t, _h, _p, _cld, _cli = uaost
|
|
66
|
+
res += f'{_s} {_t}:{_h}:{_p} {_cld} {_cli})\n'
|
|
67
|
+
else:
|
|
68
|
+
res += 'N/A)\n'
|
|
69
|
+
total += 1
|
|
70
|
+
res += 'Total: %d\n' % total
|
|
71
|
+
clim.send(res)
|
|
72
|
+
return False
|
|
73
|
+
if cmd == 'lt':
|
|
74
|
+
res = 'In-memory server transactions:\n'
|
|
75
|
+
for tid, t in self.global_config['_sip_tm'].tserver.iteritems():
|
|
76
|
+
res += '%s %s %s\n' % (tid, t.method, t.state)
|
|
77
|
+
res += 'In-memory client transactions:\n'
|
|
78
|
+
for tid, t in self.global_config['_sip_tm'].tclient.iteritems():
|
|
79
|
+
res += '%s %s %s\n' % (tid, t.method, t.state)
|
|
80
|
+
clim.send(res)
|
|
81
|
+
return False
|
|
82
|
+
if cmd in ('lt', 'llt'):
|
|
83
|
+
if cmd == 'llt':
|
|
84
|
+
mindur = 60.0
|
|
85
|
+
else:
|
|
86
|
+
mindur = 0.0
|
|
87
|
+
ctime = MonoTime()
|
|
88
|
+
res = 'In-memory server transactions:\n'
|
|
89
|
+
for tid, t in self.global_config['_sip_tm'].tserver.iteritems():
|
|
90
|
+
duration = ctime - t.rtime
|
|
91
|
+
if duration < mindur:
|
|
92
|
+
continue
|
|
93
|
+
res += '%s %s %s %s\n' % (tid, t.method, t.state, duration)
|
|
94
|
+
res += 'In-memory client transactions:\n'
|
|
95
|
+
for tid, t in self.global_config['_sip_tm'].tclient.iteritems():
|
|
96
|
+
duration = ctime - t.rtime
|
|
97
|
+
if duration < mindur:
|
|
98
|
+
continue
|
|
99
|
+
res += '%s %s %s %s\n' % (tid, t.method, t.state, duration)
|
|
100
|
+
clim.send(res)
|
|
101
|
+
return False
|
|
102
|
+
if cmd == 'd':
|
|
103
|
+
if len(args) != 1:
|
|
104
|
+
clim.send('ERROR: syntax error: d <call-id>\n')
|
|
105
|
+
return False
|
|
106
|
+
if args[0] == '*':
|
|
107
|
+
self.discAll()
|
|
108
|
+
clim.send('OK\n')
|
|
109
|
+
return False
|
|
110
|
+
dlist = [x for x in ccm.ccmap if str(x.cId) == args[0]]
|
|
111
|
+
if len(dlist) == 0:
|
|
112
|
+
clim.send('ERROR: no call with id of %s has been found\n' % args[0])
|
|
113
|
+
return False
|
|
114
|
+
for cc in dlist:
|
|
115
|
+
cc.disconnect()
|
|
116
|
+
clim.send('OK\n')
|
|
117
|
+
return False
|
|
118
|
+
if cmd == 'r':
|
|
119
|
+
if len(args) != 1:
|
|
120
|
+
clim.send('ERROR: syntax error: r [<id>]\n')
|
|
121
|
+
return False
|
|
122
|
+
idx = int(args[0])
|
|
123
|
+
dlist = [x for x in ccm.ccmap if x.id == idx]
|
|
124
|
+
if len(dlist) == 0:
|
|
125
|
+
clim.send('ERROR: no call with id of %d has been found\n' % idx)
|
|
126
|
+
return False
|
|
127
|
+
for cc in dlist:
|
|
128
|
+
if not cc.proxied:
|
|
129
|
+
continue
|
|
130
|
+
if cc.state == CCStateConnected:
|
|
131
|
+
cc.disconnect(MonoTime().getOffsetCopy(-60), origin = 'media_timeout')
|
|
132
|
+
continue
|
|
133
|
+
if cc.state == CCStateARComplete:
|
|
134
|
+
cc.uaO.disconnect(MonoTime().getOffsetCopy(-60), origin = 'media_timeout')
|
|
135
|
+
continue
|
|
136
|
+
clim.send('OK\n')
|
|
137
|
+
return False
|
|
138
|
+
clim.send('ERROR: unknown command\n')
|
|
139
|
+
return False
|
|
140
|
+
|
|
141
|
+
def set_rtp_io_socket(self, rtpp_nsock, rtpp_nsock_spec):
|
|
142
|
+
CLIManager(rtpp_nsock, self.recvCommand)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
|
|
2
|
+
# Copyright (c) 2006-2025 Sippy Software, Inc. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
|
5
|
+
# are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
# list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation and/or
|
|
12
|
+
# other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
17
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
18
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
19
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
20
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
21
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
22
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
23
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
24
|
+
|
|
25
|
+
class CCStateIdle(object):
|
|
26
|
+
sname = 'Idle'
|
|
27
|
+
class CCStateWaitRoute(object):
|
|
28
|
+
sname = 'WaitRoute'
|
|
29
|
+
class CCStateARComplete(object):
|
|
30
|
+
sname = 'ARComplete'
|
|
31
|
+
class CCStateConnected(object):
|
|
32
|
+
sname = 'Connected'
|
|
33
|
+
class CCStateDead(object):
|
|
34
|
+
sname = 'Dead'
|
|
35
|
+
class CCStateDisconnecting(object):
|
|
36
|
+
sname = 'Disconnecting'
|
|
@@ -25,19 +25,21 @@
|
|
|
25
25
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
26
|
|
|
27
27
|
from sippy.Time.MonoTime import MonoTime
|
|
28
|
+
from sippy.SipHeader import SipHeader
|
|
29
|
+
from sippy.SipWarning import SipWarning
|
|
28
30
|
|
|
29
31
|
class CCEventGeneric(object):
|
|
30
32
|
data = None
|
|
31
33
|
name = None
|
|
32
34
|
rtime = None
|
|
33
35
|
origin = None
|
|
34
|
-
|
|
36
|
+
reason_rfc3326 = None
|
|
35
37
|
extra_headers = None
|
|
36
38
|
seq = 1
|
|
37
39
|
|
|
38
40
|
def __init__(self, data = None, rtime = None, origin = None):
|
|
39
41
|
self.data = data
|
|
40
|
-
if rtime
|
|
42
|
+
if rtime is None:
|
|
41
43
|
self.rtime = MonoTime()
|
|
42
44
|
else:
|
|
43
45
|
self.rtime = rtime
|
|
@@ -50,12 +52,20 @@ class CCEventGeneric(object):
|
|
|
50
52
|
|
|
51
53
|
def getCopy(self):
|
|
52
54
|
cself = self.__class__(self.data, self.rtime, self.origin)
|
|
53
|
-
if self.
|
|
54
|
-
cself.
|
|
55
|
-
if self.
|
|
56
|
-
cself.
|
|
55
|
+
if self.extra_headers is not None:
|
|
56
|
+
cself.extra_headers = tuple(x.getCopy() for x in self.extra_headers)
|
|
57
|
+
if self.reason_rfc3326 is not None:
|
|
58
|
+
cself.reason_rfc3326 = self.reason_rfc3326.getCopy()
|
|
57
59
|
return cself
|
|
58
60
|
|
|
61
|
+
def getExtraHeaders(self):
|
|
62
|
+
extra_headers = []
|
|
63
|
+
if self.extra_headers is not None:
|
|
64
|
+
extra_headers.extend(self.extra_headers)
|
|
65
|
+
if self.reason_rfc3326 is not None:
|
|
66
|
+
extra_headers.append(SipHeader(body = self.reason_rfc3326))
|
|
67
|
+
return tuple(extra_headers) if len(extra_headers) > 0 else None
|
|
68
|
+
|
|
59
69
|
def __str__(self):
|
|
60
70
|
return self.name
|
|
61
71
|
|
|
@@ -64,7 +74,7 @@ class CCEventTry(CCEventGeneric):
|
|
|
64
74
|
max_forwards = None
|
|
65
75
|
|
|
66
76
|
def getCopy(self):
|
|
67
|
-
cself =
|
|
77
|
+
cself = super().getCopy()
|
|
68
78
|
cself.max_forwards = self.max_forwards
|
|
69
79
|
return cself
|
|
70
80
|
|
|
@@ -75,35 +85,27 @@ class CCEventTry(CCEventGeneric):
|
|
|
75
85
|
|
|
76
86
|
class CCEventRing(CCEventGeneric):
|
|
77
87
|
name = 'CCEventRing'
|
|
78
|
-
pass
|
|
79
88
|
|
|
80
89
|
class CCEventPreConnect(CCEventGeneric):
|
|
81
90
|
name = 'CCEventPreConnect'
|
|
82
|
-
pass
|
|
83
91
|
|
|
84
92
|
class CCEventConnect(CCEventGeneric):
|
|
85
93
|
name = 'CCEventConnect'
|
|
86
|
-
pass
|
|
87
94
|
|
|
88
95
|
class CCEventUpdate(CCEventGeneric):
|
|
89
96
|
name = 'CCEventUpdate'
|
|
90
97
|
max_forwards = None
|
|
91
98
|
|
|
92
99
|
def getCopy(self):
|
|
93
|
-
cself =
|
|
100
|
+
cself = super().getCopy()
|
|
94
101
|
cself.max_forwards = self.max_forwards
|
|
95
102
|
return cself
|
|
96
103
|
|
|
97
104
|
class CCEventInfo(CCEventGeneric):
|
|
98
105
|
name = 'CCEventInfo'
|
|
99
|
-
pass
|
|
100
106
|
|
|
101
107
|
class CCEventDisconnect(CCEventGeneric):
|
|
102
108
|
name = 'CCEventDisconnect'
|
|
103
|
-
pass
|
|
104
|
-
|
|
105
|
-
from sippy.SipHeader import SipHeader
|
|
106
|
-
from sippy.SipWarning import SipWarning
|
|
107
109
|
|
|
108
110
|
class CCEventFail(CCEventGeneric):
|
|
109
111
|
name = 'CCEventFail'
|
|
@@ -111,14 +113,25 @@ class CCEventFail(CCEventGeneric):
|
|
|
111
113
|
warning = None
|
|
112
114
|
|
|
113
115
|
def getCopy(self):
|
|
114
|
-
cself =
|
|
115
|
-
if self.challenges
|
|
116
|
+
cself = super().getCopy()
|
|
117
|
+
if self.challenges is not None:
|
|
116
118
|
cself.challenges = [x.getCopy() for x in self.challenges]
|
|
119
|
+
if self.warning is not None:
|
|
120
|
+
cself.warning = self.warning.getCopy()
|
|
117
121
|
return cself
|
|
118
122
|
|
|
123
|
+
def getExtraHeaders(self):
|
|
124
|
+
extra_headers = []
|
|
125
|
+
if (eh := super().getExtraHeaders()) is not None:
|
|
126
|
+
extra_headers.extend(eh)
|
|
127
|
+
if self.challenges is not None:
|
|
128
|
+
extra_headers.extend(self.challenges)
|
|
129
|
+
if self.warning is not None:
|
|
130
|
+
extra_headers.append(self.warning)
|
|
131
|
+
return tuple(extra_headers) if len(extra_headers) > 0 else None
|
|
132
|
+
|
|
119
133
|
def setWarning(self, eistr):
|
|
120
134
|
self.warning = SipHeader(body = SipWarning(text = eistr))
|
|
121
135
|
|
|
122
136
|
class CCEventRedirect(CCEventGeneric):
|
|
123
137
|
name = 'CCEventRedirect'
|
|
124
|
-
pass
|
|
@@ -125,7 +125,7 @@ class CLIConnectionManager(object):
|
|
|
125
125
|
conn.close()
|
|
126
126
|
return
|
|
127
127
|
try:
|
|
128
|
-
cm = CLIManager(conn, self.command_cb
|
|
128
|
+
cm = CLIManager(conn, self.command_cb)
|
|
129
129
|
except Exception as e:
|
|
130
130
|
dump_exception('CLIConnectionManager: unhandled exception when setting up incoming connection handler')
|
|
131
131
|
conn.close()
|
|
@@ -169,7 +169,16 @@ class _CLIManager_w(Thread):
|
|
|
169
169
|
self.wbuffer = None
|
|
170
170
|
self.w_available.release()
|
|
171
171
|
while True:
|
|
172
|
-
|
|
172
|
+
try:
|
|
173
|
+
res = self.clientsock.send(wbuffer)
|
|
174
|
+
except BrokenPipeError:
|
|
175
|
+
self.clim = None
|
|
176
|
+
return
|
|
177
|
+
except socket.error as why:
|
|
178
|
+
if why.errno != EBADF:
|
|
179
|
+
raise
|
|
180
|
+
self.clim = None
|
|
181
|
+
return
|
|
173
182
|
if res == len(wbuffer):
|
|
174
183
|
break
|
|
175
184
|
if res > 0:
|
|
@@ -235,14 +244,12 @@ class CLIManager(object):
|
|
|
235
244
|
clientsock = None
|
|
236
245
|
command_cb = None
|
|
237
246
|
close_pendind = False
|
|
238
|
-
raddr = None
|
|
239
247
|
wthr = None
|
|
240
248
|
rthr = None
|
|
241
249
|
|
|
242
|
-
def __init__(self, clientsock, command_cb
|
|
250
|
+
def __init__(self, clientsock, command_cb):
|
|
243
251
|
self.clientsock = clientsock
|
|
244
252
|
self.command_cb = command_cb
|
|
245
|
-
self.raddr = raddr
|
|
246
253
|
self.wthr = _CLIManager_w(clientsock, self)
|
|
247
254
|
self.rthr = _CLIManager_r(clientsock, self)
|
|
248
255
|
|
|
@@ -276,7 +283,7 @@ class CLIManager(object):
|
|
|
276
283
|
self.clientsock.shutdown(socket.SHUT_RDWR)
|
|
277
284
|
except Exception as e:
|
|
278
285
|
if not isinstance(e, socket.error) or e.errno != ENOTCONN: # pylint: disable=no-member
|
|
279
|
-
dump_exception('self.clientsock.shutdown(socket.SHUT_RDWR)')
|
|
286
|
+
dump_exception('CLIManager: unhandled exception in self.clientsock.shutdown(socket.SHUT_RDWR)')
|
|
280
287
|
self.clientsock.close()
|
|
281
288
|
self.wthr = None
|
|
282
289
|
self.rthr = None
|
|
@@ -29,12 +29,13 @@ from __future__ import print_function
|
|
|
29
29
|
from functools import partial
|
|
30
30
|
from datetime import datetime
|
|
31
31
|
from heapq import heappush, heappop, heapify
|
|
32
|
-
from threading import Lock
|
|
32
|
+
from threading import Lock, local as t_local
|
|
33
33
|
from random import random
|
|
34
34
|
import sys, traceback, signal
|
|
35
35
|
from _thread import get_ident
|
|
36
36
|
from sippy.Time.MonoTime import MonoTime
|
|
37
37
|
from sippy.Core.Exceptions import dump_exception, StdException
|
|
38
|
+
from queue import Queue
|
|
38
39
|
|
|
39
40
|
from elperiodic.ElPeriodic import ElPeriodic
|
|
40
41
|
|
|
@@ -123,6 +124,8 @@ class EventDispatcher2(Singleton):
|
|
|
123
124
|
ed_inum = 0
|
|
124
125
|
elp = None
|
|
125
126
|
bands = None
|
|
127
|
+
_exception = None
|
|
128
|
+
tloc_data = None
|
|
126
129
|
|
|
127
130
|
def __init__(self, freq = 100.0):
|
|
128
131
|
EventDispatcher2.state_lock.acquire()
|
|
@@ -140,6 +143,7 @@ class EventDispatcher2(Singleton):
|
|
|
140
143
|
self.elp = ElPeriodic(freq)
|
|
141
144
|
self.elp.CFT_enable(signal.SIGURG)
|
|
142
145
|
self.bands = [(freq, 0),]
|
|
146
|
+
self.tloc_data = t_local()
|
|
143
147
|
|
|
144
148
|
def signal(self, signum, frame):
|
|
145
149
|
self.signals_pending.append(signum)
|
|
@@ -233,16 +237,35 @@ class EventDispatcher2(Singleton):
|
|
|
233
237
|
def dispatchThreadCallback(self, thread_cb, cb_params):
|
|
234
238
|
try:
|
|
235
239
|
thread_cb(*cb_params)
|
|
236
|
-
except
|
|
237
|
-
if isinstance(ex, SystemExit):
|
|
238
|
-
|
|
240
|
+
except BaseException as ex:
|
|
241
|
+
if isinstance(ex, (SystemExit, KeyboardInterrupt)):
|
|
242
|
+
self._exception = ex
|
|
243
|
+
return
|
|
239
244
|
dump_exception('EventDispatcher2: unhandled exception when processing from-thread-call')
|
|
240
|
-
|
|
245
|
+
|
|
246
|
+
def dispatchThreadCallbackSync(self, res_cb_q, thread_cb, cb_params):
|
|
247
|
+
try:
|
|
248
|
+
res = thread_cb(*cb_params)
|
|
249
|
+
except BaseException as ex:
|
|
250
|
+
rval = (None, ex)
|
|
251
|
+
else:
|
|
252
|
+
rval = (res, None)
|
|
253
|
+
res_cb_q.put(rval)
|
|
241
254
|
|
|
242
255
|
def callFromThread(self, thread_cb, *cb_params):
|
|
243
256
|
self.elp.call_from_thread(self.dispatchThreadCallback, thread_cb, cb_params)
|
|
244
257
|
#print('EventDispatcher2.callFromThread completed', str(self), thread_cb, cb_params)
|
|
245
258
|
|
|
259
|
+
def callFromThreadSync(self, thread_cb, *cb_params):
|
|
260
|
+
if not hasattr(self.tloc_data, 'res_cb_q'):
|
|
261
|
+
self.tloc_data.res_cb_q = Queue()
|
|
262
|
+
res_cb_q = self.tloc_data.res_cb_q
|
|
263
|
+
self.elp.call_from_thread(self.dispatchThreadCallbackSync, res_cb_q, thread_cb, cb_params)
|
|
264
|
+
res, ex = res_cb_q.get()
|
|
265
|
+
if ex is not None:
|
|
266
|
+
raise ex
|
|
267
|
+
return res
|
|
268
|
+
|
|
246
269
|
def loop(self, timeout = None, freq = None):
|
|
247
270
|
if freq != None and self.bands[0][0] != freq:
|
|
248
271
|
for fb in self.bands:
|
|
@@ -255,8 +278,7 @@ class EventDispatcher2(Singleton):
|
|
|
255
278
|
self.bands.insert(0, fb)
|
|
256
279
|
self.endloop = False
|
|
257
280
|
self.last_ts = MonoTime()
|
|
258
|
-
if timeout
|
|
259
|
-
etime = self.last_ts.getOffsetCopy(timeout)
|
|
281
|
+
etime = None if timeout is None else self.last_ts.getOffsetCopy(timeout)
|
|
260
282
|
while True:
|
|
261
283
|
if len(self.signals_pending) > 0:
|
|
262
284
|
self.dispatchSignals()
|
|
@@ -275,6 +297,10 @@ class EventDispatcher2(Singleton):
|
|
|
275
297
|
break
|
|
276
298
|
self.elp.procrastinate()
|
|
277
299
|
self.last_ts = MonoTime()
|
|
300
|
+
if self._exception is not None:
|
|
301
|
+
ex = self._exception
|
|
302
|
+
self._exception = None
|
|
303
|
+
raise ex
|
|
278
304
|
return self.el_rval
|
|
279
305
|
|
|
280
306
|
def breakLoop(self, rval=0):
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Copyright (c) 2023 Sippy Software, Inc. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
# are permitted provided that the following conditions are met:
|
|
7
|
+
#
|
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
# list of conditions and the following disclaimer.
|
|
10
|
+
#
|
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
# this list of conditions and the following disclaimer in the documentation and/or
|
|
13
|
+
# other materials provided with the distribution.
|
|
14
|
+
#
|
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
19
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
22
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
from .SipHandlingError import SipHandlingError
|
|
27
|
+
|
|
28
|
+
class RtpProxyError(SipHandlingError):
|
|
29
|
+
code = 502
|
|
30
|
+
msg = 'Bad Gateway'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright (c) 20012-2023 Sippy Software, Inc. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
# are permitted provided that the following conditions are met:
|
|
7
|
+
#
|
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
# list of conditions and the following disclaimer.
|
|
10
|
+
#
|
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
# this list of conditions and the following disclaimer in the documentation and/or
|
|
13
|
+
# other materials provided with the distribution.
|
|
14
|
+
#
|
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
19
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
22
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
from .SipHandlingError import SipHandlingError
|
|
27
|
+
from .RtpProxyError import RtpProxyError
|
|
28
|
+
|
|
29
|
+
class SdpParseError(SipHandlingError):
|
|
30
|
+
code = 488
|
|
31
|
+
msg = 'Not Acceptable Here'
|
|
32
|
+
|
|
33
|
+
SdpHandlingErrors = (SdpParseError, RtpProxyError)
|
sippy-2.2.0/sippy/Exceptions/SipParseError.py → sippy-2.2.2/sippy/Exceptions/SipHandlingError.py
RENAMED
|
@@ -24,33 +24,23 @@
|
|
|
24
24
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
25
|
|
|
26
26
|
from sippy.SipReason import SipReason
|
|
27
|
-
from sippy.SipHeader import SipHeader
|
|
28
27
|
|
|
29
|
-
class
|
|
28
|
+
class SipHandlingError(Exception):
|
|
29
|
+
code: int
|
|
30
|
+
msg: str
|
|
30
31
|
sip_response = None
|
|
31
32
|
arg = None
|
|
32
33
|
|
|
33
|
-
def __init__(self, arg
|
|
34
|
+
def __init__(self, arg):
|
|
34
35
|
super().__init__()
|
|
35
36
|
self.arg = arg
|
|
36
|
-
self.sip_response = sip_response
|
|
37
37
|
|
|
38
38
|
def __str__(self):
|
|
39
39
|
return str(self.arg)
|
|
40
40
|
|
|
41
|
-
def getResponse(self, req=None):
|
|
42
|
-
return self.sip_response
|
|
43
|
-
|
|
44
|
-
class SdpParseError(SipParseError):
|
|
45
|
-
code = 488
|
|
46
|
-
msg = 'Not Acceptable Here'
|
|
47
41
|
def getResponse(self, req):
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
resp = req.genResponse(self.code, self.msg)
|
|
51
|
-
if (reason:=self.getReason()) is not None:
|
|
52
|
-
rsh = SipHeader(body = reason)
|
|
53
|
-
resp.appendHeader(rsh)
|
|
42
|
+
reason = self.getReason()
|
|
43
|
+
resp = req.genResponse(self.code, self.msg, ext_reason = reason)
|
|
54
44
|
return resp
|
|
55
45
|
|
|
56
46
|
def getReason(self):
|