3778 Commits

Author SHA1 Message Date
Raja Subramanian 23090163ce Configurable migration wait duration for longer waits in simulation. (#4624)
Only applies if it is more than the default 3 seconds.
2026-06-26 20:01:32 +05:30
cnderrauber eb3de092f0 update pion/sctp (#4623)
* update pion/sctp

* webrtc & datachannel
2026-06-25 21:43:07 +08:00
Raja Subramanian 1faab0c48e Add support for data blob (a. k. a. async participant attributes) (#4619)
* Async attributes on participant.

How it is different from existing participant attributes?
1. Async attribute can be added one at a time.
2. These are not included in `ParticipantInfo`.
3. Get an attribute bt participant identity and async attribute ID as
   and when needed.

* clean up

* get full definitions, not just ids

* listener OnDataTrackSchema

* name length config

* data blob

* deps

* static check

* Add missing request ID

* Update protocol commit

* Wire up StoreDataBlobResponse

* Pass request ID through in GetDataBlobResponse

* deps

* atomic

* sctp at 1.9.5

* remove proto clone

---------

Co-authored-by: Jacob Gelman <3182119+ladvoc@users.noreply.github.com>
2026-06-24 14:42:37 +05:30
Raja Subramanian 0cf53e2f0d Add option to force drain rtcService/agentService connections. (#4618)
When force: true, drain as fast as possible.
2026-06-23 16:10:50 +05:30
laosun 6658dd5454 Echo offered audio payload types in single-PC subscriber answer (#4614)
In single peer connection mode, when the server answers a subscriber's
offer, configureSenderAudio set the sender codec preferences from the
server MediaEngine's payload types. The answer could therefore advertise
Opus on a payload type the offerer never offered (server PT 111 vs
offered PT 109). Chrome tolerates this; Firefox decodes 0 samples
(silence) -- packets are received but never decoded. The forwarded RTP
already uses the offered PT, so only the answer SDP was inconsistent.
This regressed in v1.12.0 once the single-PC MediaEngine became a union
of publish+subscribe codecs.

Parse the remote offer's audio rtpmap and remap the sender audio codec
preferences to echo the offered payload types (RFC 3264 6.1) before
SetCodecPreferences.

Fixes #4599

Co-authored-by: laosun <14806343+cnvipstar@users.noreply.github.com>
2026-06-23 10:36:41 +05:30
Raja Subramanian 4facbc582a Move lock to addPendingTrack function. (#4617)
Wrapping the function with the lock outside in the only invocation was
not needed.
2026-06-23 10:30:59 +05:30
Raja Subramanian 1b69630a28 Prometheus metric for join latency. (#4616)
* Prometheus metric for join latency.

Also including a couple of other failures in the signal connection path
and moving the signal connected to after all that.

Not doing counters for the new signal failure paths. I should not have
done for the other two I added a little while ago also (
validation failure and start participant failure) as those are not
scalable to keep adding to node stats. Will probably remove those two
from node stats later. Can add those counters if they are useful.

* deprecate signal failed counters
2026-06-22 22:07:32 +05:30
Ryan Gaus 86a79f83fc fix: report participant capabilities in ParticipantInfo (#4606) 2026-06-22 09:23:33 -04:00
Raja Subramanian f7085535da Tighten up publish latency stat. (#4615)
Previously it was anchored to participant transitioning to `ACTIVE` if
the add track request happened before that. But, that has a few issues
1.`ACTIVE` is for primary peer connection which could be subscriber peer
connection.
2. `ACTIVE` also include data channel establishment.

Switch to first connected time of publisher peer connection for that to
get a more accurate measure of track publish time.
2026-06-22 17:36:06 +05:30
CloudWebRTC 13ce35fc87 fix: Clear the enableStartAtDesiredQuality flags in MaybeExpireAcquireGrace. (#4613) 2026-06-22 14:03:47 +08:00
Raja Subramanian a3a6b6de96 triviial: remove usused config. (#4611)
noticed a config in deploy config while cleaning up some other usused
config. small clean up. probably there is a bunch more that can be
cleaned up, but doing a quick one as I noticed this.
2026-06-21 16:37:21 +05:30
CloudWebRTC cfedcc71d0 feat: acquire requested video layer directly at HIGH quality by default (#4595)
* feat: acquire requested video layer directly at HIGH quality by default

Two changes that together remove the visible low->high quality ramp for a new
subscriber (both publisher-first and subscriber-first join orders):

1. Default a subscriber's initial video quality to HIGH on bind instead of LOW
   for adaptive stream, so the subscribed max layer is the top layer. Adaptive
   stream clients can still scale down afterwards based on viewport.

2. On initial layer acquisition the forwarder/selector latch directly onto the
   allocator's target (the requested top layer) instead of opportunistically
   latching onto the first lower key frame that arrives. A short
   initial-acquisition grace aims the target at the requested layer; if it does
   not show up in time, the target falls back to the highest layer seen so
   acquisition never stalls.

Always on - no configuration flag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: gate start-at-desired-quality behind EnableStartAtDesiredQuality flag

Put the "acquire requested video layer directly at HIGH quality" behavior
behind a per-subscriber EnableStartAtDesiredQuality flag (default off, so
the original low->high ramp-up is restored unless enabled).

Plumbed from config.RTC.EnableStartAtDesiredQuality through ParticipantParams
-> SubscribedTrack/DownTrack -> Forwarder -> simulcast selector, gating all
three behavior changes: the HIGH default on bind, the forwarder's
initial-acquisition grace, and the selector's direct-latch-onto-target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* remove config.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-19 20:12:54 +08:00
Raja Subramanian a011d995da Do not call nil callback (#4607) 2026-06-18 23:24:33 +05:30
Raja Subramanian 9a7fe3cc68 Do not log due to negative getting interpreted as large unsigned positive (#4605) 2026-06-18 20:08:52 +05:30
Denys Smirnov 35b5390c27 Update protocol. (#4601) 2026-06-18 13:29:21 +02:00
Raja Subramanian c6303bb15a Fix skipped packets accounting. (#4604)
* Fix skipped packets accounting.

No need to copy unskipped packet RTP header to skipped packet.
That was causing padding bytes to be counted.

Also use Header.PaddingSize as base PaddingSize is deprecated.

* PaddingSize in header in utils
2026-06-18 11:58:39 +05:30
Paul Wells b882ccc86d service: cap all metadata at 512 KiB; enforce on join, agent dispatch, and embedded agents (#4602)
* service: enforce metadata size limit in CreateRoom, bump default to 512 KiB

CreateRoom previously accepted any metadata size; only UpdateRoomMetadata
rejected oversized payloads. Mirror the same CheckMetadataSize check at
the CreateRoom API boundary so both entrypoints are bounded.

Default MaxMetadataSize moves from 64000 to 512 * 1024 to match the
practical needs of customers using room metadata for richer state. The
limit remains configurable via the existing limits.max_metadata_size knob.

* service: split room vs. participant metadata limit, enforce on join + agent dispatch

LimitConfig.MaxMetadataSize was shared between room metadata and
participant metadata. Last commit's bump to 512 KiB lifted both ceilings;
this restores the participant ceiling to 64 KB and introduces a separate
MaxRoomMetadataSize (default 512 KiB) for room metadata.

Additional enforcement:

- RoomManager.StartSession rejects joins whose JWT-grants metadata or
  attributes exceed the participant/attributes limits. The check was
  missing entirely from this path.
- AgentDispatchService.CreateDispatch and the embedded
  CreateRoomRequest.Agents path now validate metadata and attributes
  against the common 64 KB ceilings (previously unbounded).

NewAgentDispatchService gains a LimitConfig parameter; the two wire_gen
callsites are updated.

* service: collapse metadata size limit to single 512 KiB knob

Reverts the LimitConfig split introduced in the previous commit:
MaxRoomMetadataSize, CheckRoomMetadataSize, and the max_room_metadata_size
yaml key are removed. MaxMetadataSize moves back to 512 * 1024 and gates
all metadata uniformly — room (CreateRoom, UpdateRoomMetadata), participant
(UpdateParticipant, signal UpdateMetadata, JWT grants on join), and agent
dispatch (CreateDispatch + embedded RoomAgentDispatch).

MaxAttributesSize stays at 64 KB and continues to gate participant and
agent-dispatch attributes separately.

Test cases consolidated under the single knob.

* kb -> kib
2026-06-17 12:35:59 -07:00
Raja Subramanian e7c63aa537 Log subscription limit breaches (#4603) 2026-06-18 00:08:39 +05:30
Raja Subramanian 67ca7a12cf Record more RTC cancellation points. (#4600)
There are several places the participant can drop off after initiating a
connection attempt. Count those places as cancellation including when
participant is closed due to specific reasons.

Cancels should be discounted when determining RTC/ICE connectivity
success/failure percentage.
2026-06-17 20:43:29 +05:30
Paul Wells 12a023ae45 agent: thread attributes map from dispatch to job (#4598)
* agent: thread simulation flag from dispatch to job

Reads simulation from AgentDispatch / RoomAgentDispatch and copies it
onto Job in agent.LaunchJob and the inline room-agent path so workers
see the flag.

Stacked on top of livekit/protocol#1629.

* agent: replace simulation bool with attributes map

Threads the renamed attributes map (was bool simulation) from dispatch
to job and bumps the protocol pseudo-version.

* deps
2026-06-16 01:53:01 -07:00
David Colburn 1f3e06107b egress v2 api (#4592)
* egress v2

* reorganize
2026-06-12 15:17:02 -04:00
cnderrauber 9746c9a9d6 Enforce subscriptio permission to data track (#4588)
* Enforce subscriptio permission to data track

* use revoke path as same as media track

* nil check
2026-06-12 16:02:12 +08:00
shishirng 08ab361e8e [WIP] rtc: add RestartSessionTimer to re-anchor participant session duration (#4566)
* rtc: add RestartSessionTimer to re-anchor participant session duration

Exposes ParticipantImpl.RestartSessionTimer so the session timer can be
re-anchored to the actual join time. Duration is only ever emitted once
the participant becomes active, so re-anchoring at join keeps pre-join
wall-clock out of the reported/billed duration. Adds the method to the
LocalParticipant interface (fake regenerated) and a local protocol
replace to pick up SessionTimer.Reset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* tidy

* update protocol

* report ended at for inactive sessions

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Paul Wells <paulwe@gmail.com>
2026-06-11 10:02:25 -07:00
Raja Subramanian 688cc66ed8 Add API to get latest node stats. (#4589) 2026-06-11 19:31:39 +05:30
Raja Subramanian 8efc94eb68 Update DTLS to v3.1.4 (#4587) 2026-06-11 12:23:55 +05:30
Trey Hakanson 233a226438 Add ability to run pprof on dedicated HTTP server (#4584)
This allows exposing the pprof/debug endpoints in a production
environment more easily, where it shouldn't be exposed publicly.
2026-06-10 21:23:39 -07:00
Benjamin Pracht 675caa208f Add CODEOWNERS (#4583) 2026-06-10 12:16:55 -07:00
cnderrauber 816d37281d Add grants expiry to Auth context (#4581) 2026-06-10 17:44:58 +08:00
cnderrauber 7dc6877738 Preserve original expiry when refreshing token (#4580)
To avoid shortening the token expiration time during
refreshing cause client reconnect failed after network
down for a long time (>5min).
2026-06-10 14:51:10 +08:00
Raja Subramanian 8d2b827f44 Add prom metrics for peer connectino state. (#4574)
* Add prom metrics for peer connectino state.

By direction (PUBLISHER vs SUBSCRIBER) and state ("started" ->
"connected"). This gives a way to track peer connections failing to
finish establishment.

The RTC active count can be useful for primary peer connection, but not
for non-primary. This counter can be used to track any and can generally
be used to understand success/failure rate of peer connection
establishment.

* add a couple of more states

* clean up and avoid duplicate reporting fully established

* staticcheck
2026-06-09 16:11:03 +05:30
David Zhao 46c4309554 fix goreleaser workflow, version 1.13.1 (#4577) v1.13.1 2026-06-08 16:15:09 -07:00
David Zhao e0815be27d chore: improve docker test shutdown reliability (#4576) 2026-06-08 08:27:15 -07:00
Dan Root bfd9deffd7 expose TCPFallbackRTTThreshold and AllowUDPUnstableFallback via config (#4556) 2026-06-08 22:07:08 +08:00
Raja Subramanian b93c1e1607 Release v1.13.0. (#4573)
Please see note about TURN authentication without TTL backwards
compatibility removal.
v1.13.0
2026-06-08 13:46:52 +05:30
Raja Subramanian fd452212c7 Update mediatransportutil to get ICE candidate timeout config (#4572) 2026-06-08 12:42:58 +05:30
renovate[bot] 8be8c74a59 Update github workflows (#4463)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-07 23:08:50 -07:00
renovate[bot] c4e41872c5 Update go deps to v1.17.2 (#4462)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-07 23:08:05 -07:00
renovate[bot] dc8e0310ad Update go deps to v4 (#4482)
* Update go deps to v4

Generated by renovateBot

* update dockertest to v4

* fix

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
2026-06-07 23:07:40 -07:00
Ben Mayer 20fd1ad2c1 turn: allow for providing secret via file (#4564)
* turn: allow for providing secret via file

* turn: improve secret_file changes
2026-06-08 11:18:14 +08:00
Raja Subramanian 6590570d7c Pin pion/dtls to v3.1.2 (#4570) 2026-06-06 20:36:10 +05:30
Paul Wells cdbbee1f8e deps: bump protocol + psrpc to latest tips (#4565)
* deps: bump psrpc + protocol + cloud-protocol + backend-common to latest

* deps: go get -u sweep + bump counterfeiter

Direct deps bumped via go get -u ./...:
  clipperhouse/displaywidth 0.10.0 -> 0.11.0
  clipperhouse/uax29/v2 2.6.0 -> 2.7.0
  fatih/color 1.18.0 -> 1.19.0
  florianl/go-tc 0.4.7 -> 0.4.8
  hashicorp/go-version 1.8.0 -> 1.9.0
  livekit/protocol -> a7a83da5 (latest)
  ua-parser bumped
  urfave/cli/v3 3.8.0 -> 3.9.0
  otel/sdk 1.43.0 -> 1.44.0
  yaml.in/yaml/v2 2.4.2 -> 2.4.4

Indirect: mdlayher/netlink + socket bumped, mattn/* bumped, olekukonko/*
bumped, counterfeiter v6.11.1 -> v6.12.2.

Newer-major audit: no actionable majors. +incompatible: twitchtv/twirp
v8.1.3 (upstream choice, stays); docker/cli and docker/docker indirect.

Notable stuck patterns worth a separate cleanup:
- pkg/errors v0.9.1 direct dep (unmaintained; stdlib supplants)
- go.uber.org/atomic + multierr direct deps
- ory/dockertest/v3 v3.12.0 (v4 is available — cascade has migrated
  cloud-protocol, backend-common, psrpc to v4).

* deps: pin pion/webrtc/v4 v4.2.11 + pion/sctp v1.9.5

* deps: pin protocol+psrpc+MTU to landed versions
2026-06-05 14:48:51 -07:00
cnderrauber d290de8165 Correct config comment (#4563) 2026-06-04 16:43:59 +08:00
Paul Wells 77ecf920ff rtc: report participant session end time on room move (#4561)
MoveToRoom resets the participant reporter resolver to receive new
(room, participant_session) keys for the destination, but the source
room's participant_session row never gets an end_time — the periodic
duration scrape only emits one once disconnectedAt is set, and a move
doesn't transition the participant to DISCONNECTED. Report end_time
immediately before the reset so the row is closed out cleanly.
2026-06-03 21:35:39 -07:00
cnderrauber 63be96f631 Prevent panic from nil(illegal) syncState.Subscriptions message (#4560) 2026-06-04 10:32:24 +08:00
Raja Subramanian 835ef1b353 Metrics for participant active, i. e. fully established. (#4557)
* Metrics for participant active, i. e. fully established.

- Egress stub for v2 API
- Fix the participant canceled counter 🤦
- Add active counter -> this is increment when a participant becomes
  active, i. e. primary peer connection established. Can be used to
  monitor node wise connection establishment issues.
- Add singnalling validation fail counter.

With this, we have
- signalling validation fail
- signalling failed --> this is when the `startSession` fails
- signalling connected -> signalling is succesful and can send back
  joinResponse to client

on media connection side
- rtc_init -> start
- rtc_connected -> participant session created (joined)
- rtc_active -> primay peer connection established
- rtc_canceled -> could not proceed with RTC connection due to not being
  able to resume.

* signalling counters deps

* revert pion/webrtc to 4.2.12 to get SCTP without interleaving

* go back to pion/webrtc 4.2.11 and sctp 1.9.5
2026-06-03 19:50:19 +05:30
cnderrauber 5bd425346c Document of advertise_internal_ip and external_ip_only (#4554) 2026-06-02 09:50:45 +08:00
cnderrauber 356ae211a3 Config documentation for advertise_internal_ip and skip_external_ip_validation (#4552)
See https://github.com/livekit/mediatransportutil/pull/88
2026-06-01 14:37:08 +08:00
shishirng 7c319a67d4 rtc: prevent duration reporting for inactive participants (#4550)
Added a check to ensure that duration is not published for participants
that never became active.
2026-05-27 14:39:04 -04:00
Paul Wells 2dd5e63207 telemetry: split webhook-processed hook out of NewTelemetryService (#4548)
* telemetry: split webhook-processed hook registration out of NewTelemetryService

NewTelemetryService used to register a notifier processed-hook on the inner
*telemetryService directly. That made it impossible for downstream wrappers
(e.g. cloud's TelemetryService that overrides Webhook to fan out to a v3
observability pipeline) to intercept webhook events without double-firing
the legacy emission.

Lift the registration into a new exported helper RegisterWebhookHook, and
have the standalone server's wire provider createTelemetryService call it
right after construction so behavior is unchanged for callers that don't
wrap the service.
2026-05-27 09:40:55 -07:00
Paul Wells 222177a9e4 service: prevent nil deref in validate with wrapped join request (#4547)
When a client hits /rtc/v[01]/validate with a base64 WrappedJoinRequest
whose embedded JoinRequest.ClientInfo is unset, validateInternal called
AugmentClientInfo with a nil *ClientInfo and panicked at ci.Address =
GetClientIP(req). The non-wrapped branch already allocates via
ParseClientInfo; do the same here so pi.Client always gets at least the
resolved client Address.
2026-05-26 08:34:15 -07:00