Skip to content

feat(realtime-api): WebRTC relay bridge#733

Open
pallasathena92 wants to merge 1 commit intomainfrom
yifeliu/realtime-webrtc-pr3-bridge
Open

feat(realtime-api): WebRTC relay bridge#733
pallasathena92 wants to merge 1 commit intomainfrom
yifeliu/realtime-webrtc-pr3-bridge

Conversation

@pallasathena92
Copy link
Collaborator

@pallasathena92 pallasathena92 commented Mar 11, 2026

Description

Problem

The WebRTC relay feature needs a core engine that manages dual peer connections (client-facing and upstream-facing), relays RTP audio and data channel messages bidirectionally, and handles ICE/STUN candidate gathering.

Solution

Add WebRtcBridge — a self-contained module that creates two str0m Rtc peers, performs SDP offer/answer exchange with the upstream (OpenAI), and runs a bidirectional relay loop using tokio::select! over two UDP sockets. The
client-facing peer uses ICE-lite; the upstream peer optionally gathers a server-reflexive candidate via a minimal STUN Binding Request (RFC 5389).

Client (browser)
|
[UDP socket 1]
|
client_rtc (ICE-lite, answerer)
|
┌──────────┴──────────┐
│ WebRtcBridge │
│ - data channel relay│
│ - RTP audio relay │
│ - STUN gathering │
└──────────┬──────────┘
|
upstream_rtc (offerer)
|
[UDP socket 2]
|
OpenAI upstream

Changes

  • Cargo.toml (workspace) — Add str0m = { version = "0.16", default-features = false, features = ["openssl"] }.
  • model_gateway/Cargo.toml — Add str0m, multer workspace deps. Add "multipart" to reqwest features.
  • model_gateway/src/routers/openai/realtime/webrtc_bridge.rs — New file — WebRtcBridge with setup(), run(), SDP exchange, RTP forwarding, data channel relay, STUN gathering, buffered pending-to-client queue.
  • model_gateway/src/routers/openai/realtime/mod.rs — Add pub mod webrtc_bridge;. Update module doc.

Test Plan

Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated

Summary by CodeRabbit

  • New Features
    • Added a WebRTC relay bridge for bidirectional real-time connections between clients and upstream servers.
    • Improved OpenAI Realtime protocol support with enhanced peer-connection behavior.
    • Enhanced multipart form-data handling for uploads and richer request processing.

@github-actions github-actions bot added dependencies Dependency updates model-gateway Model gateway crate changes realtime-api Realtime API related changes openai OpenAI router changes labels Mar 11, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a foundational WebRTC relay feature, enabling the system to act as an intermediary for real-time communication. It establishes and manages two distinct WebRTC peer connections—one facing the client and another facing an upstream service like OpenAI. The primary function is to transparently relay both audio streams and data channel messages, ensuring full visibility and control over the real-time traffic flow. This enhancement is crucial for supporting advanced real-time API capabilities.

Highlights

  • New WebRTC Relay Bridge: Introduced a new WebRtcBridge module to manage dual WebRTC peer connections, facilitating a bidirectional relay between a client and an upstream (OpenAI) service.
  • SDP Exchange and Media Relay: Implemented Session Description Protocol (SDP) offer/answer exchange with the upstream, along with bidirectional relay of RTP audio packets and data channel messages.
  • ICE and STUN Handling: The bridge handles ICE candidate gathering, using ICE-lite for the client-facing peer and optionally gathering server-reflexive candidates via STUN Binding Requests for the upstream peer.
  • Dependency Updates: Added the str0m WebRTC stack library and multer for multipart form handling to support the new WebRTC functionality.
Changelog
  • Cargo.toml
    • Added str0m dependency with openssl feature for WebRTC stack.
  • model_gateway/Cargo.toml
    • Updated reqwest dependency to include the multipart feature.
    • Added multer workspace dependency for multipart form handling.
    • Added str0m workspace dependency for WebRTC functionality.
  • model_gateway/src/routers/openai/realtime/mod.rs
    • Added webrtc_bridge module to integrate the new WebRTC relay logic.
    • Updated module documentation to reflect the new WebRTC dual peer-connection relay approach.
  • model_gateway/src/routers/openai/realtime/webrtc_bridge.rs
    • New file implementing the WebRtcBridge struct, which manages client and upstream WebRTC peer connections.
    • Includes logic for SDP offer/answer exchange, RTP audio forwarding, data channel message relay, and STUN candidate gathering.
    • Defines error types for bridge setup and helper functions for logging and IP resolution.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

Adds a new WebRtcBridge module to the OpenAI realtime router that establishes a dual peer-connection relay (client ↔ upstream) with SDP exchange, ICE candidate handling (host/srflx), UDP socket relay, data-channel buffering, and RTP forwarding; also updates workspace dependencies for model_gateway.

Changes

