Skip to content

Commit

Permalink
[CHANGE] Began migration from SIPClient.recv to handle_new_connection
Browse files Browse the repository at this point in the history
[CHANGE] Added VoIPConnection to callback in VoIPPhone
[CHANGE] Changed _callback_MSG_Invite to use VoIPConnection instead of creating
         a new dialog
[CHANGE] Changed _create_call to be PEP8 compliant
[CHANGE] Moved TCP/TLS recv and UDP recv code to different functions for better
         readability and maintainability
[FIX] Fixed errors if calling RTP.stop when not started
[FIX] Fixed issue with code not responding to SIP_STATE_DB_LOCATION
[REMOVE] Removed call re-negotiation code as it seemed to not work as intended
  • Loading branch information
tayler6000 committed Nov 27, 2023
1 parent 9fed4a0 commit 0902757
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 110 deletions.
8 changes: 6 additions & 2 deletions pyVoIP/RTP.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,12 @@ def start(self) -> None:

def stop(self) -> None:
self.NSD = False
self.sin.close()
self.sout.close()
if hasattr(self, "sin"):
if self.sin:
self.sin.close()
if hasattr(self, "sout"):
if self.sout:
self.sout.close()

def read(self, length: int = 160, blocking: bool = True) -> bytes:
if not blocking:
Expand Down
26 changes: 18 additions & 8 deletions pyVoIP/SIP/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ def __init__(
hostname: Optional[str] = None,
remote_hostname: Optional[str] = None,
bind_port=5060,
call_callback: Optional[Callable[[SIPMessage], Optional[str]]] = None,
call_callback: Optional[
Callable[["VoIPConnection", SIPMessage], Optional[str]]
] = None,
transport_mode: TransportMode = TransportMode.UDP,
cert_file: Optional[str] = None,
key_file: Optional[str] = None,
Expand Down Expand Up @@ -120,6 +122,20 @@ def recv(self) -> None:
if pyVoIP.DEBUG:
raise

def handle_new_connection(self, conn: "VoIPConnection") -> None:
message = SIPMessage(conn.peak())
if message.type == SIPMessageType.REQUEST:
if message.method == "INVITE":
self._handle_invite(conn)

def _handle_invite(self, conn: "VoIPConnection") -> None:
message = SIPMessage(conn.peak())
if self.call_callback is None:
request = self.gen_busy(message)
conn.send(request)
else:
self.call_callback(conn, message)

def parse_message(self, message: SIPMessage) -> None:
if message.type != SIPMessageType.REQUEST:
if message.status in (
Expand All @@ -143,12 +159,6 @@ def parse_message(self, message: SIPMessage) -> None:
"TODO: Add 500 Error on Receiving SIP Response",
)
return
elif message.method == "INVITE":
if self.call_callback is None:
request = self.gen_busy(message)
self.sendto(request, message.headers["Via"]["address"])
else:
self.call_callback(message)
elif message.method == "BYE":
# TODO: If callCallback is None, the call doesn't exist, 481
if self.call_callback:
Expand Down Expand Up @@ -192,7 +202,7 @@ def start(self) -> None:
self.transport_mode,
self.bind_ip,
self.bind_port,
self.nat,
self,
self.cert_file,
self.key_file,
self.key_password,
Expand Down
37 changes: 16 additions & 21 deletions pyVoIP/VoIP/phone.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from enum import Enum
from pyVoIP import SIP, RTP
from pyVoIP.credentials import CredentialsManager
from pyVoIP.sock.sock import VoIPConnection
from pyVoIP.sock.transport import TransportMode
from pyVoIP.types import KEY_PASSWORD
from pyVoIP.VoIP.call import CallState, VoIPCall
Expand Down Expand Up @@ -101,12 +102,14 @@ def __init__(
transport_mode=self.transport_mode,
)

def callback(self, request: SIP.SIPMessage) -> Optional[str]:
def callback(
self, conn: VoIPConnection, request: SIP.SIPMessage
) -> Optional[str]:
# debug("Callback: "+request.summary())
if request.type == pyVoIP.SIP.SIPMessageType.REQUEST:
# debug("This is a message")
if request.method == "INVITE":
self._callback_MSG_Invite(request)
self._callback_MSG_Invite(conn, request)
elif request.method == "BYE":
self._callback_MSG_Bye(request)
elif request.method == "OPTIONS":
Expand All @@ -131,23 +134,13 @@ def callback(self, request: SIP.SIPMessage) -> Optional[str]:
def get_status(self) -> PhoneStatus:
return self._status

def _callback_MSG_Invite(self, request: SIP.SIPMessage) -> None:
def _callback_MSG_Invite(
self, conn: VoIPConnection, request: SIP.SIPMessage
) -> None:
call_id = request.headers["Call-ID"]
if call_id in self.calls:
debug("Re-negotiation detected!")
# TODO: this seems "dangerous" if for some reason sip server
# handles 2 and more bindings it will cause duplicate RTP-Clients
# to spawn.

# CallState.Ringing seems important here to prevent multiple
# answering and RTP-Client spawning. Find out when renegotiation
# is relevant.
if self.calls[call_id].state != CallState.RINGING:
self.calls[call_id].renegotiate(request)
return # Raise Error
if self.callClass is None:
message = self.sip.gen_busy(request)
self.sip.sendto(message, request.headers["Via"][0]["address"])
conn.send(message)
else:
debug("New call!")
sess_id = None
Expand All @@ -157,8 +150,8 @@ def _callback_MSG_Invite(self, request: SIP.SIPMessage) -> None:
self.session_ids.append(proposed)
sess_id = proposed
message = self.sip.gen_ringing(request)
self.sip.sendto(message, request.headers["Via"][0]["address"])
call = self._create_Call(request, sess_id)
conn.send(message)
call = self._create_call(conn, request, sess_id)
try:
t = Timer(1, call.ringing, [request])
t.name = f"Phone Call: {call_id}"
Expand All @@ -167,9 +160,8 @@ def _callback_MSG_Invite(self, request: SIP.SIPMessage) -> None:
self.threadLookup[t] = call_id
except Exception:
message = self.sip.gen_busy(request)
self.sip.sendto(
conn.send(
message,
request.headers["Via"][0]["address"],
)
raise

Expand Down Expand Up @@ -275,7 +267,9 @@ def _callback_RESP_Unavailable(self, request: SIP.SIPMessage) -> None:
ack = self.sip.gen_ack(request)
self.sip.sendto(ack)

def _create_Call(self, request: SIP.SIPMessage, sess_id: int) -> VoIPCall:
def _create_call(
self, conn: VoIPConnection, request: SIP.SIPMessage, sess_id: int
) -> VoIPCall:
"""
Create VoIP call object. Should be separated to enable better
subclassing.
Expand All @@ -287,6 +281,7 @@ def _create_Call(self, request: SIP.SIPMessage, sess_id: int) -> VoIPCall:
request,
sess_id,
self.bind_ip,
conn=conn,
sendmode=self.recvmode,
)
return self.calls[call_id]
Expand Down
Loading

0 comments on commit 0902757

Please sign in to comment.