From ceaabd4fcd7bde7eccd2cb43c97e7917bd19744e Mon Sep 17 00:00:00 2001 From: TJ Porter Date: Fri, 5 Jan 2024 13:38:40 -0600 Subject: [PATCH] [FIX] Fixed circular imports in SIP [FIX] Fixed flake8 errors [FIX] Fixed missed renaming of `register_failures` and `fatal_callback` [REMOVE] Removed import helpers in SIP [REMOVE] Removed some import helperse in VoIP --- pyVoIP/SIP/__init__.py | 15 +++-------- pyVoIP/SIP/client.py | 18 ++++++------- pyVoIP/VoIP/__init__.py | 8 ++---- pyVoIP/VoIP/call.py | 22 ++++++++-------- pyVoIP/VoIP/phone.py | 50 +++++++++++++++++++------------------ pyVoIP/__init__.py | 2 +- pyVoIP/sock/sock.py | 2 +- tests/test_sip_requests.py | 2 +- tests/test_sip_responses.py | 2 +- 9 files changed, 55 insertions(+), 66 deletions(-) diff --git a/pyVoIP/SIP/__init__.py b/pyVoIP/SIP/__init__.py index f4d7caa..a039aa5 100644 --- a/pyVoIP/SIP/__init__.py +++ b/pyVoIP/SIP/__init__.py @@ -3,16 +3,7 @@ from pyVoIP.SIP import message __all__ = [ - "SIPClient", - "SIPMessage", - "SIPMessageType", - "SIPParseError", - "InvalidAccountInfoError", + "error", + "client", + "message", ] - -SIPClient = client.SIPClient -SIPMessage = message.SIPMessage -SIPStatus = message.SIPStatus -SIPMessageType = message.SIPMessageType -InvalidAccountInfoError = error.InvalidAccountInfoError -SIPParseError = error.SIPParseError diff --git a/pyVoIP/SIP/client.py b/pyVoIP/SIP/client.py index 41f93c5..7d17aed 100644 --- a/pyVoIP/SIP/client.py +++ b/pyVoIP/SIP/client.py @@ -721,7 +721,7 @@ def gen_answer( body = "v=0\r\n" # TODO: Check IPv4/IPv6 body += ( - f"o=pyVoIP {sess_id} {int(sess_id)+2} IN IP4 {self.bind_ip}\r\n" + f"o=pyVoIP {sess_id} {int(sess_id) + 2} IN IP4 {self.bind_ip}\r\n" ) body += f"s=pyVoIP {pyVoIP.__version__}\r\n" # TODO: Check IPv4/IPv6 @@ -781,7 +781,7 @@ def gen_invite( # Generate body first for content length body = "v=0\r\n" body += ( - f"o=pyVoIP {sess_id} {int(sess_id)+2} IN IP" + f"o=pyVoIP {sess_id} {int(sess_id) + 2} IN IP" + f"{self.nat.bind_ip.version} {self.bind_ip}\r\n" ) body += f"s=pyVoIP {pyVoIP.__version__}\r\n" @@ -1291,25 +1291,25 @@ def register(self) -> bool: registered = self.__register() if not registered: debug("REGISTERATION FAILED") - self.registerFailures += 1 + self.register_failures += 1 else: self.phone._status = PhoneStatus.REGISTERED - self.registerFailures = 0 + self.register_failures = 0 - if self.registerFailures >= pyVoIP.REGISTER_FAILURE_THRESHOLD: + if self.register_failures >= pyVoIP.REGISTER_FAILURE_THRESHOLD: debug("Too many registration failures, stopping.") self.stop() - self.fatalCallback() + self.fatal_callback() return False self.__start_register_timer() return registered except BaseException as e: debug(f"REGISTERATION ERROR: {e}") - self.registerFailures += 1 - if self.registerFailures >= pyVoIP.REGISTER_FAILURE_THRESHOLD: + self.register_failures += 1 + if self.register_failures >= pyVoIP.REGISTER_FAILURE_THRESHOLD: self.stop() - self.fatalCallback() + self.fatal_callback() return False if isinstance(e, RetryRequiredError): time.sleep(5) diff --git a/pyVoIP/VoIP/__init__.py b/pyVoIP/VoIP/__init__.py index 9fdaba5..8149dde 100644 --- a/pyVoIP/VoIP/__init__.py +++ b/pyVoIP/VoIP/__init__.py @@ -1,10 +1,6 @@ -from pyVoIP.VoIP import status -from pyVoIP.VoIP import call, error, phone +from pyVoIP.VoIP import call, phone, status -InvalidRangeError = error.InvalidRangeError -InvalidStateError = error.InvalidStateError -NoPortsAvailableError = error.NoPortsAvailableError CallState = call.CallState -PhoneStatus = status.PhoneStatus VoIPCall = call.VoIPCall +PhoneStatus = status.PhoneStatus VoIPPhone = phone.VoIPPhone diff --git a/pyVoIP/VoIP/call.py b/pyVoIP/VoIP/call.py index d58bb6f..47bcc8b 100644 --- a/pyVoIP/VoIP/call.py +++ b/pyVoIP/VoIP/call.py @@ -1,5 +1,5 @@ from enum import Enum -from pyVoIP import RTP, SIP +from pyVoIP import RTP from pyVoIP.SIP.error import SIPParseError from pyVoIP.SIP.message import SIPMessage, SIPMessageType, SIPStatus from pyVoIP.VoIP.error import InvalidStateError @@ -116,7 +116,7 @@ def init_outgoing_call(self, ms: Optional[Dict[int, RTP.PayloadType]]): self.port = m self.assignedPorts[m] = self.ms[m] - def init_incoming_call(self, request: SIP.SIPMessage): + def init_incoming_call(self, request: SIPMessage): audio = [] video = [] for x in self.request.body["c"]: @@ -214,7 +214,7 @@ def create_rtp_clients( codecs: Dict[int, RTP.PayloadType], ip: str, port: int, - request: SIP.SIPMessage, + request: SIPMessage, baseport: int, ) -> None: for ii in range(len(request.body["c"])): @@ -260,7 +260,7 @@ def gen_ms(self) -> Dict[int, Dict[int, RTP.PayloadType]]: return m - def renegotiate(self, request: SIP.SIPMessage) -> None: + def renegotiate(self, request: SIPMessage) -> None: m = self.gen_ms() message = self.sip.gen_answer( request, self.session_id, m, self.sendmode @@ -373,7 +373,7 @@ def transfer( return True return False - def rtp_answered(self, request: SIP.SIPMessage) -> None: + def rtp_answered(self, request: SIPMessage) -> None: for i in request.body["m"]: if i["type"] == "video": # Disable Video continue @@ -406,7 +406,7 @@ def rtp_answered(self, request: SIP.SIPMessage) -> None: self.request.headers["Contact"] = request.headers["Contact"] self.request.headers["To"]["tag"] = request.headers["To"]["tag"] - def answered(self, request: SIP.SIPMessage) -> None: + def answered(self, request: SIPMessage) -> None: if self.state == CallState.DIALING: self.rtp_answered(request) elif self.state != CallState.PROGRESS: @@ -415,14 +415,14 @@ def answered(self, request: SIP.SIPMessage) -> None: ack = self.phone.sip.gen_ack(request) self.conn.send(ack) - def progress(self, request: SIP.SIPMessage) -> None: + def progress(self, request: SIPMessage) -> None: if self.state != CallState.DIALING: return self.request = request self.rtp_answered(request) self.state = CallState.PROGRESS - def not_found(self, request: SIP.SIPMessage) -> None: + def not_found(self, request: SIPMessage) -> None: if self.state != CallState.DIALING: debug( "TODO: 500 Error, received a not found response for a " @@ -447,7 +447,7 @@ def not_found(self, request: SIP.SIPMessage) -> None: # also resets all other warnings. warnings.simplefilter("default") - def unavailable(self, request: SIP.SIPMessage) -> None: + def unavailable(self, request: SIPMessage) -> None: if self.state != CallState.DIALING: debug( "TODO: 500 Error, received an unavailable response for a " @@ -471,13 +471,13 @@ def unavailable(self, request: SIP.SIPMessage) -> None: # also resets all other warnings. warnings.simplefilter("default") - def ringing(self, request: SIP.SIPMessage) -> None: + def ringing(self, request: SIPMessage) -> None: if self.state == CallState.RINGING: self.deny() else: self.request = request - def busy(self, request: SIP.SIPMessage) -> None: + def busy(self, request: SIPMessage) -> None: self.bye() def deny(self) -> None: diff --git a/pyVoIP/VoIP/phone.py b/pyVoIP/VoIP/phone.py index b329fa5..4c22f7c 100644 --- a/pyVoIP/VoIP/phone.py +++ b/pyVoIP/VoIP/phone.py @@ -1,5 +1,7 @@ -from pyVoIP import SIP, RTP +from pyVoIP import RTP from pyVoIP.credentials import CredentialsManager +from pyVoIP.SIP.client import SIPClient +from pyVoIP.SIP.message import SIPMessage, SIPStatus from pyVoIP.sock.sock import VoIPConnection from pyVoIP.sock.transport import TransportMode from pyVoIP.types import KEY_PASSWORD @@ -42,7 +44,7 @@ class VoIPPhoneParameter: rtp_port_low: Optional[int] = 10000 rtp_port_high: Optional[int] = 20000 call_class: Type[VoIPCall] = None - sip_class: Type[SIP.SIPClient] = None + sip_class: Type[SIPClient] = None class VoIPPhone: @@ -63,7 +65,7 @@ def __init__(self, voip_phone_parameter: VoIPPhoneParameter): self.sip_class = ( self.voip_phone_parameter.sip_class is not None and self.voip_phone_parameter.sip_class - or SIP.SIPClient + or SIPClient ) # data defined in class self._status = PhoneStatus.INACTIVE @@ -100,10 +102,10 @@ def __init__(self, voip_phone_parameter: VoIPPhoneParameter): ) def callback( - self, conn: VoIPConnection, request: SIP.SIPMessage + self, conn: VoIPConnection, request: SIPMessage ) -> Optional[str]: # debug("Callback: "+request.summary()) - if request.type == pyVoIP.SIP.SIPMessageType.REQUEST: + if request.type == pyVoIP.SIPMessageType.REQUEST: # debug("This is a message") if request.method == "INVITE": self._callback_MSG_Invite(conn, request) @@ -112,19 +114,19 @@ def callback( elif request.method == "OPTIONS": return self._callback_MSG_Options(request) else: - if request.status == SIP.SIPStatus.OK: + if request.status == SIPStatus.OK: self._callback_RESP_OK(request) - elif request.status == SIP.SIPStatus.NOT_FOUND: + elif request.status == SIPStatus.NOT_FOUND: self._callback_RESP_NotFound(request) - elif request.status == SIP.SIPStatus.SERVICE_UNAVAILABLE: + elif request.status == SIPStatus.SERVICE_UNAVAILABLE: self._callback_RESP_Unavailable(request) - elif request.status == SIP.SIPStatus.RINGING: + elif request.status == SIPStatus.RINGING: self._callback_RESP_Ringing(request) - elif request.status == SIP.SIPStatus.SESSION_PROGRESS: + elif request.status == SIPStatus.SESSION_PROGRESS: self._callback_RESP_Progress(request) - elif request.status == SIP.SIPStatus.BUSY_HERE: + elif request.status == SIPStatus.BUSY_HERE: self._callback_RESP_Busy(request) - elif request.status == SIP.SIPStatus.REQUEST_TERMINATED: + elif request.status == SIPStatus.REQUEST_TERMINATED: self._callback_RESP_Terminated(request) return None @@ -132,7 +134,7 @@ def get_status(self) -> PhoneStatus: return self._status def _callback_MSG_Invite( - self, conn: VoIPConnection, request: SIP.SIPMessage + self, conn: VoIPConnection, request: SIPMessage ) -> None: call_id = request.headers["Call-ID"] if self.call_class is None: @@ -162,14 +164,14 @@ def _callback_MSG_Invite( ) raise - def _callback_MSG_Bye(self, request: SIP.SIPMessage) -> None: + def _callback_MSG_Bye(self, request: SIPMessage) -> None: debug("BYE recieved") call_id = request.headers["Call-ID"] if call_id not in self.calls: return self.calls[call_id].bye() - def _callback_MSG_Options(self, request: SIP.SIPMessage) -> str: + def _callback_MSG_Options(self, request: SIPMessage) -> str: debug("Options recieved") response = self.sip.gen_busy(request) if self.call_class: @@ -177,7 +179,7 @@ def _callback_MSG_Options(self, request: SIP.SIPMessage) -> str: # TODO: Remove warning, implement RFC 3264 return response - def _callback_RESP_OK(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_OK(self, request: SIPMessage) -> None: debug("OK received") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -200,7 +202,7 @@ def _callback_RESP_OK(self, request: SIP.SIPMessage) -> None: ), ) - def _callback_RESP_Ringing(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_Ringing(self, request: SIPMessage) -> None: debug("Ringing received") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -208,7 +210,7 @@ def _callback_RESP_Ringing(self, request: SIP.SIPMessage) -> None: return self.calls[call_id].ringing(request) - def _callback_RESP_Progress(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_Progress(self, request: SIPMessage) -> None: debug("Session progress received") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -216,7 +218,7 @@ def _callback_RESP_Progress(self, request: SIP.SIPMessage) -> None: return self.calls[call_id].progress(request) - def _callback_RESP_Busy(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_Busy(self, request: SIPMessage) -> None: debug("Busy received") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -226,7 +228,7 @@ def _callback_RESP_Busy(self, request: SIP.SIPMessage) -> None: ack = self.sip.gen_ack(request) self.sip.sendto(ack) - def _callback_RESP_Terminated(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_Terminated(self, request: SIPMessage) -> None: debug("Request terminated received") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -236,7 +238,7 @@ def _callback_RESP_Terminated(self, request: SIP.SIPMessage) -> None: ack = self.sip.gen_ack(request) self.sip.sendto(ack) - def _callback_RESP_NotFound(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_NotFound(self, request: SIPMessage) -> None: debug("Not Found recieved, invalid number called?") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -250,7 +252,7 @@ def _callback_RESP_NotFound(self, request: SIP.SIPMessage) -> None: ack = self.sip.gen_ack(request) self.sip.sendto(ack) - def _callback_RESP_Unavailable(self, request: SIP.SIPMessage) -> None: + def _callback_RESP_Unavailable(self, request: SIPMessage) -> None: debug("Service Unavailable recieved") call_id = request.headers["Call-ID"] if call_id not in self.calls: @@ -265,7 +267,7 @@ def _callback_RESP_Unavailable(self, request: SIP.SIPMessage) -> None: self.sip.sendto(ack) def _create_call( - self, conn: VoIPConnection, request: SIP.SIPMessage, sess_id: int + self, conn: VoIPConnection, request: SIPMessage, sess_id: int ) -> VoIPCall: """ Create VoIP call object. Should be separated to enable better @@ -353,7 +355,7 @@ def message( self, number: str, body: str, ctype: str = "text/plain" ) -> bool: response = self.sip.message(number, body, ctype) - return response and response.status == SIP.SIPStatus.OK + return response and response.status == SIPStatus.OK def request_port(self, blocking=True) -> int: ports_available = [ diff --git a/pyVoIP/__init__.py b/pyVoIP/__init__.py index eed09fe..ff6720d 100644 --- a/pyVoIP/__init__.py +++ b/pyVoIP/__init__.py @@ -92,7 +92,7 @@ def debug(s, e=None): # noqa because import will fail if debug is not defined from pyVoIP.RTP import PayloadType # noqa: E402 -SIPCompatibleMethods = ["INVITE", "ACK", "BYE", "CANCEL", "OPTIONS"] +SIPCompatibleMethods = ["INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "NOTIFY"] SIPCompatibleVersions = ["SIP/2.0"] RTPCompatibleVersions = [2] diff --git a/pyVoIP/sock/sock.py b/pyVoIP/sock/sock.py index 58ed364..269415e 100644 --- a/pyVoIP/sock/sock.py +++ b/pyVoIP/sock/sock.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, List, Optional, Tuple, Union from pyVoIP.types import KEY_PASSWORD, SOCKETS -from pyVoIP.SIP import SIPMessage, SIPMessageType +from pyVoIP.SIP.message import SIPMessage, SIPMessageType from pyVoIP.SIP.error import SIPParseError from pyVoIP.networking.nat import NAT, AddressType from pyVoIP.sock.transport import TransportMode diff --git a/tests/test_sip_requests.py b/tests/test_sip_requests.py index 490b7c5..176b614 100644 --- a/tests/test_sip_requests.py +++ b/tests/test_sip_requests.py @@ -1,4 +1,4 @@ -from pyVoIP.SIP import SIPMessage +from pyVoIP.SIP.message import SIPMessage import pytest diff --git a/tests/test_sip_responses.py b/tests/test_sip_responses.py index 094aafb..53bde91 100644 --- a/tests/test_sip_responses.py +++ b/tests/test_sip_responses.py @@ -1,4 +1,4 @@ -from pyVoIP.SIP import SIPMessage +from pyVoIP.SIP.message import SIPMessage import pytest