Skip to content

Commit

Permalink
Use SdpParseError, make exception hierarchy more structured.
Browse files Browse the repository at this point in the history
  • Loading branch information
sobomax committed Jan 18, 2025
1 parent d3914f7 commit 66089f7
Show file tree
Hide file tree
Showing 14 changed files with 113 additions and 51 deletions.
15 changes: 2 additions & 13 deletions sippy/Exceptions/RtpProxyError.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from sippy.Exceptions.SipParseError import SdpParseError
from .SipHandlingError import SipHandlingError

class RtpProxyError(Exception):
sip_response = None
arg = None
class RtpProxyError(SipHandlingError):
code = 502
msg = 'Bad Gateway'
def __init__(self, arg):
super().__init__()
self.arg = arg

def getResponse(self, req):
return SdpParseError.getResponse(self, req)

def getReason(self):
return SdpParseError.getReason(self)
33 changes: 33 additions & 0 deletions sippy/Exceptions/SdpParseError.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) 20012-2023 Sippy Software, Inc. All rights reserved.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from .SipHandlingError import SipHandlingError
from .RtpProxyError import RtpProxyError

class SdpParseError(SipHandlingError):
code = 488
msg = 'Not Acceptable Here'

SdpHandlingErrors = (SdpParseError, RtpProxyError)
50 changes: 50 additions & 0 deletions sippy/Exceptions/SipHandlingError.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) 20012-2023 Sippy Software, Inc. All rights reserved.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from sippy.SipReason import SipReason

class SipHandlingError(Exception):
code: int
msg: str
sip_response = None
arg = None

def __init__(self, arg):
super().__init__()
self.arg = arg

def __str__(self):
return str(self.arg)

def getResponse(self, req):
reason = self.getReason()
resp = req.genResponse(self.code, self.msg, ext_reason = reason)
return resp

def getReason(self):
if self.arg is not None and len(self.arg) > 0:
return SipReason(protocol='SIP', cause=self.code,
reason=self.arg)
return None
28 changes: 4 additions & 24 deletions sippy/Exceptions/SipParseError.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,16 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from sippy.SipReason import SipReason
from sippy.SipHeader import SipHeader
from .SipHandlingError import SipHandlingError

class SipParseError(Exception):
class SipParseError(SipHandlingError):
sip_response = None
arg = None

def __init__(self, arg, sip_response = None):
super().__init__()
self.arg = arg
super().__init__(arg)
self.sip_response = sip_response

def __str__(self):
return str(self.arg)

def getResponse(self, req=None):
return self.sip_response

class SdpParseError(SipParseError):
code = 488
msg = 'Not Acceptable Here'
def getResponse(self, req):
if self.sip_response is not None:
return self.sip_response
reason = self.getReason()
resp = req.genResponse(self.code, self.msg, ext_reason = reason)
return resp

def getReason(self):
if self.arg is not None and len(self.arg) > 0:
return SipReason(protocol='SIP', cause=self.code,
reason=self.arg)
return None
return super().getResponse(req)
2 changes: 1 addition & 1 deletion sippy/Rtp_proxy/Session/side.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from sippy.SdpOrigin import SdpOrigin
from sippy.Core.Exceptions import dump_exception
from sippy.Core.EventDispatcher import ED2
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.SdpParseError import SdpParseError
from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Rtp_proxy.Session.update import update_params
from sippy.Rtp_proxy.Session.subcommand import subcommand_dtls, \
Expand Down
2 changes: 1 addition & 1 deletion sippy/Rtp_proxy/Session/subcommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.SdpParseError import SdpParseError

DTLS_TRANSPORTS = ('UDP/TLS/RTP/SAVP', 'UDP/TLS/RTP/SAVPF')
DTLS_ATTRS = ('setup', 'fingerprint', 'rtcp', 'ssrc')
Expand Down
2 changes: 1 addition & 1 deletion sippy/Rtp_proxy/Session/subcommand_ice.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from urllib.parse import unquote

from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.SdpParseError import SdpParseError
from sippy.Rtp_proxy.Session.subcommand import subcommand

ICE_ATTRS = ('ice-ufrag', 'ice-pwd')
Expand Down
5 changes: 3 additions & 2 deletions sippy/SdpBody.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from sippy.SdpGeneric import SdpGeneric
from sippy.SdpOrigin import SdpOrigin
from sippy.SdpConnecton import SdpConnecton
from sippy.Exceptions.SdpParseError import SdpParseError

