Address review comments: SRTP ROC tracking, RTP address selection, protocol hardening#24
Merged
codingjoe merged 2 commits intotranscribe-callfrom Mar 13, 2026
Merged
Conversation
…ion, STUN docstring, WhisperModel injection, README cleanup Co-authored-by: codingjoe <[email protected]>
Contributor
Author
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Copilot
AI
changed the title
[WIP] Implement call transcription
Address review comments: SRTP ROC tracking, RTP address selection, protocol hardening
Mar 13, 2026
There was a problem hiding this comment.
Pull request overview
This PR hardens core VoIP call handling by refining SRTP rollover/index tracking, improving SIP call-answer robustness and SDP-derived RTP routing decisions, and aligning docs/tests with actual runtime behavior.
Changes:
- SRTP: split send/receive ROC tracking, implement RFC 3711 receive index estimation, and use constant-time auth-tag comparison.
- SIP: add early-INVITE initialization guard, improve remote RTP address selection per RFC 4566 (including inactive port 0), and remove the non-existent
asyncio.Protocol.error_received. - Audio/docs/tests: allow injecting a pre-loaded
WhisperModel, update docstrings/tests/logging text, and adjust README claims.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
voip/stun.py |
Updates STUNProtocol docstring to reflect current callback-based readiness API. |
voip/srtp.py |
Refactors ROC tracking, adds receive index estimation, and hardens auth-tag comparison. |
voip/sip/protocol.py |
Stores initialization task, guards early INVITEs, improves RTP address selection, removes error_received. |
voip/rtp.py |
Updates docstring to match WARNING-level logging on SRTP auth failure. |
voip/audio.py |
Allows WhisperModel instance injection for shared model reuse across calls. |
tests/test_rtp.py |
Updates SRTP invalid-auth test description to match warning log behavior. |
tests/sip/test_protocol.py |
Removes tests for error_received after method removal. |
README.md |
Removes a claim about unencrypted SIP/RTP not being supported. |
You can also share your feedback on Copilot code review. Take the survey.
| # early INVITE must wait for the mux. Skip if already available. | ||
| if self._rtp_protocol is None: | ||
| if self._initialize_task is not None: | ||
| await self._initialize_task |
Comment on lines
+586
to
+590
| if remote_audio is not None and remote_audio.port != 0: | ||
| media_conn = remote_audio.connection | ||
| session_conn = request.body.connection if request.body else None | ||
| conn = media_conn or session_conn | ||
| if conn is not None: |
Comment on lines
+134
to
+138
| def _estimate_recv_index(self, seq: int) -> tuple[int, int]: | ||
| """Estimate the packet index and new ROC for a received sequence number. | ||
|
|
||
| Implements the index estimation algorithm from RFC 3711 §3.3.1. | ||
|
|
Comment on lines
21
to
+24
| All signalling uses **SIP over TLS** (SIPS, RFC 3261 §26) and all media is | ||
| protected with **SRTP** ([RFC 3711](https://tools.ietf.org/html/rfc3711)) | ||
| using the `AES_CM_128_HMAC_SHA1_80` cipher suite with SDES key exchange | ||
| ([RFC 4568](https://tools.ietf.org/html/rfc4568)). Unencrypted SIP or RTP | ||
| is not supported. | ||
| ([RFC 4568](https://tools.ietf.org/html/rfc4568)). |
Comment on lines
170
to
174
| try: | ||
| asyncio.get_running_loop().create_task(self._initialize()) | ||
| self._initialize_task = asyncio.get_running_loop().create_task( | ||
| self._initialize() | ||
| ) | ||
| except RuntimeError: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses all unresolved review comments from the call transcription PR series.
SRTP (
voip/srtp.py)_send_roc/_last_send_seqfor encryption,_recv_roc/_last_recv_seqfor decryption, per RFC 3711 §3.3.1_estimate_recv_index()implements the RFC 3711 §3.3.1 algorithm (plain arithmetic comparisons, not modular)!=withhmac.compare_digest(stdlib) to prevent timing side-channelsSIP Protocol (
voip/sip/protocol.py)c=→ session-levelc=→ SIP peer IP (per RFC 4566 §5.7); port 0 (inactive media, RFC 4566 §5.14) skips registration and NAT hole-punching_initialize_taskstored onconnection_made;_answer()awaits it only when_rtp_protocolis stillNone, preventing attribute errors without breaking testserror_received—asyncio.Protocolhas no such callback (it belongs toDatagramProtocol); removed method and its testsAudio (
voip/audio.py)WhisperModelinjection —WhisperCall.modelnow accepts a pre-loadedWhisperModelinstance in addition to a name string, enabling sharing across concurrent calls:Docs / minor
public_address(attribute no longer exists onSTUNProtocol)✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.