Skip to content

Commit 6ff7186

Browse files
committed
fix: update Route header handling in established dialogs
1 parent 439cab1 commit 6ff7186

3 files changed

Lines changed: 23 additions & 7 deletions

File tree

PySIP/sip_call.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -457,15 +457,16 @@ def construct_invite_message(
457457
def ack_generator(self, transaction):
458458
_, port = self.sip_core.get_extra_info("sockname")
459459
ip = self.my_public_ip
460+
request_uri = self.dialogue.remote_contact_uri or f"sip:{self.callee}@{self.server}:{self.port};transport={self.CTS}"
460461

461-
msg = f"ACK sip:{self.callee}@{self.server}:{self.port};transport={self.CTS} SIP/2.0\r\n"
462+
msg = f"ACK {request_uri} SIP/2.0\r\n"
462463
msg += f"Via: SIP/2.0/{self.CTS} {ip}:{port};rport;branch={transaction.branch_id};alias\r\n"
463464
msg += "Max-Forwards: 70\r\n"
464465
msg += f"From: sip:{self.caller_id}@{self.server};tag={self.dialogue.local_tag}\r\n"
465466
msg += f"To: sip:{self.callee}@{self.server};tag={self.dialogue.remote_tag}\r\n"
466467
msg += f"Call-ID: {self.call_id}\r\n"
467468
msg += f"CSeq: {transaction.cseq} ACK\r\n"
468-
msg += f"Route: <sip:{self.server}:{self.port};transport={self.CTS};lr>\r\n"
469+
msg += f"Route: <{request_uri};lr>\r\n"
469470
msg += "Content-Length: 0\r\n\r\n"
470471

471472
return msg
@@ -476,18 +477,20 @@ def bye_generator(self):
476477

477478
branch_id = self.sip_core.gen_branch()
478479
transaction = self.dialogue.add_transaction(branch_id, "BYE")
480+
request_uri = self.dialogue.remote_contact_uri or f"sip:{self.callee}@{peer_ip}:{peer_port};transport={self.CTS}"
479481

480-
msg = f"BYE sip:{self.callee}@{peer_ip}:{peer_port};transport={self.CTS} SIP/2.0\r\n"
482+
msg = f"BYE {request_uri} SIP/2.0\r\n"
481483
msg += (
482484
f"Via: SIP/2.0/{self.CTS} {self.my_public_ip}:{port};rport;"
483485
+ f"branch={branch_id};alias\r\n"
484486
)
485-
msg += 'Reason: Q.850;cause=16;text="normal call clearing"'
487+
msg += 'Reason: Q.850;cause=16;text="normal call clearing"\r\n'
486488
msg += "Max-Forwards: 70\r\n"
487489
msg += f"From: sip:{self.caller_id}@{self.server};tag={self.dialogue.local_tag}\r\n"
488490
msg += f"To: sip:{self.callee}@{self.server};tag={self.dialogue.remote_tag}\r\n"
489491
msg += f"Call-ID: {self.call_id}\r\n"
490492
msg += f"CSeq: {transaction.cseq} BYE\r\n"
493+
msg += f"Route: <{request_uri};lr>\r\n"
491494
msg += "Content-Length: 0\r\n\r\n"
492495

493496
return msg
@@ -500,8 +503,9 @@ def refer_generator(self, refer_to_callee):
500503
transaction = self.dialogue.add_transaction(branch_id, "REFER")
501504
refer_to = f"sip:{refer_to_callee}@{self.server};transport={self.CTS}"
502505
referred_by = f"sip:{self.caller_id}@{self.server}"
506+
request_uri= self.dialogue.remote_contact_uri or f"sip:{self.callee}@{self.server}:{self.port};transport={self.CTS}"
503507

504-
msg = f"REFER sip:{self.callee}@{self.server}:{self.port};transport={self.CTS} sip/2.0\r\n"
508+
msg = f"REFER {request_uri} sip/2.0\r\n"
505509
msg += f"Via: sip/2.0/{self.CTS} {ip}:{port};rport;branch={branch_id};alias\r\n"
506510
msg += "Max-Forwards: 70\r\n"
507511
msg += f"From: sip:{self.caller_id}@{self.server};tag={self.dialogue.local_tag}\r\n"
@@ -511,6 +515,7 @@ def refer_generator(self, refer_to_callee):
511515
msg += f"Refer-To: {refer_to}\r\n"
512516
msg += f"Referred-By: {referred_by}\r\n"
513517
msg += f"Contact: <sip:{self.username}@{ip}:{port};transport={self.CTS}>\r\n"
518+
msg += f"Route: <{request_uri};lr>\r\n"
514519
msg += "Content-Length: 0\r\n\r\n"
515520

516521
return msg
@@ -668,10 +673,10 @@ async def message_handler(self, msg: SipMessage):
668673
transaction = self.dialogue.add_transaction(
669674
self.sip_core.gen_branch(), "ACK"
670675
)
676+
self.dialogue.update_state(msg)
671677
ack_message = self.ack_generator(transaction)
672678
self.dialogue.auth_retry_count = 0 # reset the auth counter
673679
await self.sip_core.send(ack_message)
674-
self.dialogue.update_state(msg)
675680
await self.update_call_state(CallState.ANSWERED)
676681
return
677682

PySIP/sip_core.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ def __init__(self, call_id, local_tag, remote_tag) -> None:
420420
self.auth_retry_count = 0
421421
self._local_session_info: Optional[SDPParser] = None
422422
self._remote_session_info: Optional[SDPParser] = None
423+
self.remote_contact_uri: Optional[str] = None
423424

424425
def matches(self, call_id, local_tag, remote_tag):
425426
# We now check if the provided identifiers match this dialogue's identifiers
@@ -449,6 +450,7 @@ def find_transaction(self, branch_id):
449450
def update_state(self, message):
450451
# This method should be called with each message received/sent that pertains to this dialog
451452
self.previous_state = self.state
453+
452454
is_provisional_response = (str(message.status).startswith("18")) and (
453455
message.method == "INVITE"
454456
)
@@ -468,11 +470,12 @@ def update_state(self, message):
468470
self._remote_session_info = SDPParser(message.body)
469471

470472
elif (
471-
self.state in [DialogState.INITIAL, DialogState.EARLY] and is_final_response
473+
self.state in [DialogState.PREDIALOG, DialogState.INITIAL, DialogState.EARLY] and is_final_response
472474
):
473475
self.state = DialogState.CONFIRMED
474476
if message.body is not None:
475477
self._remote_session_info = SDPParser(message.body)
478+
self.update_remote_contact(message.get_header("Contact"))
476479
elif message.method == "BYE" and message.status is SIPStatus.OK:
477480
self.state = DialogState.TERMINATED
478481
elif message.status == SIPStatus(487) and message.method == "INVITE":
@@ -483,6 +486,13 @@ def update_state(self, message):
483486
if self.state != self.previous_state:
484487
logger.log(logging.DEBUG, f"Dialog state changed to -> {self.state}")
485488

489+
def update_remote_contact(self, contact_header: str) -> None:
490+
if contact_header:
491+
match = re.search(r'<(.+?)>', contact_header)
492+
if match:
493+
self.remote_contact_uri = match.group(1)
494+
logger.debug(f"Updated remote contact URI: {self.remote_contact_uri}")
495+
486496
@property
487497
def local_session_info(self):
488498
return self._local_session_info

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ pydub>=0.25.1
22
requests>=2.25.1
33
edge-tts>=5.0.0
44
python-dotenv>=0.19.0
5+
scipy

0 commit comments

Comments
 (0)