Skip to content

Refactor: Remove redundant trait bounds and lifetimes#9

Merged
shenjinti merged 1 commit into
restsend:mainfrom
yeoleobun:patch2
Jul 19, 2025
Merged

Refactor: Remove redundant trait bounds and lifetimes#9
shenjinti merged 1 commit into
restsend:mainfrom
yeoleobun:patch2

Conversation

@yeoleobun

Copy link
Copy Markdown
Collaborator

Summary

Clean up redundant trait bounds and lifetimes throughout the codebase.

What Changed

  • Removed unnecessary Send trait bound and lifetime parameter 'a

Why

  • SynthesisClient is not a mutable object shared between threads
  • text: &'a str is used as part of request parameter or json payload, so it is not captured by request Future

@shenjinti
shenjinti merged commit 871f2fb into restsend:main Jul 19, 2025
1 check failed
@yeoleobun
yeoleobun deleted the patch2 branch August 5, 2025 03:06
yeoleobun pushed a commit to yeoleobun/rustpbx that referenced this pull request Mar 16, 2026
parvbhullar added a commit to parvbhullar/media-gateway that referenced this pull request Apr 16, 2026
…uth correction

- Add GatewayHealthMonitor::tally_snapshot(gateway_id) observability
  helper returning a cloned HealthTally snapshot
- New integration test newly_created_gateway_appears_in_health_tallies_on_next_tick
  POSTs a gateway, drives tick_with_probe with a stub, asserts the
  monitor's tallies map now contains the new gateway id
- Correct 01-02-PLAN.md truth restsend#9: the monitor is DB-polling, there is
  no register_trunk helper — truth text and key_links updated to
  match the actual mechanism
- create_gateway handler is NOT modified; this is a documentation +
  observability fix, not new code
anujarkitekt added a commit to parvbhullar/media-gateway that referenced this pull request May 24, 2026
…apacity, CDR, leak fix, metrics

Six related changes that move the SIP↔WebRTC bridge from
"smoke-tested end-to-end" to "ready for real customers".

