sippy 2.2.0__tar.gz → 2.2.1__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.
Files changed (146) hide show
  1. {sippy-2.2.0/sippy.egg-info → sippy-2.2.1}/PKG-INFO +15 -4
  2. {sippy-2.2.0 → sippy-2.2.1}/README.md +1 -1
  3. {sippy-2.2.0 → sippy-2.2.1}/setup.py +3 -2
  4. {sippy-2.2.0 → sippy-2.2.1}/sippy/B2BRoute.py +2 -2
  5. {sippy-2.2.0 → sippy-2.2.1}/sippy/CCEvents.py +32 -19
  6. {sippy-2.2.0 → sippy-2.2.1}/sippy/CLIManager.py +6 -2
  7. {sippy-2.2.0 → sippy-2.2.1}/sippy/Core/EventDispatcher.py +1 -2
  8. sippy-2.2.1/sippy/Exceptions/RtpProxyError.py +30 -0
  9. sippy-2.2.1/sippy/Exceptions/SdpParseError.py +33 -0
  10. sippy-2.2.0/sippy/Exceptions/SipParseError.py → sippy-2.2.1/sippy/Exceptions/SipHandlingError.py +6 -16
  11. sippy-2.2.0/sippy/Exceptions/RtpProxyError.py → sippy-2.2.1/sippy/Exceptions/SipParseError.py +10 -13
  12. {sippy-2.2.0 → sippy-2.2.1}/sippy/External_command.py +1 -1
  13. {sippy-2.2.0 → sippy-2.2.1}/sippy/Math/recfilter.py +2 -2
  14. {sippy-2.2.0 → sippy-2.2.1}/sippy/MsgBody.py +1 -1
  15. {sippy-2.2.0 → sippy-2.2.1}/sippy/MultipartMixBody.py +14 -3
  16. {sippy-2.2.0 → sippy-2.2.1}/sippy/RadiusAccounting.py +1 -1
  17. {sippy-2.2.0 → sippy-2.2.1}/sippy/Radius_client.py +1 -1
  18. sippy-2.2.1/sippy/Rtp_proxy/Client/__init__.py +1 -0
  19. sippy-2.2.1/sippy/Rtp_proxy/Client/local.py +53 -0
  20. sippy-2.2.1/sippy/Rtp_proxy/Client/net.py +42 -0
  21. sippy-2.2.1/sippy/Rtp_proxy/Client/stream.py +213 -0
  22. sippy-2.2.1/sippy/Rtp_proxy/Client/udp.py +224 -0
  23. sippy-2.2.1/sippy/Rtp_proxy/Cmd/__init__.py +1 -0
  24. sippy-2.2.1/sippy/Rtp_proxy/Cmd/sequencer.py +63 -0
  25. sippy-2.2.1/sippy/Rtp_proxy/Session/__init__.py +1 -0
  26. sippy-2.2.1/sippy/Rtp_proxy/Session/side.py +263 -0
  27. sippy-2.2.1/sippy/Rtp_proxy/Session/subcommand.py +117 -0
  28. sippy-2.2.1/sippy/Rtp_proxy/Session/subcommand_ice.py +101 -0
  29. sippy-2.2.1/sippy/Rtp_proxy/Session/update.py +121 -0
  30. sippy-2.2.1/sippy/Rtp_proxy/Session/webrtc.py +42 -0
  31. sippy-2.2.1/sippy/Rtp_proxy/__init__.py +1 -0
  32. sippy-2.2.1/sippy/Rtp_proxy/client.py +279 -0
  33. sippy-2.2.1/sippy/Rtp_proxy/cmd.py +224 -0
  34. sippy-2.2.1/sippy/Rtp_proxy/session.py +221 -0
  35. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpBody.py +5 -4
  36. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipAddressHF.py +1 -1
  37. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipAuthorization.py +0 -1
  38. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipHeader.py +1 -1
  39. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipMsg.py +1 -1
  40. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRegistrationAgent.py +4 -2
  41. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRequest.py +11 -2
  42. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipTransactionManager.py +26 -22
  43. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipWWWAuthenticate.py +2 -2
  44. {sippy-2.2.0 → sippy-2.2.1}/sippy/Time/MonoTime.py +1 -1
  45. {sippy-2.2.0 → sippy-2.2.1}/sippy/UA.py +63 -40
  46. {sippy-2.2.0 → sippy-2.2.1}/sippy/UaStateConnected.py +38 -54
  47. {sippy-2.2.0 → sippy-2.2.1}/sippy/UaStateDead.py +1 -1
  48. {sippy-2.2.0 → sippy-2.2.1}/sippy/UaStateDisconnected.py +6 -9
  49. {sippy-2.2.0 → sippy-2.2.1}/sippy/UaStateFailed.py +3 -6
  50. {sippy-2.2.0 → sippy-2.2.1}/sippy/UacStateCancelling.py +7 -14
  51. {sippy-2.2.0 → sippy-2.2.1}/sippy/UacStateIdle.py +11 -12
  52. {sippy-2.2.0 → sippy-2.2.1}/sippy/UacStateRinging.py +29 -24
  53. {sippy-2.2.0 → sippy-2.2.1}/sippy/UacStateTrying.py +36 -34
  54. {sippy-2.2.0 → sippy-2.2.1}/sippy/UacStateUpdating.py +30 -32
  55. {sippy-2.2.0 → sippy-2.2.1}/sippy/UasStateIdle.py +4 -7
  56. {sippy-2.2.0 → sippy-2.2.1}/sippy/UasStateRinging.py +21 -38
  57. {sippy-2.2.0 → sippy-2.2.1}/sippy/UasStateTrying.py +18 -39
  58. {sippy-2.2.0 → sippy-2.2.1}/sippy/UasStateUpdating.py +29 -44
  59. {sippy-2.2.0 → sippy-2.2.1}/sippy/Udp_server.py +14 -10
  60. {sippy-2.2.0 → sippy-2.2.1}/sippy/Wss_server.py +1 -1
  61. {sippy-2.2.0 → sippy-2.2.1}/sippy/XMPP_server.py +3 -3
  62. sippy-2.2.0/sippy/b2bua_radius.py → sippy-2.2.1/sippy/b2bua.py +15 -18
  63. {sippy-2.2.0 → sippy-2.2.1}/sippy/b2bua_simple.py +1 -1
  64. {sippy-2.2.0 → sippy-2.2.1/sippy.egg-info}/PKG-INFO +15 -4
  65. {sippy-2.2.0 → sippy-2.2.1}/sippy.egg-info/SOURCES.txt +21 -1
  66. sippy-2.2.1/sippy.egg-info/entry_points.txt +4 -0
  67. sippy-2.2.1/tests/test_Multipart.py +45 -0
  68. sippy-2.2.0/sippy.egg-info/entry_points.txt +0 -3
  69. {sippy-2.2.0 → sippy-2.2.1}/LICENSE +0 -0
  70. {sippy-2.2.0 → sippy-2.2.1}/MANIFEST.in +0 -0
  71. {sippy-2.2.0 → sippy-2.2.1}/pyproject.toml +0 -0
  72. {sippy-2.2.0 → sippy-2.2.1}/requirements.txt +0 -0
  73. {sippy-2.2.0 → sippy-2.2.1}/setup.cfg +0 -0
  74. {sippy-2.2.0 → sippy-2.2.1}/sippy/B2BTransforms.py +0 -0
  75. {sippy-2.2.0 → sippy-2.2.1}/sippy/Core/Exceptions.py +0 -0
  76. {sippy-2.2.0 → sippy-2.2.1}/sippy/Core/__init__.py +0 -0
  77. {sippy-2.2.0 → sippy-2.2.1}/sippy/ESipHeaderCSV.py +0 -0
  78. {sippy-2.2.0 → sippy-2.2.1}/sippy/ESipHeaderIgnore.py +0 -0
  79. {sippy-2.2.0 → sippy-2.2.1}/sippy/Exceptions/__init__.py +0 -0
  80. {sippy-2.2.0 → sippy-2.2.1}/sippy/FakeAccounting.py +0 -0
  81. {sippy-2.2.0 → sippy-2.2.1}/sippy/Math/__init__.py +0 -0
  82. {sippy-2.2.0 → sippy-2.2.1}/sippy/MyConfigParser.py +0 -0
  83. {sippy-2.2.0 → sippy-2.2.1}/sippy/Network_server.py +0 -0
  84. {sippy-2.2.0 → sippy-2.2.1}/sippy/RadiusAuthorisation.py +0 -0
  85. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpConnecton.py +0 -0
  86. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpGeneric.py +0 -0
  87. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpMedia.py +0 -0
  88. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpMediaDescription.py +0 -0
  89. {sippy-2.2.0 → sippy-2.2.1}/sippy/SdpOrigin.py +0 -0
  90. {sippy-2.2.0 → sippy-2.2.1}/sippy/Security/SipNonce.py +0 -0
  91. {sippy-2.2.0 → sippy-2.2.1}/sippy/Security/__init__.py +0 -0
  92. {sippy-2.2.0 → sippy-2.2.1}/sippy/Signal.py +0 -0
  93. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipAddress.py +0 -0
  94. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipAllow.py +0 -0
  95. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipAlso.py +0 -0
  96. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipCCDiversion.py +0 -0
  97. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipCSeq.py +0 -0
  98. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipCallId.py +0 -0
  99. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipCiscoGUID.py +0 -0
  100. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipConf.py +0 -0
  101. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipContact.py +0 -0
  102. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipContentLength.py +0 -0
  103. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipContentType.py +0 -0
  104. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipDiversion.py +0 -0
  105. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipExpires.py +0 -0
  106. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipFrom.py +0 -0
  107. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipGenericHF.py +0 -0
  108. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipLogger.py +0 -0
  109. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipMaxForwards.py +0 -0
  110. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipNumericHF.py +0 -0
  111. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipPAssertedIdentity.py +0 -0
  112. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipPath.py +0 -0
  113. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipProxyAuthenticate.py +0 -0
  114. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipProxyAuthorization.py +0 -0
  115. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRAck.py +0 -0
  116. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRSeq.py +0 -0
  117. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipReason.py +0 -0
  118. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRecordRoute.py +0 -0
  119. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipReferTo.py +0 -0
  120. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipReferredBy.py +0 -0
  121. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipReplaces.py +0 -0
  122. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipResponse.py +0 -0
  123. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipRoute.py +0 -0
  124. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipServer.py +0 -0
  125. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipSupported.py +0 -0
  126. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipTo.py +0 -0
  127. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipURL.py +0 -0
  128. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipUserAgent.py +0 -0
  129. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipVia.py +0 -0
  130. {sippy-2.2.0 → sippy-2.2.1}/sippy/SipWarning.py +0 -0
  131. {sippy-2.2.0 → sippy-2.2.1}/sippy/StatefulProxy.py +0 -0
  132. {sippy-2.2.0 → sippy-2.2.1}/sippy/Time/Timeout.py +0 -0
  133. {sippy-2.2.0 → sippy-2.2.1}/sippy/Time/__init__.py +0 -0
  134. {sippy-2.2.0 → sippy-2.2.1}/sippy/Time/clock_dtime.py +0 -0
  135. {sippy-2.2.0 → sippy-2.2.1}/sippy/UaStateGeneric.py +0 -0
  136. {sippy-2.2.0 → sippy-2.2.1}/sippy/__init__.py +0 -0
  137. {sippy-2.2.0 → sippy-2.2.1}/sippy/dictionary +0 -0
  138. {sippy-2.2.0 → sippy-2.2.1}/sippy/misc.py +0 -0
  139. {sippy-2.2.0 → sippy-2.2.1}/sippy.egg-info/dependency_links.txt +0 -0
  140. {sippy-2.2.0 → sippy-2.2.1}/sippy.egg-info/requires.txt +0 -0
  141. {sippy-2.2.0 → sippy-2.2.1}/sippy.egg-info/top_level.txt +0 -0
  142. {sippy-2.2.0 → sippy-2.2.1}/tests/__init__.py +0 -0
  143. {sippy-2.2.0 → sippy-2.2.1}/tests/test_B2BRoute.py +0 -0
  144. {sippy-2.2.0 → sippy-2.2.1}/tests/test_B2BTransforms.py +0 -0
  145. {sippy-2.2.0 → sippy-2.2.1}/tests/test_SdbBody.py +0 -0
  146. {sippy-2.2.0 → sippy-2.2.1}/tests/test_Udp_server.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: sippy