f_types = {'v':SdpGeneric, 'o':SdpOrigin, 's':SdpGeneric, 'i':SdpGeneric, \
'u':SdpGeneric, 'e':SdpGeneric, 'p':SdpGeneric, 'c':SdpConnecton, \
Expand Down Expand Up @@ -96,11 +97,11 @@ def __init__(self, body = None, cself = None, ctype = None):
# Do some sanity checking, RFC4566
for header_name in [x + '_header' for x in self.top_hdrs_req]:
if getattr(self, header_name) == None:
raise Exception('Mandatory "%s=" session header is missing' % header_name[0])
raise SdpParseError('Mandatory "%s=" session header is missing' % header_name[0])
for section in self.sections:
for header_name in [x + '_header' for x in self.sect_hdrs_req]:
if getattr(section, header_name) == None:
raise Exception('Mandatory "%s=" media header is missing' % header_name[0])
raise SdpParseError('Mandatory "%s=" media header is missing' % header_name[0])

def __str__(self):
s = ''
Expand Down
3 changes: 2 additions & 1 deletion sippy/SipTransactionManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
from sippy.SipAddress import SipAddress
from sippy.SipRoute import SipRoute
from sippy.SipHeader import SipHeader
from sippy.Exceptions.SipParseError import SipParseError, SdpParseError
from sippy.Exceptions.SipParseError import SipParseError
from sippy.Exceptions.SdpParseError import SdpParseError
from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Udp_server import Udp_server, Udp_server_opts
from sippy.Network_server import Remote_address
Expand Down
7 changes: 3 additions & 4 deletions sippy/UA.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
from sippy.MsgBody import MsgBody
from sippy.Time.MonoTime import MonoTime
from sippy.Time.Timeout import TimeoutAbsMono
from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.SdpParseError import SdpHandlingErrors
from sippy.SipConf import SipConf

class UA(object):
Expand Down Expand Up @@ -395,7 +394,7 @@ def getCID(self):

def delayed_remote_sdp_update(self, event, remote_sdp_body, ex=None):
if ex is not None:
if not isinstance(ex, (RtpProxyError, SdpParseError)): raise ex
if not isinstance(ex, SdpHandlingErrors): raise ex
event = CCEventFail((ex.code, ex.msg))
event.reason_rfc3326 = ex.getReason()
else:
Expand All @@ -407,7 +406,7 @@ def delayed_remote_sdp_update(self, event, remote_sdp_body, ex=None):

def delayed_local_sdp_update(self, event, local_sdp_body, ex=None):
if ex is not None:
if not isinstance(ex, (RtpProxyError, SdpParseError)): raise ex
if not isinstance(ex, SdpHandlingErrors): raise ex
event = CCEventFail((ex.code, ex.msg))
event.reason_rfc3326 = ex.getReason()
self.equeue.append(event)
Expand Down
5 changes: 5 additions & 0 deletions sippy/UaStateConnected.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from sippy.SipReferredBy import SipReferredBy
from sippy.SipMaxForwards import SipMaxForwards
from sippy.CCEvents import CCEventDisconnect, CCEventFail, CCEventRedirect, CCEventUpdate, CCEventInfo, CCEventConnect
from sippy.Exceptions.SdpParseError import SdpHandlingErrors

class UaStateConnected(UaStateGeneric):
sname = 'Connected'
Expand Down Expand Up @@ -190,6 +191,10 @@ def recvEvent(self, event):
if body is not None and self.ua.on_local_sdp_change != None and body.needs_update:
try:
self.ua.on_local_sdp_change(body, partial(self.ua.delayed_local_sdp_update, event))
except SdpHandlingErrors as e:
event = CCEventFail((e.code, e.msg), rtime = event.rtime)
event.reason_rfc3326 = e.getReason()
self.ua.equeue.append(event)
except Exception as e:
event = CCEventFail((400, 'Malformed SDP Body'), rtime = event.rtime)
event.setWarning(str(e))
Expand Down
5 changes: 2 additions & 3 deletions sippy/UacStateTrying.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
from sippy.Time.MonoTime import MonoTime
from sippy.CCEvents import CCEventRing, CCEventConnect, CCEventFail, CCEventRedirect, \
CCEventDisconnect, CCEventPreConnect
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.RtpProxyError import RtpProxyError
from sippy.Exceptions.SdpParseError import SdpHandlingErrors

class UacStateTrying(UaStateGeneric):
sname = 'Trying(UAC)'
Expand Down Expand Up @@ -189,7 +188,7 @@ def genBYE(self):
def recvResponse(self, resp, tr):
try:
return self._recvResponse(resp, tr)
except (RtpProxyError, SdpParseError) as ex:
except SdpHandlingErrors as ex:
scode = (ex.code, ex.msg)
event = CCEventFail(scode, rtime = resp.rtime, origin = self.ua.origin)
event.reason_rfc3326 = ex.getReason()
Expand Down
5 changes: 5 additions & 0 deletions sippy/UacStateUpdating.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from sippy.UaStateGeneric import UaStateGeneric
from sippy.CCEvents import CCEventDisconnect, CCEventRing, CCEventConnect, CCEventFail, CCEventRedirect
from sippy.Exceptions.SdpParseError import SdpHandlingErrors

class UacStateUpdating(UaStateGeneric):
sname = 'Updating(UAC)'
Expand Down Expand Up @@ -69,6 +70,10 @@ def recvResponse(self, resp, tr):
cb_func = partial(self.ua.delayed_remote_sdp_update, event)
try:
body = self.ua.on_remote_sdp_change(body, cb_func)
except SdpHandlingErrors as e:
event = CCEventFail((e.code, e.msg), rtime = resp.rtime)
event.reason_rfc3326 = e.getReason()
return self.updateFailed(event)
except Exception as e:
event = CCEventFail((502, 'Bad Gateway'), rtime = resp.rtime)
event.setWarning('Malformed SDP Body received from ' \
Expand Down
2 changes: 1 addition & 1 deletion sippy/b2bua_radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
from sippy.B2BRoute import B2BRoute, SRC_PROXY, SRC_WSS, DST_SIP_UA, DST_WSS_UA
from sippy.Wss_server import Wss_server, Wss_server_opts
from sippy.SipURL import SipURL
from sippy.Exceptions.SipParseError import SdpParseError
from sippy.Exceptions.SdpParseError import SdpParseError

import gc, getopt, os
from re import sub
Expand Down

0 comments on commit 66089f7

Please sign in to comment.