1. Codec passthrough on the SIP leg (restsend#1)
- The SIP-side transcoder cap was hardcoded to `AudioCapability::pcmu()`
  regardless of what the carrier offered. Any carrier negotiating
  G.722, PCMA, or Opus-on-SIP would have its audio silently corrupted
  because the bridge would feed packets to a PCMU decoder.
- New `sip_side_audio_offer()` advertises opus, g722, pcmu, pcma on
  the inbound RTP PC. `build_inbound_rtp_pc` now also returns the
  negotiated `AudioCapability` (intersect carrier-offered set with
  our supported set in carrier-preference order — first match wins).
  Rejects with a clear error if the carrier offered nothing we
  support (was previously a silent fall-through to PCMU).
- G.729 deliberately omitted (patent-encumbered; no real
  encoder/decoder in rustrtc's default build).
- `dispatch_webrtc` plumbs the negotiated codec into
  `BridgePeer::setup_bridge_with_codecs` as the RTP-side cap. 4
  tests: PCMA-only, opus-on-SIP, multi-codec carrier preference,
  unsupported-only rejection.

2. DTMF pass-through (RFC 2833 / RFC 4733) — SIP → WebRTC (restsend#2)
- `sip_side_audio_offer()` now also includes
  `AudioCapability::telephone_event()`. WebRTC-side capability list
  in `build_outbound_webrtc_pc` adds telephone-event alongside the
  voice codec.
- The voice-codec intersection logic filters out telephone-event
  (it's signaling, not voice — would crash the transcoder if picked).
  Telephone-event PT is captured separately from the carrier's offer
  and used to install `BridgePeer::set_dtmf_sink(BridgeEndpoint::Rtp,
  dtmf_pt, ...)`. The bridge data plane already had the
  skip-transcoding-for-DTMF check (`media/bridge.rs:1328-1337`); it
  was no-op only because no sink was ever installed. With the sink
  in place, RFC 2833 telephone-event RTP packets flow verbatim from
  the SIP carrier to the WebRTC bot.
- Reverse direction (WebRTC bot → SIP carrier DTMF) is intentionally
  deferred — same sink-install pattern but keyed on the bot's
  negotiated PT from the answer SDP. Defer until needed; most
  use cases are SIP → bot.
- 3 tests: voice-vs-DTMF separation, non-standard DTMF PT respect,
  no-DTMF graceful fallback (carrier didn't offer it → sink not
  installed, debug log notes DTMF is in-band-only).

3. Capacity caps applied to webrtc dispatch (restsend#6)
- `TrunkCapacityState` + `TrunkCapacityGate` were Phase 5/T artifacts
  that had no live caller in the SIP path; the gate was never wired
  to anything. WebRTC dispatch was equally unmetered.
- New `lookup_webrtc_capacity_limits` helper in webrtc_route_dispatch
  reads `max_concurrent` + `max_cps` from the trunk row.
- `dispatch_webrtc_bridge` (call.rs) now consults the gate at the
  start of dispatch:
    * Both limits None → unlimited, skip gate.
    * `CallsExhausted` → 503 + log + CDR.
    * `CpsExhausted` → 503 + log + CDR.
    * `Ok(permit)` → stash on `WebRtcBridgeSession._permit`; RAII Drop
      releases the slot at BYE-time teardown.

4. CDR rows for bridge calls (restsend#5)
- Bridge calls used to be invisible to the CDR pipeline — billing
  and audit blind. New
  `proxy::webrtc_bridge_sessions::emit_bridge_call_record` + the
  `BridgeCallRecordInfo` shape grouping the constructor args.
- `WebRtcBridgeSession` gains 8 CDR fields (call_id, caller_uri,
  callee_uri, from_number, to_number, trunk_name, trunk_id,
  start_time) populated at dispatch time.
- Failure paths in dispatch_webrtc_bridge emit failed-call CDRs
  (capacity exhausted, dispatch error, reply_with failure, missing
  SDP, bad UTF-8, no DB connection). Success path emits the final
  CDR at BYE-time teardown with status_code=200 and
  hangup_reason=ByCaller (or Failed on adapter.close error).
- Reuses existing `CallRecord` schema; bridge calls are tagged via
  `metadata.call_type="webrtc_bridge"` so reports can filter them.
  CDR write failures log warn and never block the call.
- 2 unit tests for the emit helper (completed + failed dispositions).

5. Session-leak fix on dispatch failure (restsend#9)
- Race condition in dispatch_webrtc: after the remote bot accepts
  the offer (signaling adapter returns NegotiateOutcome with a
  SessionHandle), any subsequent failure — SDP parse, set_remote_
  description, audio_capability_for, setup_bridge_with_codecs — would
  return Err without invoking `adapter.close(ctx, &session)`. The
  bot's session leaked until its own idle timeout (often minutes).
  Same problem on the SIP side: `tx.reply_with` failure after the
  bot accepted left the session orphaned.
- Fix: post-negotiate steps in dispatch_webrtc are wrapped in a
  closure that calls `adapter.close()` first on any error, then
  propagates. `DispatchOutcome` now carries the `SignalingContext`
  so the caller (proxy::call) can drive `adapter.close` on its own
  reply_with failure without re-deriving endpoint_url/auth_header
  from the DB.
- Unit test injects a probe adapter that returns garbage answer
  SDP; asserts close fires exactly once with the right session
  handle before the function returns Err.

6. Bridge Prometheus metrics (restsend#8)
- 4 new metrics under the `rustpbx_bridge_*` namespace:
    * `rustpbx_bridge_sessions_active` (gauge) —
      inc on WebRtcBridgeSessions::insert, dec on remove.
    * `rustpbx_bridge_dispatch_total{outcome}` (counter) —
      labels: success / signaling_error / rtp_setup_error /
      reply_error. Outcomes mutually exclusive: success emits from
      call.rs only after reply_with succeeds.
    * `rustpbx_bridge_signaling_latency_seconds{adapter}` (histogram) —
      time spent in `adapter.negotiate`, labeled by adapter name.
    * `rustpbx_bridge_bye_total{outcome}` (counter) — ok /
      teardown_error, emitted from teardown_webrtc_bridge_if_present.
- Uses the same `metrics::` macro API as the rest of the codebase
  (no new deps). Observability addon exposes them at `/metrics`
  Prometheus endpoint once enabled.

cargo check --release: clean.
cargo test --release --lib proxy::bridge::webrtc: 14/14 pass
(11 with this commit, + 3 from the codec passthrough commit that
landed in the previous PR).
cargo test --release --lib proxy::webrtc_bridge_sessions: 3/3.

Open follow-ups (none blocking):
- Bot → SIP DTMF (reverse of restsend#2): symmetric `set_dtmf_sink` on
  BridgeEndpoint::WebRtc keyed on the bot-negotiated telephone-event PT.
- Re-INVITE handling (hold/resume/mid-call codec change): SIP dialog
  state machine extension; needs softphone-driven verification.
- Real-audio end-to-end validation with actual Pipecat (not just the
  mock-offer test server).
shenjinti added a commit that referenced this pull request Jul 15, 2026
refactor: Remove redundant trait bounds and lifetimes
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.

2 participants