3
- Version: 2.2.0
3
+ Version: 2.2.1
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
- [![Build Status@GitHub](https://github.com/sippy/b2bua/workflows/Check%20Python%20Wheels/badge.svg?branch=master)](https://github.com/sippy/b2bua/actions?query=branch%3Amaster++)
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
+ [![Build Status@GitHub](https://github.com/sippy/b2bua/actions/workflows/python-wheels.yml/badge.svg?branch=master)](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
- [![Build Status@GitHub](https://github.com/sippy/b2bua/workflows/Check%20Python%20Wheels/badge.svg?branch=master)](https://github.com/sippy/b2bua/actions?query=branch%3Amaster++)
1
+ [![Build Status@GitHub](https://github.com/sippy/b2bua/actions/workflows/python-wheels.yml/badge.svg?branch=master)](https://github.com/sippy/b2bua/actions/workflows/python-wheels.yml?query=branch%3Amaster++)
2
2
 
3
3
  # Sippy B2BUA
4
4
 
@@ -8,7 +8,7 @@ with open("README.md", "r") as fh:
8
8
 
9
9
  setup(
10
10
  name = "sippy",
11
- version = "2.2.0",
11
+ version = "2.2.1",
12
12
  packages = find_packages(),
13
13
 
14
14
  install_requires = requirements,
@@ -20,7 +20,8 @@ setup(
20
20
  entry_points = {
21
21
  'console_scripts': [
22
22
  'b2bua_simple = sippy.b2bua_simple:main_func',
23
- 'b2bua_radius = sippy.b2bua_radius:main_func',
23
+ 'b2bua_radius = sippy.b2bua:main_func',
24
+ 'b2bua = sippy.b2bua:main_func',
24
25
  ],
25
26
  },
26
27
 
@@ -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 != None:
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 != None:
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)
@@ -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
- reason = None
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 == None:
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.reason != None:
54
- cself.reason = self.reason.getCopy()
55
- if self.extra_headers != None:
56
- cself.extra_headers = tuple([x.getCopy() for x in self.extra_headers])
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 = CCEventGeneric.getCopy(self)
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 = CCEventGeneric.getCopy(self)
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 = CCEventGeneric.getCopy(self)
115
- if self.challenges != None:
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
@@ -169,7 +169,11 @@ class _CLIManager_w(Thread):
169
169
  self.wbuffer = None
170
170
  self.w_available.release()
171
171
  while True:
172
- res = self.clientsock.send(wbuffer)
172
+ try:
173
+ res = self.clientsock.send(wbuffer)
174
+ except BrokenPipeError:
175
+ self.clim = None
176
+ return
173
177
  if res == len(wbuffer):
174
178
  break
175
179
  if res > 0:
@@ -276,7 +280,7 @@ class CLIManager(object):
276
280
  self.clientsock.shutdown(socket.SHUT_RDWR)
277
281
  except Exception as e:
278
282
  if not isinstance(e, socket.error) or e.errno != ENOTCONN: # pylint: disable=no-member
279
- dump_exception('self.clientsock.shutdown(socket.SHUT_RDWR)')
283
+ dump_exception('CLIManager: unhandled exception in self.clientsock.shutdown(socket.SHUT_RDWR)')
280
284
  self.clientsock.close()
281
285
  self.wthr = None
282
286
  self.rthr = None
@@ -255,8 +255,7 @@ class EventDispatcher2(Singleton):
255
255
  self.bands.insert(0, fb)
256
256
  self.endloop = False
257
257
  self.last_ts = MonoTime()
258
- if timeout != None:
259
- etime = self.last_ts.getOffsetCopy(timeout)
258
+ etime = None if timeout is None else self.last_ts.getOffsetCopy(timeout)
260
259
  while True:
261
260
  if len(self.signals_pending) > 0:
262
261
  self.dispatchSignals()
@@ -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)
@@ -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 SipParseError(Exception):
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, sip_response = None):
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
- if self.sip_response is not None:
49
- return self.sip_response
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):
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2023 Sippy Software, Inc. All rights reserved.
1
+ # Copyright (c) 20012-2023 Sippy Software, Inc. All rights reserved.
2
2
  #
3
3
  # All rights reserved.
4
4
  #
@@ -23,19 +23,16 @@
23
23
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
24
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
25
 
26
- from sippy.Exceptions.SipParseError import SdpParseError
26
+ from .SipHandlingError import SipHandlingError
27
27
 
28
- class RtpProxyError(Exception):
28
+ class SipParseError(SipHandlingError):
29
29
  sip_response = None
30
- arg = None
31
- code = 502
32
- msg = 'Bad Gateway'
33
- def __init__(self, arg):
34
- super().__init__()
35
- self.arg = arg
36
30
 
37
- def getResponse(self, req):
38
- return SdpParseError.getResponse(self, req)
31
+ def __init__(self, arg, sip_response = None):
32
+ super().__init__(arg)
33
+ self.sip_response = sip_response
39
34
 
40
- def getReason(self):
41
- return SdpParseError.getReason(self)
35
+ def getResponse(self, req):
36
+ if self.sip_response is not None:
37
+ return self.sip_response
38
+ return super().getResponse(req)
@@ -69,7 +69,7 @@ class _Worker(Thread):
69
69
  wi.result_callback = None
70
70
  wi.callback_parameters = None
71
71
  continue
72
- batch = [x + b'\n' for x in wi.data]
72
+ batch = [x.encode() + b'\n' for x in wi.data]
73
73
  batch.append(b'\n')
74
74
  pipe.stdin.writelines(batch)
75
75
  pipe.stdin.flush()
@@ -38,7 +38,7 @@ class recfilter(object):
38
38
  b = None
39
39
 
40
40
  def __init__(self, fcoef, initval):
41
- #print 'recfilter::init()'
41
+ #print('recfilter::init()')
42
42
  self.lastval = float(initval)
43
43
  self.a = 1.0 - float(fcoef)
44
44
  self.b = float(fcoef)
@@ -49,5 +49,5 @@ class recfilter(object):
49
49
 
50
50
  class recfilter_ts(local, recfilter):
51
51
  def __init__(self, *args):
52
- #print 'recfilter_ts::init()'
52
+ #print('recfilter_ts::init()')
53
53
  recfilter.__init__(self, *args)
@@ -81,5 +81,5 @@ class MsgBody(object):
81
81
  return MsgBody(self.content)
82
82
  return MsgBody(cself = self)
83
83
 
84
- if not 'MultipartMixBody' in globals():
84
+ if 'MultipartMixBody' not in globals():
85
85
  from sippy.MultipartMixBody import MultipartMixBody
@@ -39,11 +39,22 @@ class MultipartMixBody():
39
39
  assert bparts[-1].strip() == '--'
40
40
  parts = [p.lstrip() for p in bparts[1:-1]]
41
41
  self.parts = []
42
+ self.part_headers = []
42
43
  for sect in parts:
43
- ct, sect = sect.split('\r\n', 1)
44
- ct = SipHeader(ct).getBody()
44
+ headers = []
45
+ ct = None
46
+ headersect, sect = sect.split('\r\n\r\n', 1)
47
+ # parse sub headers
48
+ for hl in headersect.split('\r\n'):
49
+ h = SipHeader(hl)
50
+ if h.name == "content-type":
51
+ ct = h.getBody()
52
+ else:
53
+ headers.append(h)
54
+ # add part
45
55
  sect = MsgBody(sect, ct)
46
56
  self.parts.append(sect)
57
+ self.part_headers.append(headers)
47
58
  self.boundary = ctype.params["boundary"]
48
59
 
49
60
  def __str__(self):
@@ -67,5 +78,5 @@ class MultipartMixBody():
67
78
  cself.boundary = self.boundary
68
79
  return cself
69
80
 
70
- if not 'MsgBody' in globals():
81
+ if 'MsgBody' not in globals():
71
82
  from sippy.MsgBody import MsgBody
@@ -158,7 +158,7 @@ class RadiusAccounting(object):
158
158
  if self.user_agent != None:
159
159
  attributes.append(('h323-ivr-out', 'sip_ua:' + self.user_agent))
160
160
  if self.p1xx_ts != None:
161
- attributes.append(('Acct-Delay-Time', round(self.p1xx_ts)))
161
+ attributes.append(('Acct-Delay-Time', round(self.p1xx_ts.realt)))
162
162
  if self.p100_ts != None:
163
163
  attributes.append(('provisional-timepoint', self.ftime(self.p100_ts.realt)))
164
164
  pattributes = ['%-32s = \'%s\'\n' % (x[0], str(x[1])) for x in attributes]
@@ -68,7 +68,7 @@ class Radius_client(External_command):
68
68
  return
69
69
  nav = []
70
70
  for av in result[:-1]:
71
- a, v = [x.strip() for x in av.split(' = ', 1)]
71
+ a, v = [x.strip() for x in av.decode().split(' = ', 1)]
72
72
  v = v.strip('\'')
73
73
  if (a == 'Cisco-AVPair' or a in self._cisco_vsa_names):
74
74
  t = v.split('=', 1)
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
2
+ # Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without modification,
7
+ # are permitted provided that the following conditions are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation and/or
14
+ # other materials provided with the distribution.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
20
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+ from sippy.Rtp_proxy.Client.stream import Rtp_proxy_client_stream
28
+
29
+ import socket
30
+
31
+ class Rtp_proxy_client_local(Rtp_proxy_client_stream):
32
+ is_local = True
33
+
34
+ def __init__(self, global_config, address = '/var/run/rtpproxy.sock', \
35
+ bind_address = None, nworkers = 1):
36
+ Rtp_proxy_client_stream.__init__(self, global_config = global_config, \
37
+ address = address, bind_address = bind_address, nworkers = nworkers, \
38
+ family = socket.AF_UNIX)
39
+
40
+ if __name__ == '__main__':
41
+ from sippy.Core.EventDispatcher import ED2
42
+ class robj(object):
43
+ rval = None
44
+ r = robj()
45
+ def display(res, ro, arg):
46
+ print(res, arg)
47
+ ro.rval = (res, arg)
48
+ ED2.breakLoop()
49
+ rc = Rtp_proxy_client_local({'_sip_address':'1.2.3.4'})
50
+ rc.send_command('VF 123456', display, r, 'abcd')
51
+ ED2.loop()
52
+ rc.shutdown()
53
+ assert(r.rval == ('0', 'abcd'))
@@ -0,0 +1,42 @@
1
+ # Copyright (c) 2016 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 socket import getaddrinfo, SOCK_DGRAM, AF_INET, AF_INET6
27
+
28
+ class Rtp_proxy_client_net(object):
29
+ sock_type = None # Set me in superclass!
30
+
31
+ def getdestbyaddr(self, address, af):
32
+ #print('getaddrinfo', address[0], address[1], af, self.sock_type)
33
+ if af == AF_INET6 and address[0].startswith('['):
34
+ return address
35
+ ainfo = getaddrinfo(address[0], address[1], af, self.sock_type)
36
+ amatch = [x[4] for x in ainfo if x[0] == af]
37
+ if len(amatch) == 0:
38
+ raise Exception('no match for the %s in AF %s' % (address, af))
39
+ amatch = amatch[0]
40
+ if af == AF_INET6:
41
+ return (('[%s]' % amatch[0], amatch[1]))
42
+ return ((amatch[0], amatch[1]))