Commit Graph
940 Commits
Author SHA1 Message Date
Paul Wells 1ba2cadccd agent: release JobTerminate handler when job ends before registration (#4908)
* agent: release JobTerminate handler when job ends before registration

JobRequest registered the job's JobTerminate handler after AssignJob
returned, so an ended UpdateJobStatus or worker disconnect handled in
between deregistered nothing and the handler leaked. AssignJob also sent
the assignment before recording the job as running, so an immediate
ended update was dropped.

Record the job before sending the assignment, and after registering the
handler recheck under h.mu that the job is still running and its worker
still registered, deregistering otherwise.

Fixes #4901

* replace utils.CloneProto with proto.CloneOf

* agent: wait on worker readiness and poll for released handlers in test
2026-09-25 00:58:22 -07:00
cnderrauber 6b2e3ece69 Increase receiver loadbalance threshold when batch io enabled (#4899)
* Increase receiver loadbalance threshold when batch io enabled

With batch IO the send syscall moves to the BatchConn flush goroutine, so WriteRTP only
translates the packet and enqueues it. Increash the threshold to reduce

* lint
2026-09-23 13:54:40 +08:00
cnderrauber 885c869ffa Add sdk lable to session start time and participant join (#4885) 2026-09-21 13:14:36 +08:00
Paul Wells d5c691836f deps: update psrpc to v0.8.0 (#4882)
* deps: update psrpc to v0.8.0

psrpc v0.8.0 splits the brokers into leaf packages so importing psrpc no
longer pulls in nats.go and go-redis, and drops the root constructors:

  - return psrpc.NewRedisMessageBus(rc, opts...)
  + return redisbus.New(rc, opts...)

getMessageBus keeps its NewLocalMessageBus branch -- that shim stays at the
root because localbus costs no dependency. wire_gen.go carries a verbatim
copy of the provider, so it gets the identical edit rather than a wire
rerun, which would churn unrelated output.

redisbus.New takes ...bus.BusOption and psrpc.BusOption is an alias for it,
so PSRPCConfig.BusOptions() spreads in unchanged.

The nats-io requirements drop out of go.mod; this module only ever used the
Redis bus, and nats came in indirectly through psrpc's root package.

* Reorder import statements in ioservice_sip_test.go
2026-09-20 16:45:40 -07:00
Raja Subramanian a487105a64 Get participant by authed identity in WHIP participant service. (#4861)
Addresses - https://github.com/livekit/livekit/security/advisories/GHSA-gfh2-98qv-ggmw
2026-09-12 15:33:24 +05:30
Sapan Diwakar adf44a2eb6 turn: accept PROXY protocol on the TCP listener (#4852)
* turn: accept PROXY protocol on the TCP listener

Behind a TLS-terminating or reverse proxy that dials from its own address,
the embedded TURN server reports the proxy's address to the client as
XOR-MAPPED-ADDRESS. Firefox rejects a loopback or wildcard mapped address
and abandons the allocation, so relay-only clients never get a relay
candidate (#4851).

Add turn.proxy_protocol. When set, the TCP listener requires a PROXY
protocol v1/v2 header on every connection and uses the client address it
carries; connections without the header are rejected. The header is read
before TLS, so it works with both the built-in TLS listener and
external_tls.

* turn: only trust PROXY headers from configured proxies

A PROXY header from any peer that can reach the port would let a direct
client claim an arbitrary source address. Add
turn.proxy_protocol_trusted_cidrs, defaulting to loopback, and close
connections from any other address before reading the header.
2026-09-09 16:16:44 +08:00
Paul Wells e18fbcc0fa wire psrpc bus compression into the message bus constructor (#4844)
getMessageBus built the bus from the redis client alone, so there was no
way to reach the gzip settings psrpc v0.7.6 added at the bus boundary.
Take rpc.PSRPCConfig, which the wire graph already provides, and pass its
bus options to both the redis and the local bus.

Compression is off by default. A peer on an older psrpc cannot decode a
compressed payload and drops it silently, so egress, ingress, SIP and
agent workers all have to be upgraded before quality is raised.
2026-09-05 06:58:59 -07:00
Benjamin PrachtandClaude Opus 5 91f33da004 ingress: add opt-in support for udp:// URL pull ingress (#4810)
* ingress: add opt-in support for udp:// URL pull ingress

URL pull ingress previously accepted only http, https and srt source
URLs. Add udp:// as an accepted scheme, gated behind a new
`ingress.enable_udp_url_pull` config option that defaults to false, so
unauthenticated UDP sources are not reachable unless the operator opts
in.

Also add a counterfeiter fake for IngressLauncher and a test covering
the scheme validation matrix.

The ingress handler binds a local socket on the caller supplied address
and port instead of connecting out like the http and srt sources do.
Spell out what that means for operators in both the config field doc
comment and config-sample.yaml: caller controlled local port binding,
unauthenticated and spoofable input, and multicast relaying of traffic
on the handler's local network.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 12:11:14 -07:00
cnderrauberandClaude Opus 5 a1f46b310a Do not escape the ICE server URI in the WHIP Link header (#4795)
The link target was passed through url.PathEscape, which turns the '?' of
turn:host:3478?transport=udp into %3F. The target of a Link header field
is a URI reference and "?transport=" is part of TURN URI syntax
, not a query string, so a publisher that percent-decodes the
target ends up with an unparsable host.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 11:14:15 +08:00
Paul Wells 54496c765d report a reason on room-ended telemetry (#4815)
* report a reason on room-ended telemetry

Room.Close already took a ParticipantCloseReason, but OnClose was func()
with no arguments, so the reason was structurally dropped before it could
reach RoomEnded.

Add types.RoomCloseReason and carry it through Close -> OnClose -> RoomEnded,
where it lands on both the analytics event and the room_finished webhook.

Room.Close now takes the room reason and derives the participant reason from
it, so the two can never disagree. ToParticipantCloseReason maps each reason
to exactly what its call site passed before, so no participant-facing
behaviour changes; a table test pins that mapping.

* fix(test): update webhook test for RoomCloseReason

test/ was outside the packages checked before pushing, so this Close call
site was missed. Also assert the reason reaches the room_finished webhook,
which the unit test cannot cover since it runs with a nil notifier.
2026-08-28 23:41:59 -07:00
Alex FeldgendlerandClaude Opus 5 64a1211517 Skip the docker-backed service tests when there is no docker (#4799)
Let the docker-backed service tests be skipped with a flag.

TestMain called log.Fatalf when it could not reach a docker daemon, so
the whole package refused to run without one, including every test in it
that needs no container at all.

Record why docker is unavailable instead, and gate the tests that want a
container on it. A run asks to go without them with -docker=false;
otherwise a missing daemon still fails the package, so an unreachable
daemon stays a broken build rather than a run that quietly covers less
than the last one did.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 10:32:15 -07:00
cnderrauber f7954d5747 Return created ingress info from io service (#4787)
The stream key is randomly generated for each request. Return
exsiting record if the `ingressID` already exists on retry.
2026-08-25 09:03:09 +08:00
Genseric 788d4c3544 TEL-912 Adding response for TransferSIPParticipant rpc (#4783)
* Replacing empty return type with rpc.CreateIngressResponse and livekit.TransferSIPParticipantResponse

* removing ambiguous comment
2026-08-21 14:27:06 -04:00
Raja SubramanianandClaude Opus 5 c52b1b2a30 Flush pending signal responses before closing the web socket. (#4776)
* Flush pending signal responses before closing the web socket.

When the request direction of a signalling connection goes away, the
web socket was closed right away. Responses that the participant had
already sent were dropped.

This loses the leave request on migration. The media node writes
leave(RESUME) and closes the signalling connection just after. The
close won the race, so the client saw a plain web socket close with
code 1000 and never got the leave. It then did a full reconnect
instead of a resume.

Now the response pump is signalled first and drains what is pending,
then the web socket is closed. The producer closes the response
source after its last write, so draining till the source is closed is
a complete flush. A deadline bounds the case where the source stays
open.

The web socket is still closed on all paths, so the ping worker does
not leak.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Give the response pump a margin over the drain deadline.

Both waits used the same timeout and started at about the same time.
So when the drain ran to its deadline, the outer wait could give up at
the same moment and close the web socket while the pump was still
writing. That write failed and the message was lost. It also logged a
timeout even though nothing was stuck.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 01:13:50 +05:30
Raja Subramanian 0ef7ee440c Fix deadlock in regress codec check. (#4775) 2026-08-19 20:17:53 +05:30
Benjamin Pracht 2cad1cc936 Update renovate and pinning behavior, run tools from go.mod (#4759)
- Renovate

config:recommended (config:base is deprecated) and matchPackageNames globs instead of the deprecated matchPackagePrefixes.
Vulnerability alerts get a fast path: 2-day quarantine, no concurrency/hourly/schedule limits.
Go modules are no longer grouped into one "go deps" PR — each gets its own, so a bad bump can be reverted alone. The pion modules stay grouped as a documented exception: they're co-released and interdependent, so individual PRs wouldn't build.
First-party github.com/livekit/** skips the 2-week quarantine.
go.mod's go directive is no longer an update target — the build toolchain is pinned in the Dockerfile instead.
Dockerfile deps get pinDigests; the golang image is ungrouped with separateMinorPatch so a patch and a minor bump are each separately approvable.
Custom manager to bump the builder image's -alpineA.B suffix together with its digest, which the stock docker manager holds fixed.

- Pinning

Both Dockerfiles pin golang and alpine by digest alongside the readable tag.
GOTOOLCHAIN=local so a go.mod bump fails loudly instead of silently downloading a different toolchain.
apk upgrade in the runtime stage — a digest pin plus the 2-week quarantine would otherwise ship base-package CVEs Alpine has already fixed. This relies on a cold layer cache, which holds today because the release workflow configures no buildx cache; there's a comment saying so.
Workflows resolve the Go version from the Dockerfile via .github/scripts/go-version.sh, so tests, releases and images share one toolchain.

- Tools

All four code generators now come from the module graph, and tools/tools.go (the pre-Go-1.24 blank-import idiom) is replaced by go.mod tool directives:

tool	how	why
goimports	go tool	lives in x/tools — its own module is the one being selected
gotestfmt	go tool	zero dependencies, nothing to skew
wire	go run	pins x/tools v0.24.1; building it in our graph changes its output
counterfeiter	go run	unchanged, matches its //go:generate directives

The wire distinction is load-bearing. Building wire inside our module raises it from the x/tools v0.24.1 it pins to our v0.48.0, and that module version difference changes what it generates: it falls back to v/v2/v3 instead of deriving real identifiers from the type. wire_gen.go is regenerated here to match the in-module build — a cosmetic rename of 9 lines, with no other change to the generated code.

golangci-lint deliberately keeps its action rather than becoming a tool: it pins its own x/tools (v0.44.0 vs our v0.48.0) for the analyzers it bundles, adding it to go.mod would double our go.mod/go.sum (158→338 / 441→889 lines), and the action supplies caching, only-new-issues and PR annotations that invoking a binary can't. Its version stays manual by request.
2026-08-17 09:25:02 -07:00
Milos PesicandClaude Fable 5 b0e2d89826 Redact stream keys in UpdateStream API log fields (#4763)
* Redact stream keys in UpdateStream API log fields

UpdateStream add/remove urls were logged raw into the API request log,
including rtmp stream keys and mux/twitch shorthand keys. Redact them
with utils.RedactStreamKey before appending log fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Bump protocol for query-value redaction fallback

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 14:19:30 +02:00
Raja Subramanian 035bef4111 Log invalid APIKey on API failures. (#4762)
Useful to understand which key is used.
2026-08-14 17:20:10 +05:30
cnderrauber dbe06aa8d1 Experimental WARP (#4649)
* Experimental WARP

* fix panic

* go dep

* stats
2026-08-14 16:26:08 +08:00
Raja Subramanian df20578a78 Remove auth token from log/being sent back to client on invalid token… (#4756)
* Remove auth token from log/being sent back to client on invalid token error

* actually remove API key also
2026-08-14 11:51:14 +05:30
Raja SubramanianandClaude Opus 4.8 f72254ba6b Limit API request body size (#4757)
Bound the size of HTTP request bodies on the main API listener so large
messages cannot exhaust memory. Configurable via limit.max_api_request_body_size
(defaults to 10 MiB, 0 disables).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-14 10:36:40 +05:30
Raja Subramanian 2561589868 Fail server start up on partial prom config. (#4749)
* Fail server start up on partial prom config.

* tweaking error message a bit
2026-08-13 13:49:17 +05:30
Raja Subramanian 35fe831f1d Close web socket connections in all paths. (#4747)
* Close web socket connections in all paths.

There was a leak of WebSocket pingWorker if the initial response write
errored as it did not close the WebSocket connection.

* graceful close
2026-08-12 15:15:38 +05:30
Raja SubramanianandClaude Opus 4.8 3c6e56232e Add configurable read-message size limit on signalling WebSockets (#4743)
* Add configurable read-message size limit on signalling WebSockets

Set a read limit on both the client-facing (/rtc) and agent worker
WebSocket connections so an oversized frame is rejected by the transport
before being buffered. The limits are operator-tunable via
signal_message_size_limit and agent_signal_message_size_limit, both
defaulting to 2 MiB (0 disables).

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

* Add tests for signalling WebSocket read-message size limit

Cover the configurable signal_message_size_limit added in the prior
commit:
- config: assert both limits default to 2 MiB and that a YAML override
  (including 0 to disable) is parsed correctly.
- full-path integration: a real client connects to /rtc on a single-node
  server and an oversized frame is rejected by the transport with a 1009
  close; a 0 limit leaves the connection unbounded and signalling
  proceeds.

Adds setupSingleNodeTestWithConfig so a single-node server can be started
with config overrides.

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

* Bound decompressed size of signalling WebSocket messages

conn.SetReadLimit only accounts for the compressed bytes read off the
wire, and the client-facing /rtc upgrader negotiates permessage-deflate,
so a small compressed frame could still expand into a much larger buffer
once inflated. Enforce the same limit on the decompressed message by
reading through NextReader + io.LimitReader in WSSignalConnection instead
of the unbounded ReadMessage.

The transport-level SetReadLimit is kept as the cheap wire-level guard;
the new check is the decompressed-size backstop.

Adds NextReader to the WebsocketClient interface (regenerated fake) and a
unit test plus permessage-deflate integration tests covering the
amplification case.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-12 12:07:26 +05:30
cnderrauber fad2cc4afe Use request id to make api idempotence on sdk retry (#4694)
* Use request id to make api idempotence on sdk retry

Derive resource id from request id
2026-08-12 09:28:39 +08:00
Raja SubramanianandClaude Opus 4.8 223587e140 Add per-participant concurrent TURN allocation quota (#4744)
* Add per-participant concurrent TURN allocation quota

The embedded TURN server authenticated each Allocate request but placed
no cap on how many relay allocations a single participant credential
could hold. One participant could reuse its credential across many client
5-tuples and open one relay socket/port per request, exhausting the
shared relay-port range for everyone else.

Add a configurable per-participant limit (turn.per_user_relay_allocation_limit,
default 4) wired to Pion's QuotaHandler, keyed by the participant ID from
HandleAuth. Slots are reserved before allocation and released when the
allocation ends, under a single lock, so concurrent Allocate bursts cannot
race past the limit; reservations are keyed by source address so retransmits
are idempotent. Over-quota requests receive 486 (Allocation Quota Reached).

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

* Reclaim unconfirmed TURN allocation reservations

Allow reserved a quota slot before Pion built the relay, but the slot was
only released on the allocation-deleted event. An Allocate that passed the
quota check and then failed to create a relay (e.g. relay-port range
exhausted) emits no event, so the reservation leaked: after enough failures
a participant could lock itself out with 486, and the tracking map grew
without bound.

Reservations now start pending and are confirmed on allocation-created; each
pending reservation carries a reclaim timer that frees the slot after a TTL,
so a failed attempt cannot hold a slot forever while concurrent-burst safety
is preserved.

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

* Make TURN reservation reclaim identity-aware

The reclaim timer captured only userID+key. Because Timer.Stop cannot cancel
a callback that has already fired and is waiting on the lock, a stale timer
could delete a replacement reservation created for the same userID+key after
the original was released, leaving a live allocation untracked and letting the
participant exceed its cap.

reclaimPending now captures the slot pointer and only removes the entry when
the map still holds that exact slot, so a stale timer is a no-op.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-11 23:12:07 +05:30
Raja Subramanian 7167f91493 Validate TURN config to guard against invalid values (#4742) 2026-08-11 20:34:49 +05:30
Felix-Ayush 4618b63eb7 Fix AgentHandler.DrainConnections deadlock on worker close. (#4710)
Snapshot workers and release h.mu before Close so HandleConnection can deregister without blocking drain.
2026-08-03 14:49:23 +05:30
He Chen 93422be0c5 TELCU-1: send resolved ringing timeout (#4697) 2026-07-23 15:29:24 -07:00
Ninad Pundalik afb9142c1e Add status code for twirp request latency prometheus metric (#4621)
* Add status code for twirp request latency prometheus metric

* Drop the twirp error codes as that adds a lot of coardinality
2026-07-22 15:52:30 +05:30
Raja Subramanian 8c14a617f5 Use proto logger to get named enums in the logs. (#4679) 2026-07-16 23:50:13 +05:30
Alex Fish cc87a83e1f TEL-730: Log soft validation errors. (#4671) 2026-07-15 09:06:01 -07:00
dcd08bec63 Fix goroutine leak from orphaned signal relay streams (#4674)
* Fix goroutine leak from orphaned signal relay streams

signalService.RelaySignal blocks on the first `<-stream.Channel()` waiting for the StartSession message. psrpc's streamHandler.handleOpenRequest only closes the stream after the handler returns, so if a stream is opened but the client goes away before sending StartSession, the channel is never fed and never closed, and this goroutine blocks forever. Under mass reconnects this leaks one goroutine (and its retained objects) per orphaned stream; they only clear on process restart.

Wrap the initial receive in a select that also returns when the stream context is cancelled or after config.SignalRelay.RetryTimeout, so an orphaned stream returns before Hijack() and psrpc closes it.

Signed-off-by: SKaterinenko <skaterinenko@gmail.com>

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Paul Wells <paulwe@gmail.com>
2026-07-15 05:41:16 -07:00
Florian Loretan 7818dd21b9 fix: bound data-track buffering under downlink congestion (targetLatency) (#4667)
* fix: bound data-track buffering under downlink congestion

The SFU data-track down-channel writer was constructed with targetLatency=0,
which disables the buffered-amount/latency-based drop in writeUnreliable. Under
subscriber downlink congestion, frames were queued unbounded and in order in the
per-subscriber SCTP send buffer instead of being dropped, so end-to-end latency
grew without limit and only drained once congestion cleared. This contradicts
data tracks being a low-latency, lossy transport.

Wire a dedicated `datachannel_data_track_target_latency` config through to both
data-track writer call sites (mirroring how `datachannel_lossy_target_latency`
controls the lossy publishData channel), reusing lossyDataChannelMinBufferedAmount
as the drop floor. Defaults to 100ms so data tracks are latency-bounded out of
the box; set to 0 to restore the previous unbounded behavior.

Fixes #4666

* fix: track drained bytes on successful unreliable data channel writes

writeUnreliable only called BitrateCalculator.AddBytes when a write failed,
so on the common success path the calculator never received samples. As a
result Bitrate() had no data and the latency-based drop threshold collapsed to
the static minBufferedAmount floor, making the per-subscriber latency control
(datachannel_lossy_target_latency and the new datachannel_data_track_target_latency)
effectively inert. Call AddBytes after every write, matching writeReliable.
2026-07-14 10:06:09 +08:00
Raja Subramanian 19c3d00fc9 Add option to exclude local IPv6 candidates. (#4657)
Could be useful option to try in certain conditions where flakey IPv6
infrastructure is suspected for connection issues.
2026-07-10 15:56:58 +05:30
Raja Subramanian cb46452b5d Export migration to LocalParticipant interface. (#4652)
Can be used during delayed egress start.
2026-07-09 12:23:33 +05:30
Benjamin PrachtandClaude Opus 4.8 d1b031a9dd Stop WHIP session notifier when participant leaves (#4637)
The WHIP connection-notify loop kept issuing RPCs after the participant
had left the room. Guard sendConnectionNotify against a closed
participant (returning ErrParticipantNotFound) and treat that error as a
clean loop exit. Also reorder DeleteSession so the participant is removed
before its WHIP OnClose entry is cleared.

Adds tests covering loop termination on participant leave, context
cancellation, and the closed-participant guard.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 14:07:21 +01:00
cnderrauber 46e5caedbe Report average bitrates for whip ingress (#4634) 2026-07-01 17:06:49 +08:00
Raja SubramanianandJacob Gelman 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
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
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 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
Raja Subramanian 688cc66ed8 Add API to get latest node stats. (#4589) 2026-06-11 19:31:39 +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
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
David Zhao e0815be27d chore: improve docker test shutdown reliability (#4576) 2026-06-08 08:27:15 -07:00