Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ assembly is created (see issue #36).
- **Host** exposes **MediaDevices** as the API entry point for capture access.
- A **Caller** sends an SDP offer and a **Callee** returns an SDP answer.

## Flagged ambiguities
## Notes

- "Host" previously meant the signaling initiator peer; resolved to the API root
object. Signaling roles are now **Caller** and **Callee**.
- **Host** is a static API entry point (like Navigator in browsers), not a signaling
role. Do not confuse with **Caller** and **Callee**, which are peer roles.
- **Caller** and **Callee** roles are bound to TCP roles: Caller is the TCP client
(connects first, sends offer); Callee is the TCP server (listens first, answers
offer). This alignment is documented in ADR-0002.
5 changes: 5 additions & 0 deletions docs/adr/0002-caller-callee-tcp-alignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Caller and Callee roles align with TCP connection roles

WebRTC roles (Caller/Callee, defined by offer/answer semantics) will be bound to transport roles (TCP client/server) to avoid confusion in the BasicVideoChat example. The Caller initiates the TCP connection (acts as client) and sends the offer; the Callee listens for the TCP connection (acts as server) and responds with an answer.

We rejected decoupling transport and WebRTC roles because it adds cognitive load without benefit — a single peer cannot simultaneously listen (server) while also creating the offer (Caller) in a direct peer-to-peer TCP model. Binding them simplifies the example and documentation, making it clear to new readers that roles are stable and consistent throughout the session.
18 changes: 9 additions & 9 deletions examples/BasicVideoChat/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public MainWindow()
private bool IsCaller => CallerRadio.IsChecked == true;

private void CallerRadio_Checked(object sender, RoutedEventArgs e) =>
IpBox.IsEnabled = false;
IpBox.IsEnabled = true;

private void CalleeRadio_Checked(object sender, RoutedEventArgs e) =>
IpBox.IsEnabled = true;
IpBox.IsEnabled = false;

private async void ConnectBtn_Click(object sender, RoutedEventArgs e)
{
Expand Down Expand Up @@ -102,10 +102,11 @@ private async Task StartCallAsync()

if (IsCaller)
{
var callerIp = IpBox.Text.Trim();
var port = int.TryParse(PortBox.Text, out var p) ? p : DefaultPort;
SetStatus($"Listening on port {port}...");
await _signaling.ListenAsync(port);
SetStatus("Callee connected. Creating offer...");
SetStatus($"Connecting to {callerIp}:{port}...");
await _signaling.ConnectAsync(callerIp, port);
SetStatus("Connected. Creating offer...");

// Drive the offer explicitly here rather than relying on OnNegotiationNeeded,
// since we control when the signaling channel is ready.
Expand All @@ -116,11 +117,10 @@ private async Task StartCallAsync()
}
else
{
var callerIp = IpBox.Text.Trim();
var port = int.TryParse(PortBox.Text, out var p) ? p : DefaultPort;
SetStatus($"Connecting to {callerIp}:{port}...");
await _signaling.ConnectAsync(callerIp, port);
SetStatus("Connected. Waiting for offer...");
SetStatus($"Listening on port {port}...");
await _signaling.ListenAsync(port);
SetStatus("Caller connected. Waiting for offer...");
}
}

Expand Down
4 changes: 2 additions & 2 deletions examples/BasicVideoChat/Signaling/TcpSignalingChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ namespace BasicVideoChat.Signaling;
/// Minimal TCP signaling channel for peer-to-peer connection setup.
/// </summary>
/// <remarks>
/// One peer calls <see cref="ListenAsync"/> (Host) and the other calls
/// <see cref="ConnectAsync"/> (Guest). Messages are newline-delimited JSON.
/// The Caller calls <see cref="ConnectAsync"/> (TCP client) and the Callee calls
/// <see cref="ListenAsync"/> (TCP server). Messages are newline-delimited JSON.
/// <para>
/// The read loop awaits <see cref="MessageHandler"/> before processing the next message,
/// ensuring that <c>SetRemoteDescription</c> always completes before any
Expand Down
Loading