Skip to content

RFC 3261: distinguish outbound proxy from registrar + AOR-based CLI#23

Merged
codingjoe merged 4 commits intotranscribe-callfrom
copilot/sub-pr-8-again
Mar 13, 2026
Merged

RFC 3261: distinguish outbound proxy from registrar + AOR-based CLI#23
codingjoe merged 4 commits intotranscribe-callfrom
copilot/sub-pr-8-again

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 13, 2026

RFC 3261 §8.1.2 separates the outbound proxy (the server a UA physically connects to) from the registrar (§10, whose URI is derived from the AOR domain). These can differ — e.g. proxy.carrier.com as the TLS endpoint while carrier.com is the registrar domain.

Changes

Protocol (voip/sip/protocol.py)

  • SessionInitiationProtocol: renamed server_addressoutbound_proxy (tuple[str, int] | None, default None); optional because the UA may connect directly to the registrar with no explicit proxy configured
  • Class docstring: added RFC 3261 topology overview explaining the outbound proxy / registrar / AOR distinction and when they differ
  • register(): docstring and debug logging now explicitly distinguish proxy from registrar ("Sending REGISTER via outbound proxy … to registrar …")
# Proxy and registrar on the same host (most common)
SIP(aor="sips:[email protected]", username="alice", ******)

# Proxy differs from the registrar domain
SIP(
    aor="sips:[email protected]",        # registrar → sips:carrier.com
    outbound_proxy=("proxy.carrier.com", 5061),
    username="alice",
    ******,
)

CLI (voip/__main__.py)

The transcribe command now takes the AOR as a positional argument. All connection parameters are derived from it by default; individual pieces can be overridden:

voip sip transcribe sips:[email protected] --password secret
voip sip transcribe sip:[email protected]:5060 --password secret
voip sip transcribe sips:[email protected] --proxy proxy.carrier.com --password secret
  • _parse_aor(): new helper that extracts (scheme, user, host, port) from a SIP URI
  • Transport auto-detection from port: port 5060 → plain TCP; any other port → TLS. --no-tls still overrides explicitly.
  • sip: scheme defaults to port 5060 (plain TCP); sips: defaults to port 5061 (TLS).
  • --username: optional override for the user part from the AOR
  • --proxy HOST[:PORT]: optional override for the outbound proxy address when it differs from the registrar domain in the AOR
  • SIP_TCP_PORT = 5060 / SIP_TLS_PORT = 5061: named constants replacing magic numbers

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…ance

RFC 3261 §8.1.2 distinguishes between the outbound proxy (the server a
UA sends all requests to) and the registrar (whose domain is derived from
the AOR per §10). The two can differ — e.g. proxy.carrier.com vs carrier.com.

- Rename `server_address` → `outbound_proxy` (optional, default None)
- Update class docstring with RFC 3261 UAC topology overview
- Update `register()` docstring/logging to log proxy vs registrar
- Update CLI --server/--aor help text to use RFC 3261 terminology
- Update all test references accordingly

Co-authored-by: codingjoe <[email protected]>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

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:

  • stun.cloudflare.com
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest tests/sip/test_protocol.py -x --no-header -q -p no:cacheprovider --override-ini=addopts= (dns block)
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest tests/sip/test_protocol.py tests/test_main.py -x --no-header -q --override-ini=addopts= p/bin/git (dns block)
    • Triggering command: /home/REDACTED/.local/bin/pytest pytest tests/ -x --no-header -q --override-ini=addopts= (dns block)

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 RFC 3261: distinguish outbound proxy from registrar Mar 13, 2026
Copilot AI requested a review from codingjoe March 13, 2026 16:53
Copy link
Copy Markdown
Owner

@codingjoe codingjoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot let's change the CLI and protocol. We provide the aor by as a position argument to the CLI, like sip:[email protected]:port and by default parse all information (except for the PW from it). However, username, the proxy domain, the realm, protocol (sip/sips) can be separately overwritten.

We default to port 5061/tls. If port 5060 is given we we establish TCP transport w/o ssl. Over the transport type can still be overriden via the cli.

- Add `_parse_aor()` to extract (scheme, user, host, port) from a SIP URI
- Replace `--server` + `--aor` + `--username` options with positional AOR
  argument (e.g. sips:[email protected] or sip:[email protected]:5060)
- Auto-detect transport from port: 5060 → plain TCP, anything else → TLS
  (--no-tls still overrides)
- Add `--username` option to override user part from AOR
- Add `--proxy HOST[:PORT]` option to override outbound proxy address when it
  differs from the registrar domain in the AOR
- Extract SIP_TCP_PORT=5060 / SIP_TLS_PORT=5061 named constants
- Update README CLI example and Python API example
- Rewrite tests in test_main.py to cover new positional AOR interface