Cohort / File(s) Summary
Workspace root
Cargo.toml
Added workspace dependency str0m = "0.16" with default-features = false and features = ["openssl"].
model_gateway deps
model_gateway/Cargo.toml
Added workspace deps multer, str0m; added "multipart" feature to reqwest.
Realtime router surface
model_gateway/src/routers/openai/realtime/mod.rs
Exported new webrtc_bridge module and updated Realtime API comment to describe dual peer-connection relay.
WebRTC bridge implementation
model_gateway/src/routers/openai/realtime/webrtc_bridge.rs
New comprehensive WebRtcBridge + BridgeSetupError: UDP binding, optional STUN srflx gather, upstream SDP exchange, client/offered RTC creation, data-channel buffering, RTP forwarding, run loop, cancellation handling, and helper utilities (STUN, SDP logging, candidate resolution).

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Bridge as WebRtcBridge
    participant Upstream as UpstreamServer
    participant Registry as RealtimeRegistry

    Client->>Bridge: setup(client SDP offer)
    Bridge->>Bridge: bind dual UDP sockets
    Bridge->>Bridge: optional STUN gather (srflx)
    Bridge->>Upstream: POST SDP offer / multipart
    Upstream-->>Bridge: SDP answer
    Bridge->>Client: return sanitized answer SDP

    Client->>Bridge: run(registry)
    loop Relay loop
        Client->>Bridge: UDP packet (media/data)
        Bridge->>Bridge: feed RTC input / handle events
        Bridge->>Upstream: forward packets / channel data
        Upstream->>Bridge: UDP response / channel data
        Bridge->>Client: forward packets / channel data
        Bridge->>Registry: update connection state
    end

    Client->>Bridge: cancellation
    Bridge-->>Registry: final state update
    Bridge-->>Client: exit
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • CatherineSue
  • key4ng
  • gongwei-130
  • slin1237

Poem

🐰 I bound two sockets, stitched two SDP seams,
I hopped through STUN and forwarded dreams.
Data channels buffered while bytes took flight,
A rabbit-bridge humming through day and night. 🥕🌉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(realtime-api): WebRTC relay bridge' directly and accurately describes the main change: implementing a WebRTC relay bridge for the realtime API.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch yifeliu/realtime-webrtc-pr3-bridge

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a WebRTC relay bridge, a significant new feature. The implementation in webrtc_bridge.rs is comprehensive and well-structured. I've identified a couple of areas for improvement. A high-severity issue is the use of blocking I/O in an async context, which could lead to performance problems. I've also suggested a medium-severity efficiency improvement for the main event loop's timeout handling. Overall, this is a solid implementation of a complex feature.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@model_gateway/src/routers/openai/realtime/webrtc_bridge.rs`:
- Around line 467-475: The relay loop currently swallows UDP send errors when
handling Output::Transmit, so DTLS/SRTP packets are dropped silently; modify the
block that calls self.socket(side).send_to in the Output::Transmit arm to check
the Result, log the error with context (call_id, side via
Self::side_label(side), destination, and length) and then immediately tear down
or close the affected side (use the existing teardown/close/shutdown routine for
the bridge or ICE on this side) instead of ignoring the error; ensure the change
touches the Output::Transmit match arm and uses the same identifiers
(self.socket(side), t.destination, t.contents.len(), Self::side_label, call_id)
so failures are visible and the side is taken down promptly.
- Line 293: The code currently treats upstream_channel (upstream_channel_id) as
usable immediately and caches it after Event::ChannelClose, which causes
client→upstream events to be dropped when self.upstream_rtc.channel(ch_id) is
None; add explicit upstream channel readiness tracking and a small pending
queue: introduce a field (e.g., upstream_channel_state or upstream_channel_ready
plus a VecDeque pending_client_events) and when setting upstream_channel:
Some(upstream_channel_id) do not mark it usable until you receive
Event::ChannelOpen for that id; on client events, if
self.upstream_rtc.channel(ch_id) is None or the readiness flag is false, push
the event into pending_client_events; on Event::ChannelOpen for that id, set
readiness true and flush the queued events to the upstream channel; on
Event::ChannelClose for that id, clear the cached upstream_channel id, set
readiness false, and drop/clear the pending queue so nothing is mistakenly
retained; update all related branches (the ones around upstream_channel usage at
the shown diff and the other ranges noted) to consult the readiness flag and
queue instead of silently dropping events.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9f4fb1c2-fe69-427d-9015-a5cd435f1884

📥 Commits

Reviewing files that changed from the base of the PR and between 2a018d4 and e6a6e46.

📒 Files selected for processing (4)
  • Cargo.toml
  • model_gateway/Cargo.toml
  • model_gateway/src/routers/openai/realtime/mod.rs
  • model_gateway/src/routers/openai/realtime/webrtc_bridge.rs

Signed-off-by: yifeliu <yifengliu9@gmail.com>
@pallasathena92 pallasathena92 force-pushed the yifeliu/realtime-webrtc-pr3-bridge branch from e6a6e46 to 3ea1ba1 Compare March 12, 2026 03:05
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@model_gateway/src/routers/openai/realtime/webrtc_bridge.rs`:
- Line 546: The write calls currently drop errors with "let _ =
ch.write(data.binary, &data.data)" which hides failures; change each occurrence
(the ch.write calls that pass data.binary and &data.data) to check the Result
and log failures at trace level (e.g., if let Err(e) = ch.write(data.binary,
&data.data) { trace!(error = ?e, binary = data.binary, "DataChannel write
failed"); }) so write errors are recorded without noisy logs; apply this pattern
to all similar sites (the ch.write calls around the same code paths).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 934d8ddf-74e0-40bf-9a53-5c174f840e7d

📥 Commits

Reviewing files that changed from the base of the PR and between e6a6e46 and 3ea1ba1.

📒 Files selected for processing (4)
  • Cargo.toml
  • model_gateway/Cargo.toml
  • model_gateway/src/routers/openai/realtime/mod.rs
  • model_gateway/src/routers/openai/realtime/webrtc_bridge.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Dependency updates model-gateway Model gateway crate changes openai OpenAI router changes realtime-api Realtime API related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant