SpawnDev.RTC.Server 1.0.7

dotnet add package SpawnDev.RTC.Server --version 1.0.7
                    
NuGet\Install-Package SpawnDev.RTC.Server -Version 1.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SpawnDev.RTC.Server" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SpawnDev.RTC.Server" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="SpawnDev.RTC.Server" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SpawnDev.RTC.Server --version 1.0.7
                    
#r "nuget: SpawnDev.RTC.Server, 1.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SpawnDev.RTC.Server@1.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SpawnDev.RTC.Server&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=SpawnDev.RTC.Server&version=1.0.7
                    
Install as a Cake Tool

SpawnDev.RTC.Server

NuGet License: MIT

WebRTC signaling server for SpawnDev.RTC consumers. Hosts the WebTorrent tracker wire protocol so any ASP.NET Core app can run a room-based signaling endpoint with a single app.UseRtcSignaling("/announce") call. Bundles an embedded RFC 5766 STUN/TURN server that can run alongside on the same host.

For the client library see SpawnDev.RTC.

What this gives you

Three composable pieces, all opt-in:

Piece Method Purpose
Signaling tracker app.UseRtcSignaling("/announce") WebSocket endpoint that brokers WebRTC offer/answer between peers. Bit-compatible with the public WebTorrent tracker fleet — your clients (using SpawnDev.RTC, JS WebTorrent, libtorrent v2 with WSS, etc.) just point at your URL instead of wss://tracker.openwebtorrent.com.
STUN/TURN server builder.Services.AddRtcStunTurn(opts => ...) Full RFC 5766 TURN with classic long-term creds OR ephemeral HMAC creds (RFC 8489 §9.2 / TURN REST API pattern). Optionally tracker-gated so only currently-announced peers can allocate. Replaces coturn for SpawnDev-style deployments.
Origin allowlist property on the signaling-server options Browser-side abuse protection: only origins on the allowlist can open a signaling WebSocket. Non-browser clients (desktop C#, curl, Node.js ws) bypass the check automatically because they don't send an Origin header.

Install

<PackageReference Include="SpawnDev.RTC.Server" Version="1.0.5" />

Or run the standalone host directly: SpawnDev.RTC.ServerApp — single executable, Docker image, env-var configurable. Both the library and the app share the same internals; pick whichever suits your deployment.

Quickstart — embedded signaling

using SpawnDev.RTC.Server.Extensions;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWebSockets();
app.UseRtcSignaling("/announce");   // your tracker is now live

app.Run();

Every WebTorrent-compatible client can now use wss://your-host/announce as a tracker URL. Peers in the same infohash room get paired automatically.

Quickstart — embedded STUN/TURN

Add it during service registration, separate from signaling. Both can run in the same host process:

using SpawnDev.RTC.Server.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRtcStunTurn(opts =>
{
    opts.Enabled = true;
    opts.ListenAddress = "0.0.0.0";
    opts.Port = 3478;                            // standard STUN/TURN port
    opts.Realm = "your-domain.example";

    // Long-term credentials (classic TURN auth)
    opts.LongTermUsername = "alice";
    opts.LongTermPassword = "alice-secret";

    // OR ephemeral REST API credentials (preferred for production)
    opts.EphemeralSharedSecret = "your-32-byte-shared-secret-here";
    opts.EphemeralLifetime = TimeSpan.FromHours(1);

    // OR tracker-gated ephemeral: only peers currently announced to your
    // tracker can allocate. Combine with the signaling layer above.
    opts.TrackerGated = true;

    opts.RelayPortRangeStart = 49152;            // for NAT port forwarding
    opts.RelayPortRangeEnd = 65535;
});

var app = builder.Build();

app.UseWebSockets();
app.UseRtcSignaling("/announce");

app.Run();

Or bind from appsettings.json:

builder.Services.AddRtcStunTurn(builder.Configuration.GetSection("Turn"));
{
  "Turn": {
    "Enabled": true,
    "Port": 3478,
    "Realm": "your-domain.example",
    "EphemeralSharedSecret": "your-32-byte-shared-secret-here"
  }
}

Full options + walkthrough at Docs/stun-turn-server.md in the parent repo.

Origin allowlist

Browsers send an Origin header on every WebSocket connection. Setting AllowedOrigins rejects browser connections from origins not on the list — useful for keeping a tracker private to your own apps without firewalling the port:

app.UseRtcSignaling("/announce", opts =>
{
    opts.AllowedOrigins = new[] { "https://app.example.com", "https://staging.example.com" };
});

Desktop / CLI clients (SpawnDev.RTC desktop, JS WebTorrent on Node, curl) don't send Origin; the allowlist auto-bypasses them so non-browser clients keep working. Locked by OriginAllowlist_E2E_MissingOriginBypassesList in the RTC test suite.

What's in the package

  • TrackerSignalingServer — the signaling endpoint. Speaks the same wire protocol as tracker.openwebtorrent.com (JSON announce / offer / answer / signal messages over WebSocket). Per-room pairing keyed on info_hash.
  • StunTurnServerHostedService — the embedded TURN server, registered as an IHostedService so the lifetime is managed by ASP.NET Core's host. Built on the bundled SipSorcery fork.
  • EphemeralTurnCredentials — utility for issuing/validating ephemeral usernames + HMAC passwords. Pair with TurnServerConfig.ResolveHmacKey for tenant-aware credential rotation.
  • UseRtcSignaling / AddRtcStunTurn extension methods on IApplicationBuilder / IServiceCollection.

Production deployments

hub.spawndev.com:44365 runs this exact stack. Real-world load: dozens of concurrent rooms, simultaneous TURN allocations, browser + desktop clients pairing through it daily.

For the standalone-executable + Docker route, see the SpawnDev.RTC.ServerApp project — same library, env-var-driven configuration, single deployable artifact.

Dependencies

  • SpawnDev.RTC 1.1.6 (signaling client primitives, room key types)
  • ASP.NET Core 10 (Microsoft.AspNetCore.App framework reference)
  • SipSorcery fork (bundled inline via SpawnDev.RTC) — for the TURN server's underlying RFC 5766 implementation

Documentation

Topic Doc
Signaling protocol overview Docs/signaling-overview.md
Running a tracker (this library) Docs/run-a-tracker.md
STUN/TURN server reference Docs/stun-turn-server.md

License

MIT — see LICENSE.txt in the parent repository.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.7 43 4/29/2026
1.0.5 91 4/25/2026
1.0.4 89 4/24/2026
1.0.3 81 4/24/2026
1.0.1 95 4/23/2026
1.0.0 98 4/22/2026

v1.0.7 stable: rolls up rc.1's tracker-parity fixes plus 1.0.6's `peers`-field-omission fix into a single stable cut. Two parity fixes against the bittorrent-tracker JS reference (webtorrent/bittorrent-tracker server.js), found by `tracker-debug/verify-tracker-parity.mjs` head-to-head test against the local bittorrent-tracker npm package. (1) Answer-relay path: when an announce frame carries `answer + to_peer_id + offer_id` (a reply to a forwarded offer), the JS reference forwards the answer to the targeted peer and returns no announce response to the sender. The C# server now matches - was previously sending an extra announce-response frame in this case. (2) Stopped event: when an announce carries `event=stopped`, the JS reference removes the peer from the room AND sends back an announce-response with the updated counts (so `incomplete=0` etc. reflect post-stop state). The C# server now matches - was previously returning early without sending any response. Plus the `peers`-field-omission fix from 1.0.6: omit the `peers` field entirely (instead of `peers=[]`) when there are no peers to return, matching the JS reference. All three fixes only affect the announce-response framing; the data-channel WebRTC flow itself is unchanged. Verified end-to-end against the live hub at `wss://hub.spawndev.com:44365/announce`: all 6 scenarios PARITY OK against JS reference. Transitively pulls in SpawnDev.RTC 1.1.8 stable (Desktop OnBufferedAmountLow + browser connection-state polling fallback + opt-in DiagnosticsEnabled).