Co-authored-by: codingjoe <[email protected]>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

@copilot let's change the CLI and protocol. We provide the aor by as a position argument to the CLI, like sip:[email protected]:port and by default parse all information (except for the PW from it)....

Done in commit 9af9dca. The transcribe command now takes the AOR as a positional argument:

voip sip transcribe sips:[email protected] --password secret
voip sip transcribe sip:[email protected]:5060 --password secret
voip sip transcribe sips:[email protected] --proxy proxy.carrier.com --password secret

Behaviour:

  • All info parsed from AOR by default (except password): scheme, username, host, port
  • Port determines transport: port 5060 → plain TCP; anything else → TLS. --no-tls still overrides.
  • sip: scheme defaults to port 5060 (plain TCP); sips: defaults to port 5061 (TLS).
  • --username overrides the user part from the AOR.
  • --proxy HOST[:PORT] overrides the outbound proxy address when it differs from the registrar domain in the AOR.
  • Port constants extracted as SIP_TCP_PORT = 5060 / SIP_TLS_PORT = 5061.

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:

  • stun.cloudflare.com
    • Triggering command: /usr/bin/python python -m pytest tests/ -x --no-header -q --override-ini=addopts= (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title RFC 3261: distinguish outbound proxy from registrar RFC 3261: distinguish outbound proxy from registrar + AOR-based CLI Mar 13, 2026
Copilot AI requested a review from codingjoe March 13, 2026 18:05
@codingjoe
Copy link
Copy Markdown
Owner

pre-commit.ci run

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 13, 2026

Codecov Report

❌ Patch coverage is 93.02326% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.62%. Comparing base (e837249) to head (b4d4f41).
⚠️ Report is 1 commits behind head on transcribe-call.

Files with missing lines Patch % Lines
voip/__main__.py 94.87% 2 Missing ⚠️
voip/sip/protocol.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##           transcribe-call      #23      +/-   ##
===================================================
- Coverage            94.74%   94.62%   -0.13%     
===================================================
  Files                   16       16              
  Lines                 1276     1303      +27     
===================================================
+ Hits                  1209     1233      +24     
- Misses                  67       70       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codingjoe codingjoe marked this pull request as ready for review March 13, 2026 18:15
Copilot AI review requested due to automatic review settings March 13, 2026 18:15
@codingjoe codingjoe merged commit 0ea2f31 into transcribe-call Mar 13, 2026
15 of 18 checks passed
@codingjoe codingjoe deleted the copilot/sub-pr-8-again branch March 13, 2026 18:15
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements RFC 3261 §8.1.2 by distinguishing the outbound proxy from the registrar in the SIP protocol layer, and reworks the CLI to accept the AOR (Address of Record) as a positional argument from which connection parameters are derived automatically.

Changes:

  • Renamed server_addressoutbound_proxy (now optional, defaults to None) in SessionInitiationProtocol, with updated docstrings explaining the RFC 3261 outbound proxy / registrar distinction.
  • Reworked the transcribe CLI command to take the AOR as a positional argument, with _parse_aor() helper for URI parsing and scheme-based transport auto-detection (sip: → TCP/5060, sips: → TLS/5061).
  • Updated all tests and README documentation to reflect the new API surface.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
voip/sip/protocol.py Renamed server_addressoutbound_proxy (optional), added RFC 3261 topology docstring, improved register() logging to distinguish proxy from registrar.
voip/__main__.py AOR positional argument, _parse_aor() helper, _parse_hostport() rename, scheme-based transport auto-detection, named port constants.
tests/test_main.py Comprehensive new tests for _parse_aor, _parse_hostport, and all CLI transport/proxy/AOR behaviors.
tests/sip/test_protocol.py Mechanical rename of server_address=outbound_proxy= across all test instantiations.
README.md Updated CLI example and Python API example to use the new interface.

You can also share your feedback on Copilot code review. Take the survey.

"""
scheme, _, rest = value.partition(":")
if not scheme or not rest:
raise click.BadParameter(f"Invalid SIP URI: {value!r}. Expected sip[s]:user@host[:port].")
host, _, port_str = hostport.partition(":")
if not host:
raise click.BadParameter(f"Invalid SIP URI: {value!r}. Missing host.")
port: int | None = int(port_str) if port_str else None
Comment on lines +216 to +220
if proxy is not None:
proxy_addr = _parse_hostport(ctx, None, proxy)
else:
# Default port: SIP_TCP_PORT for sip scheme, SIP_TLS_PORT for sips.
default_port = SIP_TCP_PORT if scheme == "sip" else SIP_TLS_PORT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants