Compare commits

...

754 Commits

Author SHA1 Message Date
github-actions[bot]
e099d367dd Version Packages (#747)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-02 17:35:54 +02:00
renovate[bot]
fb8bb59f73 Update dependency @changesets/cli to v2.27.7 (#718)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 13:03:20 +02:00
renovate[bot]
aa335df02e Update dependency @bufbuild/protobuf to v1.10.0 (#694)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 13:02:48 +02:00
renovate[bot]
e17caf57c8 Update dependency @bufbuild/protoc-gen-es to v1.10.0 (#693)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-01 12:55:47 +02:00
Benjamin Pracht
82786f41fd Additions to agent protocol (#717)
This PR:

- Adds StartAgentJobRequest/StopAgentJobRequest calls to start an handle manually mange an agent lifecycle
- Deprecates the JobType field in WorkerInfo as workers will now be expected to handle both kinds jobs (if the namespace supports both kinds in the first place)
- Adds a metadata string -> string map to Job to allow agent implementation to take anonymous (to us) parameters
- Adds a JobStatus and error fields to Job for status reporting (Similar to egress and ingress)
- Makes livekit_agent.proto indentation consistent with other proto files
- Add room configuration and management APIs to the Room service. Rooms configuration allow bundling most room configuration parameters under a single id, that can eventually be put as part of the room creation token.
2024-06-27 10:30:58 -07:00
Raja Subramanian
b2dc8deac6 Update retryable-http (#749)
* Update retryable-http

Dependabot flagged a securty updat
https://github.com/livekit/livekit/security/dependabot/9

* tidy
2024-06-25 12:17:03 +05:30
lukasIO
6dec8d27f9 Add ErrorResponse (#743)
* Add ErrorResponse

* generated protobuf

* Create purple-swans-study.md

* Update purple-swans-study.md

* Add ErrorResponse to possible server responses

* generated protobuf

* Use reason error instead of uint error code

* generated protobuf

* Add invalid argument error

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-21 10:33:50 +02:00
github-actions[bot]
288772c53c Version Packages (#746)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-06-20 20:13:28 +03:00
Denys Smirnov
79b5ea9ea9 Add SIP grants. (#745) 2024-06-20 17:49:41 +03:00
Denys Smirnov
7814d0fbc2 Fix typo in SIP Trunk conversion. (#744) 2024-06-20 17:49:23 +03:00
github-actions[bot]
f50408c48c Version Packages (#736)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-06-19 22:29:44 -07:00
David Zhao
e0c49d3c9d Support for key/value attributes on Participant (#733)
* Support for key/value attributes on Participant

Key/value attributes lets us:
* allow various components to provide more information about the participant (i.e. SIP including the phone number)
* allow Agents to communicate their own status to the end user via RTC
* enable applications to update specific fields without overriding others

* generated protobuf

* Attribute support for SIP.

* generated protobuf

* generated protobuf

* allow specifying attributes during token generation

* Remove sip prefix and rename phone number attrs.

* regenerate protos

* update tests

* add kv attrs to sip token

* add attribute test

* changeset

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Denys Smirnov <dennwc@pm.me>
2024-06-19 22:27:09 -07:00
Denys Smirnov
32c577d805 Split SIP Trunk configuration to inbound and outbound parts. (#738) 2024-06-17 21:42:19 +03:00
David Zhao
61e656c292 Downgrade significance of number matching to patch (#740)
Since it does not change the protocol itself, downgrading to patch
2024-06-14 11:15:32 +03:00
Paul Wells
425cb974f7 update yaml config tags (#741) 2024-06-13 23:08:01 -07:00
David Zhao
725bc923f9 Unique IDs for analytics events and stats (#739)
* Unique IDs for analytics events and stats

* generated protobuf

* changeset

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-13 22:47:16 -07:00
Denys Smirnov
0411da6790 Simplify number matching rules. Make '+' optional. (#737) 2024-06-13 13:26:21 +03:00
Benjamin Pracht
114aac165b Add KillIngressSession to ingress RPC (#735) 2024-06-12 13:15:27 -07:00
David Colburn
1dd95af542 s3 session token (#734)
* s3 session token

* changeset

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-11 17:39:00 -07:00
Paul Wells
fcde125058 move analytics rpc to common rpc path (#732)
* move analytics rpc to common rpc path

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-05 23:44:24 -07:00
Paul Wells
429fec77a6 move analytics recorder service out of livekit package (#731)
* move analytics recorder service out of livekit package

* files

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-05 19:39:00 -07:00
Paul Wells
d5e9f0a2f9 refactor guid out of utils (#730)
* refactor guid out of utils

* cleanup
2024-06-05 19:07:23 -07:00
github-actions[bot]
90207b41e2 Version Packages (#715)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-06-01 23:39:34 -07:00
David Zhao
c2a0176030 Include node_id with analytics events (#727)
* Include node_id with analytics events

in order to make it easier to reconcile in a distributed setup

* generated protobuf

* changeset

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-01 23:10:00 -07:00
Paul Wells
ec704e0cf2 fix psrpc method kind metric label (#725) 2024-05-28 18:32:58 -07:00
Denys Smirnov
142d7f108f Match SIP Trunks by source IP or mask. (#724) 2024-05-28 20:55:36 +03:00
Paul Wells
c721a3ed39 add message bytes to psrpc metrics observer (#723)
* add message bytes to psrpc metrics observer

* deps
2024-05-26 12:36:38 -07:00
Lukas Herman
2ec622e468 fix: rate intermittent flaky tests (#721)
changes:
  * add retries to advance clock to unblock rate limiters
  * rewrite some tests to be more robust and simpler
  * add assertCount with noise to consider oversubscribed CI machines
  * remove parallel tests, reduce CPU pressure on CI machines
  * replaced assert with require
2024-05-24 10:40:50 -04:00
cnderrauber
6410d008bf Add forward metrics (#722)
* Add forward metrics

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-24 14:14:35 +08:00
Denys Smirnov
90dfd668f4 Add support for additional SIP transports. (#719) 2024-05-23 20:14:47 +03:00
cnderrauber
04d15340d0 Move LatencyAggregate into utils (#720) 2024-05-23 15:30:33 +08:00
Denys Smirnov
47e4c6bba7 Rename participant_identity in Transcription (#706)
There are two fields named participant_identity in context of Transcription. It's not clear which one corresponds to the transcriber agent, and which one is for the participant which got its speech transcribed.

This change renames the Transcription field to transcribed_participant_identity so to clarify that it's used for the transcribed participant.
2024-05-17 21:58:51 +03:00
Sean DuBois
5aa3d97713 Add ICERestartWHIPResource to RPC (#716)
* Add ICERestartWHIPResource to RPC

* Create witty-tomatoes-smile.md

---------

Co-authored-by: Benjamin Pracht <benjamin@livekit.io>
2024-05-14 11:44:17 -07:00
David Colburn
511f517b1a add error code to egress info (#714)
* add error code to egress info

* generated protobuf

* add changeset

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-13 10:52:57 -04:00
github-actions[bot]
04372ebead Version Packages (#708)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-13 12:06:58 +02:00
Raja Subramanian
30cee625bf Adding a simulation option for leave request. (#713)
* Adding a simulation option for leave request.

@lukasIO I was thinking of making the simulation option
just a `LeaveRequest`. And when simulating, client side
can just set `Action` field of `LeaveRequest`.
But, decided against it as I did not use case for it
and also wanted to keep it simple/specific.

Let me know if I should change that to a generic `LeaveRequest`.
If doing generic `LeaveRequest`, server behaviour would be
1. `Action = DISCONNECT`: server will close the participant and send a
   `LeaveRequest` with `Action = DISCONNECT`.
2. `Action = RESUME`, server will send `LeaveRequest` with `Action = RESUME`
   and it will not include self region in `RegionSettings`.
3. `Action = RECONNECT`, server will send `LeaveRequest` with `Action = RECONNECT`
   and it will not include self region in `RegionSettings`.

As the current simulation is only for full reconnect, it will behave
like #3 above.

Also, this option will be supported in cloud.

Please let me know if I should change this or just leave it as a
boolean.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-13 00:06:19 +05:30
Benjamin Pracht
93a26f478d Add RedactAutoEncodedOutput to support redacting auto egress types (#712)
Also redact image outputs, and support AliOSS uploads for auto egress

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-10 09:56:06 -07:00
Benjamin Pracht
dd69a5f011 Move egress request redacting routines to protocol (#711) 2024-05-09 15:26:22 -07:00
Paul Wells
e079b2245f avoid allocation from timeout queue iterator (#710) 2024-05-09 02:37:16 -07:00
Denys Smirnov
38423424ed Allow number filtering on Dispatch Rules (#707)
Allow inbound number filtering on  SIP Dispatch Rules. It works similar to Trunks, where rules without a number filter are grouped together and take less priority than number-specific rules.

While at it, simplify the rule evaluation.

Previously it was doing some hand-crafted checks for evaluation path, that matched the validation path. Same double logic existed for priorities as well.

Now the validation is always called from evaluation, thus sharing the logic. And rule selection is simplified by just picking the first one after priority filtering.
2024-05-07 19:23:35 +03:00
Paul Wells
72c0789f38 allow setting min log level for logger (#705)
* allow setting min log level for logger

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-06 22:22:14 -07:00
github-actions[bot]
5f0256e10a Version Packages (#700)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-02 19:20:07 +02:00
lukasIO
f547128159 Add changeset for #703 (#704) 2024-05-02 18:35:25 +02:00
Denys Smirnov
e0c63d7698 Add Twirp interceptor that prints curl commands (#702)
* Add Twirp interceptor that prints curl commands.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-01 22:08:30 +03:00
Théo Monnom
c286435a2d move language to TranscriptionSegment (#703) 2024-05-01 18:52:16 +02:00
Denys Smirnov
151d757a97 Expose Logger constructor for Zap (#701)
* Expose Logger constructor for Zap.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-01 13:27:48 +03:00
Denys Smirnov
e7962f4444 Pass additional metadata for SIP. (#696) 2024-04-26 13:44:03 +03:00
lukasIO
67ad5a7734 Convert changesets action output to JSON before accessing it (#699) 2024-04-26 10:38:55 +02:00
github-actions[bot]
17f16c6d15 Protocol release 1.14.0
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-26 09:21:23 +02:00
Raja Subramanian
fd19ad24b8 Deprecate UpdateVideoLayers. (#698)
* Deprecate UpdateVideoLayers.

Believe this was never used.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-26 12:00:20 +05:30
Raja Subramanian
2d50a79222 Add audio features to TrackInfo. (#697)
* Add audio features to TrackInfo.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-26 10:12:38 +05:30
Benjamin Pracht
6d5a8047e6 WHIP protocol change (#680)
This PR adds an optional "enable_transcoding" entry to the ingress APIs and deprecates the bypass_transcoding entry. This is in preparation of disabling "enable_transcoding" by default for WHIP.
2024-04-25 19:35:05 +02:00
dependabot[bot]
bad3fc9684 Bump golang.org/x/net from 0.21.0 to 0.23.0 (#695)
* Bump golang.org/x/net from 0.21.0 to 0.23.0

Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.21.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* update to go 1.23

* go 1.22

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mathew Kamkar <578302+matkam@users.noreply.github.com>
2024-04-22 10:36:05 -07:00
Paul Wells
524ca6a3a3 reduce allocations from guids (#692)
* reduce allocations from guids

* fix

* fix

* less lock thrashing
2024-04-21 13:07:37 -07:00
Paul Wells
e418881086 refactor pion prefix matching (#691) 2024-04-20 12:52:47 -07:00
Denys Smirnov
da776daae7 Add optional name for SIP participant. (#687) 2024-04-19 15:02:57 +03:00
Paul Wells
91a1cc854d lazily initialize pion loggers (#689)
* lazily initialize pion loggers

* cleanup
2024-04-18 19:00:32 -07:00
David Zhao
0bc8068edc Added changeset for Transcriptions (#686) 2024-04-18 13:01:38 -07:00
Benjamin Pracht
2bce16cdcc Transcription/Timed metadata protocol (#679)
---------

Co-authored-by: David Zhao <dz@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-18 18:27:33 +02:00
Lukas Herman
b7e396271d fix: rate limit update and slack unit (#685)
* add an atomic update to rate and slack

* fix: slack should be int instead of Duration

* add documentation to rateLimit and slack
2024-04-17 13:22:27 -04:00
David Colburn
cb008da1d6 add directOutput interface (#681) 2024-04-16 10:29:53 -07:00
Benjamin Pracht
2d633a51d8 Add updated_at field to ingress (#684)
* Add updated_at field to ingress

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-16 17:43:43 +02:00
David Colburn
e746785292 fix rpc package (#678)
* fix rpc package

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-11 14:27:17 -07:00
github-actions[bot]
ef65d2b4c8 Version Packages (#669)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-11 00:07:27 -07:00
Paul Wells
b6a979d8cf add iterator to timeseries (#677)
* add iterator to timeseries

* cleanup

* cleanup
2024-04-09 23:02:26 -07:00
Lukas Herman
c69c1b0580 add Clock interface and LeakyBucket (#675)
* add Clock interface and LeakyBucket

* add SimulatedClock

* removed self reference and format

* renamed t to lb

* replaced sync/atomic with uber/atomic

* add source to the license comment

* favor value over pointer receiver for SystemClock

* use atomic.Int value

* use mutex based instead

* add source

* update comments and hide mutex

* add SetRateLimitOnTheFly

* fix: source in rate_test

* skip unstable slack tests on Github
2024-04-09 11:32:35 -04:00
Paul Wells
fec2972501 support curried psrpc metric labels (#676) 2024-04-09 00:26:52 -07:00
renovate[bot]
14e8de50d5 chore(deps): update dependency @bufbuild/protoc-gen-es to v1.8.0 (#661)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-04 23:22:11 +02:00
renovate[bot]
0519f4b851 fix(deps): update dependency @bufbuild/protobuf to v1.8.0 (#662)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-04 18:50:58 +02:00
Théo Monnom
bc6c7ffd71 agents protocol proposal (#595)
* simulate-job

* generated protobuf

* wip

* job_cost

* Update livekit_agent.proto

* generated protobuf

* Update livekit_agent.proto

* generated protobuf

* Update livekit_agent.proto

* Update livekit_agent.proto

* Update livekit_agent.proto

* generated protobuf

* Update livekit_agent.proto

* renamed to pong

Co-authored-by: David Zhao <dz@livekit.io>

* Update livekit_agent.proto

* Update livekit_agent.proto

* generated protobuf

* remove job_cost & ParticipantPermission

* generated protobuf

* Update livekit_agent.proto

* generated protobuf

* wip

* generated protobuf

* generated protobuf

* Update livekit_agent.proto

* generated protobuf

* generated protobuf

* handler namespace

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
Co-authored-by: David Colburn <xero73@gmail.com>
2024-04-03 22:49:52 +02:00
Raja Subramanian
fc68e8d82b Add start/end time to analytics stream info (#673)
* Add start/end time to analytics stream info

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-03 12:02:58 +05:30
David Zhao
766ababa37 Include projectID in node snapshots (#672)
* Include projectID in node snapshots

* generated protobuf

* removed project_id from event & stat

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-31 13:31:40 -07:00
Denys Smirnov
93ff4a23a3 Add and option to play ringtone for SIP outbound calls. (#671) 2024-03-29 22:54:06 +02:00
Paul Wells
38f2e3216c add hedge retry helper (#670)
* add hedge retry helper

* cleanup

* fix
2024-03-28 09:48:12 -07:00
Denys Smirnov
e2c0cf8043 Support for converting Logger into slog.Handler. (#668)
This change allows to take an existing Logger and convert it into slog.Handler.

New ToSlogHandler function will check if the Logger implementation is a known one (Zap or Logr) and will convert it with package-specific functions.
2024-03-27 01:23:19 +02:00
Paul Wells
a512748415 simplify key types (#667) 2024-03-25 10:36:45 -07:00
shishirng
a2f6423fd1 Analytics client meta update (#665)
* add optional client meta fields
* generated protobuf

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 14:53:01 -04:00
Paul Wells
9b0ad21a6f export client params options helper (#666) 2024-03-22 11:11:10 -07:00
Paul Wells
0d9caadf76 simplify timed version (#664) 2024-03-21 02:45:38 -07:00
github-actions[bot]
62e1809e72 Version Packages (#654)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-19 13:28:20 +01:00
lukasIO
981fefbbe9 Add signal requests for local track updates (#651)
* Add signal requests for local track updates

* changeset

* fix indices

* fix field naming

* generated protobuf

* address comment

* generated protobuf

* Remove video features for now

* generated protobuf

* whitespace

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-19 13:26:46 +01:00
Denys Smirnov
44e9dc34b4 Allow sending DTMF when creating SIP participant (#658)
* Allow sending DTMF when creating SIP participant.

* generated protobuf

* Add changeset.

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-14 22:39:25 +02:00
Denys Smirnov
4d22b4ce36 Move CPU stats to a separate hwstats package. Fixes #659. (#660) 2024-03-14 22:24:40 +02:00
Paul Wells
feb177f216 call config observers synchronously (#657)
* call config observers synchronously

* cleanup
2024-03-13 21:34:20 -07:00
renovate[bot]
a9939bcd31 fix(deps): update module google.golang.org/protobuf to v1.33.0 [security] (#656)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-13 21:00:44 -07:00
Paul Wells
8d755b44a9 add emit config update helper (#655) 2024-03-13 16:09:39 -07:00
Denys Smirnov
912f0cf1cd Add bounds check when trimming the number. (#650) 2024-03-13 15:27:33 +02:00
lukasIO
d676388462 Fix tag name string formatting (#653) 2024-03-13 13:57:09 +01:00
github-actions[bot]
b4eb83d841 Version Packages (#652)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-13 13:43:32 +01:00
lukasIO
de46ab020c Add a v-version tag for golang module (#646)
* Add a v-version tag for golang module

* fix array access

* changeset
2024-03-13 13:40:19 +01:00
Raja Subramanian
cf54792d06 Report drift based on adjusted report time. (#648)
* Report drift based on adjusted report time.

RTCP Sender Reports from publisher are re-based to SFU time base.
Add a field to display drift based on re-mapped time.

* generated protobuf

* change name

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-13 14:00:05 +05:30
Paul Wells
34e705a573 add config observer test (#645)
* add config observer test

* cleanup
2024-03-11 16:36:54 -07:00
Paul Wells
76870e1f15 add configobserver utility (#644)
* add configobserver utility

* deps
2024-03-11 13:22:50 -07:00
David Colburn
00c977ffbb endpoint -> proxy (#638)
* endpoint -> proxy

* generated protobuf

* proxy config

* reorganize

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-11 10:47:44 -07:00
github-actions[bot]
e96e23e254 Version Packages (#643)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-11 16:12:58 +01:00
lukasIO
61bb42ead5 Simplify exports paths and re-export BigInt helper (#642)
* Simplify exports paths

* changeset

* Re-export proto bigint helper
2024-03-11 16:09:11 +01:00
github-actions[bot]
47adc43f01 Version Packages (#641)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-11 11:21:02 +01:00
lukasIO
5726c611cb Export livekit_room stubs for protocol package (#640)
* export livekit_room stubs for protocol package

* changeset

* forgot ingress
2024-03-11 11:17:58 +01:00
David Zhao
da55a5e169 Update to xsync v3 (#639) 2024-03-10 13:05:29 -07:00
renovate[bot]
497e77b264 fix(deps): update module github.com/go-jose/go-jose/v3 to v3.0.3 [security] (#631)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-10 10:46:14 -07:00
David Colburn
fae28895ef Add gcp custom endpoint (#637)
* add gcp custom endpoint

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-08 09:08:39 -08:00
github-actions[bot]
0ea9ef145f Version Packages (#636)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-08 16:30:01 +01:00
lukasIO
bf6b141cd7 Fix JS file import paths (#635)
* Fix JS file import paths

* add changeset
2024-03-08 16:26:37 +01:00
lukasIO
66b79e3526 Install protoc in release action (#634) 2024-03-08 15:59:04 +01:00
lukasIO
2aa840f1f9 Fix script name typo (#633) 2024-03-08 15:36:42 +01:00
lukasIO
c04669aee6 Separate protobufs and set up changesets publishing workflow (#629)
* Separate protobufs from module code

* update generate workflow

* install mage only

* fix paths

* generated protobuf

* fix test action

* fix cache dependency path

* setup versioning

* add golang workspace file

* delete generated files from git

* Update gitinore

* fix release workflow

* Move go code back to root

* fix working directory

* fix changeset script

* revert debug changes

* remove go cache path

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-08 10:37:35 +01:00
David Colburn
37d8b0515d add details field to egressInfo (#628)
* add details field to egressInfo

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-07 11:42:36 -08:00
Denys Smirnov
1552274d8d Accept SIP DTMF via data channel (#630)
* Accept SIP DTMF via data channel.

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-07 20:56:47 +02:00
Paul Wells
dde5199e52 add departure timeout to room create request (#626)
* add departure timeout to room create request

* gen

* cleanup

* gen
2024-03-05 08:42:05 -08:00
Paul Wells
50165a956a add departure timeout to room (#625) 2024-03-05 07:54:36 -08:00
renovate[bot]
6dd778938f fix(deps): update module golang.org/x/mod to v0.16.0 (#624)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 22:37:53 -08:00
renovate[bot]
174a2f4bdb fix(deps): update go deps (#622)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-01 22:27:42 -08:00
Denys Smirnov
7a70c5da9b Expose trunks/dispatch validation for API/CLI. Deprecate regexps for inbound. (#623) 2024-03-01 11:38:19 +02:00
renovate[bot]
4f0d066ef6 fix(deps): update go deps (#615)
* fix(deps): update go deps

Generated by renovateBot

* fix static check

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
2024-02-27 23:50:29 -08:00
Denys Smirnov
92c5e52943 Update usage of core.Fuse. (#621) 2024-02-27 22:10:02 +02:00
Benjamin Pracht
6e689b5c35 Add ImageOutput to egress EncodedOutput utils (#612) 2024-02-26 13:24:46 -08:00
Paul Wells
3339e807ff add caller to log output (#620)
* fix log caller

* add test for log output
2024-02-26 08:38:55 -08:00
Paul Wells
4a97b58328 reduce logger heap objects (#618)
* reduce logger heap objects

* deps
2024-02-26 05:35:35 -08:00
Paul Wells
19dc977fde reuse zap logger stderr lock (#617)
* reuse zap logger stderr lock

* typo
2024-02-25 13:10:13 -08:00
Paul Wells
454dff3b81 move psrpc logging/metrics utilities (#616)
* move psrpc logging/metrics utilities

* inject const labels
2024-02-24 00:21:49 -08:00
lukasIO
8a2fd58ff0 Add js protocol package (#601)
* Add js protocol package

* add agent and webhook

* fix version

* remove unneeded tsconfig

* add index type file

* Add js release action

* test workflow

* install protoc

* install nodejs first

* remove dev branch

* move into packages folder

* add other files

* add egress, ingress, sip

* fix commit path

* Add types entry point

* add gitattributes

* no dry run
2024-02-23 14:33:53 +01:00
Paul Wells
50cd638fea add stack traces to error logs (#614) 2024-02-23 01:26:09 -08:00
renovate[bot]
7efe51fa26 fix(deps): update golang.org/x/exp digest to 814bf88 (#613)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-22 22:32:50 -08:00
renovate[bot]
e8f01e457b fix(deps): update module google.golang.org/grpc to v1.62.0 (#611)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-21 20:57:04 -08:00
Paul Wells
0293e1ec08 log caller (#610)
* log caller

* fix depth
2024-02-21 14:43:29 -08:00
Paul Wells
a9e0faf6f0 allow intercepting logging (#609)
* allow intercepting logging

* roll back nats
2024-02-20 20:46:29 -08:00
renovate[bot]
233997882d fix(deps): update go deps (#607)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 17:32:18 -08:00
Paul Wells
6fbf4a2604 initialize lock tracker timestamp (#608) 2024-02-20 16:18:34 -08:00
renovate[bot]
79e078b74c fix(deps): update module github.com/redis/go-redis/v9 to v9.5.0 (#606)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-18 11:43:32 -08:00
David Zhao
51aba73c05 Update YAML keys for redis.tls config for consistency (#605) 2024-02-17 12:21:22 -08:00
Benjamin Pracht
2e75b8fb46 Add CreateIngress to IOInfoService (#604) 2024-02-14 12:57:53 -08:00
renovate[bot]
9d20a1af52 fix(deps): update go deps (#602)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-13 17:41:28 -08:00
Raja Subramanian
cee767e2d9 Close await chan when there is no change in message. (#603)
* Close await chan when there is no change in message.

Else, call sites waiting on update to be applied could hang.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-02-13 13:13:47 +05:30
renovate[bot]
16bebde903 fix(deps): update module github.com/pion/webrtc/v3 to v3.2.27 (#600)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 19:41:32 -08:00
David Colburn
611223e34f Revert egress client jitter (#599)
* revert egress client jitter

* tidy
2024-02-08 16:56:16 -08:00
renovate[bot]
ee031bdb59 fix(deps): update go deps (#586)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 08:28:55 -08:00
Denys Smirnov
d89487fdbc More specific SIP call dispatch result codes. (#596) 2024-02-08 17:54:07 +02:00
David Colburn
d010895a56 increase channel size for egress internal (#598) 2024-02-07 19:31:24 -08:00
Benjamin Pracht
9c3dabb016 Add participant_metadata to UpdateIngress (#597) 2024-02-07 14:22:07 -08:00
Benjamin Pracht
dd867b5144 Add metadata parameter to BuildIngressToken (#594) 2024-02-07 09:14:06 -08:00
Benjamin Pracht
eb3e3303ab Allow setting ingress participant metadata (#593) 2024-02-06 16:12:30 -08:00
Benjamin Pracht
cabaa7e10a Null CPU monitor for use on other platforms than linux/darwin (#592)
go-osstat only supports reporting CPU usage on linux and Darwin. We do not use it on linux, so create null cpu monitor for use on all platforms other than linux and Darwin. Display a warning to report that resource management is not supported.
2024-02-06 14:29:39 -08:00
Evgeny Volkov
e1abe07c1c tls config extension for redis (#569)
* tls config extension for redis (supported client certificates, serverName and insecure)

* review fixes
2024-02-06 12:58:28 -08:00
Raja Subramanian
39eb9f38a0 Notify disabled tracks in SyncState. (#591)
* Notify disabled tracks in SyncState.

When migrating, the new server would not know if a subscriber mute was
active on any of the subscribed tracks. Client would have to notify that
so that the new server can apply the setting upon subscription.

Add a list of disabled tracks to sync state.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-02-06 22:30:43 +05:30
Benjamin Pracht
7394a1c07b Add topic parameter to ListActiveIngress (#590) 2024-02-05 14:17:58 -08:00
Denys Smirnov
c8f2018245 Add optional token for SIP outbound. (#589) 2024-02-05 18:13:51 +02:00
Benjamin Pracht
67252493b1 Add logging_keys parameter to GetIngressInfoResponse and StartIngress (#588) 2024-01-31 11:53:04 -08:00
David Colburn
54f76fc686 add jitter to StartEgress request (#587) 2024-01-29 16:38:42 -08:00
Raja Subramanian
31b03e6905 Augment LeaveRequest with alternate regions. (#585)
* Augment LeaveRequest with alternate regions.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-25 14:07:57 +05:30
Denys Smirnov
f56f11e568 Generate unique room names for SIP. (#584) 2024-01-24 22:16:54 +02:00
Denys Smirnov
3bd4ca5433 Remove unused SIP participant APIs. (#578) 2024-01-24 18:38:16 +02:00
renovate[bot]
34c5703691 fix(deps): update module google.golang.org/grpc to v1.61.0 (#583)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-23 21:09:49 -08:00
renovate[bot]
3b4fd6ea4a fix(deps): update golang.org/x/exp digest to 1b97071 (#580)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-21 21:18:39 -08:00
Paul Wells
9e82495c04 add psrpc redis keepalive (#582)
* add psrpc redis keepalive

* generated protobuf

* codegen

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-21 06:12:01 -08:00
renovate[bot]
9430659b3b chore(deps): update actions/cache action to v4 (#576)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-20 16:28:25 -08:00
Raja Subramanian
4f497ff252 Reverting adding controller id and selection reason to start session (#581)
* Reverting adding controller id and selection reason to start session

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-20 12:10:21 +05:30
Raja Subramanian
9786b97e9c Add ControllerId and SelectionReason to StartSession. (#579)
* Add ControllerId and SelectionReason to StartSession.

This will allow media node to have those information.
Main purpose will be able to log it in all in one context.

* generated protobuf

* change name from controller_id -> controller_node_id

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-19 15:29:47 +05:30
Paul Wells
cf33ad3861 remove psrpc enabled config (#577)
* remove psrpc enabled config

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-18 03:25:40 -08:00
lukasIO
6dc023d7ed Add simulate scenarios for disconnecting signal during connection resume (#575)
* Add simulation of disconnect_signal_on_resume.

* generated protobuf

* simulate signal on resume no messages

* generated protobuf

---------

Co-authored-by: boks1971 <raja.gobi@tutanota.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-17 16:58:16 +05:30
David Colburn
e17b08e9a4 Add topics to ListActiveEgress (#574)
* add topics to ListActiveEgress

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-16 17:03:18 -08:00
Denys Smirnov
2e48332992 Pass participant kind in the grant. (#571) 2024-01-16 17:19:18 +02:00
Sean DuBois
8ad4c79e2d Enable topics for InternalUpdateSIPParticipant (#573) 2024-01-12 16:06:31 -05:00
renovate[bot]
3d9c1f2c79 fix(deps): update go deps (#572)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-12 09:36:03 -08:00
renovate[bot]
701a31e4f6 fix(deps): update golang.org/x/exp digest to 0dcbfd6 (#568)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-10 15:01:55 -08:00
renovate[bot]
0811dbfe03 fix(deps): update module github.com/redis/go-redis/v9 to v9.4.0 (#566)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-07 10:31:53 -08:00
Raja Subramanian
a0e8241b1a Return a clon of message so that internal field does not get mutated by (#565)
some body else modifying using the reference.
2024-01-05 16:47:49 +05:30
renovate[bot]
4c708cfc9c fix(deps): update golang.org/x/exp digest to be819d1 (#564)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-03 16:18:12 -08:00
shishirng
4f3e8bebf9 Add projectID key to event, stat (#562)
* Add projectID key to event, stat
* generated protobuf

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-03 06:03:18 -05:00
Paul Wells
ce67e4e290 simplify deferred logger flush (#563)
* simplify deferred logger flush

* test

* test
2024-01-03 00:23:31 -08:00
Paul Wells
01b5f081d6 add timed version to room (#561)
* add version to room

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-30 01:41:20 -08:00
Paul Wells
e3a3fe05e3 allow waiting for protoproxy update (#560) 2023-12-30 01:41:02 -08:00
Paul Wells
bbf0ee4d3d add sql value support to timed version (#559) 2023-12-30 01:40:33 -08:00
renovate[bot]
00aac29859 fix(deps): update module github.com/prometheus/client_golang to v1.18.0 (#558)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-27 20:09:44 -08:00
renovate[bot]
9f667267f8 fix(deps): update golang.org/x/exp digest to 02704c9 (#557)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-25 17:52:30 -08:00
shishirng
80e8b5a2d1 analytics: send local room state (#554)
* Add IngestNodeRoomState for sending node's room state
* generated protobuf

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-22 18:44:45 -05:00
renovate[bot]
00894c56f4 Update module google.golang.org/protobuf to v1.32.0 (#556)
* Update module google.golang.org/protobuf to v1.32.0

Generated by renovateBot

* generated protobuf

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-22 09:40:18 -08:00
Paul Wells
927be345ba fix lock tracker incremental scan (#555) 2023-12-21 16:50:17 -08:00
renovate[bot]
1442b24a4e Update module github.com/go-logr/logr to v1.4.1 (#552)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 16:19:08 -08:00
Paul Wells
e9e5fcd7d3 fix typo (#553) 2023-12-21 02:03:46 -08:00
renovate[bot]
88366c462f Update go deps (#546)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 23:57:55 -08:00
Paul Wells
b038d892cb add deferred logger (#551) 2023-12-20 23:02:43 -08:00
dependabot[bot]
b41cfc907b Bump golang.org/x/crypto from 0.16.0 to 0.17.0 (#550)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-20 17:04:28 -08:00
David Zhao
c09e8e07fd Added AgentRegistered broadcast to clients (#549)
* Added AgentRegistered broadcast to clients

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-20 08:09:56 -08:00
Sina Shabani
66b6b22962 Adds Redis pool size and timeout (#516) 2023-12-18 23:09:14 -08:00
Raja Subramanian
8fb7e76324 Add Version to TrackInfo. (#548)
* Add Version to TrackInfo.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-19 11:42:22 +05:30
Denys Smirnov
3045ec7650 Add Type for a Participant. (#542) 2023-12-14 03:35:06 +02:00
Benjamin Pracht
b5b083960d Implement exponential backoff in egress RPC client retry logic (#545) 2023-12-13 15:22:37 -08:00
renovate[bot]
8950f73cd1 Update module google.golang.org/grpc to v1.60.0 (#543)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-11 23:16:41 -08:00
Paul Wells
a2b800d10c generate lightweight stack traces for stuck locks (#544)
* generate lightweight stack traces for stuck locks

* x/slices
2023-12-11 20:41:41 -08:00
renovate[bot]
297e4990e7 Update golang.org/x/exp digest to f3f8817 (#541)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 22:26:09 -08:00
renovate[bot]
2ed21c5cf7 Update actions/setup-go action to v5 (#539)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 16:48:41 -08:00
David Colburn
7bba17ea78 remove ps, remove noisy error logs (#540) 2023-12-06 09:46:12 -08:00
renovate[bot]
7a29c2ea3a Update go deps (#528)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-05 13:51:36 -08:00
David Colburn
4bd1ed6a02 process monitoring (#529)
* process monitoring

* generated protobuf

* don't need min

* updates

* fix float

* update names, cpu calculation

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-05 10:46:13 -08:00
Sean DuBois
a64882f692 Add token and ws_url to EvaluateSIPDispatchRulesResponse (#538) 2023-12-04 13:48:53 -05:00
Sean DuBois
5ffa9f0c65 Add called host to SIP Trunk+DispatchRule request (#537) 2023-12-04 11:40:31 -05:00
David Zhao
afa0350bcd Add call depth to Pion logger (#536)
Currently all pion logs are showing a caller within the logger itself, which is incorrect
2023-12-02 10:16:55 -08:00
Denys Smirnov
ec88d89da1 Move SIP rules from LiveKit server. (#534) 2023-11-30 12:36:07 -05:00
David Colburn
3b3c5b2329 fix clientParams assumptions (#533) 2023-11-29 15:21:39 -08:00
Paul Wells
6b5d53eb96 add last read time to link report (#532) 2023-11-29 11:00:05 -08:00
Raja Subramanian
1c3f5fe919 Rename ConnectionQuality DISCONNECTED -> LOST (#531)
* Rename ConnectionQuality DISCONECTED -> LOST

DISCONNECTED seems to indicate that it is irreversible.
LOST is short and does not have that terminal kind of feel.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 23:05:44 +05:30
David Zhao
ff80e6fd1b Docs for Egress storage fields (#530)
* Docs for Egress storage fields

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 09:35:07 -08:00
David Zhao
61e646265f Improve consistency for Egress/Ingress client constructors (#526)
Other psrpc clients are using this syntax to set logger, default timeouts/etc
2023-11-27 22:55:55 -08:00
spennihana
fd7066503f [S3 Upload] Add content disposition field (#525) 2023-11-27 13:48:43 -08:00
Raja Subramanian
1dda6d8eb0 Add DISCONNECTED to ConnectionQuality (#527)
* Add  to ConnectionQuality

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-27 22:56:39 +05:30
Raja Subramanian
3f612979d8 Traffic load (#524)
* Traffic load

Protos for representing simple traffic information, just packets and
bytes.

* generated protobuf

* utils

* add TrafficLoadToTrafficRate

* clean up proto

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-26 22:43:22 +05:30
Denys Smirnov
0cb26043c3 Update SIP protocol for outbound calls. (#523) 2023-11-21 10:37:49 -08:00
renovate[bot]
7a00fc1a03 Update module github.com/livekit/psrpc to v0.5.2 (#522)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-19 09:28:57 -08:00
Denys Smirnov
aa43aa7482 Update SIP protocol (#520)
* SIP: Remove redundant SIPDispatchRulePin.

* SIP: Add NoPin flag to the EvaluateSIPDispatchRulesRequest.
2023-11-16 09:17:04 -05:00
renovate[bot]
9b360fc73e Update module github.com/pion/webrtc/v3 to v3.2.23 (#521)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-16 00:22:51 -08:00
Paul Wells
cfc741037c use shortuuid alphabet for guid encoding (#519) 2023-11-15 08:06:05 -08:00
Raja Subramanian
7afb922269 Log webhook event details. (#518)
* Log webhook event details.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-14 15:00:32 +05:30
Sean DuBois
e65cc3e9fe Add SIP RPC (#514) 2023-11-13 20:25:16 -05:00
renovate[bot]
6c267cfdfc Update module github.com/livekit/psrpc to v0.5.1 (#517)
* Update module github.com/livekit/psrpc to v0.5.1

Generated by renovateBot

* generated protobuf

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-13 15:53:20 -08:00
renovate[bot]
43d65340ff Update go deps (#515)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-10 22:24:37 -08:00
renovate[bot]
625c7d8020 Update go deps (#504)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-09 11:36:41 -08:00
David Colburn
e230ee2d84 Add agent to participant permission (#513)
* add agent to participant permission

* generated protobuf

* agent values

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-07 10:51:01 -08:00
David Colburn
9020450e5f add CheckEnabled rpc (#512)
* add CheckEnabled rpc

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-06 16:28:16 -08:00
David Colburn
6d382559cf Agents (#511)
* rebased

* regenerate

* generated protobuf

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-03 11:22:11 -07:00
Sean DuBois
9f01c9ed76 Add SIP Support (#507) 2023-11-01 23:29:23 -04:00
Paul Wells
4a12e0152e increase default psrpc timeout (#510)
* increase default psrpc timeout

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-31 23:10:46 -07:00
Paul Wells
02a4a42603 split room service (#509)
* split room service

* generated protobuf

* cleanup

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-31 21:08:27 -07:00
David Zhao
873785a90b Bump protoc version (#506)
* Bump protoc version

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-27 12:28:06 -07:00
David Colburn
da745471e8 remove deprecated rpc (#505)
* remove deprecated rpc

* generated protobuf

* update add changes path

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-26 12:48:54 -07:00
Paul Wells
f8b1277b3c update psrpc (#503)
* update psrpc

* dep

* fix generate
2023-10-25 20:06:39 -07:00
Paul Wells
07ca9d4e47 update psrpc (#501) 2023-10-23 19:43:26 -07:00
David Colburn
b34cb4eb7f psrpc 0.3.4 (#500)
* psrpc 0.3.4

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-23 16:35:55 -07:00
David Colburn
197fbc31df audio + video quality (#499)
* audio + video quality

* generated protobuf

* remove override comment

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-23 13:32:52 -07:00
David Colburn
0a1ad709d1 add quality, remove updateOutputs (#498)
* add quality, remove updateOutputs

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-23 12:39:13 -07:00
Paul Wells
5fd3ded802 add missing service fake (#497) 2023-10-22 22:27:29 -07:00
Paul Wells
26c91640f8 add room psrpc interface (#496)
* add room psrpc interface

* update potos
2023-10-22 22:20:51 -07:00
David Colburn
fac7f187fc combine all egress requests into IOInfo (#495)
* combine all egress requests into IOInf
o

* generated protobuf

* increase StartEgress timeout

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-18 12:46:36 -07:00
renovate[bot]
25bcccdb94 Update module google.golang.org/grpc to v1.59.0 (#494)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-17 18:15:22 -07:00
David Zhao
102818c393 Fix protoproxy test flakiness (#493) 2023-10-15 16:22:34 -07:00
renovate[bot]
a8ab5b3eda Update go deps (#469)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-15 15:27:44 -07:00
Mathew Kamkar
37fc34151e update deps (#491) 2023-10-13 19:33:16 -07:00
Paul Wells
97f4c927dd add psrpc middleware to suppress errors (#490) 2023-10-05 13:44:26 -07:00
Paul Wells
a187ed4f54 check psrpc compiler version (#489)
* check psrpc compiler version

* fix
2023-10-03 04:11:40 -07:00
Paul Wells
525419ade0 truncate bytes in proto logs (#488)
* truncate bytes in proto logs

* fix
2023-10-01 19:38:23 -07:00
David Zhao
19fdb609a9 Fixed multirpc logging (#487) 2023-10-01 19:28:19 -07:00
Paul Wells
5b156a9beb simplify bitmap range ops (#486)
* simplify bitmap range ops

* tidy
2023-09-29 23:17:45 -07:00
Benjamin Pracht
a020215c5c Improve consistency of some egress images fields naming (#485) 2023-09-29 12:36:53 -07:00
Benjamin Pracht
a73f47fb8b Add egress image output (#457) 2023-09-28 15:01:38 -07:00
cnderrauber
281e00a4a6 Move playout_delay & sync_streams to internal model (#484)
* Move playout_delay & sync_streams to internal model

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 14:58:09 +08:00
cnderrauber
fcfd77e3a3 Add SyncStreams flag to room (#483)
* Add SyncStreams flag to room

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-28 14:04:11 +08:00
David Colburn
b6137b803b retry on unavailable (#482) 2023-09-25 14:30:22 -07:00
Paul Wells
9087b5d95a disable tracking lock stack traces by default (#481) 2023-09-23 15:25:17 -07:00
cnderrauber
821c244d8c Add generic type cast for ids and strings (#478) 2023-09-20 16:49:13 +08:00
Raja Subramanian
0708b5a5bb Mark marshallable fields with yaml and omitempty (#477) 2023-09-19 23:54:18 +05:30
cnderrauber
dd24d07183 Add max playoutdelay (#476)
* Add max playoutdelay

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-18 21:05:19 +08:00
Paul Wells
eae220ae8d add infra link service (#474)
* add infra link service

* cleanup
2023-09-17 04:19:33 -07:00
Raja Subramanian
cf9f95141e bit map (#473)
copying Paul's go playground mostly.
2023-09-16 01:53:28 +05:30
David Colburn
933a0f5464 add auto participant egress (#472)
* add auto participant egress

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-13 21:38:55 -07:00
Paul Wells
1f2c03c3e5 add unimplemented psrpc metrics observer for tests (#471) 2023-09-13 21:09:23 -07:00
Benjamin Pracht
2770beb37a Add ingress high motion presets (#470) 2023-09-13 18:01:32 -07:00
Raja Subramanian
47d330eafb Log Pion trace level logs at Debug level. (#468) 2023-09-11 21:35:09 +05:30
renovate[bot]
0b9fd43dce chore(deps): update magefile/mage-action action to v3 (#467)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-10 14:45:48 -07:00
renovate[bot]
60ffcadbac fix(deps): update module github.com/pion/webrtc/v3 to v3.2.19 (#466)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-08 15:22:13 -07:00
David Zhao
8dbc929ca4 Allow RoomService.SendData to use participant identities (#464)
* Allow RoomService.SendData to use participant identities

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-08 13:58:55 -07:00
renovate[bot]
c32b942fd3 fix(deps): update module google.golang.org/grpc to v1.58.0 (#463)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-07 00:42:49 -07:00
renovate[bot]
2d65160247 fix(deps): update go deps (#454)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-05 23:20:24 -07:00
Paul Wells
fc1aa19ec2 add psrpc logger middleware (#461)
* add psrpc logger middleware

* missing file
2023-09-05 10:10:50 -07:00
Paul Wells
079ca0da61 add function to get graph node ids (#462) 2023-09-05 10:09:31 -07:00
renovate[bot]
946a39bf5d chore(deps): update actions/checkout action to v4 (#459)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-05 00:06:00 -07:00
Benjamin Pracht
ce275be4e6 Add entries for live playlist support (#458) 2023-08-30 14:46:03 -07:00
Raja Subramanian
dfb5162c7c RTPDrift as a separate model. (#456)
* RTPDrift as a separate model.

* generated protobuf

* remove deprecated stuff

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-29 00:13:41 +05:30
David Colburn
9f0a8f87da Participant composite (#443)
* participant composite egress

* generated protobuf

* remove composite

* generated protobuf

* export GetOutputType

* generated protobuf

* remove duplicate code

* add screenshare option

* revert psrcp

* generated protobuf

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-25 00:01:27 -07:00
Benjamin Pracht
ecca17670d Add ENDPOINT_COMPLETE ingress state (#455) 2023-08-24 13:49:03 -07:00
David Zhao
eb956a83ae Use identity when delivering data messages (#453)
* Use identity when delivering data messages

Participant ID is specific to a connection, and can be tricky to determine.
Allowing data messages to be delivered by identity instead

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-19 18:00:04 -07:00
renovate[bot]
923c1cfa18 fix(deps): update go deps (#450)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-18 12:23:19 -07:00
Raja Subramanian
74c0ca0a5b update psrpc (#452)
* update psrpc

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-18 12:19:39 +05:30
cnderrauber
13abb13b71 remove unused field (#451)
* remove unused field

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-17 15:52:18 +08:00
renovate[bot]
e0eaae8584 fix(deps): update module github.com/maxbrunsfeld/counterfeiter/v6 to v6.7.0 (#449)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-16 10:24:44 -07:00
Benjamin Pracht
14b7eb70d2 Update ingress layer validation logic to make sure both dimensions increase for each layer (#447)
This is a preamble to changing the ingress logic to boxing the input video into the layer dimension, instead of resizing to the layer dimensions regardless of aspect ratio.

This may cause some existing ingress to stop working.
2023-08-11 16:13:53 -07:00
renovate[bot]
f2f3cad866 fix(deps): update golang.org/x/exp digest to 89c5cff (#446)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-11 15:09:39 -07:00
David Colburn
6b455c1116 silence notifier http client (#445)
* notifier log error -> warn

* silence all
2023-08-10 12:29:58 -07:00
renovate[bot]
3892d26946 fix(deps): update golang.org/x/exp digest to 352e893 (#444)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-09 21:46:21 -07:00
David Colburn
24573198ef update egress intefaces (#442) 2023-08-08 13:39:25 -07:00
renovate[bot]
536a3e888e fix(deps): update golang.org/x/exp digest to 050eac2 (#441) 2023-08-08 01:19:37 -07:00
renovate[bot]
f31745a2f2 fix(deps): update go deps (#437)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-05 13:23:06 -07:00
David Zhao
f3bba12b3e Component support for logger (#436)
* Component support for logger

With the ability to dynamically update log levels per component

* support hierarchical config

* consolidate pion logger to use components
2023-08-03 11:59:04 -07:00
Benjamin Pracht
405389fa48 Support URL pull in ingress (#438) 2023-08-03 10:14:19 -07:00
cnderrauber
d791f31b6e Add playoutdelay to CreateRoomRequest (#439)
* Add playoutdelay to CreateRoomRequest

* generated protobuf

* Remove max from PlayoutDelay

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-03 16:11:22 +08:00
Raja Subramanian
caf65ebc47 Filter out a TURN log. (#440)
Most frequent error, but all of it is due to non-existent stuff.
Plus, not watched for any debugging.
2023-08-03 12:39:07 +05:30
renovate[bot]
881a872e15 fix(deps): update golang.org/x/exp digest to d63ba01 (#434)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-01 21:31:20 -07:00
Théo Monnom
3cd286c9c2 add python & cpp sdk to clientinfo (#435)
* add python & cpp sdk to clientinfo

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-01 20:34:41 -07:00
Raja Subramanian
d45d830f69 De-duped slice util (#433) 2023-07-29 18:17:40 +05:30
renovate[bot]
5ca6b8f6bc fix(deps): update golang.org/x/exp digest to b0cb94b (#432)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-28 16:42:57 -07:00
David Zhao
f38c24c72d Skip noisy TURN log (#430) 2023-07-27 19:42:19 -07:00
Paul Wells
e1a077ae92 move timeout queue helper to utils (#431) 2023-07-27 19:40:59 -07:00
David Zhao
c9e9ae555f Add license headers & NOTICE (#429)
* Add license headers & NOTICE

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-27 16:43:25 -07:00
renovate[bot]
49975d3873 fix(deps): update module google.golang.org/grpc to v1.57.0 (#428)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-26 17:09:23 -07:00
Benjamin Pracht
357ef3ca23 Add average_bitrate to ingress state (#427) 2023-07-26 13:28:35 -07:00
renovate[bot]
e3b3e994e9 fix(deps): update golang.org/x/exp digest to 515e97e (#425)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-26 13:07:57 -07:00
David Colburn
5cbcc24208 Remove deprecated egress rpc (#426)
* remove old rpc system

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-25 17:11:32 -07:00
renovate[bot]
cd2fe7d63f fix(deps): update go deps (#418)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-20 19:16:23 -07:00
David Zhao
1cc5a5d915 Fix rare race condition with missed protoproxy update. (#424)
Also do not update refreshedAt unless content has changed
2023-07-19 14:31:52 -07:00
Raja Subramanian
9d0d6c9e94 Do not update if the model does not change. (#423)
* Do not update if the model does not change.

* No need for equality function

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-15 13:58:01 +05:30
Benjamin Pracht
3c53edc919 Move pprof support to protocol. Allow listing ingress by ingress ID. (#422) 2023-07-14 09:02:26 +08:00
David Colburn
71d539707e Egress request metadata (#421)
* request metadata

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-12 21:37:03 -04:00
David Colburn
7d8704997b Add location to startEgressRequest (#420)
* add location to startEgressRequest

* generate

* generated protobuf

* psrpc 0.3.2

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-12 20:25:00 -04:00
Benjamin Pracht
b0d723aaa9 Export redactStreamKey as RedactIdentifier (#419) 2023-07-11 15:41:19 +08:00
Benjamin Pracht
193f7bd191 Move redact.go from egress (#417) 2023-07-11 08:39:53 +08:00
renovate[bot]
fc3437606a fix(deps): update go deps (#416)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-08 22:58:39 -07:00
renovate[bot]
fefcd74b77 fix(deps): update go deps (#399)
* fix(deps): update go deps

Generated by renovateBot

* generated protobuf

* improve protoproxy test reliability

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
2023-07-08 22:48:29 -07:00
kannonski
8460641348 Fix livekit-server termination after Redis master switch over (#401)
Fixes livekit/livekit#1559
2023-07-08 22:36:12 -07:00
Paul Wells
99e39d9896 add math utils (#415) 2023-07-05 23:39:19 -07:00
David Colburn
424b21fd0e retry on egress timeout or resource exhausted (#414) 2023-07-05 14:55:02 -07:00
cnderrauber
448dac4d68 Add stream to track request/info (#411)
* Add stream to track request/info

* Add PlayoutDelay to RoomConfig

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-03 15:37:52 +08:00
Raja Subramanian
e5323cdb4a Timed aggregator. (#412)
* Timed aggregator.

Online aggretor over time.

Samples added aggregate (scaled by amount of time a sample
has lived for) at the time of adding sample.

Can get aggregate, aggregate duration and average value later.

First use: in scorer to keep track of aggregate bandwidth, average
distance from desired layer

* Feedback + check for backwards time in getters.
2023-07-01 09:58:48 +05:30
Benjamin Pracht
8e67918879 Add stream_key to DeleteWHIPResourceRequest (#413) 2023-06-30 14:52:51 -07:00
David Colburn
cda2a8ac91 Use floats for cpu (#410)
* use floats for cpu

* change CPUStats.NumCPU

* missed a return
2023-06-29 18:29:18 -07:00
Benjamin Pracht
0644d9a979 Fix NumCPU implementation for cgroup v1 (#409) 2023-06-29 16:07:10 -07:00
Benjamin Pracht
5cff0336ab Add resourceID to IngressState (#408) 2023-06-28 18:50:34 -07:00
Paul Wells
519c96683d add graph node delete method (#407) 2023-06-22 10:20:00 -07:00
Paul Wells
c108af2ebf allow annotating rather than omitting field sampler matches (#406) 2023-06-20 18:14:38 -07:00
Benjamin Pracht
ce9e603cfd Make the framerate field a double in InputVideoState (#405) 2023-06-20 09:16:27 -07:00
Paul Wells
089430752e add room log sampler (#404)
* add room log sampler

* go deps

* feedback

* cleanup
2023-06-18 17:50:42 -07:00
Raja Subramanian
89359963fc Spelling (#403)
* Spelling

* mage bootstrap

* generated protobuf

* SE_UNKNOWN

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-14 23:08:26 +05:30
David Zhao
7d128913f3 Create missed queueUpdate channel for ProtoProxy (#402)
This caused immediate updates to not go through right away.
2023-06-10 20:06:50 -07:00
Paul Wells
6cb3e577e2 make graph accessors consistent (#400) 2023-06-08 05:55:54 -07:00
David Colburn
0aad9fb9e7 add updatedAt to egressInfo (#398)
* add updatedAt to egressInfo

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-07 11:38:07 -07:00
renovate[bot]
1838b80b57 fix(deps): update module github.com/hashicorp/go-retryablehttp to v0.7.4 (#395)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-06 23:26:59 -07:00
shishirng
01ae0cb0fa Add EGRESS/INGRESS UPDATE events (#396)
* Add EGRESS/INGRESS UPDATE events

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-06 14:14:33 -04:00
renovate[bot]
7f36858dcf fix(deps): update go deps (#384)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 22:22:50 -07:00
Paul Wells
d8cc358109 add event observer list util (#394)
* add event observer list util

* update psrpc

* update codegen

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-05 18:22:16 -07:00
David Colburn
a186ecb11a Add await start to web egress (#393)
* add await start to web egress

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-01 14:21:00 -07:00
Mikhail Chekh
89c91393d0 Fix call numCPU in root cgroup (#388) 2023-05-31 10:14:46 -07:00
cnderrauber
2a4d1a607b Add TrackNotFound to Subscription Error (#392)
* Add TrackNotFound to Subscription Error

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-31 11:08:40 +08:00
lukasIO
262f7eca9b Fix typo in subscription response (#391)
* fix typo in subscription response

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-30 15:29:12 +02:00
cnderrauber
b8c7e33fa0 Add SubscriptionResponse signal message (#390)
* Add SubscriptionResponse signal message

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-30 18:15:27 +08:00
David Zhao
dbea81ff07 Log adapter for retryablehttp (#389)
* Log adapter for retryablehttp

* call depth of 1
2023-05-29 10:38:45 -07:00
Benjamin Pracht
52cca4239c Add Audio/Video options for passthrough (#387) 2023-05-25 15:57:06 -07:00
David Zhao
4c2100267b ability to disable codecs only for publish (#386)
* ability to disable codecs only for publish

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 21:23:59 -07:00
lukasIO
efad03ffe4 Add server injected frame trailer bytes to join response (#381)
* Add server injected frame trailer bytes to join response

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 09:49:55 +02:00
renovate[bot]
eefdb3b712 fix(deps): update go deps (#383)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-18 21:53:05 -07:00
shishirng
8999a6b785 send min and median connection scores (#382)
* Send min and media connection scores along with avg(current score)
* generated protobuf

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 13:13:13 -04:00
renovate[bot]
3af63581bf fix(deps): update go deps (#375)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-18 09:32:06 -07:00
Paul Wells
08ebbda448 add graph util (#380) 2023-05-14 22:26:51 -07:00
Paul Wells
c3734b9b46 add event emitter (#379)
* add director node type

* add event emitter

* add tests

* generated protobuf

* feedback

* correct require

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 20:42:41 -07:00
Raja Subramanian
c5dc103838 Add sample rate and drift to RTP stats (#378)
* Add sample rate and drift to RTP stats

* make tests a bit more robust

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 14:38:13 +05:30
Paul Wells
26fe70550b add b62 encoding for guids (#376)
* add b62 encoding for guids

* add test

* cleanup

* cleanup
2023-05-12 11:59:53 -07:00
Paul Wells
40c26a892d add structured logging for protobuf messages (#377) 2023-05-12 11:03:44 -07:00
David Colburn
cadccd5410 update notifier (#374)
* update notifier

* update drop test

* fix draining

* change webhookCheckInterval back
2023-05-09 17:21:13 -07:00
Paul Wells
e2f4e65f58 record stack trace in lock tracker (#373)
* record stack trace in lock tracker

* copy stack
2023-05-07 02:02:38 -07:00
David Zhao
ac74d1e920 Periodically process webhooks queue, in case an event was not flushed (#372)
* Periodically process webhooks queue, in case an event was not flushed

* more resilient goroutines check

* added more logging
2023-05-05 16:35:07 -07:00
renovate[bot]
6c978d46a6 fix(deps): update module google.golang.org/grpc to v1.55.0 (#371)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-04 22:34:08 -07:00
renovate[bot]
466f2f5cfe fix(deps): update module go.uber.org/atomic to v1.11.0 (#370)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-03 21:23:50 -07:00
David Colburn
22791f5141 GetTypes (#369)
* GetTypes

* remove websocket type
2023-05-03 12:19:11 -07:00
renovate[bot]
dcea9e925a fix(deps): update go deps (#364)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-03 10:01:21 -07:00
Benjamin Pracht
b2974692eb Move ErrInvalidIngressType to protocol (#368) 2023-05-01 14:37:48 -07:00
Benjamin Pracht
59f4b65928 Move the WHIP RPC handler to IngressHandler (#367) 2023-04-28 14:25:33 -07:00
Benjamin Pracht
db5afb1c7f Protocol support for WHIP ingress (#366)
The pion logger package was extracted from livekit-server. The err_array code is from egress.
2023-04-27 18:13:59 -07:00
Paul Wells
79477e28a1 add signal relay close prop (#365) 2023-04-26 22:50:46 -07:00
renovate[bot]
5ea01f3d4a fix(deps): update go deps (#362)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-24 21:27:33 -07:00
Raja Subramanian
c54f5f7f41 Adding a few more bits (#361)
- getting samples after some time
- getting linear extrapolated value

some day, I will use all of these :-)
2023-04-24 13:09:01 +05:30
renovate[bot]
33317cadbc fix(deps): update module github.com/pion/webrtc/v3 to v3.1.61 (#360)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-23 21:53:06 -07:00
David Zhao
eee263b380 Improve protoproxy test reliability (#359) 2023-04-22 21:09:04 -07:00
David Zhao
a68f38ce7d Added ProtoProxy util, NumPublishers field (#358)
ProtoProxy achieves two goals:
- avoids needless regeneration of readonly protobufs
- update certain changes periodically
2023-04-22 20:25:51 -07:00
Paul Wells
eb3ef0f4bf add method to check if timed version is uninitialized (#357) 2023-04-22 06:14:40 -07:00
Raja Subramanian
6707e562d4 Adding a collapse duration for repeated values. (#356)
* Adding a collapse duration for repeated values.

Hoping to use this struct more widely. Hopefully in stream allocator.
That's what I am looking at now.

* add kendall's tau

* introduce update op latest
2023-04-22 11:23:06 +05:30
Raja Subramanian
3058e52593 Moving timeseries to own module and adding more stats/tests. (#355)
* Moving timeseries to own module and adding more stats/tests.

* clean up
2023-04-22 09:33:22 +05:30
renovate[bot]
31f880940e fix(deps): update golang.org/x/exp digest to 133eef4 (#352)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-21 12:28:10 -07:00
David Colburn
0975cb52f6 Update psrpc (#354)
* psrpc 0.3

* generated protobuf

* bootstrap install latest

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-21 12:22:04 -07:00
renovate[bot]
1e793a8870 fix(deps): update go deps (#349)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-16 21:53:46 -07:00
David Zhao
d2054890a6 Fix incorrectly wiping out dropped count (#351) 2023-04-16 09:33:59 -07:00
David Zhao
f54aaadb8c Revamped notifier to avoid out of order delivery (#350)
Moving to a structure where each URL occupies their own delivery goroutine.
This avoids blocking of notifications to other URLs.
2023-04-15 01:04:56 -07:00
renovate[bot]
2f08c82d22 fix(deps): update module github.com/prometheus/client_golang to v1.15.0 (#348)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-13 15:08:39 -07:00
Raja Subramanian
5fea69067b Explicitly set if subscriber_allow_pause is valid (#347)
* Explicitly set if subscriber_allow_pause is valid

Need to know if `false` (which would be default if not set) is
explicitly set or not.

* generated protobuf

* Use optional, thank you Lukas

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-13 16:49:58 +05:30
Raja Subramanian
bfe64b24ff SubscriberAllowPause as a connection option. (#346)
* `SubscriberAllowPause` as a connection option.

This allows controlling stream allocator allow pause or not decision
through a connection option.

NOTE: Thinking ahead a bit, would we allow pause or not at a track
level? We are going to do subscription priority. Maybe, we can also
allow pause or not at track level by adding it to `UpdateTrackSettings`.
Wondering if things are going to be confusing if we do that also.
I think the hierarchy would be (order of increasing precedence)
- from config
- connection option added in this PR will take effect if set
- track level allow pause config if we decide to do this (have to
  make sure that we can determine that the value was explicitly set in
  the protocol message vs using default value in protocol message).

* psrpc updated compile

* generated protobuf

* update bootstrap psrpc

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-13 16:08:19 +05:30
David Zhao
2956c3424f Improve webhook resilience with retryablehttp (#345) 2023-04-12 16:28:35 -07:00
Benjamin Pracht
f70173e98e Improve IngressInfo validation for serialization use cases. Also enforce even layer dimensions (#344) 2023-04-12 13:16:17 -10:00
Benjamin Pracht
0947b07013 Allow empty layer array (#343) 2023-04-10 07:32:37 -10:00
Paul Wells
30f8b4c081 add sequence and batch request fields for signal (#342)
* add sequence and batch request fields for signal

* codegen

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-09 18:11:18 -07:00
Paul Wells
0f2f2cde6f update psrpc (#341) 2023-04-07 23:09:19 -07:00
David Zhao
b911c52c6d Fixes CanPublishSource check, added helper functions (#340) 2023-04-07 17:56:05 -07:00
Benjamin Pracht
48e7d8e34e Validate ingress info encoding parameters (#339) 2023-04-07 11:43:56 -07:00
Paul Wells
927c9ea2b4 add responses field to signal relay response (#338)
* add responses field to signal relay response

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 12:56:05 -07:00
Benjamin Pracht
802309c658 Work around phantom CPU core reporting in group v1 (#337) 2023-04-05 12:46:50 -07:00
Paul Wells
8c8b87686b update psrpc (#336)
* update psrpc

* generated protobuf

* cleanup

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 03:33:03 -07:00
David Zhao
47b8b5fce6 Add region settings message. (#335)
* Add region settings message.

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-04 20:51:22 -07:00
David Zhao
a1a39a16f4 Update from square/go-jose.v2 to go-jose/go-jose/v3 (#334)
square/go-jose is deprecated
2023-04-04 18:09:17 -07:00
renovate[bot]
86bb95f8e6 fix(deps): update go deps (#327)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-02 13:44:05 -07:00
David Zhao
c2bf62e740 Simulated subscriber bandwidth (#333)
* Simulated subscriber bandwidth

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-31 23:14:38 -07:00
Paul Wells
2336d2c655 Revert "add clock offset to timed version generator (#330)" (#332)
This reverts commit 7488296390.
2023-03-30 17:30:29 -07:00
Raja Subramanian
f1bba9bc14 Adding a time series utility. (#331)
* Adding a time series utility.

Also adding a `SWEEPER` node type.

* generated protobuf

* regen with protoco 3.21.12

* generated protobuf

* remove unnecessary prune calls

* slice -> list

* correct comment

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 21:48:57 +05:30
Mathew Kamkar
7488296390 add clock offset to timed version generator (#330)
* add clock offset to timed version generator

* fix interface
2023-03-29 23:27:28 -07:00
Paul Wells
7d4c517bf4 add workergroup util (#329) 2023-03-23 22:01:34 -07:00
Benjamin Pracht
e78c5b18c0 Enable all ingress presets (#328) 2023-03-21 18:13:29 -07:00
David Zhao
ffdcdd67ac Added react-native and rust SDKs (#326)
* Added react-native and rust SDKs

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-21 13:34:38 -07:00
renovate[bot]
379e1d3084 fix(deps): update module google.golang.org/protobuf to v1.30.0 (#325)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 10:49:41 -07:00
Benjamin Pracht
6b747fe252 Ingress protocol changes to allow specifying encoding presets (#324) 2023-03-16 09:55:31 -07:00
renovate[bot]
8fcafa0923 fix(deps): update go deps (#315)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 00:36:27 -07:00
renovate[bot]
5cdd7c494f chore(deps): update actions/setup-go action to v4 (#323)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-15 13:10:12 -07:00
David Colburn
6d1cd857eb list active egress option (#321)
* list active egress only

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-13 20:57:39 -07:00
Benjamin Pracht
c3e5be2aff Update ingress protocol definition to use the same constants as Egress for audio and video codecs (#319)
Also Add utils to convert codec enums to mime type, add VP8 constant
2023-03-10 09:46:19 -08:00
David Zhao
a1819deeab Publish and subscribe rtpstats (#317) 2023-03-08 23:46:19 -08:00
David Colburn
c2dcec981a bytes -> string gcp credentials (#318)
* bytes -> string credentials

* undo psrpc

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-08 18:27:49 -08:00
lukasIO
a094b92547 Add can_update_metadata field to participant permissions (#316)
* add can_update_metadata field to participant permissions

* generated protobuf

* re-add next id comment

* add name update to metadata update

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-07 12:03:19 +01:00
lukasIO
176d6d15b6 Add topic to UserPacket (#314)
* add topic to UserPacket

* generated protobuf

* mark topic as optional

* generated protobuf

* add topic also to SendDataRequest

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-06 10:44:55 +01:00
Paul Wells
c0705dbb69 Add signal relay interface (#313)
* add signal psrpc interface

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-02 18:56:09 -08:00
Paul Wells
dac2223d7a nil safe NewTimedVersionFromProto (#312) 2023-03-01 20:10:04 -08:00
Paul Wells
721dbba55d add method to get time.Time from TimedVersion (#311)
* time.Time from TimedVersion method

* time.Time rundtrip test
2023-02-28 15:52:27 -08:00
renovate[bot]
073251b64a fix(deps): update go deps (#302)
* fix(deps): update go deps

Generated by renovateBot

* go-throttle -> core

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: David Colburn <xero73@gmail.com>
2023-02-27 16:01:08 -08:00
Paul Wells
5fa71af6c3 range check min version (#309) 2023-02-27 15:08:48 -08:00
Paul Wells
2cf53863d5 update to psrpc v0.2.9 (#310)
* upgrade psrpc

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-27 15:05:30 -08:00
Paul Wells
43f5fc64e9 return TimedVersion update success/failure (#307) 2023-02-23 19:07:56 -08:00
cnderrauber
e946da680c parallel execute function (#306) 2023-02-22 11:00:27 +08:00
Paul Wells
26f188cb84 move TimedVersion from livekit (#305)
* move TimedVersion from livekit

* Store/Load

* cleanup

* prevent comparison

* nocmp generator

* comment for unused import

* skip update for equal

* uber atomic

* cleanup

* cleanup

* ensure ts is non-negative

* cleanup

* simplify

* cleanup

* cleanup

* assert -> require
2023-02-18 11:34:29 -08:00
David Zhao
cc52c6ef83 Allow retrieving unsampled logger for critical log lines (#304) 2023-02-17 21:48:58 -08:00
David Colburn
563f18426b Remove deprecated ingress rpc (#303)
* remove ingress rpc

* revert psrpc changes

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-17 13:11:33 -08:00
David Colburn
8a6b0e0562 Prevent breakage due to casting (#301)
* prevent breakage due to casting

* remove protoc version

* move old rpc systems back

* generated protobuf

* add deprecated comments

* handle new proto in SendRequest

* remove extra fields

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-15 15:59:03 -08:00
David Colburn
4a1ada9899 Move psrpc to protocol (#300)
* move psrpc to protocol

* generated protobuf

* add psrpc to proto target

* deprecate more fields

* update static check and generate

* generated protobuf

* update renovate

* use latest protoc

* psrpc 0.2.6

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-15 12:06:09 -08:00
Benjamin Pracht
3db2ee16ef Allow using the 1st sample date/time as suffix when using the egress segmented output (#299) 2023-02-13 20:12:32 -08:00
David Zhao
ec5189c9fd chore: update go module versions (#298) 2023-02-12 21:56:16 -08:00
David Zhao
9a57a8c5b2 Fix support for Redis cluster mode, updated to v9 (#297)
* Fix support for Redis cluster mode, updated to v9

* update to Go 1.18
2023-02-12 21:48:01 -08:00
David Colburn
812bcb9904 Allow multiple outputs (#287)
* multiple outputs

* generated protobuf

* add comments

* generated protobuf

* add error to stream info

* update outputs

* generated protobuf

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-09 00:04:59 -08:00
David Colburn
800036bdb4 Add egress_id option to list egress (#296)
* add egress_id to list egress

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-09 00:01:54 -08:00
lukasIO
410ca1ce35 Revert #292 (#295)
* revert #1380

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 18:13:19 +00:00
cnderrauber
f6d32e15b0 Add reconnect reason and signal rtt calculation (#293)
* Add reconnect reason and signal rtt calculation

* generated protobuf

* rename prefix

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-06 10:23:48 +08:00
lukasIO
a6f6dde5db Include room, participant and other_participants in reconnect response (#292)
* include participant and other_participants in reconnect response

* generated protobuf

* generated protobuf

* also send down room

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-03 14:42:05 +00:00
David Zhao
5a66fc1d10 Source specific permissions and protocol to update participant's metadata (#282) 2023-02-02 00:34:58 -08:00
Paul Wells
358df22e41 reduce number of goroutines spawned during testing (#291) 2023-02-01 19:59:12 -08:00
Paul Wells
c71216774a fix lock tracker init for race detector (#290)
* add room/identity to node rtc messages

* fix lock tracker init for race detector

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 19:46:47 -08:00
David Zhao
fa1edc35c8 Ensure we don't lose context or other logger options (#289) 2023-02-01 01:21:09 -08:00
Paul Wells
cacdab7b41 add room/identity to node rtc messages (#288)
* add room/identity to node rtc messages

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 18:16:55 -08:00
David Zhao
9987dca3a3 Fix item sampler to avoid stacking with default sampler (#285) 2023-01-30 17:22:49 -08:00
David Zhao
a1d02655b0 Added subscription priority to UpdateTrackSettings (#281) 2023-01-29 10:54:01 -08:00
Paul Wells
f55bf39335 add norace directive to scanTrackedLocks (#280)
race detector panics if we access an object that is being gced. it
is safe here because until the finalizer finishes the `trackedLock`
won't be freed and finalizer and scan functions all hold
`weakRefLock`.
2023-01-27 20:27:00 -08:00
Paul Wells
10b378e3bc add toggle for lock tracking (#279) 2023-01-27 13:35:45 -08:00
Paul Wells
b75d0aed9e add lock tracker (#278)
* add lock tracker

* add noop to appease statick check

* cleanup

* cleanup
2023-01-27 02:58:19 -08:00
David Colburn
8368e5ada7 authenticated protoc setup (#277) 2023-01-25 15:02:55 -08:00
David Zhao
d208f34298 Including event for subscription failures (#276)
* Including event for subscription failures.

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-23 20:53:13 -08:00
Dan McFaul
7c8172cb6e participant_rtc_init stats (#275)
* adding rtc_init

* rename participant stats

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-23 12:20:15 -07:00
David Zhao
8a49ab3e6c Added additional track events (#273)
In order to capture publish and subscribe success rate, and mute status.
2023-01-15 15:19:42 -08:00
Dan McFaul
abfad31c5f adding more node stats (#268)
* adding more node stats

* fix merge conflicts

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-11 12:56:42 -07:00
cnderrauber
f637ca8e67 Add reconnect response to update configuration while reconnecting (#271)
* Add reconnect response to update configuration while reconnecting

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-11 17:19:21 +08:00
Mathew Kamkar
34cae0997a add memory total and used to node stats (#269)
* add memory total, used

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-10 12:16:47 -08:00
lukasIO
fa87d56355 Add encryption field to TrackInfo (#265)
* Add e2ee enum to TrackInfo

* generated protobuf

* rename to EncryptionType

* generated protobuf

* Nest encryption type in message

* generated protobuf

* Update livekit_models.proto

Co-authored-by: David Zhao <dz@livekit.io>

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
2022-12-28 10:19:32 +01:00
Benjamin Pracht
d4406dd279 Add an option to set the key frame interval to EncodingOptions (#266) 2022-12-28 17:21:40 +13:00
David Zhao
d9b5a759b9 chore: shortuuid v4 (#264) 2022-12-23 23:31:31 -08:00
Raja Subramanian
fc943512b0 ICE config definition. (#261)
* ICE config definition.

For use in cloud model also.

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-19 09:45:53 +05:30
renovate[bot]
e586f56c17 Update module github.com/pion/webrtc/v3 to v3.1.50 (#260)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-18 14:39:33 -08:00
Raja Subramanian
e43a6056a6 Introduce encoded participant key (#259)
* Introduce encoded participant key

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-10 11:09:57 +05:30
David Zhao
5875a37d2c Added ToZap method to return the underlying Zap logger (#258) 2022-12-09 14:22:30 -08:00
David Zhao
46717d5070 Support for participant-level log sampling (#257) 2022-12-08 23:53:20 -08:00
Benjamin Pracht
5420927b79 Add ingress state ended_at field (#256) 2022-12-07 18:06:23 -08:00
David Zhao
7e96a46219 Added helper to check if Redis configuration is provided (#255) 2022-12-04 12:36:51 -08:00
renovate[bot]
524a374588 Update module go.uber.org/zap to v1.24.0 (#254)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-30 13:33:39 -08:00
renovate[bot]
e20cc76010 Update module github.com/pion/webrtc/v3 to v3.1.49 (#253)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-24 11:29:09 -08:00
renovate[bot]
ec328397c7 Update module github.com/pion/webrtc/v3 to v3.1.48 (#215)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-18 17:37:54 -08:00
renovate[bot]
e2424e9a12 Update module github.com/twitchtv/twirp to v8.1.3+incompatible (#238)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-18 17:34:39 -08:00
renovate[bot]
c04cca18e5 Update module google.golang.org/grpc to v1.51.0 (#226)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-18 17:33:32 -08:00
Benjamin Pracht
56b42b9030 Document bitrate unit in VideoLayer (#251) 2022-11-18 10:09:19 -08:00
Benjamin Pracht
b1eab0ff38 Fallback to osstat if a matching cgroup implementation cannot be found, and fix core count computation (#249)
This should fix WSL2 support.
2022-11-11 11:21:45 -08:00
Benjamin Pracht
9303619f01 Fix typo in logger config (#248) 2022-11-08 14:44:55 -08:00
renovate[bot]
0f6e21a1e3 Update module github.com/prometheus/client_golang to v1.14.0 (#246)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-08 12:40:58 -08:00
Benjamin Pracht
5353facf2d Use UniversalClient in ingress redis RPC (#245) 2022-11-07 14:20:34 -08:00
renovate[bot]
86e2d92816 Update module github.com/prometheus/client_golang to v1.13.1 (#244)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-06 22:46:19 -08:00
David Zhao
8449c11069 Configurable logger sampling parameters (#243) 2022-10-27 23:34:58 -07:00
Tom Xiong
92c1211d70 Support redis cluster (#241)
* use redis.UniversalClient instead of single-node client, FailoverClient and ClusterClient to support Redis Cluster mode
2022-10-27 23:34:42 -07:00
David Colburn
d3635b1226 Web egress (#242)
* add web egress

* generated protobuf

* add to other messages

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-26 13:37:34 -07:00
renovate[bot]
e5d7144e26 Update module go.uber.org/atomic to v1.10.0 (#236)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-25 23:17:56 -07:00
Benjamin Pracht
5b5031cf27 Add IngressAdmin grant (#240) 2022-10-25 18:03:02 -07:00
Raja Subramanian
b01c630e70 Track memory load in node stats. (#239)
* Track memory load in node stats.

Using a single metric defined as memory_used / memory_total
to capture fraction of total memory in use.

* generated protobuf

* group with other system stats

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-25 20:21:30 +05:30
David Colburn
41f5b55c95 AliOSS fix (#237)
* update field numbers

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-24 11:38:18 -07:00
Tom Xiong
659e8f58fb add AliOSS upload support for egress (#234) 2022-10-24 11:34:56 -07:00
Nikita Konev
8810b9cc84 Added metadata and tagging (#231) 2022-10-24 11:29:52 -07:00
renovate[bot]
b80cd331f2 Update module github.com/stretchr/testify to v1.8.1 (#235)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-24 09:45:29 -07:00
cnderrauber
3f47968225 add fps field to Subscribe Setting (#230)
* add fps field to Subscribe Setting

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-21 14:38:48 +08:00
Benjamin Pracht
f69b436be8 Move video output validation to protocol (#233) 2022-10-20 09:24:42 -07:00
Benjamin Pracht
2a4be29988 Add support for cgroup v1 to cpu stats function (#232) 2022-10-19 11:24:40 -07:00
Benjamin Pracht
9b09be77ef Cgroup aware idle CPU computation (#229)
On linux, this will report the amount of idle CPU relative to the cgroup defined quota. On other OSs, the idle cpu for the whole host is reported
2022-10-17 15:12:12 -07:00
David Colburn
cd9e72d48a Update comments (#228)
* update comments

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-17 11:25:41 -07:00
David Colburn
85bf30570f Add StartedAt and EndedAt to fileInfo and segmentsInfo (#227)
* add StartedAt and EndedAt to fileInfo and segmentsInfo

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-14 16:13:13 -07:00
cnderrauber
b0c33b869a move ExtractStreamID to sdp util (#225)
* move ExtractStreamID to sdp util

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-14 15:53:41 +08:00
cnderrauber
21e14f319a add disable_red, stereo fields for audio track (#224)
* add disable_red, stereo field for audio track

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-14 15:32:45 +08:00
Nikita Konev
19dd0a128e Added ForcePathStyle to S3Upload (#223) 2022-10-13 13:32:58 -07:00
David Colburn
d9bc6cd9cb move disable_manifest into file outputs (#222)
* move disable_manifest into file outputs

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-07 14:26:51 -07:00
lukasIO
f5abcac3a5 Add name to UpdateParticipantRequest (#221)
* add name to updateParticipantRequest

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-07 11:59:36 +02:00
David Colburn
698ea84725 Add disable manifest option (#220)
* add disable manifest option

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-10-06 13:55:53 -07:00
renovate[bot]
a17234b098 Update module google.golang.org/grpc to v1.50.0 (#219)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-06 13:19:09 -07:00
Benjamin Pracht
af8105ee44 Add created and deleted ingress events (#218) 2022-10-04 11:09:14 -07:00
Benjamin Pracht
44a5ed6b4d Change Ingress RPC interface to take and return State instead of full info (#217) 2022-10-03 11:10:58 -07:00
David Zhao
dc2a7bc3a0 Moved AutoEgress and RoomInternal definitions (#216)
* Moved AutoEgress and RoomInternal definitions

Clients do not need these definitions. livekit_models also shouldn't have
a dependency on livekit_egress
2022-09-28 23:04:52 -07:00
Benjamin Pracht
bafacf7041 Use ErrNoResponse constant in ingress RPC implementation (#214) 2022-09-26 11:01:22 -07:00
Benjamin Pracht
19ead11853 Add ErrNoResponse to ingress (#213) 2022-09-22 13:44:13 -07:00
Benjamin Pracht
e982494841 Add ingress id to analytics payload. Add Ingress timed out error (#212) 2022-09-21 14:10:20 -07:00
David Colburn
8645a138fb Remove participant composite temporarily (#211)
* remove participant composite

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-20 16:37:42 -07:00
David Zhao
782f517a6e Use custom mime-type to avoid overeager JSON parsing. (#210)
Middlewares/server frameworks have a tendency of replacing req.body with
parsed JSON object. We do not want this behavior as our Webhook receiver
needs to validate the raw string body against the `Authorization` header
2022-09-19 21:03:55 -07:00
David Colburn
581466192d Remove template base from pc request (#209)
* remove template base from pc request

* generated protobuf

* adjust ids

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-19 16:23:13 -07:00
David Colburn
df6fc3665f Add participant composite to egress info (#208)
* add participant composite to egress info

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-19 15:31:54 -07:00
David Colburn
b6794d3f26 Create RoomInternal pb (#207)
* create RoomInternal pb

* generated protobuf

* add comment

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-19 14:35:33 -07:00
David Colburn
36c8b27288 Remove egress from room proto, add participant composite (#206)
* remove egress from room proto, add participant composite

* identity

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-19 13:50:31 -07:00
David Zhao
2b91fd8ace Switching to Apache-2.0 license to be consistent with rest of repos (#205) 2022-09-16 19:08:15 -07:00
David Colburn
e8fddf3452 Auto egress (#204)
* egress in create room request

* regen

* generated protobuf

* autoegress in room proto

* autoegress in room proto

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-16 12:06:26 -07:00
renovate[bot]
a193b475b9 Update module github.com/pion/webrtc/v3 to v3.1.44 (#203)
* Update module github.com/pion/webrtc/v3 to v3.1.44

Generated by renovateBot

* generated protobuf

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-15 10:28:09 -07:00
cnderrauber
6ec04e9ca4 add previous offer to syncstate (#202)
* add previous offer to syncstate

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-09 17:06:45 +08:00
cnderrauber
ca55e87895 add participant id for reconnect (#201)
* add participant id for reconnect

* generated protobuf

* style

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-09-07 10:58:39 +08:00
Benjamin Pracht
df2069bbbe Move ErrIngressOutOfDate to protocol (#200) 2022-09-06 15:05:30 -07:00
Benjamin Pracht
284d6b2729 Add Participant Identity and Name to ingress token (#199) 2022-08-31 11:05:59 -07:00
Benjamin Pracht
093984de8e Return ws_url and token in GetIngressInfo response (#198) 2022-08-30 09:06:04 -07:00
Benjamin Pracht
0291fd7fdf Add ingress token creation (#197) 2022-08-29 15:58:53 -07:00
David Colburn
28c92d8f69 Stream status and egress updated (#196)
* stream status and egress updated

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-25 19:51:00 -07:00
David Colburn
d8431e35ee Add new status (#195)
* add new status

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-25 14:24:28 -07:00
renovate[bot]
9cbacea721 Update module google.golang.org/grpc to v1.49.0 (#192)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-24 17:07:56 -07:00
renovate[bot]
cda57bb73f Update module go.uber.org/zap to v1.23.0 (#194)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-24 17:00:14 -07:00
cnderrauber
a1c2809ddc add force relay and tls field (#193)
* add force relay and tls field

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-24 19:20:19 +08:00
shishirng
cd39f4ca4d send egress/ingress info in analytics events (#191)
* send egress/ingress info in analytics events

Signed-off-by: shishir gowda <shishir@livekit.io>

* generated protobuf

Signed-off-by: shishir gowda <shishir@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-19 16:04:18 -04:00
renovate[bot]
ac9f2c2b91 Update module github.com/pion/sdp/v3 to v3.0.6 (#190)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-17 21:29:25 -07:00
cnderrauber
613285ea6f use sdp/v3 (#189) 2022-08-17 15:38:30 +08:00
cnderrauber
bd098187d8 move sdp process to sdp package (#188) 2022-08-17 15:31:03 +08:00
Raja Subramanian
ac91aad4ad Track header bytes in RTPStats (#187)
* Track header bytes in RTPStats

Header bytes are included in total bytes* fields.
Tracking it separately to be able to calculate RTP transport overhead.

* generated protobuf

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-14 13:10:51 +05:30
David Zhao
937fb9ce9f Added connection type and network info (#186) 2022-08-13 23:31:59 -07:00
David Zhao
df83c83769 Consolidate server information under ServerInfo (#185)
* Consolidate server information under ServerInfo

* go mod tidy

* generated protobuf

* adding node_id too

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-10 10:27:33 -07:00
Benjamin Pracht
d76090cba2 Add StartedAt field to ingress info State (#184) 2022-08-08 21:00:42 -07:00
renovate[bot]
e09066ac7e Update module go.uber.org/zap to v1.22.0 (#183)
* Update module go.uber.org/zap to v1.22.0

Generated by renovateBot

* generated protobuf

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-08 15:35:13 -07:00
renovate[bot]
cfae06c397 Update module github.com/prometheus/client_golang to v1.13.0 (#181)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-06 12:19:29 -07:00
David Zhao
2d0d2484b0 bump generator versions (#182)
* bump generator versions

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-06 12:17:49 -07:00
lukasIO
dc99a5ad3c Add ping pong and pingtimeout for ws connection (#180)
* add ping pong and pingtimeout for ws connection

* swap ping direction

* declare ping as message

* use int64

* generated protobuf

Co-authored-by: David Zhao <dz@livekit.io>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-05 09:05:32 -07:00
Benjamin Pracht
ae34dc3ec4 Remove StartIngressRequest (#179)
This removes the StartIngressRequest messages and RPC handers, as ingress will start an ingress on RTMP connection. A similar message may be needed again when we support other protocols such as SRT, but it is hard to tell exactly if the message as it exists today is the one that will be needed for this support.
2022-08-01 10:50:11 -07:00
David Colburn
67539ebcab add room name to egress info (#178) 2022-07-28 16:49:08 -05:00
renovate[bot]
a358bbbcc9 Update module google.golang.org/protobuf to v1.28.1 (#177)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-28 09:15:05 -07:00
Benjamin Pracht
ac26418a52 Allow to request ingress info through RPC (#176)
This creates a "RPC" interface that combines both client and server interfaces, and merges the client and server constructors as both sides of the RPC now act as client and server. This also adds a new channel getter for entity requests.
2022-07-27 14:59:41 -07:00
David Colburn
ad9c55ddef Ingress proto updates (#175)
* Ingress updates

* generate

* stop -> delete
2022-07-26 11:41:53 -07:00
Raja Subramanian
cb6a3a0942 Revert "Add option to use sid where applicable. (#172)" (#174)
This reverts commit 5eea37b737.
2022-07-21 15:05:44 +05:30
Raja Subramanian
5eea37b737 Add option to use sid where applicable. (#172)
* Add option to use `sid` where applicable.

Intention is to provide APIs that can address more targeted resource.
As room name and participant identity are designed to re-used,
they address all resources matching the name/identity when using
room service APIs.

By providing option to address using `sid`, a specific resource can
be targeted.

Funtionally, if both `name/identity` and `sid` are given, `name`
takes precedence.

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-21 10:56:45 +05:30
Raja Subramanian
86da225219 TimedVersion model (#169) 2022-07-21 08:39:58 +05:30
David Zhao
59d9284912 UpdateIngress API to allow re-use (#171)
* UpdateIngress API to allow re-use

* return reusable in IngressInfo

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-20 16:22:38 -07:00
Benjamin Pracht
7250306954 Add stream_key parameter to ingest info (#170) 2022-07-20 15:18:13 -07:00
Mathew Kamkar
47777c7162 Packet stats from TC (#154)
* system level packet stats

* generated protobuf

* packet drop percent

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-15 10:27:01 -07:00
renovate[bot]
c9236084b6 Update module google.golang.org/grpc to v1.48.0 (#165)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 23:11:46 -07:00
renovate[bot]
ed3bb7fac5 Update module github.com/maxbrunsfeld/counterfeiter/v6 to v6.5.0 (#167)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 23:07:53 -07:00
renovate[bot]
8e6746864e Update module github.com/stretchr/testify to v1.8.0 (#164)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 23:07:12 -07:00
renovate[bot]
3911a509c1 Update module google.golang.org/protobuf to v1.28.0 (#166)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 23:05:04 -07:00
renovate[bot]
fbd9c34bc0 Update module github.com/prometheus/client_golang to v1.12.2 (#168)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 23:04:04 -07:00
renovate[bot]
cb05bd0f1b Update module gopkg.in/square/go-jose.v2 to v2.6.0 (#163)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:55:49 -07:00
renovate[bot]
3834dd8302 Update actions/checkout action to v3 (#160)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:52:22 -07:00
renovate[bot]
8b26199464 Update EndBug/add-and-commit action to v9 (#162)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:51:27 -07:00
renovate[bot]
1c257e2045 Update actions/setup-go action to v3 (#161)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:50:39 -07:00
renovate[bot]
8f61585578 Update actions/cache action to v3 (#159)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:49:40 -07:00
renovate[bot]
245526104d Update module gopkg.in/yaml.v3 to v3.0.1 (#157)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:48:59 -07:00
renovate[bot]
f9c9c8da7f Update module github.com/twitchtv/twirp to v8.1.2 (#156)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:47:04 -07:00
renovate[bot]
dfc58f1dc1 Update module github.com/lithammer/shortuuid/v3 to v3.0.7 (#155)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:44:14 -07:00
renovate[bot]
9968158c02 Update dominikh/staticcheck-action action to v1.2.0 (#158)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 22:36:39 -07:00
renovate[bot]
d506ba1dc9 Update module github.com/jxskiss/base62 to v1 (#152)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 15:17:22 -07:00
renovate[bot]
de8ecdefc9 Update magefile/mage-action action to v2 (#153)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 15:17:08 -07:00
renovate[bot]
54e2e20ad3 Update module github.com/go-logr/logr to v1.2.3 (#149)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 15:08:35 -07:00
renovate[bot]
8bb739d1b0 Update module github.com/go-redis/redis/v8 to v8.11.5 (#150)
Generated by renovateBot

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 15:08:29 -07:00
renovate[bot]
8778627ef3 Configure Renovate (#147)
* Add renovate.json

* renovate update

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: David Zhao <dz@livekit.io>
2022-07-14 15:06:07 -07:00
David Colburn
1afd55ebd0 dtx -> disable_dtx 2022-07-14 14:32:14 -07:00
Benjamin Pracht
1cadd9613c Add some errors used across services (#148)
This adds ErrNoResponse and ErrEgressTimedOut
2022-07-14 13:54:05 -07:00
Benjamin Pracht
df4d3bb245 Make sure we do not override the egressid when forwarding messages from the controller (#145)
This allows to have consistent Egress IDs across API calls, and solves UpdateLayout failures
2022-07-10 13:01:55 -07:00
Raja Subramanian
9d760dc384 Add connection_id to RTCNodeMessage (#146)
* Add connection_id to RTCNodeMessage

Used only in cloud to distinguish participant sessions.

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-10 16:26:11 +05:30
David Colburn
cad53a3185 add sentinel options 2022-07-06 11:34:50 -07:00
David Colburn
d81614de18 add standard redis config and client (#144) 2022-07-06 11:29:02 -07:00
David Colburn
f03f3734be Ingress updates (#143)
* ingress updates

* generated protobuf

* undo refactor

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-06 11:10:06 -07:00
David Colburn
137b876761 remove recording (#142)
* remove recording

* remove generated files

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-05 17:10:59 -07:00
Benjamin Pracht
31ce725fa5 Ingest protocol modifications (#137) 2022-07-05 09:56:48 -07:00
David Zhao
5f996eb446 Added connection failure as a reason (#141)
* Added connection failure as a reason

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-07-02 21:13:58 -07:00
David Zhao
aaed1a401b renamed to DisconnectReason (#140) 2022-07-02 10:48:51 -07:00
David Zhao
f3de65a58b Send clients reason for LeaveRequest (#139) 2022-07-02 10:05:37 -07:00
David Colburn
eb06e1619a add error to RecordError 2022-06-23 15:04:47 -07:00
David Colburn
e65f582336 add RecordError to span 2022-06-23 15:01:32 -07:00
David Colburn
4a8409f8f2 Tracing (#138) 2022-06-23 14:24:07 -07:00
cnderrauber
d1616e3cb8 publish new codec when subscriber need (#136) 2022-06-16 16:57:27 +08:00
David Colburn
e66f32ebb7 Rpc handler (#135)
* updated egress rpc

* new statuses

* update sendresponse

* update names

* update claim

* nil redis client
2022-06-13 11:59:08 -07:00
David Colburn
fa5221e452 Remove Lock from message bus interface (#134) 2022-06-08 17:10:44 -07:00
cnderrauber
5e07772153 add disabled codecs (#133) 2022-06-08 14:39:07 +08:00
Benjamin Pracht
b8779c1fd4 Add Segments info and support for SegmentedFileOutput in Room Composite Egress (#132)
- Add Segments info to return information about the generated segment files in Egress status updates.
- Add support for SegmentedFileOutput in Room Composite Egress
2022-06-07 13:26:02 -07:00
cnderrauber
e36e6426a0 add simulate switch candidate (#131)
* add simulate siwtch candidate

* newline
2022-06-07 17:43:30 +08:00
Benjamin Pracht
57d294a934 Add support for Segmented Stream outputs to the egress protocol (#130)
Add support for Segmented Stream outputs to the Egress protocol. HLS is the first example of such an output. We use a new output type as some fields (prefix, playlist path) are specific to this kind of output.
2022-06-06 21:10:40 -07:00
David Colburn
7e4ab2da14 Add close to message bus (#129) 2022-06-06 13:11:10 -07:00
Raja Subramanian
51a8116f88 Track participant join total + rate (#128)
* Track participant join total + rate

* generated protobuf

* singular

* WIP commit

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-30 15:51:38 +05:30
cnderrauber
2ecd4805e7 simulcast codecs support (#127)
* WIP

* work with dynacast codec

* generated protobuf

* migration worked

* generated protobuf

* remove unused code

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-26 17:19:38 +08:00
Raja Subramanian
ff07c68fb2 nil check (#126) 2022-05-25 15:08:53 +05:30
Raja Subramanian
91c49df893 ClaimGrants clone (#125)
* ClaimGrants clone

* Check for nil
2022-05-25 14:06:50 +05:30
David Zhao
084233d23a Node stats to keep track of retransmissions. (#124) 2022-05-10 00:13:53 -07:00
David Colburn
377f74b29d update duration fields (#123)
* update duration fields

* compat
2022-05-02 11:25:19 -07:00
Raja Subramanian
688e4f627b Nack ACKs and repeated (#122) 2022-05-02 22:38:52 +05:30
David Zhao
cef16c8ef3 Also accept identity for perms requests (#121) 2022-05-01 21:37:29 -07:00
David Zhao
fa9efaff8c Added ParticipantInfo.isPublisher (#119)
to indicate if the participant can publish tracks
2022-04-21 12:35:17 -07:00
David Zhao
e3f2240801 Moved common logging functions to protocol (#118) 2022-04-19 23:58:34 -07:00
Raja Subramanian
25b60c4bb0 AdaptiveStream in StartSession (#117)
* AdaptiveStream in StartSession

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-04-20 10:38:03 +05:30
David Colburn
7a6bb27499 Add RPCs, add default stream protocol (#116)
* Add RPCs, add default stream protocol

* add filepath for track egress

* fix numbers
2022-04-18 22:49:03 -07:00
Raja Subramanian
cacdaa5bf0 Renaming fields as they could be total or delta (#115) 2022-04-16 20:30:20 +05:30
David Colburn
0d59783336 update track and track composite (#114)
* update track and track composite

* revert

* add comments

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-04-15 16:17:54 -05:00
David Zhao
fd7cd24bac Ingress protobufs (#113) 2022-04-15 00:17:40 -07:00
David Zhao
539c40c917 Remove deprecated JWT token (#112)
* Remove deprecated JWT token

* remove deprecated tests

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-04-14 01:22:48 -07:00
cnderrauber
3c712ad5c9 add target field to syncstate's datatrack info (#111) 2022-04-07 13:56:43 +08:00
Raja Subramanian
f5e8e20530 Add region to participant info (#110)
* Add region to participant info

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-31 14:51:21 +05:30
David Zhao
54544c489c Helper method to receive WebhookEvent (#109) 2022-03-30 16:14:23 -07:00
David Colburn
6ba1221db3 WebComposite -> RoomComposite (#108) 2022-03-30 15:31:40 -07:00
David Zhao
56fa20a020 Server-initiated unpublish & permissions (#107)
* Remote unpublish, participant permissions, cleanup
2022-03-20 23:58:03 -07:00
David Zhao
8dff6f89d2 Webhook events for track published (#106)
* Webhook events for track published

* timeout for webhook notifications to avoid hang
2022-03-18 22:24:01 -07:00
Mathew Kamkar
51f5188bc4 include cpu load in node stats (#105)
* include percent cpu in node stats

* cpu load out of 1.0 instead of percent
2022-03-16 14:46:50 -07:00
Raja Subramanian
6f2a49e449 More stats (#104)
* More stats

- Number of key frames, last key frame
- Split out PLI sent for layer locking purposes

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-16 17:33:21 +05:30
Raja Subramanian
5cea5d444f Include RTT in the mix (#103)
* Add RTT

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-14 12:54:22 +05:30
Raja Subramanian
a91198e400 RTPStats (#102)
* RTPStats

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-11 22:27:04 +05:30
cnderrauber
874d12bf8b helper method (#101) 2022-03-07 14:55:30 +08:00
David Zhao
dbd455d2c1 Server region (#100)
* Region of the server (for display/debugging purposes)
2022-03-02 11:25:33 -08:00
shishirng
f3ffabe240 Track publisher details (#99)
* Send publisher info in events - used for TRACK_SUBSCRIBED event

Signed-off-by: shishir gowda <shishir@livekit.io>

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-28 13:41:53 -05:00
cnderrauber
4b44edff9e add data channel info to sync_state (#98)
* add data channel info to sync_state

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-25 17:20:16 +08:00
David Zhao
078505af8b Add static check CI (#97)
* Add static check CI

* fix static check errors
2022-02-24 23:36:09 -08:00
Raja Subramanian
fd3aaffcb8 Removing AtomicFlag, just use uber atomic.Bool (#96) 2022-02-25 12:38:26 +05:30
David Colburn
13b2038518 don't override egressID 2022-02-24 15:29:47 -08:00
lukasIO
82e5542f21 client configuration system (#90)
* add client configuration options

* generated protobuf

* fix indenting, add screen videoconfiguration

* generated protobuf

* fix naming

* generated protobuf

* condense client configuration for failsafety

* generated protobuf

* use enum for client setting

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-24 18:05:40 +01:00
David Colburn
2d72f8bc52 update internal egress request 2022-02-23 15:07:44 -08:00
David Colburn
d8c251e132 update BuildEgressToken 2022-02-23 11:52:54 -08:00
David Colburn
896d5ae1df Update layout rpc (#95)
* update layout rpc

* identity

* remove identity
2022-02-23 11:49:27 -08:00
David Colburn
5b8573f2a6 file upload options (#94)
* file upload options

* filename -> filepath

* az -> azure
2022-02-22 21:51:09 -08:00
shishirng
946db440fa Telemetry max subscribed video quality event (#93)
* new TRACK_MAX_SUBSCRIBED_VIDEO_QUALITY analytics event type

Signed-off-by: shishir gowda <shishir@livekit.io>

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-22 19:00:17 -05:00
David Colburn
ec6020d865 Egress (#92)
* egress

* generated protobuf

* remove ingress

* update egress package

* update optional enums

* generated protobuf

* updated proto

* add sent_at to start request

* generated protobuf

* default codecs

* remove extra codecs for now

* generated protobuf

* put recording back

* add connection options

* generated protobuf

* put recording back

* add sent_at and room_id

* generated protobuf

* add sent_at and room_id

* generated protobuf

* update egressInfo

* put recordingInfo back in webhooks

* egress events

* update analytics event

* egress status

* deprecate recording rpcs

* undo some changes

* key/secret -> token

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-22 00:21:29 -08:00
Raja Subramanian
28685be063 Types for ConnectionID, NodeID, ParticipantKey (#91)
* Types for ConnectionID, NodeID, ParticipantKey

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-21 08:34:10 +05:30
David Zhao
fed47fd8d1 Add track published/unpublished webhooks (#89) 2022-02-15 16:59:37 -08:00
Raja Subramanian
7f83990101 Adding total_frames (#86)
* Adding total_frames

Also setting up per stream stats

* generated protobuf

* Some renaming

* Restructure

* generated protobuf

* Add retransmit stats

* generated protobuf

* primary, reransmit and padding as separate

* generated protobuf

* type tweaks

* generated protobuf

* jitter in uint32 microseconds

* generated protobuf

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-08 12:34:40 +05:30
shishirng
40df25091b Active participant (#87)
* Add PARTICIPANT_ACTIVE event to track client state change

Signed-off-by: shishir gowda <shishir@livekit.io>

* generated protobuf

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-07 17:14:12 -05:00
David Zhao
e71d5db387 Use Go 1.17 in CI 2022-02-03 12:55:32 -08:00
David Zhao
3d4fe0c532 Adds version field to ParticipantInfo (#85) 2022-02-03 12:54:46 -08:00
shishirng
d79c2afbfc pass clients address in clientInfo (#84)
Signed-off-by: shishir gowda <shishir@livekit.io>
2022-01-29 10:36:28 -05:00
shishirng
77f0aed23c client meta message to cpature client join details (#82)
Signed-off-by: shishir gowda <shishir@livekit.io>
2022-01-27 15:17:30 -05:00
shishirng
b94955852f new track event for capturing updates (#81)
Signed-off-by: shishir gowda <shishir@livekit.io>
2022-01-24 14:27:41 -05:00
David Zhao
01c702cc14 Refresh token response: enables server to issue client new tokens (#80) 2022-01-23 22:26:18 -08:00
Raja Subramanian
e3f90e2957 Rename UpdateSubscriptionPermissions -> SubscriptionPermission (#78) 2022-01-22 11:55:47 +05:30
shishirng
bde53c19d1 Pass clientInfo object instead of expanding it (#77)
Signed-off-by: shishir gowda <shishir@livekit.io>
2022-01-20 14:28:14 -05:00
shishirng
a4208afda1 Add client into the analytics events (#76)
Signed-off-by: shishir gowda <shishir@livekit.io>
2022-01-13 17:22:00 -05:00
David Zhao
71562c1a1a Moved ClientInfo to models.proto, added additional device details (#75)
* Moved ClientInfo to models.proto, added additional device details

* IOS -> SWIFT
2022-01-12 23:33:21 -08:00
David Zhao
5a6a910c76 Simulate protocol for server-side leave messages (#74) 2022-01-11 23:08:35 -08:00
David Zhao
dd7165e713 Simulate signal message (#73) 2022-01-10 14:40:51 -08:00
David Zhao
d2b420f73d Set ruby_package option to LiveKit (#72)
* set ruby_package option to LiveKit

* append ::Proto
2022-01-08 21:49:09 -08:00
cnderrauber
a7f937bb7b Session migration (#71)
* session migration

* create array wthe size

* solve comment

Co-authored-by: cnderrauber <zengjie9004@gmail.com>
2022-01-08 13:22:20 +08:00
Raja Subramanian
2c4c8d7764 Add VideoQuality_OFF enum to denote mute/off condition (#70)
* Add VideoQuality_OFF enum to denote mute/off condition

NONE is taken by recording, so used OFF.

* protoc version
2022-01-04 12:29:46 +05:30
Raja Subramanian
c441eb5f03 type alias -> type definition (#69) 2022-01-03 10:24:53 +05:30
Raja Subramanian
feaea540b8 Make room name a type definition (#68) 2022-01-02 09:31:02 +05:30
Théo Monnom
0b14193039 Added C# namespace + Unity SDK (#66) 2021-12-30 14:51:58 -08:00
shishirng
cfba8f9933 rename room_sid to room_id (#67)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-12-30 15:15:19 -05:00
Artur Shellunts
dfabd14143 Add RTT in alanytics stats event (#65) 2021-12-30 10:59:53 +01:00
Raja Subramanian
88ab66e0e7 LiveKit type aliases (#62)
* LiveKit type aliases

Idea is to start with aliases so that this can be done in small steps.
The plan is to move to a type definition once we have most of the stuff
moved over to get stronger type checks.

* Sid -> ID
2021-12-28 14:18:26 +05:30
David Zhao
550362e3f0 Enable setting name with AccessToken helper (#64) 2021-12-27 23:56:02 -08:00
David Zhao
b146ec0953 Various API improvements (#63)
* ListRooms to support filter
* Webhook to return unique ID and timestamp
* TrackInfo to include track MIME type
* ParticipantInfo to include name field
2021-12-27 23:23:00 -08:00
Raja Subramanian
da651cb088 Include participant_sid in UpdateSubscription (#61) 2021-12-23 09:10:36 +05:30
Raja Subramanian
cf8fab999a Publisher controlled track subscriptions (#59)
* Publisher controlled track subscriptions

* formatting

* Include participant_sid in SubscriptionPermissionUpdate
2021-12-22 11:59:11 +05:30
shishirng
0895daea96 Store connection ratings with track info (#60)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-12-21 18:18:48 -05:00
Raja Subramanian
d2f1ed9110 Protocol message to indicate changes in max subscribed quality. (#58)
* Protocol message to indicate changes in max subscribed quality.

* Forgot to include track_sid in SubscribedQualityUpdate message

* correct typos
2021-12-19 11:55:17 +05:30
David Colburn
f77609470e Recording profiles (#57)
* encoding profiles

* switch to string
2021-12-14 19:18:01 -06:00
shishirng
ab99909273 Add score to ConnectionQualityInfo (#56)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-12-14 16:13:52 -05:00
Mathew Kamkar
81dc057627 move node id generation into this repo (#55) 2021-12-10 15:41:41 -08:00
Jesse H Willett
8785fbf5c1 Moving generated Go protobuf files to match go_package (#54) 2021-12-08 13:58:11 -08:00
shishirng
35d468c37d rename analytics.proto to livekit_analytics.proto (#53)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-12-07 16:32:31 -05:00
David Zhao
c7e8051ed6 Client provided layer size information (#52)
* Client provided layer size information

* fix up comment

* regenerated protos
2021-12-06 11:58:00 -08:00
Raja Subramanian
dfd89d696f Change structure of streaming status update (#51)
Use a single list with an enum for state indication.
2021-12-04 11:51:24 +05:30
David Colburn
70f4073aa0 update recording template, add field to room (#50)
* update recording template, add field to room

* allow multiple rtmp results

* more updates

* add recorder bool

* add recorder to participant

* add recorder

* mod tidy
2021-12-03 17:43:38 -08:00
David Zhao
9b83b60b2e Update boostrap to install protoc-gen-go-grpc 2021-12-02 17:46:50 -08:00
Raja Subramanian
8de3224f92 Protocol message to notify streaming status. (#49)
With `StreamAllocator`, SFU could pause/resume streams
based on bandwidth availability. Adding an update
message to notify clients about the state of streaming.
2021-11-24 22:13:06 +05:30
shishirng
b5eee90222 Send room name in stats message (#48)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-11-23 15:50:55 -05:00
shishirng
9ba7d5ce77 Use ClientInfo.SDK for client type and rename access key to analytics_key (#47)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-11-16 14:14:27 -05:00
shishirng
05b3888f5a Add sdk type, region and access_key to events message (#46)
Signed-off-by: shishir gowda <shishir@livekit.io>
2021-11-15 18:15:09 -05:00
David Colburn
9e08a795f4 update analytics stats (#45)
* update analytics stats

* remove room_name

* rr_time -> delay
2021-11-12 14:30:46 -06:00
lukasIO
3280169f2d add content type header to webhook requests (#44) 2021-11-11 13:08:05 -08:00
David Colburn
6872ea1637 add event types (#43)
* add event types

* add track id

* add recording events
2021-11-10 19:47:03 -06:00
shishirng
be219082bb Add analtyics proto and service defn (#40) 2021-11-10 18:34:16 -05:00
David Colburn
a61c6c03f7 origin -> media (#42) 2021-11-10 16:56:55 -06:00
Mathew Kamkar
91c31dabb0 RTC Node KeepAlive message (#41)
* KeepAlive message

* end return
2021-11-09 17:09:24 -08:00
David Colburn
b3847c8d35 regenerate proto files 2021-11-08 16:03:12 -08:00
David Colburn
4dede7984e Add recording_started webhook, add ctx to notifier (#39)
* add recording_started webhook, add ctx to notifier

* update test
2021-11-08 18:00:12 -06:00
David Zhao
f73cb2ec8d ScreenShareAudio track source 2021-11-06 15:28:05 -07:00
David Zhao
1e9063c438 Connection quality updates (#38) 2021-11-02 23:21:23 -07:00
Mathew Kamkar
f3bd2c316e use defaultLogger when sink is nil 2021-11-02 13:46:37 -07:00
Mathew Kamkar
bde5600f68 Abiltiy to use non default logger (#37)
* with logger

* WithLogger as type of logr.Logger

* simplify
2021-11-02 12:16:15 -07:00
David Zhao
bae8dd8bc5 use ioutil for Go 1.15 compat 2021-10-25 12:59:55 -07:00
David Colburn
125748935a combine s3_path and file 2021-10-25 12:55:18 -07:00
Mathew Kamkar
25ee0223e5 prometheus metrics on message bus (#36) 2021-10-22 10:03:29 -07:00
David Colburn
bc7778f2a7 interface -> proto.Message (#35) 2021-10-21 16:18:21 -05:00
David Zhao
dcb35c40c9 Subscriber track settings API change (#34)
* Subscriber track settings API to take in width & height instead of quality enum

* generated go
2021-10-21 10:29:38 -07:00
David Colburn
4d580badfd add turn nodetype (#33) 2021-10-18 16:14:37 -05:00
David Zhao
5e7fe78240 Track source for common types (#32) 2021-10-14 12:38:49 -07:00
Raja Subramanian
52cda35f86 Add disable_dtx field to AddTrack request. (#31)
DTX (Discontinuous Transmission) is used to save
on audio bandwidth during silence periods.

It is enabled from server side in SDP answer.
Add a field to allow configuration from client side.
2021-10-13 10:38:42 +05:30
David Colburn
ffb5cb48d0 update recording response (#30)
* update recording response

* update RPC

* take responsibility of ids
2021-10-08 13:35:09 -05:00
David Colburn
1dadf89309 recording v2 (#28)
* recording v2

* input oneof

* input.input_url -> input.url

* update channels

* simplify reservation

* recording request

* recording response

* recording rpc

* add reserve func

* close subscriber

* file option

* remove scaling
2021-10-06 23:36:55 -05:00
David Zhao
c90319ba3b Added Region in Node (#29) 2021-10-06 17:07:22 -07:00
David Zhao
3b3b0e68ec renegerate protobuf 2021-10-01 10:33:50 -07:00
Théo Monnom
540b5df27f Add num_participants field to Room (#27) 2021-10-01 10:26:23 -07:00
David Zhao
a054fef89e Rename UpdateRoomRequest to UpdateRoomMetadataRequest 2021-09-24 09:36:38 -07:00
lukasIO
0f9ae3e730 add room metadata field, update method and update signal (#26) 2021-09-24 09:35:08 -07:00
David Colburn
e3e7ce0232 notifier interface, message bus queue (#25)
* notifier interface, message bus queue

* remove ctx

* change name
2021-09-22 15:32:51 -05:00
David Colburn
b60237c535 recording webhooks (#24)
* recording webhooks

* use token instead of api key+secret

* remove token
2021-09-21 17:18:30 -05:00
David Zhao
4472a315d9 add Go as a client SDK 2021-09-17 15:17:04 -07:00
David Zhao
9afc4773a6 speaker change updates (#23) 2021-09-17 11:09:59 -07:00
Mathew Kamkar
8ecd5eeca7 add node state field (#22) 2021-09-14 14:58:57 -07:00
hn8
4a04d5c374 Fix logr usage (#21)
* Fix logr usage

- logr.Error() doesn't check level
- logr convention: V0 info, V1 debug, V2 trace

* Remove zap dependency
2021-09-10 13:44:32 -05:00
David Zhao
055674311d JoinResponse to indicate subscriber should be primary (#20)
* JoinResponse to indicate subscriber should be primary

* fix name convention
2021-09-09 00:10:13 -07:00
David Colburn
2b75ba9799 Debugw, Infow, etc 2021-09-07 14:09:16 -07:00
David Colburn
e3b107f710 Update buildtest.yaml 2021-09-07 14:59:17 -05:00
David Colburn
e6c77cb1df testall -> test 2021-09-07 12:57:19 -07:00
David Colburn
4d124d0a9e skip build 2021-09-07 12:56:00 -07:00
David Colburn
be8bcf07f0 master -> main 2021-09-07 12:54:59 -07:00
David Colburn
e1a7347506 add test workflow 2021-09-07 12:53:25 -07:00
David Colburn
1ecf8e9a45 add mage test 2021-09-07 12:51:38 -07:00
David Colburn
0f1f07c6fe add logging to protocol 2021-09-07 12:32:40 -07:00
David Colburn
11c6a1d9ee message bus (#19)
* message bus

* fix lock interface

* return interface
2021-09-02 15:37:08 -05:00
David Colburn
054f93553c simplify recording reservation (#18) 2021-09-01 22:42:53 -05:00
David Zhao
619cad0f3a explicit server mute request (#17) 2021-09-01 20:30:53 -07:00
David Colburn
5e3f9f4013 Add NodeType (#16)
* add node type

* add server node type
2021-08-27 15:48:46 -05:00
David Colburn
94556abf61 add protos (#15)
* add protos

* simplify magefile
2021-08-27 12:53:45 -05:00
David Colburn
e400b89dd4 add default preset none 2021-08-25 13:13:06 -07:00
David Colburn
ce6c95a5d7 remove unused import 2021-08-25 12:56:14 -07:00
David Colburn
a7c76b98b8 rename enum values 2021-08-25 12:52:49 -07:00
David Colburn
5a1fc089af fix for json (#14) 2021-08-25 14:50:15 -05:00
Mathew Kamkar
17ea3742d0 packet and system node stats (#13)
* packet and system node stats

* more packet and system stats
2021-08-25 11:03:59 -07:00
David Zhao
9eaf4db7ff moved shared data types to models 2021-08-18 22:53:32 -07:00
David Zhao
d60d683ac8 Use pointers for perms in order to allow nil (#11)
* nullable permission grants

* nil perms, canPublishData

* convenience setters
2021-08-18 22:47:47 -07:00
Chester Ming
46321822a0 SendData Server API (#10)
* SendData Server API

* SendData Server-API adjustments based on suggestions
2021-08-18 22:00:13 -07:00
David Zhao
6319eef0ca enable publishing a track while it's muted 2021-08-10 17:01:33 -07:00
David Zhao
8ce287b9f7 rename webhook type field to event 2021-08-09 23:34:08 -07:00
David Zhao
04db819c8e Merge pull request #8 from livekit/webhooks
protocol support for webhooks
2021-08-08 22:58:24 -07:00
David Zhao
8a63993232 removed token from proto body 2021-08-08 22:57:25 -07:00
David Zhao
8d0a9538d3 refactor, removed recording-related webhooks 2021-08-08 22:53:23 -07:00
David Zhao
992c4b2da9 webhook support 2021-08-08 22:17:46 -07:00
David Colburn
9caa97ddfc move recording options, use oneof (#7)
* move options, use oneof

* use start recording request in reservation

* models unused in internal
2021-08-06 17:53:47 -05:00
David Colburn
4c64ffcf86 Recording api (#6)
* recording apis

* split recording service

* type -> layout

* remove from create

* add roomRecord option
2021-08-04 20:54:51 -05:00
David Colburn
0bcc2a37a8 revert recording rpcs 2021-08-03 00:15:07 -07:00
David Colburn
43e9e95940 consistency 2021-07-31 13:02:35 -07:00
David Colburn
f50e369785 add recording utils 2021-07-26 23:42:01 -07:00
David Colburn
1f2364dac4 Recording (#5) 2021-07-26 23:20:03 -05:00
David Colburn
031bb23807 add hidden field to startSession 2021-07-20 17:19:46 -07:00
David Colburn
71fedf0a8a Hidden participants (#4)
* add hidden field

* add hidden to participant info

* add comment

* move hidden
2021-07-19 17:08:11 -05:00
David Colburn
ccbb4aba6e mod tidy 2021-07-07 22:05:50 -07:00
David Colburn
602726cf90 Merge pull request #3 from livekit/leave-reconnect
leave request can_reconnect
2021-07-08 00:04:12 -05:00
David Colburn
eb172da5e6 Update livekit_rtc.proto
Co-authored-by: David Zhao <david@davidzhao.com>
2021-07-08 00:03:59 -05:00
David Colburn
54ceb519ad can_reconnect 2021-07-07 21:05:09 -07:00
David Zhao
f025d10a3d Merge pull request #2 from livekit/adaptive-layers
ability to set active simulcast layers
2021-07-07 17:58:24 -07:00
David Zhao
36adae5957 use VideoQuality const instead of uint32 2021-07-07 16:35:40 -07:00
David Zhao
b806a0c87d ability to set active simulcast layers 2021-07-07 16:32:56 -07:00
David Zhao
7402ef7903 allow room to specify enabled codecs 2021-07-02 14:11:33 -07:00
David Zhao
fb9ed845bd improved documentation in proto 2021-06-29 11:54:17 -07:00
David Zhao
367ddff398 Server API for selective subscriptions 2021-06-23 13:54:43 -07:00
David Zhao
f6980aac49 video dimensions in publish and trackinfo 2021-06-18 15:58:33 -07:00
David Zhao
a93de94603 Merge pull request #1 from FeepsDev/datachannel_destination
Add the ability to send data to specific participants
2021-06-07 09:04:41 -07:00
Théo Monnom
f7e29983dd UserPacket destination filter 2021-06-06 19:57:25 +02:00
David Zhao
416943d37e auto subscribe in startSession 2021-05-22 21:56:30 -07:00
David Zhao
5edd2b18f8 DataPacket API 2021-04-26 18:00:48 -07:00
David Zhao
3b0a05aaaa Explicit leave in SignalResponse. Internal DeleteRoom message 2021-04-21 22:50:48 -07:00
David Zhao
64e12ed39e added protocol_version and use_plan_b to internal 2021-04-16 13:56:38 -07:00
David Zhao
8860ae3a5d remove unnecessary leave message from internal RTC 2021-04-08 21:06:39 -07:00
David Zhao
a6c9b46d03 explicit leave message 2021-04-08 21:02:44 -07:00
David Zhao
dd96c3f6b1 include timestamp of when participant joined room 2021-03-27 23:51:12 -07:00
David Zhao
654838f6e8 renamed mute field to disabled 2021-03-26 13:46:14 -07:00
David Zhao
6a204962ac fix duplicated event type, do not use optional fields 2021-03-20 22:13:27 -07:00
David Zhao
88f6f707e6 breaking API update - SetMetadata takes in opaque string, allow updating permissions when updating a participant 2021-03-20 22:09:52 -07:00
David Zhao
27ff355a51 rename protobuf files to avoid import conflict 2021-03-19 23:11:29 -07:00
David Zhao
b7893e35ae include participant permission in routing protocol 2021-03-15 23:35:17 -07:00
David Zhao
0491a5048e publish/subscribe permissions, Room API to update participant metadata 2021-03-15 23:01:55 -07:00
David Zhao
5fb296a571 update dependencies 2021-03-15 11:35:25 -07:00
David Zhao
b4b2437b4e switch base62 library 2021-03-15 11:31:13 -07:00
221 changed files with 67691 additions and 564 deletions

8
.changeset/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

15
.changeset/config.json Normal file
View File

@@ -0,0 +1,15 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": [
"@livekit/changesets-changelog-github",
{ "repo": "livekit/protocol" }
],
"commit": false,
"fixed": [["github.com/livekit/protocol", "@livekit/protocol"]],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [],
"privatePackages": { "version": true, "tag": true }
}

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
packages/js/src/gen/* linguist-generated=true

57
.github/workflows/buildtest.yaml vendored Normal file
View File

@@ -0,0 +1,57 @@
# Copyright 2023 LiveKit, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Test
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/go/bin
~/.cache
key: livekit-protocol
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Set up gotestfmt
run: go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@v2.4.1
- name: Download Go modules
run: go mod download
- name: Static Check
uses: amarpal/staticcheck-action@master
with:
checks: '["all", "-ST1000", "-ST1003", "-ST1020", "-ST1021", "-ST1022", "-SA1019"]'
install-go: false
- name: Test
run: |
set -euo pipefail
MallocNanoZone=0 go test -race -json -v ./... 2>&1 | gotestfmt

75
.github/workflows/generate.yaml vendored Normal file
View File

@@ -0,0 +1,75 @@
# Copyright 2023 LiveKit, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Generate
on:
workflow_dispatch:
push:
branches-ignore: [main]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- name: Install Protoc
uses: arduino/setup-protoc@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ">=1.20"
- name: Go mod tidy
run: go mod tidy
- name: Install generators
uses: magefile/mage-action@v3
with:
version: latest
install-only: true
- name: Bootstrap
run: mage bootstrap
- name: Generate Protobuf
run: mage proto
- uses: pnpm/action-setup@v2
with:
version: 8
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install JS dependencies
run: pnpm install
- name: Test generate JS files
run: |
pnpm --filter @livekit/protocol run generate:proto
- name: Add changes
uses: EndBug/add-and-commit@v9
with:
add: '["livekit", "rpc", "infra"]'
default_author: github_actions
message: generated protobuf

52
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Protoc
uses: arduino/setup-protoc@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: pnpm/action-setup@v2
with:
version: 8
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Create Release Pull Request or Publish packages
id: changesets
uses: changesets/action@v1
with:
# This expects you to have a script called ci:publish which does a build for your packages and calls changeset publish
publish: pnpm ci:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create git tag for golang package
if: steps.changesets.outputs.published == 'true'
uses: rickstaa/action-create-tag@v1
id: tag_create
with:
tag: ${{format('v{0}', fromJson(steps.changesets.outputs.publishedPackages)[0].version)}}
tag_exists_error: false
message: "github.com/livekit/protocol@${{fromJson(steps.changesets.outputs.publishedPackages)[0].version}}"

3
.gitignore vendored
View File

@@ -13,3 +13,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/
.idea/
node_modules/

2
.idea/.gitignore generated vendored
View File

@@ -6,3 +6,5 @@
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
# GitHub Copilot persisted chat sessions
/copilot/chatSessions

16
.idea/modules.xml generated
View File

@@ -1,4 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2023 LiveKit, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project version="4">
<component name="ProjectModuleManager">
<modules>

17
.idea/protoeditor.xml generated
View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProtobufLanguageSettings">
<option name="autoConfigEnabled" value="false" />
<option name="importPathEntries">
<list>
<ImportPathEntry>
<option name="location" value="jar://$APPLICATION_PLUGINS_DIR$/protobuf-editor.jar!/include" />
</ImportPathEntry>
<ImportPathEntry>
<option name="location" value="file://$PROJECT_DIR$" />
</ImportPathEntry>
</list>
</option>
<option name="descriptorPath" value="google/protobuf/descriptor.proto" />
</component>
</project>

16
.idea/vcs.xml generated
View File

@@ -1,4 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2023 LiveKit, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<enabled-global>
<option value="goimports" />
</enabled-global>
</component>
</project>

119
CHANGELOG.md Normal file
View File

@@ -0,0 +1,119 @@
# github.com/livekit/protocol
## 1.19.1
## 1.19.0
### Minor Changes
- Add SIP grants. - [#745](https://github.com/livekit/protocol/pull/745) ([@dennwc](https://github.com/dennwc))
### Patch Changes
- Fix typo in SIP Trunk conversion. - [#744](https://github.com/livekit/protocol/pull/744) ([@dennwc](https://github.com/dennwc))
## 1.18.0
### Minor Changes
- Split SIP Trunk configuration to inbound and outbound parts. - [#738](https://github.com/livekit/protocol/pull/738) ([@dennwc](https://github.com/dennwc))
- add Participant attributes key/val storage - [#733](https://github.com/livekit/protocol/pull/733) ([@davidzhao](https://github.com/davidzhao))
### Patch Changes
- Simplify number matching rules for SIP. - [#737](https://github.com/livekit/protocol/pull/737) ([@dennwc](https://github.com/dennwc))
- Added session token option for s3 uploads - [#734](https://github.com/livekit/protocol/pull/734) ([@frostbyte73](https://github.com/frostbyte73))
- Include analytics event ids - [#739](https://github.com/livekit/protocol/pull/739) ([@davidzhao](https://github.com/davidzhao))
## 1.17.0
### Minor Changes
- Add support for additional SIP transports. - [#719](https://github.com/livekit/protocol/pull/719) ([@dennwc](https://github.com/dennwc))
- Add ICERestartWHIPResource to RPC - [#716](https://github.com/livekit/protocol/pull/716) ([@Sean-Der](https://github.com/Sean-Der))
### Patch Changes
- Added error code field to EgressInfo - [#714](https://github.com/livekit/protocol/pull/714) ([@frostbyte73](https://github.com/frostbyte73))
- Include node_id with analytics events - [#727](https://github.com/livekit/protocol/pull/727) ([@davidzhao](https://github.com/davidzhao))
- Match SIP Trunks by source IP or mask. - [#724](https://github.com/livekit/protocol/pull/724) ([@dennwc](https://github.com/dennwc))
- Add notice to use participant identity from DataPacket for transcriptions. - [#706](https://github.com/livekit/protocol/pull/706) ([@dennwc](https://github.com/dennwc))
## 1.16.0
### Minor Changes
- - Add RedactAutoEncodedOutput to support redacting auto egress types - [#712](https://github.com/livekit/protocol/pull/712) ([@biglittlebigben](https://github.com/biglittlebigben))
- Redact image outputs
- Support AliOSS uploads for auto egress
- Allow inbound number filtering on SIP Dispatch Rules - [#707](https://github.com/livekit/protocol/pull/707) ([@dennwc](https://github.com/dennwc))
- Move egress request redacting routines to protocol - [#711](https://github.com/livekit/protocol/pull/711) ([@biglittlebigben](https://github.com/biglittlebigben))
## 1.15.0
### Minor Changes
- Expose Logger constructor for Zap. - [#701](https://github.com/livekit/protocol/pull/701) ([@dennwc](https://github.com/dennwc))
- Add metadata to SIP trunks, dispatch rules and participants. Change SIP participant identity prefix to `sip_`. - [#696](https://github.com/livekit/protocol/pull/696) ([@dennwc](https://github.com/dennwc))
- Move language into TranscriptionSegment #703 - [#704](https://github.com/livekit/protocol/pull/704) ([@lukasIO](https://github.com/lukasIO))
## 1.14.0
### Minor Changes
- Added real-time Transcription protocol - [#686](https://github.com/livekit/protocol/pull/686) ([@davidzhao](https://github.com/davidzhao))
- WHIP protocol change - [#680](https://github.com/livekit/protocol/pull/680) ([@biglittlebigben](https://github.com/biglittlebigben))
Deprecate the bypass_transcoding property in all ingress APIs and introduce the optional enable_transcoding property. This property will default to false for WHIP and to true for all other ingress types.
### Patch Changes
- Add SIP participant name. - [#687](https://github.com/livekit/protocol/pull/687) ([@dennwc](https://github.com/dennwc))
## 1.13.0
### Minor Changes
- Add and option to play ringtone for SIP outbound calls. - [#671](https://github.com/livekit/protocol/pull/671) ([@dennwc](https://github.com/dennwc))
### Patch Changes
- Add initial support for slog. - [#668](https://github.com/livekit/protocol/pull/668) ([@dennwc](https://github.com/dennwc))
## 1.12.0
### Minor Changes
- Moved CPU stats to a separate hwstats package, removing cgo dependency. - [#660](https://github.com/livekit/protocol/pull/660) ([@dennwc](https://github.com/dennwc))
### Patch Changes
- Fixed bounds check when masking short SIP numbers. - [#650](https://github.com/livekit/protocol/pull/650) ([@dennwc](https://github.com/dennwc))
- Add signal requests for local track updates - [#651](https://github.com/livekit/protocol/pull/651) ([@lukasIO](https://github.com/lukasIO))
- Allow sending DTMF when creating SIP participant. - [#658](https://github.com/livekit/protocol/pull/658) ([@dennwc](https://github.com/dennwc))
## 1.11.0
### Minor Changes
- Align package version with manually tagged golang module - [#646](https://github.com/livekit/protocol/pull/646) ([@lukasIO](https://github.com/lukasIO))
## 1.10.4
## 1.10.3
## 1.10.2

215
LICENSE
View File

@@ -1,21 +1,202 @@
MIT License
Copyright (c) 2021 livekit
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1. Definitions.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

13
NOTICE Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2023 LiveKit, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

31
agent/token.go Normal file
View File

@@ -0,0 +1,31 @@
package agent
import (
"time"
"github.com/livekit/protocol/auth"
"github.com/livekit/protocol/livekit"
)
func BuildAgentToken(apiKey, secret, roomName, participantIdentity, participantName, participantMetadata string, permissions *livekit.ParticipantPermission) (string, error) {
grant := &auth.VideoGrant{
RoomJoin: true,
Agent: true,
Room: roomName,
CanSubscribe: &permissions.CanSubscribe,
CanPublish: &permissions.CanPublish,
CanPublishData: &permissions.CanPublishData,
Hidden: permissions.Hidden,
CanUpdateOwnMetadata: &permissions.CanUpdateMetadata,
}
at := auth.NewAccessToken(apiKey, secret).
AddGrant(grant).
SetIdentity(participantIdentity).
SetName(participantName).
SetKind(livekit.ParticipantInfo_AGENT).
SetValidFor(1 * time.Hour).
SetMetadata(participantMetadata)
return at.ToJWT()
}

View File

@@ -1,24 +1,38 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"time"
"gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt"
"github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/livekit/protocol/livekit"
)
const (
defaultValidDuration = 6 * time.Hour
)
// Signer that produces token signed with API key and secret
// AccessToken produces token signed with API key and secret
type AccessToken struct {
apiKey string
secret string
identity string
videoGrant *VideoGrant
metadata map[string]interface{}
validFor time.Duration
apiKey string
secret string
grant ClaimGrants
validFor time.Duration
}
func NewAccessToken(key string, secret string) *AccessToken {
@@ -29,7 +43,7 @@ func NewAccessToken(key string, secret string) *AccessToken {
}
func (t *AccessToken) SetIdentity(identity string) *AccessToken {
t.identity = identity
t.grant.Identity = identity
return t
}
@@ -38,13 +52,46 @@ func (t *AccessToken) SetValidFor(duration time.Duration) *AccessToken {
return t
}
func (t *AccessToken) AddGrant(grant *VideoGrant) *AccessToken {
t.videoGrant = grant
func (t *AccessToken) SetName(name string) *AccessToken {
t.grant.Name = name
return t
}
func (t *AccessToken) SetMetadata(md map[string]interface{}) *AccessToken {
t.metadata = md
func (t *AccessToken) SetKind(kind livekit.ParticipantInfo_Kind) *AccessToken {
t.grant.SetParticipantKind(kind)
return t
}
func (t *AccessToken) AddGrant(grant *VideoGrant) *AccessToken {
t.grant.Video = grant
return t
}
func (t *AccessToken) AddSIPGrant(grant *SIPGrant) *AccessToken {
t.grant.SIP = grant
return t
}
func (t *AccessToken) SetMetadata(md string) *AccessToken {
t.grant.Metadata = md
return t
}
func (t *AccessToken) SetAttributes(attrs map[string]string) *AccessToken {
if len(attrs) == 0 {
return t
}
if t.grant.Attributes == nil {
t.grant.Attributes = make(map[string]string)
}
for k, v := range attrs {
t.grant.Attributes[k] = v
}
return t
}
func (t *AccessToken) SetSha256(sha string) *AccessToken {
t.grant.Sha256 = sha
return t
}
@@ -68,14 +115,7 @@ func (t *AccessToken) ToJWT() (string, error) {
Issuer: t.apiKey,
NotBefore: jwt.NewNumericDate(time.Now()),
Expiry: jwt.NewNumericDate(time.Now().Add(validFor)),
ID: t.identity,
Subject: t.grant.Identity,
}
grants := &ClaimGrants{}
if t.videoGrant != nil {
grants.Video = t.videoGrant
}
if t.metadata != nil {
grants.Metadata = t.metadata
}
return jwt.Signed(sig).Claims(cl).Claims(grants).CompactSerialize()
return jwt.Signed(sig).Claims(cl).Claims(&t.grant).CompactSerialize()
}

View File

@@ -1,69 +1,108 @@
package auth_test
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"gopkg.in/square/go-jose.v2/jwt"
"github.com/go-jose/go-jose/v3/jwt"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/auth"
"github.com/livekit/protocol/livekit"
"github.com/livekit/protocol/utils"
"github.com/livekit/protocol/utils/guid"
)
func TestAccessToken(t *testing.T) {
t.Parallel()
t.Run("keys must be set", func(t *testing.T) {
token := auth.NewAccessToken("", "")
token := NewAccessToken("", "")
_, err := token.ToJWT()
assert.Equal(t, auth.ErrKeysMissing, err)
require.Equal(t, ErrKeysMissing, err)
})
t.Run("generates a decodeable key", func(t *testing.T) {
t.Run("generates a decode-able key", func(t *testing.T) {
apiKey, secret := apiKeypair()
videoGrant := &auth.VideoGrant{RoomJoin: true, Room: "myroom"}
at := auth.NewAccessToken(apiKey, secret).
videoGrant := &VideoGrant{RoomJoin: true, Room: "myroom"}
sipGrant := &SIPGrant{Admin: true}
at := NewAccessToken(apiKey, secret).
AddGrant(videoGrant).
AddSIPGrant(sipGrant).
SetValidFor(time.Minute * 5).
SetKind(livekit.ParticipantInfo_AGENT).
SetIdentity("user")
value, err := at.ToJWT()
//fmt.Println(raw)
assert.NoError(t, err)
require.NoError(t, err)
assert.Len(t, strings.Split(value, "."), 3)
require.Len(t, strings.Split(value, "."), 3)
// ensure it's a valid JWT
token, err := jwt.ParseSigned(value)
assert.NoError(t, err)
require.NoError(t, err)
decodedGrant := auth.ClaimGrants{}
decodedGrant := ClaimGrants{}
err = token.UnsafeClaimsWithoutVerification(&decodedGrant)
assert.NoError(t, err)
require.NoError(t, err)
assert.EqualValues(t, videoGrant, decodedGrant.Video)
require.EqualValues(t, livekit.ParticipantInfo_AGENT, decodedGrant.GetParticipantKind())
require.EqualValues(t, videoGrant, decodedGrant.Video)
require.EqualValues(t, sipGrant, decodedGrant.SIP)
})
t.Run("missing kind should be interpreted as standard", func(t *testing.T) {
apiKey, secret := apiKeypair()
value, err := NewAccessToken(apiKey, secret).
AddGrant(&VideoGrant{RoomJoin: true, Room: "myroom"}).
ToJWT()
require.NoError(t, err)
token, err := jwt.ParseSigned(value)
require.NoError(t, err)
decodedGrant := ClaimGrants{}
err = token.UnsafeClaimsWithoutVerification(&decodedGrant)
require.NoError(t, err)
// default validity
require.EqualValues(t, livekit.ParticipantInfo_STANDARD, decodedGrant.GetParticipantKind())
})
t.Run("default validity should be more than a minute", func(t *testing.T) {
apiKey, secret := apiKeypair()
videoGrant := &auth.VideoGrant{RoomJoin: true, Room: "myroom"}
at := auth.NewAccessToken(apiKey, secret).
videoGrant := &VideoGrant{RoomJoin: true, Room: "myroom"}
at := NewAccessToken(apiKey, secret).
AddGrant(videoGrant)
value, err := at.ToJWT()
require.NoError(t, err)
token, err := jwt.ParseSigned(value)
require.NoError(t, err)
claim := jwt.Claims{}
decodedGrant := auth.ClaimGrants{}
decodedGrant := ClaimGrants{}
err = token.UnsafeClaimsWithoutVerification(&claim, &decodedGrant)
assert.NoError(t, err)
assert.EqualValues(t, videoGrant, decodedGrant.Video)
require.NoError(t, err)
require.EqualValues(t, videoGrant, decodedGrant.Video)
// default validity
assert.True(t, claim.Expiry.Time().Sub(claim.IssuedAt.Time()) > time.Minute)
require.True(t, claim.Expiry.Time().Sub(claim.IssuedAt.Time()) > time.Minute)
})
}
func apiKeypair() (string, string) {
return utils.NewGuid(utils.APIKeyPrefix), utils.RandomSecret()
return guid.New(utils.APIKeyPrefix), utils.RandomSecret()
}

View File

@@ -1,18 +1,327 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"maps"
"strings"
"golang.org/x/exp/slices"
"github.com/livekit/protocol/livekit"
)
type VideoGrant struct {
// actions on rooms
RoomCreate bool `json:"roomCreate,omitempty"`
RoomList bool `json:"roomList,omitempty"`
RoomRecord bool `json:"roomRecord,omitempty"`
// actions on a particular room
RoomAdmin bool `json:"roomAdmin,omitempty"`
RoomJoin bool `json:"roomJoin,omitempty"`
Room string `json:"room,omitempty"`
// permissions within a room, if none of the permissions are set explicitly
// it will be granted with all publish and subscribe permissions
CanPublish *bool `json:"canPublish,omitempty"`
CanSubscribe *bool `json:"canSubscribe,omitempty"`
CanPublishData *bool `json:"canPublishData,omitempty"`
// TrackSource types that a participant may publish.
// When set, it supersedes CanPublish. Only sources explicitly set here can be published
CanPublishSources []string `json:"canPublishSources,omitempty"` // keys keep track of each source
// by default, a participant is not allowed to update its own metadata
CanUpdateOwnMetadata *bool `json:"canUpdateOwnMetadata,omitempty"`
// actions on ingresses
IngressAdmin bool `json:"ingressAdmin,omitempty"` // applies to all ingress
// participant is not visible to other participants
Hidden bool `json:"hidden,omitempty"`
// indicates to the room that current participant is a recorder
Recorder bool `json:"recorder,omitempty"`
// indicates that the holder can register as an Agent framework worker
// it is also set on all participants that are joining as Agent
Agent bool `json:"agent,omitempty"`
}
type SIPGrant struct {
// Admin grants access to all SIP features.
Admin bool `json:"admin,omitempty"`
// Call allows making outbound SIP calls.
Call bool `json:"call,omitempty"`
}
type ClaimGrants struct {
Identity string `json:"-"`
Video *VideoGrant `json:"video,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Identity string `json:"-"`
Name string `json:"name,omitempty"`
Kind string `json:"kind,omitempty"`
Video *VideoGrant `json:"video,omitempty"`
SIP *SIPGrant `json:"sip,omitempty"`
// for verifying integrity of the message body
Sha256 string `json:"sha256,omitempty"`
Metadata string `json:"metadata,omitempty"`
// Key/value attributes to attach to the participant
Attributes map[string]string `json:"attributes,omitempty"`
}
func (c *ClaimGrants) SetParticipantKind(kind livekit.ParticipantInfo_Kind) {
c.Kind = kindFromProto(kind)
}
func (c *ClaimGrants) GetParticipantKind() livekit.ParticipantInfo_Kind {
return kindToProto(c.Kind)
}
func (c *ClaimGrants) Clone() *ClaimGrants {
if c == nil {
return nil
}
clone := *c
clone.Video = c.Video.Clone()
clone.SIP = c.SIP.Clone()
clone.Attributes = maps.Clone(c.Attributes)
return &clone
}
func (v *VideoGrant) SetCanPublish(val bool) {
v.CanPublish = &val
}
func (v *VideoGrant) SetCanPublishData(val bool) {
v.CanPublishData = &val
}
func (v *VideoGrant) SetCanSubscribe(val bool) {
v.CanSubscribe = &val
}
func (v *VideoGrant) SetCanPublishSources(sources []livekit.TrackSource) {
v.CanPublishSources = make([]string, 0, len(sources))
for _, s := range sources {
v.CanPublishSources = append(v.CanPublishSources, sourceToString(s))
}
}
func (v *VideoGrant) SetCanUpdateOwnMetadata(val bool) {
v.CanUpdateOwnMetadata = &val
}
func (v *VideoGrant) GetCanPublish() bool {
if v.CanPublish == nil {
return true
}
return *v.CanPublish
}
func (v *VideoGrant) GetCanPublishSource(source livekit.TrackSource) bool {
if !v.GetCanPublish() {
return false
}
// don't differentiate between nil and unset, since that distinction doesn't survive serialization
if len(v.CanPublishSources) == 0 {
return true
}
sourceStr := sourceToString(source)
for _, s := range v.CanPublishSources {
if s == sourceStr {
return true
}
}
return false
}
func (v *VideoGrant) GetCanPublishSources() []livekit.TrackSource {
if len(v.CanPublishSources) == 0 {
return nil
}
sources := make([]livekit.TrackSource, 0, len(v.CanPublishSources))
for _, s := range v.CanPublishSources {
sources = append(sources, sourceToProto(s))
}
return sources
}
func (v *VideoGrant) GetCanPublishData() bool {
if v.CanPublishData == nil {
return v.GetCanPublish()
}
return *v.CanPublishData
}
func (v *VideoGrant) GetCanSubscribe() bool {
if v.CanSubscribe == nil {
return true
}
return *v.CanSubscribe
}
func (v *VideoGrant) GetCanUpdateOwnMetadata() bool {
if v.CanUpdateOwnMetadata == nil {
return false
}
return *v.CanUpdateOwnMetadata
}
func (v *VideoGrant) MatchesPermission(permission *livekit.ParticipantPermission) bool {
if permission == nil {
return false
}
if v.GetCanPublish() != permission.CanPublish {
return false
}
if v.GetCanPublishData() != permission.CanPublishData {
return false
}
if v.GetCanSubscribe() != permission.CanSubscribe {
return false
}
if v.GetCanUpdateOwnMetadata() != permission.CanUpdateMetadata {
return false
}
if v.Hidden != permission.Hidden {
return false
}
if v.Recorder != permission.Recorder {
return false
}
if v.Agent != permission.Agent {
return false
}
if !slices.Equal(v.GetCanPublishSources(), permission.CanPublishSources) {
return false
}
return true
}
func (v *VideoGrant) UpdateFromPermission(permission *livekit.ParticipantPermission) {
if permission == nil {
return
}
v.SetCanPublish(permission.CanPublish)
v.SetCanPublishData(permission.CanPublishData)
v.SetCanPublishSources(permission.CanPublishSources)
v.SetCanSubscribe(permission.CanSubscribe)
v.SetCanUpdateOwnMetadata(permission.CanUpdateMetadata)
v.Hidden = permission.Hidden
v.Recorder = permission.Recorder
v.Agent = permission.Agent
}
func (v *VideoGrant) ToPermission() *livekit.ParticipantPermission {
pp := &livekit.ParticipantPermission{
CanPublish: v.GetCanPublish(),
CanPublishData: v.GetCanPublishData(),
CanSubscribe: v.GetCanSubscribe(),
CanPublishSources: v.GetCanPublishSources(),
CanUpdateMetadata: v.GetCanUpdateOwnMetadata(),
Hidden: v.Hidden,
Recorder: v.Recorder,
Agent: v.Agent,
}
return pp
}
func (v *VideoGrant) Clone() *VideoGrant {
if v == nil {
return nil
}
clone := *v
if v.CanPublish != nil {
canPublish := *v.CanPublish
clone.CanPublish = &canPublish
}
if v.CanSubscribe != nil {
canSubscribe := *v.CanSubscribe
clone.CanSubscribe = &canSubscribe
}
if v.CanPublishData != nil {
canPublishData := *v.CanPublishData
clone.CanPublishData = &canPublishData
}
if v.CanPublishSources != nil {
clone.CanPublishSources = make([]string, len(v.CanPublishSources))
copy(clone.CanPublishSources, v.CanPublishSources)
}
if v.CanUpdateOwnMetadata != nil {
canUpdateOwnMetadata := *v.CanUpdateOwnMetadata
clone.CanUpdateOwnMetadata = &canUpdateOwnMetadata
}
return &clone
}
func (s *SIPGrant) Clone() *SIPGrant {
if s == nil {
return nil
}
clone := *s
return &clone
}
func sourceToString(source livekit.TrackSource) string {
return strings.ToLower(source.String())
}
func sourceToProto(sourceStr string) livekit.TrackSource {
switch sourceStr {
case "camera":
return livekit.TrackSource_CAMERA
case "microphone":
return livekit.TrackSource_MICROPHONE
case "screen_share":
return livekit.TrackSource_SCREEN_SHARE
case "screen_share_audio":
return livekit.TrackSource_SCREEN_SHARE_AUDIO
default:
return livekit.TrackSource_UNKNOWN
}
}
func kindFromProto(source livekit.ParticipantInfo_Kind) string {
return strings.ToLower(source.String())
}
func kindToProto(sourceStr string) livekit.ParticipantInfo_Kind {
switch sourceStr {
case "", "standard":
return livekit.ParticipantInfo_STANDARD
case "ingress":
return livekit.ParticipantInfo_INGRESS
case "egress":
return livekit.ParticipantInfo_EGRESS
case "sip":
return livekit.ParticipantInfo_SIP
case "agent":
return livekit.ParticipantInfo_AGENT
default:
return livekit.ParticipantInfo_STANDARD
}
}

100
auth/grants_test.go Normal file
View File

@@ -0,0 +1,100 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"reflect"
"strconv"
"testing"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/livekit"
)
func TestGrants(t *testing.T) {
t.Parallel()
t.Run("clone default grant", func(t *testing.T) {
grants := &ClaimGrants{}
clone := grants.Clone()
require.NotSame(t, grants, clone)
require.Same(t, grants.Video, clone.Video)
require.True(t, reflect.DeepEqual(grants, clone))
require.True(t, reflect.DeepEqual(grants.Video, clone.Video))
})
t.Run("clone nil video", func(t *testing.T) {
grants := &ClaimGrants{
Identity: "identity",
Name: "name",
Sha256: "sha256",
Metadata: "metadata",
}
clone := grants.Clone()
require.NotSame(t, grants, clone)
require.Same(t, grants.Video, clone.Video)
require.True(t, reflect.DeepEqual(grants, clone))
require.True(t, reflect.DeepEqual(grants.Video, clone.Video))
})
t.Run("clone with video", func(t *testing.T) {
tr := true
fa := false
video := &VideoGrant{
RoomCreate: true,
RoomList: false,
RoomRecord: true,
RoomAdmin: false,
RoomJoin: true,
Room: "room",
CanPublish: &tr,
CanSubscribe: &fa,
CanPublishData: nil,
Hidden: true,
Recorder: false,
}
grants := &ClaimGrants{
Identity: "identity",
Name: "name",
Kind: "kind",
Video: video,
Sha256: "sha256",
Metadata: "metadata",
}
clone := grants.Clone()
require.NotSame(t, grants, clone)
require.NotSame(t, grants.Video, clone.Video)
require.NotSame(t, grants.Video.CanPublish, clone.Video.CanPublish)
require.NotSame(t, grants.Video.CanSubscribe, clone.Video.CanSubscribe)
require.Same(t, grants.Video.CanPublishData, clone.Video.CanPublishData)
require.True(t, reflect.DeepEqual(grants, clone))
require.True(t, reflect.DeepEqual(grants.Video, clone.Video))
})
}
func TestParticipantKind(t *testing.T) {
const kindMin, kindMax = livekit.ParticipantInfo_STANDARD, livekit.ParticipantInfo_AGENT
for k := kindMin; k <= kindMax; k++ {
k := k
t.Run(k.String(), func(t *testing.T) {
require.Equal(t, k, kindToProto(kindFromProto(k)))
})
}
const kindNext = kindMax + 1
if _, err := strconv.Atoi(kindNext.String()); err != nil {
t.Errorf("Please update kindMax to match protobuf. Missing value: %s", kindNext)
}
}

View File

@@ -1,3 +1,17 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (

View File

@@ -1,3 +1,17 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
@@ -36,3 +50,26 @@ func (p *FileBasedKeyProvider) GetSecret(key string) string {
func (p *FileBasedKeyProvider) NumKeys() int {
return len(p.keys)
}
type SimpleKeyProvider struct {
apiKey string
apiSecret string
}
func NewSimpleKeyProvider(apiKey, apiSecret string) *SimpleKeyProvider {
return &SimpleKeyProvider{
apiKey: apiKey,
apiSecret: apiSecret,
}
}
func (p *SimpleKeyProvider) GetSecret(key string) string {
if key == p.apiKey {
return p.apiSecret
}
return ""
}
func (p *SimpleKeyProvider) NumKeys() int {
return 1
}

View File

@@ -1,11 +1,25 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth_test
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/auth"
)
@@ -16,7 +30,7 @@ func TestFileBasedKeyProvider(t *testing.T) {
"key2": "secret2",
"key3": "secret3",
}
f, err := ioutil.TempFile("", "keyfile")
f, err := os.CreateTemp("", "keyfile")
assert.NoError(t, err)
defer func() {
os.Remove(f.Name())
@@ -30,6 +44,7 @@ func TestFileBasedKeyProvider(t *testing.T) {
f.Close()
r, err := os.Open(f.Name())
require.NoError(t, err)
defer r.Close()
p, err := auth.NewFileBasedKeyProviderFromReader(r)
assert.NoError(t, err)

View File

@@ -1,9 +1,23 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"time"
"gopkg.in/square/go-jose.v2/jwt"
"github.com/go-jose/go-jose/v3/jwt"
)
type APIKeyTokenVerifier struct {
@@ -12,6 +26,7 @@ type APIKeyTokenVerifier struct {
apiKey string
}
// ParseAPIToken parses an encoded JWT token and
func ParseAPIToken(raw string) (*APIKeyTokenVerifier, error) {
tok, err := jwt.ParseSigned(raw)
if err != nil {
@@ -23,14 +38,18 @@ func ParseAPIToken(raw string) (*APIKeyTokenVerifier, error) {
return nil, err
}
return &APIKeyTokenVerifier{
v := &APIKeyTokenVerifier{
token: tok,
apiKey: out.Issuer,
identity: out.ID,
}, nil
identity: out.Subject,
}
if v.identity == "" {
v.identity = out.ID
}
return v, nil
}
// Returns the API key this token was signed with
// APIKey returns the API key this token was signed with
func (v *APIKeyTokenVerifier) APIKey() string {
return v.apiKey
}
@@ -56,6 +75,6 @@ func (v *APIKeyTokenVerifier) Verify(key interface{}) (*ClaimGrants, error) {
}
// copy over identity
claims.Identity = out.ID
claims.Identity = v.identity
return &claims, nil
}

View File

@@ -1,10 +1,25 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/go-jose/go-jose/v3/json"
"github.com/stretchr/testify/require"
"github.com/livekit/protocol/auth"
)
@@ -15,21 +30,22 @@ func TestVerifier(t *testing.T) {
accessToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDg5MzAzMDgsImlzcyI6IkFQSUQzQjY3dXhrNE5qMkdLaVJQaWJBWjkiLCJuYmYiOjE2MDg5MjY3MDgsInJvb21fam9pbiI6dHJ1ZSwicm9vbV9zaWQiOiJteWlkIiwic3ViIjoiQVBJRDNCNjd1eGs0TmoyR0tpUlBpYkFaOSJ9.cmHEBq0MLyRqphmVLM2cLXg5ao5Sro7am8yXhcYKcwE"
t.Run("cannot decode with incorrect key", func(t *testing.T) {
v, err := auth.ParseAPIToken(accessToken)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, apiKey, v.APIKey())
require.Equal(t, apiKey, v.APIKey())
_, err = v.Verify("")
assert.Error(t, err)
require.Error(t, err)
_, err = v.Verify("anothersecret")
assert.Error(t, err)
require.Error(t, err)
})
t.Run("key has expired", func(t *testing.T) {
v, err := auth.ParseAPIToken(accessToken)
require.NoError(t, err)
_, err = v.Verify(secret)
assert.Error(t, err)
require.Error(t, err)
})
t.Run("unexpired token is verified", func(t *testing.T) {
@@ -39,16 +55,16 @@ func TestVerifier(t *testing.T) {
SetValidFor(time.Minute).
SetIdentity("me")
authToken, err := at.ToJWT()
assert.NoError(t, err)
require.NoError(t, err)
v, err := auth.ParseAPIToken(authToken)
assert.NoError(t, err)
assert.Equal(t, apiKey, v.APIKey())
assert.Equal(t, "me", v.Identity())
require.NoError(t, err)
require.Equal(t, apiKey, v.APIKey())
require.Equal(t, "me", v.Identity())
decoded, err := v.Verify(secret)
assert.NoError(t, err)
assert.Equal(t, &claim, decoded.Video)
require.NoError(t, err)
require.Equal(t, &claim, decoded.Video)
})
t.Run("ensure metadata can be passed through", func(t *testing.T) {
@@ -56,22 +72,47 @@ func TestVerifier(t *testing.T) {
"user": "value",
"number": float64(3),
}
md, _ := json.Marshal(metadata)
attrs := map[string]string{"mykey": "myval", "secondkey": "secondval"}
at := auth.NewAccessToken(apiKey, secret).
AddGrant(&auth.VideoGrant{
RoomAdmin: true,
Room: "myroom",
}).
SetMetadata(metadata)
SetMetadata(string(md)).
SetAttributes(attrs)
authToken, err := at.ToJWT()
assert.NoError(t, err)
require.NoError(t, err)
v, err := auth.ParseAPIToken(authToken)
assert.NoError(t, err)
require.NoError(t, err)
decoded, err := v.Verify(secret)
assert.NoError(t, err)
require.NoError(t, err)
assert.EqualValues(t, metadata, decoded.Metadata)
require.EqualValues(t, string(md), decoded.Metadata)
require.EqualValues(t, attrs, decoded.Attributes)
})
t.Run("nil permissions are handled", func(t *testing.T) {
grant := &auth.VideoGrant{
Room: "myroom",
RoomJoin: true,
}
grant.SetCanPublishData(false)
at := auth.NewAccessToken(apiKey, secret).
AddGrant(grant)
token, err := at.ToJWT()
require.NoError(t, err)
v, err := auth.ParseAPIToken(token)
require.NoError(t, err)
decoded, err := v.Verify(secret)
require.NoError(t, err)
require.Nil(t, decoded.Video.CanSubscribe)
require.Nil(t, decoded.Video.CanPublish)
require.False(t, *decoded.Video.CanPublishData)
})
}

57
bootstrap.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
# Copyright 2023 LiveKit, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if ! command -v protoc &> /dev/null
then
echo "protoc is required and not found. please install"
exit 1
fi
if ! command -v mage &> /dev/null
then
pushd /tmp
git clone https://github.com/magefile/mage
cd mage
go run bootstrap.go
rm -rf /tmp/mage
popd
fi
if ! command -v mage &> /dev/null
then
echo "Ensure `go env GOPATH`/bin is in your \$PATH"
exit 1
fi
go mod download
GO_VERSION=`go version | { read _ _ v _; echo ${v#go}; }`
GO_TARGET_VERSION=1.17
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
if [ $(version $GO_VERSION) -ge $(version $GO_TARGET_VERSION) ];
then
go install github.com/twitchtv/twirp/protoc-gen-twirp@v8.1.3
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31.0
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3
go install github.com/livekit/psrpc/protoc-gen-psrpc@v0.5.1
else
go get -u github.com/twitchtv/twirp/protoc-gen-twirp@v8.1.3
go get -u google.golang.org/protobuf/cmd/protoc-gen-go@v1.30.0
go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
go get -u github.com/livekit/psrpc/protoc-gen-psrpc@v0.3.1
fi

24
egress/errors.go Normal file
View File

@@ -0,0 +1,24 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package egress
import (
"github.com/livekit/psrpc"
)
var (
ErrNoResponse = psrpc.NewErrorf(psrpc.Unavailable, "no response from egress service")
ErrEgressTimedOut = psrpc.NewErrorf(psrpc.DeadlineExceeded, "egress timed out")
)

75
egress/redact.go Normal file
View File

@@ -0,0 +1,75 @@
package egress
import (
"github.com/livekit/protocol/livekit"
"github.com/livekit/protocol/utils"
)
func RedactUpload(req UploadRequest) {
if s3 := req.GetS3(); s3 != nil {
s3.AccessKey = utils.Redact(s3.AccessKey, "{access_key}")
s3.Secret = utils.Redact(s3.Secret, "{secret}")
return
}
if gcp := req.GetGcp(); gcp != nil {
gcp.Credentials = utils.Redact(gcp.Credentials, "{credentials}")
return
}
if azure := req.GetAzure(); azure != nil {
azure.AccountName = utils.Redact(azure.AccountName, "{account_name}")
azure.AccountKey = utils.Redact(azure.AccountKey, "{account_key}")
return
}
if aliOSS := req.GetAliOSS(); aliOSS != nil {
aliOSS.AccessKey = utils.Redact(aliOSS.AccessKey, "{access_key}")
aliOSS.Secret = utils.Redact(aliOSS.Secret, "{secret}")
return
}
}
func RedactAutoEncodedOutput(out AutoEncodedOutput) {
if files := out.GetFileOutputs(); len(files) == 1 {
RedactUpload(files[0])
}
if segments := out.GetSegmentOutputs(); len(segments) == 1 {
RedactUpload(segments[0])
}
}
func RedactEncodedOutputs(out EncodedOutput) {
RedactAutoEncodedOutput(out)
if streams := out.GetStreamOutputs(); len(streams) == 1 {
RedactStreamKeys(streams[0])
}
if images := out.GetImageOutputs(); len(images) == 1 {
RedactUpload(images[0])
}
if o, ok := out.(EncodedOutputDeprecated); ok {
if file := o.GetFile(); file != nil {
RedactUpload(file)
} else if stream := o.GetStream(); stream != nil {
RedactStreamKeys(stream)
} else if segment := o.GetSegments(); segment != nil {
RedactUpload(segment)
}
}
}
func RedactDirectOutputs(out DirectOutput) {
if f := out.GetFile(); f != nil {
RedactUpload(f)
}
}
func RedactStreamKeys(stream *livekit.StreamOutput) {
for i, url := range stream.Urls {
if redacted, ok := utils.RedactStreamKey(url); ok {
stream.Urls[i] = redacted
}
}
}

139
egress/redact_test.go Normal file
View File

@@ -0,0 +1,139 @@
package egress
import (
"testing"
"google.golang.org/protobuf/proto"
"github.com/livekit/protocol/livekit"
"github.com/stretchr/testify/require"
)
var (
file = &livekit.EncodedFileOutput{
Output: &livekit.EncodedFileOutput_S3{
S3: &livekit.S3Upload{
AccessKey: "ACCESS_KEY",
Secret: "LONG_SECRET_STRING",
},
},
}
image = &livekit.ImageOutput{
Output: &livekit.ImageOutput_AliOSS{
AliOSS: &livekit.AliOSSUpload{
AccessKey: "ACCESS_KEY",
Secret: "LONG_SECRET_STRING",
},
},
}
segments = &livekit.SegmentedFileOutput{
Output: &livekit.SegmentedFileOutput_Gcp{
Gcp: &livekit.GCPUpload{
Credentials: "CREDENTIALS",
},
},
}
directFile = &livekit.DirectFileOutput{
Output: &livekit.DirectFileOutput_Azure{
Azure: &livekit.AzureBlobUpload{
AccountName: "ACCOUNT_NAME",
AccountKey: "ACCOUNT_KEY",
},
},
}
)
func TestRedactUpload(t *testing.T) {
cl := proto.Clone(file)
RedactUpload(cl.(UploadRequest))
require.Equal(t, "{access_key}", cl.(*livekit.EncodedFileOutput).Output.(*livekit.EncodedFileOutput_S3).S3.AccessKey)
require.Equal(t, "{secret}", cl.(*livekit.EncodedFileOutput).Output.(*livekit.EncodedFileOutput_S3).S3.Secret)
cl = proto.Clone(image)
RedactUpload(cl.(UploadRequest))
require.Equal(t, "{access_key}", cl.(*livekit.ImageOutput).Output.(*livekit.ImageOutput_AliOSS).AliOSS.AccessKey)
require.Equal(t, "{secret}", cl.(*livekit.ImageOutput).Output.(*livekit.ImageOutput_AliOSS).AliOSS.Secret)
cl = proto.Clone(segments)
RedactUpload(cl.(UploadRequest))
require.Equal(t, "{credentials}", cl.(*livekit.SegmentedFileOutput).Output.(*livekit.SegmentedFileOutput_Gcp).Gcp.Credentials)
cl = proto.Clone(directFile)
RedactUpload(cl.(UploadRequest))
require.Equal(t, "{account_name}", cl.(*livekit.DirectFileOutput).Output.(*livekit.DirectFileOutput_Azure).Azure.AccountName)
require.Equal(t, "{account_key}", cl.(*livekit.DirectFileOutput).Output.(*livekit.DirectFileOutput_Azure).Azure.AccountKey)
}
func TestRedactStreamOutput(t *testing.T) {
so := &livekit.StreamOutput{
Urls: []string{
"rtmps://foo.bar.com/app/secret_stream_key",
},
}
RedactStreamKeys(so)
require.Equal(t, "rtmps://foo.bar.com/app/{sec...key}", so.Urls[0])
}
func TestRedactEncodedOutputs(t *testing.T) {
trackComposite := &livekit.TrackCompositeEgressRequest{
FileOutputs: []*livekit.EncodedFileOutput{
file,
},
}
cl := proto.Clone(trackComposite)
RedactEncodedOutputs(cl.(EncodedOutput))
require.Equal(t, "{access_key}", cl.(*livekit.TrackCompositeEgressRequest).FileOutputs[0].Output.(*livekit.EncodedFileOutput_S3).S3.AccessKey)
require.Equal(t, "{secret}", cl.(*livekit.TrackCompositeEgressRequest).FileOutputs[0].Output.(*livekit.EncodedFileOutput_S3).S3.Secret)
roomComposite := &livekit.RoomCompositeEgressRequest{
ImageOutputs: []*livekit.ImageOutput{
image,
},
}
cl = proto.Clone(roomComposite)
RedactEncodedOutputs(cl.(EncodedOutput))
require.Equal(t, "{access_key}", cl.(*livekit.RoomCompositeEgressRequest).ImageOutputs[0].Output.(*livekit.ImageOutput_AliOSS).AliOSS.AccessKey)
require.Equal(t, "{secret}", cl.(*livekit.RoomCompositeEgressRequest).ImageOutputs[0].Output.(*livekit.ImageOutput_AliOSS).AliOSS.Secret)
participant := &livekit.ParticipantEgressRequest{
SegmentOutputs: []*livekit.SegmentedFileOutput{
segments,
},
}
cl = proto.Clone(participant)
RedactEncodedOutputs(cl.(EncodedOutput))
require.Equal(t, "{credentials}", cl.(*livekit.ParticipantEgressRequest).SegmentOutputs[0].Output.(*livekit.SegmentedFileOutput_Gcp).Gcp.Credentials)
}
func TestRedactDirectOutput(t *testing.T) {
track := &livekit.TrackEgressRequest{
Output: &livekit.TrackEgressRequest_File{
File: &livekit.DirectFileOutput{
Output: &livekit.DirectFileOutput_S3{
S3: &livekit.S3Upload{
AccessKey: "ACCESS_KEY",
Secret: "SECRET",
},
},
},
},
}
RedactDirectOutputs(track)
require.Equal(t, "{access_key}", track.Output.(*livekit.TrackEgressRequest_File).File.Output.(*livekit.DirectFileOutput_S3).S3.AccessKey)
require.Equal(t, "{secret}", track.Output.(*livekit.TrackEgressRequest_File).File.Output.(*livekit.DirectFileOutput_S3).S3.Secret)
}

44
egress/token.go Normal file
View File

@@ -0,0 +1,44 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package egress
import (
"time"
"github.com/livekit/protocol/auth"
"github.com/livekit/protocol/livekit"
)
func BuildEgressToken(egressID, apiKey, secret, roomName string) (string, error) {
f := false
t := true
grant := &auth.VideoGrant{
RoomJoin: true,
Room: roomName,
CanSubscribe: &t,
CanPublish: &f,
CanPublishData: &f,
Hidden: true,
Recorder: true,
}
at := auth.NewAccessToken(apiKey, secret).
AddGrant(grant).
SetIdentity(egressID).
SetKind(livekit.ParticipantInfo_EGRESS).
SetValidFor(24 * time.Hour)
return at.ToJWT()
}

132
egress/types.go Normal file
View File

@@ -0,0 +1,132 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package egress
import "github.com/livekit/protocol/livekit"
const (
EgressTypeRoomComposite = "room_composite"
EgressTypeWeb = "web"
EgressTypeParticipant = "participant"
EgressTypeTrackComposite = "track_composite"
EgressTypeTrack = "track"
OutputTypeFile = "file"
OutputTypeStream = "stream"
OutputTypeSegments = "segments"
OutputTypeImages = "images"
OutputTypeMultiple = "multiple"
Unknown = "unknown"
)
// Outputs that can be used in egress that are started automatically on room creation
type AutoEncodedOutput interface {
GetFileOutputs() []*livekit.EncodedFileOutput
GetSegmentOutputs() []*livekit.SegmentedFileOutput
}
type EncodedOutput interface {
AutoEncodedOutput
GetStreamOutputs() []*livekit.StreamOutput
GetImageOutputs() []*livekit.ImageOutput
}
type EncodedOutputDeprecated interface {
GetFile() *livekit.EncodedFileOutput
GetStream() *livekit.StreamOutput
GetSegments() *livekit.SegmentedFileOutput
}
type DirectOutput interface {
GetFile() *livekit.DirectFileOutput
GetWebsocketUrl() string
}
type UploadRequest interface {
GetS3() *livekit.S3Upload
GetGcp() *livekit.GCPUpload
GetAzure() *livekit.AzureBlobUpload
GetAliOSS() *livekit.AliOSSUpload
}
func GetTypes(request interface{}) (string, string) {
switch req := request.(type) {
case *livekit.EgressInfo_RoomComposite:
return EgressTypeRoomComposite, GetOutputType(req.RoomComposite)
case *livekit.EgressInfo_Web:
return EgressTypeWeb, GetOutputType(req.Web)
case *livekit.EgressInfo_Participant:
return EgressTypeParticipant, GetOutputType(req.Participant)
case *livekit.EgressInfo_TrackComposite:
return EgressTypeTrackComposite, GetOutputType(req.TrackComposite)
case *livekit.EgressInfo_Track:
return EgressTypeTrack, GetOutputType(req.Track)
}
return Unknown, Unknown
}
func GetOutputType(req interface{}) string {
if r, ok := req.(EncodedOutput); ok {
outputs := make([]string, 0)
if len(r.GetFileOutputs()) > 0 {
outputs = append(outputs, OutputTypeFile)
}
if len(r.GetStreamOutputs()) > 0 {
outputs = append(outputs, OutputTypeStream)
}
if len(r.GetSegmentOutputs()) > 0 {
outputs = append(outputs, OutputTypeSegments)
}
if len(r.GetImageOutputs()) > 0 {
outputs = append(outputs, OutputTypeImages)
}
switch len(outputs) {
default:
return OutputTypeMultiple
case 1:
return outputs[0]
case 0:
if r, ok := req.(EncodedOutputDeprecated); ok {
if r.GetFile() != nil {
return OutputTypeFile
}
if r.GetStream() != nil {
return OutputTypeStream
}
if r.GetSegments() != nil {
return OutputTypeSegments
}
}
}
}
if r, ok := req.(DirectOutput); ok {
if r.GetFile() != nil {
return OutputTypeFile
}
if r.GetWebsocketUrl() != "" {
return OutputTypeStream
}
}
return Unknown
}

81
egress/types_test.go Normal file
View File

@@ -0,0 +1,81 @@
package egress
import (
"testing"
"github.com/livekit/protocol/livekit"
"github.com/stretchr/testify/require"
)
func TestGetOutputType(t *testing.T) {
roomReq := &livekit.RoomCompositeEgressRequest{
FileOutputs: []*livekit.EncodedFileOutput{
&livekit.EncodedFileOutput{},
},
}
ot := GetOutputType(roomReq)
require.Equal(t, OutputTypeFile, ot)
roomReq = &livekit.RoomCompositeEgressRequest{
Output: &livekit.RoomCompositeEgressRequest_File{
File: &livekit.EncodedFileOutput{},
},
}
ot = GetOutputType(roomReq)
require.Equal(t, OutputTypeFile, ot)
trackReq := &livekit.TrackCompositeEgressRequest{
SegmentOutputs: []*livekit.SegmentedFileOutput{
&livekit.SegmentedFileOutput{},
},
}
ot = GetOutputType(trackReq)
require.Equal(t, OutputTypeSegments, ot)
trackReq = &livekit.TrackCompositeEgressRequest{
Output: &livekit.TrackCompositeEgressRequest_Segments{
Segments: &livekit.SegmentedFileOutput{},
},
}
ot = GetOutputType(trackReq)
require.Equal(t, OutputTypeSegments, ot)
webReq := &livekit.WebEgressRequest{
StreamOutputs: []*livekit.StreamOutput{
&livekit.StreamOutput{},
},
}
ot = GetOutputType(webReq)
require.Equal(t, OutputTypeStream, ot)
webReq = &livekit.WebEgressRequest{
Output: &livekit.WebEgressRequest_Stream{
Stream: &livekit.StreamOutput{},
},
}
ot = GetOutputType(webReq)
require.Equal(t, OutputTypeStream, ot)
participantReq := &livekit.ParticipantEgressRequest{
ImageOutputs: []*livekit.ImageOutput{
&livekit.ImageOutput{},
},
}
ot = GetOutputType(participantReq)
require.Equal(t, OutputTypeImages, ot)
participantReq.SegmentOutputs = []*livekit.SegmentedFileOutput{
&livekit.SegmentedFileOutput{},
}
ot = GetOutputType(participantReq)
require.Equal(t, OutputTypeMultiple, ot)
}

91
go.mod
View File

@@ -1,14 +1,87 @@
module github.com/livekit/protocol
go 1.16
go 1.22
require (
github.com/google/go-cmp v0.5.5 // indirect
github.com/lithammer/shortuuid/v3 v3.0.6
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
gopkg.in/square/go-jose.v2 v2.5.1
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
github.com/benbjohnson/clock v1.3.5
github.com/bufbuild/protoyaml-go v0.1.9
github.com/eapache/channels v1.1.0
github.com/frostbyte73/core v0.0.10
github.com/fsnotify/fsnotify v1.7.0
github.com/gammazero/deque v0.2.1
github.com/go-jose/go-jose/v3 v3.0.3
github.com/go-logr/logr v1.4.1
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/jxskiss/base62 v1.1.0
github.com/lithammer/shortuuid/v4 v4.0.0
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1
github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5
github.com/mackerelio/go-osstat v0.2.4
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1
github.com/pion/logging v0.2.2
github.com/pion/sdp/v3 v3.0.6
github.com/pion/webrtc/v3 v3.2.28
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.19.0
github.com/prometheus/procfs v0.12.0
github.com/puzpuzpuz/xsync/v3 v3.1.0
github.com/redis/go-redis/v9 v9.5.1
github.com/stretchr/testify v1.9.0
github.com/twitchtv/twirp v8.1.3+incompatible
github.com/zeebo/xxh3 v1.0.2
go.uber.org/atomic v1.11.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
go.uber.org/zap/exp v0.2.0
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8
golang.org/x/mod v0.16.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.33.0
gopkg.in/yaml.v3 v3.0.1
)
require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bufbuild/protovalidate-go v0.6.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/cel-go v0.20.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/nats-io/nats.go v1.31.0 // indirect
github.com/nats-io/nkeys v0.4.6 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/pion/datachannel v1.5.5 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
github.com/pion/ice/v2 v2.3.13 // indirect
github.com/pion/interceptor v0.1.25 // indirect
github.com/pion/mdns v0.0.12 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.12 // indirect
github.com/pion/rtp v1.8.3 // indirect
github.com/pion/sctp v1.8.12 // indirect
github.com/pion/srtp/v2 v2.0.18 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/transport/v2 v2.2.3 // indirect
github.com/pion/turn/v2 v2.1.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.19.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
)

312
go.sum
View File

@@ -1,6 +1,47 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1 h1:2IGhRovxlsOIQgx2ekZWo4wTPAYpck41+18ICxs37is=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1/go.mod h1:Tgn5bgL220vkFOI0KPStlcClPeOJzAv4uT+V8JXGUnw=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bufbuild/protovalidate-go v0.6.1 h1:uzW8r0CDvqApUChNj87VzZVoQSKhcVdw5UWOE605UIw=
github.com/bufbuild/protovalidate-go v0.6.1/go.mod h1:4BR3rKEJiUiTy+sqsusFn2ladOf0kYmA2Reo6BHSBgQ=
github.com/bufbuild/protoyaml-go v0.1.9 h1:anV5UtF1Mlvkkgp4NWA6U/zOnJFng8Orq4Vf3ZUQHBU=
github.com/bufbuild/protoyaml-go v0.1.9/go.mod h1:KCBItkvZOK/zwGueLdH1Wx1RLyFn5rCH7YjQrdty2Wc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k=
github.com/eapache/channels v1.1.0/go.mod h1:jMm2qB5Ubtg9zLd+inMZd2/NUvXgzmWXsDaLyQIGfH0=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/frostbyte73/core v0.0.10 h1:D4DQXdPb8ICayz0n75rs4UYTXrUSdxzUfeleuNJORsU=
github.com/frostbyte73/core v0.0.10/go.mod h1:XsOGqrqe/VEV7+8vJ+3a8qnCIXNbKsoEiu/czs7nrcU=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -8,91 +49,294 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw=
github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc=
github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lithammer/shortuuid/v3 v3.0.6 h1:pr15YQyvhiSX/qPxncFtqk+v4xLEpOZObbsY/mKrcvA=
github.com/lithammer/shortuuid/v3 v3.0.6/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d h1:HONlVR8gkr5QibYNVFtj8ajfqRAKt21DmdzeZXZl6VQ=
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d/go.mod h1:nFZ1y9JiUDciefRL0X6OTobqQGgFCR+lbnn1lWsoQk0=
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0 h1:8E6DrFvII6QR4eJ3PkFvV+lc03P+2qwqTPLm1ax7694=
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0/go.mod h1:fcEyUyXZXoV4Abw8DX0t7wyL8mCDxXyU4iAFZfT3IHw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y=
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkDaKb5iXdynYrzB84ErPPO4LbRASk58=
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ=
github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5 h1:mTZyrjk5WEWMsvaYtJ42pG7DuxysKj21DKPINpGSIto=
github.com/livekit/psrpc v0.5.3-0.20240526192918-fbdaf10e6aa5/go.mod h1:CQUBSPfYYAaevg1TNCc6/aYsa8DJH4jSRFdCeSZk5u0=
github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs=
github.com/mackerelio/go-osstat v0.2.4/go.mod h1:Zy+qzGdZs3A9cuIqmgbJvwbmLQH9dJvtio5ZjJTbdlQ=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM=
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I=
github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E=
github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8=
github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY=
github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
github.com/pion/ice/v2 v2.3.13 h1:xOxP+4V9nSDlUaGFRf/LvAuGHDXRcjIdsbbXPK/w7c8=
github.com/pion/ice/v2 v2.3.13/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw=
github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc=
github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8=
github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
github.com/pion/rtcp v1.2.12 h1:bKWiX93XKgDZENEXCijvHRU/wRifm6JV5DGcH6twtSM=
github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/rtp v1.8.3 h1:VEHxqzSVQxCkKDSHro5/4IUUG1ea+MFdqR2R3xSpNU8=
github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
github.com/pion/sctp v1.8.12 h1:2VX50pedElH+is6FI+OKyRTeN5oy4mrk2HjnGa3UCmY=
github.com/pion/sctp v1.8.12/go.mod h1:cMLT45jqw3+jiJCrtHVwfQLnfR0MGZ4rgOJwUOIqLkI=
github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo=
github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc=
github.com/pion/transport/v2 v2.2.3 h1:XcOE3/x41HOSKbl1BfyY1TF1dERx7lVvlMCbXU7kfvA=
github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pion/turn/v2 v2.1.3 h1:pYxTVWG2gpC97opdRc5IGsQ1lJ9O/IlNhkzj7MMrGAA=
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
github.com/pion/webrtc/v3 v3.2.28 h1:ienStxZ6HcjtH2UlmnFpMM0loENiYjaX437uIUpQSKo=
github.com/pion/webrtc/v3 v3.2.28/go.mod h1:PNRCEuQlibrmuBhOTnol9j6KkIbUG11aHLEfNpUYey0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/puzpuzpuz/xsync/v3 v3.1.0 h1:EewKT7/LNac5SLiEblJeUu8z5eERHrmRLnMQL2d7qX4=
github.com/puzpuzpuz/xsync/v3 v3.1.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU=
github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap/exp v0.2.0 h1:FtGenNNeCATRB3CmB/yEUnjEFeJWpB/pMcy7e2bKPYs=
go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201026091529-146b70c837a4 h1:awiuzyrRjJDb+OXi9ceHO3SDxVoN3JER57mhtqkdQBs=
golang.org/x/net v0.0.0-20201026091529-146b70c837a4/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6 h1:rbvTkL9AkFts1cgI78+gG6Yu1pwaqX6hjSJAatB78E4=
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38=
google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

472
infra/link.pb.go Normal file
View File

@@ -0,0 +1,472 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.2
// protoc v4.23.4
// source: infra/link.proto
package infra
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type WatchLocalLinksRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *WatchLocalLinksRequest) Reset() {
*x = WatchLocalLinksRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_infra_link_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WatchLocalLinksRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WatchLocalLinksRequest) ProtoMessage() {}
func (x *WatchLocalLinksRequest) ProtoReflect() protoreflect.Message {
mi := &file_infra_link_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WatchLocalLinksRequest.ProtoReflect.Descriptor instead.
func (*WatchLocalLinksRequest) Descriptor() ([]byte, []int) {
return file_infra_link_proto_rawDescGZIP(), []int{0}
}
type WatchLocalLinksResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LocalRegion string `protobuf:"bytes,1,opt,name=local_region,json=localRegion,proto3" json:"local_region,omitempty"`
RemoteRegion string `protobuf:"bytes,2,opt,name=remote_region,json=remoteRegion,proto3" json:"remote_region,omitempty"`
Rtt int64 `protobuf:"varint,3,opt,name=rtt,proto3" json:"rtt,omitempty"`
Jitter int64 `protobuf:"varint,4,opt,name=jitter,proto3" json:"jitter,omitempty"`
PacketLoss float64 `protobuf:"fixed64,5,opt,name=packet_loss,json=packetLoss,proto3" json:"packet_loss,omitempty"`
Disabled bool `protobuf:"varint,6,opt,name=disabled,proto3" json:"disabled,omitempty"`
LastRead *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=last_read,json=lastRead,proto3" json:"last_read,omitempty"`
}
func (x *WatchLocalLinksResponse) Reset() {
*x = WatchLocalLinksResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_infra_link_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WatchLocalLinksResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WatchLocalLinksResponse) ProtoMessage() {}
func (x *WatchLocalLinksResponse) ProtoReflect() protoreflect.Message {
mi := &file_infra_link_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WatchLocalLinksResponse.ProtoReflect.Descriptor instead.
func (*WatchLocalLinksResponse) Descriptor() ([]byte, []int) {
return file_infra_link_proto_rawDescGZIP(), []int{1}
}
func (x *WatchLocalLinksResponse) GetLocalRegion() string {
if x != nil {
return x.LocalRegion
}
return ""
}
func (x *WatchLocalLinksResponse) GetRemoteRegion() string {
if x != nil {
return x.RemoteRegion
}
return ""
}
func (x *WatchLocalLinksResponse) GetRtt() int64 {
if x != nil {
return x.Rtt
}
return 0
}
func (x *WatchLocalLinksResponse) GetJitter() int64 {
if x != nil {
return x.Jitter
}
return 0
}
func (x *WatchLocalLinksResponse) GetPacketLoss() float64 {
if x != nil {
return x.PacketLoss
}
return 0
}
func (x *WatchLocalLinksResponse) GetDisabled() bool {
if x != nil {
return x.Disabled
}
return false
}
func (x *WatchLocalLinksResponse) GetLastRead() *timestamppb.Timestamp {
if x != nil {
return x.LastRead
}
return nil
}
type SimulateLinkStateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LocalRegion string `protobuf:"bytes,1,opt,name=local_region,json=localRegion,proto3" json:"local_region,omitempty"`
RemoteRegion string `protobuf:"bytes,2,opt,name=remote_region,json=remoteRegion,proto3" json:"remote_region,omitempty"`
Rtt *int64 `protobuf:"varint,3,opt,name=rtt,proto3,oneof" json:"rtt,omitempty"`
Jitter *int64 `protobuf:"varint,4,opt,name=jitter,proto3,oneof" json:"jitter,omitempty"`
PacketLoss *float64 `protobuf:"fixed64,5,opt,name=packet_loss,json=packetLoss,proto3,oneof" json:"packet_loss,omitempty"`
Disabled *bool `protobuf:"varint,6,opt,name=disabled,proto3,oneof" json:"disabled,omitempty"`
Timeout int64 `protobuf:"varint,7,opt,name=timeout,proto3" json:"timeout,omitempty"`
}
func (x *SimulateLinkStateRequest) Reset() {
*x = SimulateLinkStateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_infra_link_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SimulateLinkStateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SimulateLinkStateRequest) ProtoMessage() {}
func (x *SimulateLinkStateRequest) ProtoReflect() protoreflect.Message {
mi := &file_infra_link_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SimulateLinkStateRequest.ProtoReflect.Descriptor instead.
func (*SimulateLinkStateRequest) Descriptor() ([]byte, []int) {
return file_infra_link_proto_rawDescGZIP(), []int{2}
}
func (x *SimulateLinkStateRequest) GetLocalRegion() string {
if x != nil {
return x.LocalRegion
}
return ""
}
func (x *SimulateLinkStateRequest) GetRemoteRegion() string {
if x != nil {
return x.RemoteRegion
}
return ""
}
func (x *SimulateLinkStateRequest) GetRtt() int64 {
if x != nil && x.Rtt != nil {
return *x.Rtt
}
return 0
}
func (x *SimulateLinkStateRequest) GetJitter() int64 {
if x != nil && x.Jitter != nil {
return *x.Jitter
}
return 0
}
func (x *SimulateLinkStateRequest) GetPacketLoss() float64 {
if x != nil && x.PacketLoss != nil {
return *x.PacketLoss
}
return 0
}
func (x *SimulateLinkStateRequest) GetDisabled() bool {
if x != nil && x.Disabled != nil {
return *x.Disabled
}
return false
}
func (x *SimulateLinkStateRequest) GetTimeout() int64 {
if x != nil {
return x.Timeout
}
return 0
}
type SimulateLinkStateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *SimulateLinkStateResponse) Reset() {
*x = SimulateLinkStateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_infra_link_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SimulateLinkStateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SimulateLinkStateResponse) ProtoMessage() {}
func (x *SimulateLinkStateResponse) ProtoReflect() protoreflect.Message {
mi := &file_infra_link_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SimulateLinkStateResponse.ProtoReflect.Descriptor instead.
func (*SimulateLinkStateResponse) Descriptor() ([]byte, []int) {
return file_infra_link_proto_rawDescGZIP(), []int{3}
}
var File_infra_link_proto protoreflect.FileDescriptor
var file_infra_link_proto_rawDesc = []byte{
0x0a, 0x10, 0x69, 0x6e, 0x66, 0x72, 0x61, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x18, 0x0a, 0x16, 0x57, 0x61, 0x74, 0x63,
0x68, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x22, 0x81, 0x02, 0x0a, 0x17, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x63, 0x61,
0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21,
0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x67, 0x69, 0x6f,
0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69,
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65,
0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x74, 0x74, 0x18, 0x03, 0x20,
0x01, 0x28, 0x03, 0x52, 0x03, 0x72, 0x74, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6a, 0x69, 0x74, 0x74,
0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6a, 0x69, 0x74, 0x74, 0x65, 0x72,
0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x6c, 0x6f, 0x73, 0x73, 0x18,
0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x6f, 0x73,
0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20,
0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x37, 0x0a,
0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61,
0x73, 0x74, 0x52, 0x65, 0x61, 0x64, 0x22, 0xa7, 0x02, 0x0a, 0x18, 0x53, 0x69, 0x6d, 0x75, 0x6c,
0x61, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x67,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65,
0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72,
0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x03, 0x72,
0x74, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x03, 0x72, 0x74, 0x74, 0x88,
0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x6a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01,
0x28, 0x03, 0x48, 0x01, 0x52, 0x06, 0x6a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12,
0x24, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x6c, 0x6f, 0x73, 0x73, 0x18, 0x05,
0x20, 0x01, 0x28, 0x01, 0x48, 0x02, 0x52, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x6f,
0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x03, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x42, 0x06, 0x0a, 0x04, 0x5f, 0x72, 0x74, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6a, 0x69, 0x74,
0x74, 0x65, 0x72, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x6c,
0x6f, 0x73, 0x73, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
0x22, 0x1b, 0x0a, 0x19, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b,
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xaa, 0x01,
0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x4e, 0x0a, 0x0f, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c,
0x6f, 0x63, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x1b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x74,
0x63, 0x68, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x11, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61,
0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74,
0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61,
0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x69, 0x6e, 0x66, 0x72, 0x61, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_infra_link_proto_rawDescOnce sync.Once
file_infra_link_proto_rawDescData = file_infra_link_proto_rawDesc
)
func file_infra_link_proto_rawDescGZIP() []byte {
file_infra_link_proto_rawDescOnce.Do(func() {
file_infra_link_proto_rawDescData = protoimpl.X.CompressGZIP(file_infra_link_proto_rawDescData)
})
return file_infra_link_proto_rawDescData
}
var file_infra_link_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_infra_link_proto_goTypes = []any{
(*WatchLocalLinksRequest)(nil), // 0: rpc.WatchLocalLinksRequest
(*WatchLocalLinksResponse)(nil), // 1: rpc.WatchLocalLinksResponse
(*SimulateLinkStateRequest)(nil), // 2: rpc.SimulateLinkStateRequest
(*SimulateLinkStateResponse)(nil), // 3: rpc.SimulateLinkStateResponse
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
}
var file_infra_link_proto_depIdxs = []int32{
4, // 0: rpc.WatchLocalLinksResponse.last_read:type_name -> google.protobuf.Timestamp
0, // 1: rpc.Link.WatchLocalLinks:input_type -> rpc.WatchLocalLinksRequest
2, // 2: rpc.Link.SimulateLinkState:input_type -> rpc.SimulateLinkStateRequest
1, // 3: rpc.Link.WatchLocalLinks:output_type -> rpc.WatchLocalLinksResponse
3, // 4: rpc.Link.SimulateLinkState:output_type -> rpc.SimulateLinkStateResponse
3, // [3:5] is the sub-list for method output_type
1, // [1:3] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_infra_link_proto_init() }
func file_infra_link_proto_init() {
if File_infra_link_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_infra_link_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*WatchLocalLinksRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_infra_link_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*WatchLocalLinksResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_infra_link_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*SimulateLinkStateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_infra_link_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*SimulateLinkStateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_infra_link_proto_msgTypes[2].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_infra_link_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_infra_link_proto_goTypes,
DependencyIndexes: file_infra_link_proto_depIdxs,
MessageInfos: file_infra_link_proto_msgTypes,
}.Build()
File_infra_link_proto = out.File
file_infra_link_proto_rawDesc = nil
file_infra_link_proto_goTypes = nil
file_infra_link_proto_depIdxs = nil
}

190
infra/link_grpc.pb.go Normal file
View File

@@ -0,0 +1,190 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.4.0
// - protoc v4.23.4
// source: infra/link.proto
package infra
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.62.0 or later.
const _ = grpc.SupportPackageIsVersion8
const (
Link_WatchLocalLinks_FullMethodName = "/rpc.Link/WatchLocalLinks"
Link_SimulateLinkState_FullMethodName = "/rpc.Link/SimulateLinkState"
)
// LinkClient is the client API for Link service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type LinkClient interface {
WatchLocalLinks(ctx context.Context, in *WatchLocalLinksRequest, opts ...grpc.CallOption) (Link_WatchLocalLinksClient, error)
SimulateLinkState(ctx context.Context, in *SimulateLinkStateRequest, opts ...grpc.CallOption) (*SimulateLinkStateResponse, error)
}
type linkClient struct {
cc grpc.ClientConnInterface
}
func NewLinkClient(cc grpc.ClientConnInterface) LinkClient {
return &linkClient{cc}
}
func (c *linkClient) WatchLocalLinks(ctx context.Context, in *WatchLocalLinksRequest, opts ...grpc.CallOption) (Link_WatchLocalLinksClient, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &Link_ServiceDesc.Streams[0], Link_WatchLocalLinks_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
x := &linkWatchLocalLinksClient{ClientStream: stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Link_WatchLocalLinksClient interface {
Recv() (*WatchLocalLinksResponse, error)
grpc.ClientStream
}
type linkWatchLocalLinksClient struct {
grpc.ClientStream
}
func (x *linkWatchLocalLinksClient) Recv() (*WatchLocalLinksResponse, error) {
m := new(WatchLocalLinksResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *linkClient) SimulateLinkState(ctx context.Context, in *SimulateLinkStateRequest, opts ...grpc.CallOption) (*SimulateLinkStateResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SimulateLinkStateResponse)
err := c.cc.Invoke(ctx, Link_SimulateLinkState_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// LinkServer is the server API for Link service.
// All implementations must embed UnimplementedLinkServer
// for forward compatibility
type LinkServer interface {
WatchLocalLinks(*WatchLocalLinksRequest, Link_WatchLocalLinksServer) error
SimulateLinkState(context.Context, *SimulateLinkStateRequest) (*SimulateLinkStateResponse, error)
mustEmbedUnimplementedLinkServer()
}
// UnimplementedLinkServer must be embedded to have forward compatible implementations.
type UnimplementedLinkServer struct {
}
func (UnimplementedLinkServer) WatchLocalLinks(*WatchLocalLinksRequest, Link_WatchLocalLinksServer) error {
return status.Errorf(codes.Unimplemented, "method WatchLocalLinks not implemented")
}
func (UnimplementedLinkServer) SimulateLinkState(context.Context, *SimulateLinkStateRequest) (*SimulateLinkStateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SimulateLinkState not implemented")
}
func (UnimplementedLinkServer) mustEmbedUnimplementedLinkServer() {}
// UnsafeLinkServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to LinkServer will
// result in compilation errors.
type UnsafeLinkServer interface {
mustEmbedUnimplementedLinkServer()
}
func RegisterLinkServer(s grpc.ServiceRegistrar, srv LinkServer) {
s.RegisterService(&Link_ServiceDesc, srv)
}
func _Link_WatchLocalLinks_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(WatchLocalLinksRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(LinkServer).WatchLocalLinks(m, &linkWatchLocalLinksServer{ServerStream: stream})
}
type Link_WatchLocalLinksServer interface {
Send(*WatchLocalLinksResponse) error
grpc.ServerStream
}
type linkWatchLocalLinksServer struct {
grpc.ServerStream
}
func (x *linkWatchLocalLinksServer) Send(m *WatchLocalLinksResponse) error {
return x.ServerStream.SendMsg(m)
}
func _Link_SimulateLinkState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimulateLinkStateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LinkServer).SimulateLinkState(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Link_SimulateLinkState_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LinkServer).SimulateLinkState(ctx, req.(*SimulateLinkStateRequest))
}
return interceptor(ctx, in, info, handler)
}
// Link_ServiceDesc is the grpc.ServiceDesc for Link service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Link_ServiceDesc = grpc.ServiceDesc{
ServiceName: "rpc.Link",
HandlerType: (*LinkServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SimulateLinkState",
Handler: _Link_SimulateLinkState_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "WatchLocalLinks",
Handler: _Link_WatchLocalLinks_Handler,
ServerStreams: true,
},
},
Metadata: "infra/link.proto",
}

45
ingress/errors.go Normal file
View File

@@ -0,0 +1,45 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ingress
import (
"fmt"
"github.com/livekit/psrpc"
)
var (
ErrIngressOutOfDate = psrpc.NewErrorf(psrpc.FailedPrecondition, "trying to ovewrite an ingress with an older version")
ErrIngressTimedOut = psrpc.NewErrorf(psrpc.DeadlineExceeded, "ingress timed out")
ErrNoResponse = psrpc.NewErrorf(psrpc.Unavailable, "no response from ingress service")
ErrInvalidOutputDimensions = NewInvalidVideoParamsError("invalid output media dimensions")
ErrInvalidIngressType = psrpc.NewErrorf(psrpc.InvalidArgument, "invalid ingress type")
)
func ErrInvalidIngress(s string) psrpc.Error {
return psrpc.NewErrorf(psrpc.InvalidArgument, "invalid ingress: %s", s)
}
func NewInvalidVideoParamsError(s string) error {
return psrpc.NewError(psrpc.InvalidArgument, fmt.Errorf("invalid video parameters: %s", s))
}
func NewInvalidAudioParamsError(s string) error {
return psrpc.NewError(psrpc.InvalidArgument, fmt.Errorf("invalid audio parameters: %s", s))
}
func NewInvalidTranscodingBypassError(s string) error {
return psrpc.NewError(psrpc.InvalidArgument, fmt.Errorf("invalid transcoding bypass configuration: %s", s))
}

43
ingress/token.go Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ingress
import (
"time"
"github.com/livekit/protocol/auth"
"github.com/livekit/protocol/livekit"
)
func BuildIngressToken(apiKey, secret, roomName, participantIdentity, participantName, participantMetadata string) (string, error) {
f := false
t := true
grant := &auth.VideoGrant{
RoomJoin: true,
Room: roomName,
CanSubscribe: &f,
CanPublish: &t,
}
at := auth.NewAccessToken(apiKey, secret).
AddGrant(grant).
SetIdentity(participantIdentity).
SetName(participantName).
SetKind(livekit.ParticipantInfo_INGRESS).
SetValidFor(24 * time.Hour).
SetMetadata(participantMetadata)
return at.ToJWT()
}

283
ingress/validation.go Normal file
View File

@@ -0,0 +1,283 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ingress
import (
"github.com/livekit/protocol/livekit"
)
// This validates that ingress options have no consistency issues and provide enough parameters
// to be usable by the ingress service. Options that pass this test may still need some fields to be poulated with default values
// before being used in a media pipeline.
func Validate(info *livekit.IngressInfo) error {
if info == nil {
return ErrInvalidIngress("missing IngressInfo")
}
// For now, require a room to be set. We should eventually allow changing the room on an active ingress
if info.RoomName == "" {
return ErrInvalidIngress("no room name")
}
return ValidateForSerialization(info)
}
// Sparse info with not all required fields populated are acceptable for serialization, provided values are consistent
func ValidateForSerialization(info *livekit.IngressInfo) error {
if info == nil {
return ErrInvalidIngress("missing IngressInfo")
}
if info.InputType != livekit.IngressInput_RTMP_INPUT && info.InputType != livekit.IngressInput_WHIP_INPUT && info.InputType != livekit.IngressInput_URL_INPUT {
return ErrInvalidIngress("unsupported input type")
}
// Validate source
switch info.InputType {
case livekit.IngressInput_RTMP_INPUT,
livekit.IngressInput_WHIP_INPUT:
if info.StreamKey == "" {
return ErrInvalidIngress("no stream key")
}
case livekit.IngressInput_URL_INPUT:
if info.Url == "" {
return ErrInvalidIngress("no source URL")
}
}
if info.ParticipantIdentity == "" {
return ErrInvalidIngress("no participant identity")
}
err := ValidateBypassTranscoding(info)
if err != nil {
return err
}
err = ValidateEnableTranscoding(info)
if err != nil {
return err
}
err = ValidateVideoOptionsConsistency(info.Video)
if err != nil {
return err
}
err = ValidateAudioOptionsConsistency(info.Audio)
if err != nil {
return err
}
return nil
}
func ValidateBypassTranscoding(info *livekit.IngressInfo) error {
if !info.BypassTranscoding {
return nil
}
if info.InputType != livekit.IngressInput_WHIP_INPUT {
return NewInvalidTranscodingBypassError("bypassing transcoding impossible with selected input type")
}
videoOptions := info.Video
if videoOptions != nil && videoOptions.EncodingOptions != nil {
return NewInvalidTranscodingBypassError("video encoding options must be empty if transcoding bypass is selected")
}
audioOptions := info.Audio
if audioOptions != nil && audioOptions.EncodingOptions != nil {
return NewInvalidTranscodingBypassError("audio encoding options must be empty if transcoding bypass is selected")
}
return nil
}
func ValidateEnableTranscoding(info *livekit.IngressInfo) error {
var enableTranscoding bool
if info.InputType == livekit.IngressInput_WHIP_INPUT {
enableTranscoding = false
if info.EnableTranscoding != nil {
enableTranscoding = *info.EnableTranscoding
}
} else {
enableTranscoding = true
if info.EnableTranscoding != nil && *info.EnableTranscoding == false {
return NewInvalidTranscodingBypassError("bypassing transcoding impossible with selected input type")
}
}
if !enableTranscoding {
videoOptions := info.Video
if videoOptions != nil && videoOptions.EncodingOptions != nil {
return NewInvalidTranscodingBypassError("video encoding options must be empty if transcoding is disabled")
}
audioOptions := info.Audio
if audioOptions != nil && audioOptions.EncodingOptions != nil {
return NewInvalidTranscodingBypassError("audio encoding options must be empty if transcoding is disabled")
}
}
return nil
}
func ValidateVideoOptionsConsistency(options *livekit.IngressVideoOptions) error {
if options == nil {
return nil
}
switch options.Source {
case livekit.TrackSource_UNKNOWN,
livekit.TrackSource_CAMERA,
livekit.TrackSource_SCREEN_SHARE:
// continue
default:
return NewInvalidVideoParamsError("invalid track source")
}
switch o := options.EncodingOptions.(type) {
case nil:
// Default, continue
case *livekit.IngressVideoOptions_Preset:
_, ok := livekit.IngressVideoEncodingPreset_name[int32(o.Preset)]
if !ok {
return NewInvalidVideoParamsError("invalid preset")
}
case *livekit.IngressVideoOptions_Options:
err := ValidateVideoEncodingOptionsConsistency(o.Options)
if err != nil {
return err
}
}
return nil
}
func ValidateVideoEncodingOptionsConsistency(options *livekit.IngressVideoEncodingOptions) error {
if options == nil {
return NewInvalidVideoParamsError("empty options")
}
if options.FrameRate < 0 {
return NewInvalidVideoParamsError("invalid framerate")
}
switch options.VideoCodec {
case livekit.VideoCodec_DEFAULT_VC,
livekit.VideoCodec_H264_BASELINE,
livekit.VideoCodec_VP8:
// continue
default:
return NewInvalidVideoParamsError("video codec unsupported")
}
layersByQuality := make(map[livekit.VideoQuality]*livekit.VideoLayer)
for _, layer := range options.Layers {
if layer.Height == 0 || layer.Width == 0 {
return ErrInvalidOutputDimensions
}
if layer.Width%2 == 1 {
return ErrInvalidIngress("layer width must be even")
}
if layer.Height%2 == 1 {
return ErrInvalidIngress("layer height must be even")
}
if _, ok := layersByQuality[layer.Quality]; ok {
return NewInvalidVideoParamsError("more than one layer with the same quality level")
}
layersByQuality[layer.Quality] = layer
}
var oldW, oldH uint32
for q := livekit.VideoQuality_LOW; q <= livekit.VideoQuality_HIGH; q++ {
layer, ok := layersByQuality[q]
if !ok {
continue
}
if layer.Height < oldH {
return NewInvalidVideoParamsError("video layers do not have increasing height with increasing quality")
}
if layer.Width < oldW {
return NewInvalidVideoParamsError("video layers do not have increasing width with increasing quality")
}
oldW = layer.Width
oldH = layer.Height
}
return nil
}
func ValidateAudioOptionsConsistency(options *livekit.IngressAudioOptions) error {
if options == nil {
return nil
}
switch options.Source {
case livekit.TrackSource_UNKNOWN,
livekit.TrackSource_MICROPHONE,
livekit.TrackSource_SCREEN_SHARE_AUDIO:
// continue
default:
return NewInvalidAudioParamsError("invalid track source")
}
switch o := options.EncodingOptions.(type) {
case nil:
// Default, continue
case *livekit.IngressAudioOptions_Preset:
_, ok := livekit.IngressAudioEncodingPreset_name[int32(o.Preset)]
if !ok {
return NewInvalidAudioParamsError("invalid preset")
}
case *livekit.IngressAudioOptions_Options:
err := ValidateAudioEncodingOptionsConsistency(o.Options)
if err != nil {
return err
}
}
return nil
}
func ValidateAudioEncodingOptionsConsistency(options *livekit.IngressAudioEncodingOptions) error {
if options == nil {
return NewInvalidAudioParamsError("empty options")
}
switch options.AudioCodec {
case livekit.AudioCodec_DEFAULT_AC,
livekit.AudioCodec_OPUS:
// continue
default:
return NewInvalidAudioParamsError("audio codec unsupported")
}
if options.Channels > 2 {
return NewInvalidAudioParamsError("invalid audio channel count")
}
return nil
}

312
ingress/validation_test.go Normal file
View File

@@ -0,0 +1,312 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ingress
import (
"testing"
"github.com/livekit/protocol/livekit"
"github.com/stretchr/testify/require"
)
func TestValidate(t *testing.T) {
info := &livekit.IngressInfo{}
err := Validate(info)
require.Error(t, err)
info.StreamKey = "stream_key"
err = Validate(info)
require.Error(t, err)
info.RoomName = "room_name"
err = Validate(info)
require.Error(t, err)
info.ParticipantIdentity = "participant_identity"
err = Validate(info)
require.NoError(t, err)
// make sure video parameters are validated. Full validation logic tested in the next test
info.Video = &livekit.IngressVideoOptions{}
err = Validate(info)
require.NoError(t, err)
info.Video.Source = livekit.TrackSource_MICROPHONE
err = Validate(info)
require.Error(t, err)
info.Video.Source = livekit.TrackSource_CAMERA
// make sure audio parameters are validated. Full validation logic tested in the next test
info.Audio = &livekit.IngressAudioOptions{}
err = Validate(info)
require.NoError(t, err)
info.Audio.Source = livekit.TrackSource_CAMERA
err = Validate(info)
require.Error(t, err)
info.Audio.Source = livekit.TrackSource_SCREEN_SHARE_AUDIO
err = Validate(info)
require.NoError(t, err)
}
func TestValidateBypassTranscoding(t *testing.T) {
info := &livekit.IngressInfo{}
err := ValidateBypassTranscoding(info)
require.NoError(t, err)
info.BypassTranscoding = true
err = ValidateBypassTranscoding(info)
require.Error(t, err)
info.InputType = livekit.IngressInput_WHIP_INPUT
err = ValidateBypassTranscoding(info)
require.NoError(t, err)
info.Video = &livekit.IngressVideoOptions{}
err = ValidateBypassTranscoding(info)
require.NoError(t, err)
info.Video.EncodingOptions = &livekit.IngressVideoOptions_Preset{}
err = ValidateBypassTranscoding(info)
require.Error(t, err)
info.Video = nil
info.Audio = &livekit.IngressAudioOptions{}
err = ValidateBypassTranscoding(info)
require.NoError(t, err)
info.Audio.EncodingOptions = &livekit.IngressAudioOptions_Options{
Options: &livekit.IngressAudioEncodingOptions{},
}
err = ValidateBypassTranscoding(info)
require.Error(t, err)
}
func TestValidateEnableTranscoding(t *testing.T) {
info := &livekit.IngressInfo{}
T := true
F := false
err := ValidateEnableTranscoding(info)
require.NoError(t, err)
info.InputType = livekit.IngressInput_WHIP_INPUT
err = ValidateEnableTranscoding(info)
require.NoError(t, err)
info.Audio = &livekit.IngressAudioOptions{}
info.Audio.EncodingOptions = &livekit.IngressAudioOptions_Options{}
err = ValidateEnableTranscoding(info)
require.Error(t, err)
info.Audio.EncodingOptions = nil
info.EnableTranscoding = &T
err = ValidateEnableTranscoding(info)
require.NoError(t, err)
info.EnableTranscoding = &F
err = ValidateEnableTranscoding(info)
require.NoError(t, err)
info.Video = &livekit.IngressVideoOptions{}
info.Video.EncodingOptions = &livekit.IngressVideoOptions_Preset{}
err = ValidateEnableTranscoding(info)
require.Error(t, err)
info.Video.EncodingOptions = nil
info.InputType = livekit.IngressInput_RTMP_INPUT
err = ValidateEnableTranscoding(info)
require.Error(t, err)
info.EnableTranscoding = &T
err = ValidateEnableTranscoding(info)
require.NoError(t, err)
}
func TestValidateVideoOptionsConsistency(t *testing.T) {
video := &livekit.IngressVideoOptions{}
err := ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
video.Source = livekit.TrackSource_MICROPHONE
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.Source = livekit.TrackSource_CAMERA
video.EncodingOptions = &livekit.IngressVideoOptions_Preset{
Preset: livekit.IngressVideoEncodingPreset(42),
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions = &livekit.IngressVideoOptions_Preset{
Preset: livekit.IngressVideoEncodingPreset_H264_1080P_30FPS_1_LAYER,
}
err = ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
video.EncodingOptions = &livekit.IngressVideoOptions_Options{
Options: &livekit.IngressVideoEncodingOptions{
VideoCodec: livekit.VideoCodec_H264_HIGH,
},
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions = &livekit.IngressVideoOptions_Options{
Options: &livekit.IngressVideoEncodingOptions{
VideoCodec: livekit.VideoCodec_DEFAULT_VC,
},
}
err = ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{},
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 640,
Height: 480,
},
}
err = ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 641,
Height: 480,
},
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 640,
Height: 480,
Quality: livekit.VideoQuality_HIGH,
},
&livekit.VideoLayer{
Width: 640,
Height: 480,
Quality: livekit.VideoQuality_LOW,
},
}
err = ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 640,
Height: 480,
Quality: livekit.VideoQuality_HIGH,
},
&livekit.VideoLayer{
Width: 1280,
Height: 720,
Quality: livekit.VideoQuality_HIGH,
},
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 640,
Height: 480,
Quality: livekit.VideoQuality_HIGH,
},
&livekit.VideoLayer{
Width: 1280,
Height: 720,
Quality: livekit.VideoQuality_LOW,
},
}
err = ValidateVideoOptionsConsistency(video)
require.Error(t, err)
video.EncodingOptions.(*livekit.IngressVideoOptions_Options).Options.Layers = []*livekit.VideoLayer{
&livekit.VideoLayer{
Width: 640,
Height: 480,
Quality: livekit.VideoQuality_LOW,
},
&livekit.VideoLayer{
Width: 1280,
Height: 720,
Quality: livekit.VideoQuality_HIGH,
},
}
err = ValidateVideoOptionsConsistency(video)
require.NoError(t, err)
}
func TestValidateAudioOptionsConsistency(t *testing.T) {
audio := &livekit.IngressAudioOptions{}
err := ValidateAudioOptionsConsistency(audio)
require.NoError(t, err)
audio.Source = livekit.TrackSource_CAMERA
err = ValidateAudioOptionsConsistency(audio)
require.Error(t, err)
audio.Source = livekit.TrackSource_SCREEN_SHARE_AUDIO
audio.EncodingOptions = &livekit.IngressAudioOptions_Preset{
Preset: livekit.IngressAudioEncodingPreset(42),
}
err = ValidateAudioOptionsConsistency(audio)
require.Error(t, err)
audio.EncodingOptions = &livekit.IngressAudioOptions_Preset{
Preset: livekit.IngressAudioEncodingPreset_OPUS_MONO_64KBS,
}
err = ValidateAudioOptionsConsistency(audio)
require.NoError(t, err)
audio.EncodingOptions = &livekit.IngressAudioOptions_Options{
Options: &livekit.IngressAudioEncodingOptions{
AudioCodec: livekit.AudioCodec_AAC,
},
}
err = ValidateAudioOptionsConsistency(audio)
require.Error(t, err)
audio.EncodingOptions = &livekit.IngressAudioOptions_Options{
Options: &livekit.IngressAudioEncodingOptions{
AudioCodec: livekit.AudioCodec_OPUS,
Channels: 3,
},
}
err = ValidateAudioOptionsConsistency(audio)
require.Error(t, err)
audio.EncodingOptions.(*livekit.IngressAudioOptions_Options).Options.Channels = 2
err = ValidateAudioOptionsConsistency(audio)
require.NoError(t, err)
}

View File

@@ -1,64 +0,0 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/livekit-server/proto/livekit";
// internal protos, not exposed to clients
import "rtc.proto";
import "room.proto";
message Node {
string id = 1;
string ip = 2;
uint32 num_cpus = 3;
NodeStats stats = 4;
}
message NodeStats {
// when server was started
int64 started_at = 1;
// when server last reported its status
int64 updated_at = 2;
uint32 num_rooms = 3;
uint32 num_clients = 4;
uint32 num_tracks_in = 5;
uint32 num_tracks_out = 6;
}
// message to RTC nodes
message RTCNodeMessage {
string participant_key = 1;
oneof message {
StartSession start_session = 2;
SignalRequest request = 3;
// internal messages
RoomParticipantIdentity remove_participant = 4;
MuteRoomTrackRequest mute_track = 5;
}
}
// message to Signal nodes
message SignalNodeMessage {
string connection_id = 1;
oneof message {
SignalResponse response = 2;
EndSession end_session = 3;
}
}
message StartSession {
string room_name = 1;
string identity = 2;
string connection_id = 3;
// if a client is reconnecting (i.e. resume instead of restart)
bool reconnect = 4;
// metadata to pass to participant
string metadata = 5;
}
message EndSession {
}
message RemoveParticipant {
string participant_id = 1;
}

1
livekit/README.md Normal file
View File

@@ -0,0 +1 @@
Generated protobuf stubs

19
livekit/attrs.go Normal file
View File

@@ -0,0 +1,19 @@
package livekit
// Names of participant attributes for SIP.
const (
// AttrSIPPrefix is shared for all SIP attributes.
AttrSIPPrefix = "sip."
// AttrSIPCallID attribute contains LiveKit SIP call ID.
AttrSIPCallID = AttrSIPPrefix + "callID"
// AttrSIPTrunkID attribute contains LiveKit SIP Trunk ID used for the call.
AttrSIPTrunkID = AttrSIPPrefix + "trunkID"
// AttrSIPDispatchRuleID attribute contains LiveKit SIP DispatchRule ID used for the inbound call.
AttrSIPDispatchRuleID = AttrSIPPrefix + "ruleID"
// AttrSIPTrunkNumber attribute contains number associate with LiveKit SIP Trunk.
// This attribute will be omitted if HidePhoneNumber is set.
AttrSIPTrunkNumber = AttrSIPPrefix + "trunkPhoneNumber"
// AttrSIPPhoneNumber attribute contains number external to LiveKit SIP (caller for inbound and called number for outbound).
// This attribute will be omitted if HidePhoneNumber is set.
AttrSIPPhoneNumber = AttrSIPPrefix + "phoneNumber"
)

2430
livekit/livekit_agent.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.4.0
// - protoc v4.23.4
// source: livekit_agent.proto
package livekit
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.62.0 or later.
const _ = grpc.SupportPackageIsVersion8
const (
AgentService_CreateAgentJobDefinition_FullMethodName = "/livekit.AgentService/CreateAgentJobDefinition"
AgentService_DeleteAgentJobDefinition_FullMethodName = "/livekit.AgentService/DeleteAgentJobDefinition"
AgentService_ListAgentJobDefinitions_FullMethodName = "/livekit.AgentService/ListAgentJobDefinitions"
)
// AgentServiceClient is the client API for AgentService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AgentServiceClient interface {
CreateAgentJobDefinition(ctx context.Context, in *CreateAgentJobDefinitionRequest, opts ...grpc.CallOption) (*JobDefinition, error)
DeleteAgentJobDefinition(ctx context.Context, in *DeleteAgentJobDefinitionRequest, opts ...grpc.CallOption) (*JobDefinition, error)
ListAgentJobDefinitions(ctx context.Context, in *ListAgentJobDefinitionsRequesst, opts ...grpc.CallOption) (*ListAgentJobDefinitionsResponse, error)
}
type agentServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAgentServiceClient(cc grpc.ClientConnInterface) AgentServiceClient {
return &agentServiceClient{cc}
}
func (c *agentServiceClient) CreateAgentJobDefinition(ctx context.Context, in *CreateAgentJobDefinitionRequest, opts ...grpc.CallOption) (*JobDefinition, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(JobDefinition)
err := c.cc.Invoke(ctx, AgentService_CreateAgentJobDefinition_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *agentServiceClient) DeleteAgentJobDefinition(ctx context.Context, in *DeleteAgentJobDefinitionRequest, opts ...grpc.CallOption) (*JobDefinition, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(JobDefinition)
err := c.cc.Invoke(ctx, AgentService_DeleteAgentJobDefinition_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *agentServiceClient) ListAgentJobDefinitions(ctx context.Context, in *ListAgentJobDefinitionsRequesst, opts ...grpc.CallOption) (*ListAgentJobDefinitionsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListAgentJobDefinitionsResponse)
err := c.cc.Invoke(ctx, AgentService_ListAgentJobDefinitions_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AgentServiceServer is the server API for AgentService service.
// All implementations must embed UnimplementedAgentServiceServer
// for forward compatibility
type AgentServiceServer interface {
CreateAgentJobDefinition(context.Context, *CreateAgentJobDefinitionRequest) (*JobDefinition, error)
DeleteAgentJobDefinition(context.Context, *DeleteAgentJobDefinitionRequest) (*JobDefinition, error)
ListAgentJobDefinitions(context.Context, *ListAgentJobDefinitionsRequesst) (*ListAgentJobDefinitionsResponse, error)
mustEmbedUnimplementedAgentServiceServer()
}
// UnimplementedAgentServiceServer must be embedded to have forward compatible implementations.
type UnimplementedAgentServiceServer struct {
}
func (UnimplementedAgentServiceServer) CreateAgentJobDefinition(context.Context, *CreateAgentJobDefinitionRequest) (*JobDefinition, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateAgentJobDefinition not implemented")
}
func (UnimplementedAgentServiceServer) DeleteAgentJobDefinition(context.Context, *DeleteAgentJobDefinitionRequest) (*JobDefinition, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteAgentJobDefinition not implemented")
}
func (UnimplementedAgentServiceServer) ListAgentJobDefinitions(context.Context, *ListAgentJobDefinitionsRequesst) (*ListAgentJobDefinitionsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListAgentJobDefinitions not implemented")
}
func (UnimplementedAgentServiceServer) mustEmbedUnimplementedAgentServiceServer() {}
// UnsafeAgentServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AgentServiceServer will
// result in compilation errors.
type UnsafeAgentServiceServer interface {
mustEmbedUnimplementedAgentServiceServer()
}
func RegisterAgentServiceServer(s grpc.ServiceRegistrar, srv AgentServiceServer) {
s.RegisterService(&AgentService_ServiceDesc, srv)
}
func _AgentService_CreateAgentJobDefinition_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateAgentJobDefinitionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AgentServiceServer).CreateAgentJobDefinition(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AgentService_CreateAgentJobDefinition_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AgentServiceServer).CreateAgentJobDefinition(ctx, req.(*CreateAgentJobDefinitionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AgentService_DeleteAgentJobDefinition_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteAgentJobDefinitionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AgentServiceServer).DeleteAgentJobDefinition(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AgentService_DeleteAgentJobDefinition_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AgentServiceServer).DeleteAgentJobDefinition(ctx, req.(*DeleteAgentJobDefinitionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AgentService_ListAgentJobDefinitions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListAgentJobDefinitionsRequesst)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AgentServiceServer).ListAgentJobDefinitions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AgentService_ListAgentJobDefinitions_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AgentServiceServer).ListAgentJobDefinitions(ctx, req.(*ListAgentJobDefinitionsRequesst))
}
return interceptor(ctx, in, info, handler)
}
// AgentService_ServiceDesc is the grpc.ServiceDesc for AgentService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AgentService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "livekit.AgentService",
HandlerType: (*AgentServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreateAgentJobDefinition",
Handler: _AgentService_CreateAgentJobDefinition_Handler,
},
{
MethodName: "DeleteAgentJobDefinition",
Handler: _AgentService_DeleteAgentJobDefinition_Handler,
},
{
MethodName: "ListAgentJobDefinitions",
Handler: _AgentService_ListAgentJobDefinitions_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "livekit_agent.proto",
}

File diff suppressed because it is too large Load Diff

4943
livekit/livekit_egress.pb.go Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4545
livekit/livekit_models.pb.go Normal file

File diff suppressed because it is too large Load Diff

1898
livekit/livekit_room.pb.go Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4907
livekit/livekit_rtc.pb.go Normal file

File diff suppressed because it is too large Load Diff

2569
livekit/livekit_sip.pb.go Normal file

File diff suppressed because it is too large Load Diff

3408
livekit/livekit_sip.twirp.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.2
// protoc v4.23.4
// source: livekit_webhook.proto
package livekit
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type WebhookEvent struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// one of room_started, room_finished, participant_joined, participant_left,
// track_published, track_unpublished, egress_started, egress_updated, egress_ended,
// ingress_started, ingress_ended
Event string `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"`
Room *Room `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"`
// set when event is participant_* or track_*
Participant *ParticipantInfo `protobuf:"bytes,3,opt,name=participant,proto3" json:"participant,omitempty"`
// set when event is egress_*
EgressInfo *EgressInfo `protobuf:"bytes,9,opt,name=egress_info,json=egressInfo,proto3" json:"egress_info,omitempty"`
// set when event is ingress_*
IngressInfo *IngressInfo `protobuf:"bytes,10,opt,name=ingress_info,json=ingressInfo,proto3" json:"ingress_info,omitempty"`
// set when event is track_*
Track *TrackInfo `protobuf:"bytes,8,opt,name=track,proto3" json:"track,omitempty"`
// unique event uuid
Id string `protobuf:"bytes,6,opt,name=id,proto3" json:"id,omitempty"`
// timestamp in seconds
CreatedAt int64 `protobuf:"varint,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
NumDropped int32 `protobuf:"varint,11,opt,name=num_dropped,json=numDropped,proto3" json:"num_dropped,omitempty"`
}
func (x *WebhookEvent) Reset() {
*x = WebhookEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_livekit_webhook_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WebhookEvent) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WebhookEvent) ProtoMessage() {}
func (x *WebhookEvent) ProtoReflect() protoreflect.Message {
mi := &file_livekit_webhook_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WebhookEvent.ProtoReflect.Descriptor instead.
func (*WebhookEvent) Descriptor() ([]byte, []int) {
return file_livekit_webhook_proto_rawDescGZIP(), []int{0}
}
func (x *WebhookEvent) GetEvent() string {
if x != nil {
return x.Event
}
return ""
}
func (x *WebhookEvent) GetRoom() *Room {
if x != nil {
return x.Room
}
return nil
}
func (x *WebhookEvent) GetParticipant() *ParticipantInfo {
if x != nil {
return x.Participant
}
return nil
}
func (x *WebhookEvent) GetEgressInfo() *EgressInfo {
if x != nil {
return x.EgressInfo
}
return nil
}
func (x *WebhookEvent) GetIngressInfo() *IngressInfo {
if x != nil {
return x.IngressInfo
}
return nil
}
func (x *WebhookEvent) GetTrack() *TrackInfo {
if x != nil {
return x.Track
}
return nil
}
func (x *WebhookEvent) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *WebhookEvent) GetCreatedAt() int64 {
if x != nil {
return x.CreatedAt
}
return 0
}
func (x *WebhookEvent) GetNumDropped() int32 {
if x != nil {
return x.NumDropped
}
return 0
}
var File_livekit_webhook_proto protoreflect.FileDescriptor
var file_livekit_webhook_proto_rawDesc = []byte{
0x0a, 0x15, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x5f, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f,
0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74,
0x1a, 0x14, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x5f,
0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x6c, 0x69,
0x76, 0x65, 0x6b, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xec, 0x02, 0x0a, 0x0c, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x04, 0x72, 0x6f,
0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b,
0x69, 0x74, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x3a, 0x0a,
0x0b, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x50, 0x61, 0x72,
0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x70, 0x61,
0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x0b, 0x65, 0x67, 0x72,
0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12,
0x37, 0x0a, 0x0c, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e,
0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x69, 0x6e, 0x67,
0x72, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x28, 0x0a, 0x05, 0x74, 0x72, 0x61, 0x63,
0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69,
0x74, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x74, 0x72, 0x61,
0x63, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74,
0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x44, 0x72, 0x6f, 0x70, 0x70,
0x65, 0x64, 0x42, 0x46, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
0x6c, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0xaa, 0x02, 0x0d, 0x4c, 0x69, 0x76, 0x65,
0x4b, 0x69, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0xea, 0x02, 0x0e, 0x4c, 0x69, 0x76, 0x65,
0x4b, 0x69, 0x74, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_livekit_webhook_proto_rawDescOnce sync.Once
file_livekit_webhook_proto_rawDescData = file_livekit_webhook_proto_rawDesc
)
func file_livekit_webhook_proto_rawDescGZIP() []byte {
file_livekit_webhook_proto_rawDescOnce.Do(func() {
file_livekit_webhook_proto_rawDescData = protoimpl.X.CompressGZIP(file_livekit_webhook_proto_rawDescData)
})
return file_livekit_webhook_proto_rawDescData
}
var file_livekit_webhook_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_livekit_webhook_proto_goTypes = []any{
(*WebhookEvent)(nil), // 0: livekit.WebhookEvent
(*Room)(nil), // 1: livekit.Room
(*ParticipantInfo)(nil), // 2: livekit.ParticipantInfo
(*EgressInfo)(nil), // 3: livekit.EgressInfo
(*IngressInfo)(nil), // 4: livekit.IngressInfo
(*TrackInfo)(nil), // 5: livekit.TrackInfo
}
var file_livekit_webhook_proto_depIdxs = []int32{
1, // 0: livekit.WebhookEvent.room:type_name -> livekit.Room
2, // 1: livekit.WebhookEvent.participant:type_name -> livekit.ParticipantInfo
3, // 2: livekit.WebhookEvent.egress_info:type_name -> livekit.EgressInfo
4, // 3: livekit.WebhookEvent.ingress_info:type_name -> livekit.IngressInfo
5, // 4: livekit.WebhookEvent.track:type_name -> livekit.TrackInfo
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_livekit_webhook_proto_init() }
func file_livekit_webhook_proto_init() {
if File_livekit_webhook_proto != nil {
return
}
file_livekit_models_proto_init()
file_livekit_egress_proto_init()
file_livekit_ingress_proto_init()
if !protoimpl.UnsafeEnabled {
file_livekit_webhook_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*WebhookEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_livekit_webhook_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_livekit_webhook_proto_goTypes,
DependencyIndexes: file_livekit_webhook_proto_depIdxs,
MessageInfos: file_livekit_webhook_proto_msgTypes,
}.Build()
File_livekit_webhook_proto = out.File
file_livekit_webhook_proto_rawDesc = nil
file_livekit_webhook_proto_goTypes = nil
file_livekit_webhook_proto_depIdxs = nil
}

96
livekit/sip.go Normal file
View File

@@ -0,0 +1,96 @@
package livekit
// ToProto implements DataPacket in Go SDK.
func (p *SipDTMF) ToProto() *DataPacket {
return &DataPacket{
Value: &DataPacket_SipDtmf{
SipDtmf: p,
},
}
}
// AsInbound converts legacy SIPTrunkInfo to SIPInboundTrunkInfo.
func (p *SIPTrunkInfo) AsInbound() *SIPInboundTrunkInfo {
if p == nil || p.Kind == SIPTrunkInfo_TRUNK_OUTBOUND {
return nil
}
var nums []string
if p.OutboundNumber != "" {
nums = []string{p.OutboundNumber}
}
return &SIPInboundTrunkInfo{
SipTrunkId: p.SipTrunkId,
Name: p.Name,
Metadata: p.Metadata,
Numbers: nums,
AllowedAddresses: p.InboundAddresses,
AllowedNumbers: p.InboundNumbers,
AuthUsername: p.InboundUsername,
AuthPassword: p.InboundPassword,
}
}
// AsTrunkInfo converts SIPInboundTrunkInfo to legacy SIPTrunkInfo.
func (p *SIPInboundTrunkInfo) AsTrunkInfo() *SIPTrunkInfo {
if p == nil {
return nil
}
var num string
if len(p.Numbers) != 0 {
num = p.Numbers[0]
}
return &SIPTrunkInfo{
SipTrunkId: p.SipTrunkId,
Kind: SIPTrunkInfo_TRUNK_INBOUND,
Name: p.Name,
Metadata: p.Metadata,
OutboundNumber: num,
InboundAddresses: p.AllowedAddresses,
InboundNumbers: p.AllowedNumbers,
InboundUsername: p.AuthUsername,
InboundPassword: p.AuthPassword,
}
}
// AsOutbound converts legacy SIPTrunkInfo to SIPOutboundTrunkInfo.
func (p *SIPTrunkInfo) AsOutbound() *SIPOutboundTrunkInfo {
if p == nil || p.Kind == SIPTrunkInfo_TRUNK_INBOUND {
return nil
}
var nums []string
if p.OutboundNumber != "" {
nums = []string{p.OutboundNumber}
}
return &SIPOutboundTrunkInfo{
SipTrunkId: p.SipTrunkId,
Name: p.Name,
Metadata: p.Metadata,
Address: p.OutboundAddress,
Transport: p.Transport,
Numbers: nums,
AuthUsername: p.OutboundUsername,
AuthPassword: p.OutboundPassword,
}
}
// AsTrunkInfo converts SIPOutboundTrunkInfo to legacy SIPTrunkInfo.
func (p *SIPOutboundTrunkInfo) AsTrunkInfo() *SIPTrunkInfo {
if p == nil {
return nil
}
var num string
if len(p.Numbers) != 0 {
num = p.Numbers[0]
}
return &SIPTrunkInfo{
SipTrunkId: p.SipTrunkId,
Kind: SIPTrunkInfo_TRUNK_OUTBOUND,
Name: p.Name,
Metadata: p.Metadata,
OutboundAddress: p.Address,
Transport: p.Transport,
OutboundNumber: num,
OutboundUsername: p.AuthUsername,
OutboundPassword: p.AuthPassword,
}
}

37
livekit/sip_test.go Normal file
View File

@@ -0,0 +1,37 @@
package livekit
import (
"github.com/stretchr/testify/require"
"testing"
)
func TestSIPTrunkAs(t *testing.T) {
t.Run("inbound", func(t *testing.T) {
in := &SIPInboundTrunkInfo{
SipTrunkId: "id",
Name: "name",
Metadata: "{}",
Numbers: []string{"+1"},
AllowedAddresses: []string{"sip.com"},
AllowedNumbers: []string{"+2", "+3"},
AuthUsername: "user",
AuthPassword: "pass",
}
got := in.AsTrunkInfo().AsInbound()
require.Equal(t, in, got)
})
t.Run("outbound", func(t *testing.T) {
out := &SIPOutboundTrunkInfo{
SipTrunkId: "id",
Name: "name",
Metadata: "{}",
Address: "sip.com",
Transport: 1,
Numbers: []string{"+1"},
AuthUsername: "user",
AuthPassword: "pass",
}
got := out.AsTrunkInfo().AsOutbound()
require.Equal(t, out, got)
})
}

84
livekit/types.go Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package livekit
import (
"github.com/bufbuild/protoyaml-go"
"gopkg.in/yaml.v3"
)
type TrackID string
type ParticipantID string
type ParticipantIdentity string
type ParticipantName string
type RoomID string
type RoomName string
type ConnectionID string
type NodeID string
type RoomKey struct {
ProjectID string
RoomName RoomName
}
type ParticipantKey struct {
RoomKey
Identity ParticipantIdentity
}
type stringTypes interface {
ParticipantID | RoomID | TrackID | ParticipantIdentity | ParticipantName | RoomName | ConnectionID | NodeID
}
func IDsAsStrings[T stringTypes](ids []T) []string {
strs := make([]string, 0, len(ids))
for _, id := range ids {
strs = append(strs, string(id))
}
return strs
}
func StringsAsIDs[T stringTypes](ids []string) []T {
asID := make([]T, 0, len(ids))
for _, id := range ids {
asID = append(asID, T(id))
}
return asID
}
type Guid interface {
TrackID | ParticipantID | RoomID
}
type GuidBlock [9]byte
func (r *RoomEgress) UnmarshalYAML(value *yaml.Node) error {
// Marshall the Node back to yaml to pass it to the protobuf specific unmarshaller
str, err := yaml.Marshal(value)
if err != nil {
return err
}
return protoyaml.Unmarshal(str, r)
}
func (r *RoomAgent) UnmarshalYAML(value *yaml.Node) error {
// Marshall the Node back to yaml to pass it to the protobuf specific unmarshaller
str, err := yaml.Marshal(value)
if err != nil {
return err
}
return protoyaml.Unmarshal(str, r)
}

2
livekit/types_test Normal file
View File

@@ -0,0 +1,2 @@
func TestUnmarshallRoomEgress(t testing.T) {
}

66
livekit/types_test.go Normal file
View File

@@ -0,0 +1,66 @@
package livekit
import (
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
func TestUnmarshallRoomEgress(t *testing.T) {
y := `
a:
room:
room_name: room name
b:
participant:
file_outputs:
- s3:
access_key: key
`
obj := make(map[string]*RoomEgress)
err := yaml.Unmarshal([]byte(y), &obj)
require.NoError(t, err)
require.Equal(t, 2, len(obj))
re := obj["a"]
require.NotNil(t, re)
require.Equal(t, re.Room.RoomName, "room name")
re = obj["b"]
require.NotNil(t, re)
require.Equal(t, 1, len(re.Participant.FileOutputs))
require.Equal(t, "key", re.Participant.FileOutputs[0].Output.(*EncodedFileOutput_S3).S3.AccessKey)
}
func TestUnmarshallRoomAgent(t *testing.T) {
y := `
a:
agents:
- type: 0
room: test room
- type: 1
participant_identity:
- id1
- id2
namespace: nm
`
obj := make(map[string]*RoomAgent)
err := yaml.Unmarshal([]byte(y), &obj)
require.NoError(t, err)
require.Equal(t, 1, len(obj))
re := obj["a"]
require.NotNil(t, re)
require.Equal(t, len(re.Agents), 2)
require.Equal(t, JobType_JT_ROOM, re.Agents[0].Type)
require.Equal(t, "test room", re.Agents[0].Room)
require.Equal(t, JobType_JT_PUBLISHER, re.Agents[1].Type)
require.Equal(t, "nm", re.Agents[1].Namespace)
require.Equal(t, 2, len(re.Agents[1].ParticipantIdentity))
require.Equal(t, "id1", re.Agents[1].ParticipantIdentity[0])
require.Equal(t, "id2", re.Agents[1].ParticipantIdentity[1])
}

74
logger/config.go Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logger
import "sync"
type Config struct {
JSON bool `yaml:"json,omitempty"`
Level string `yaml:"level,omitempty"`
// true to enable log sampling, where the same log message and level will be throttled.
// we have two layers of sampling
// 1. global sampling - within a second, it will log the first SampleInitial, then every SampleInterval messages.
// 2. per participant/track sampling - to be used with Logger.WithItemSampler(). This would be used to throttle
// the logs for a particular participant/track.
Sample bool `yaml:"sample,omitempty"`
ComponentLevels map[string]string `yaml:"component_levels,omitempty"`
// global sampling per server
// when sampling, the first N logs will be logged
SampleInitial int `yaml:"sample_initial,omitempty"`
// when sampling, every Mth log will be logged
SampleInterval int `yaml:"sample_interval,omitempty"`
// participant/track level sampling
ItemSampleSeconds int `yaml:"item_sample_seconds,omitempty"`
ItemSampleInitial int `yaml:"item_sample_initial,omitempty"`
ItemSampleInterval int `yaml:"item_sample_interval,omitempty"`
lock sync.Mutex `yaml:"-"`
onUpdatedCallbacks []ConfigObserver `yaml:"-"`
}
type ConfigObserver func(*Config) error
func (c *Config) Update(o *Config) error {
c.lock.Lock()
c.JSON = o.JSON
c.Level = o.Level
c.Sample = o.Sample
c.SampleInitial = o.SampleInitial
c.SampleInterval = o.SampleInterval
c.ItemSampleSeconds = o.ItemSampleSeconds
c.ItemSampleInitial = o.ItemSampleInitial
c.ItemSampleInterval = o.ItemSampleInterval
c.ComponentLevels = o.ComponentLevels
callbacks := c.onUpdatedCallbacks
c.lock.Unlock()
for _, cb := range callbacks {
if err := cb(c); err != nil {
return err
}
}
return nil
}
func (c *Config) AddUpdateObserver(cb ConfigObserver) {
c.lock.Lock()
defer c.lock.Unlock()
c.onUpdatedCallbacks = append(c.onUpdatedCallbacks, cb)
}

442
logger/logger.go Normal file
View File

@@ -0,0 +1,442 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logger
import (
"log/slog"
"os"
"strings"
"sync"
"time"
"github.com/go-logr/logr"
"github.com/puzpuzpuz/xsync/v3"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/livekit/protocol/logger/zaputil"
)
var (
discardLogger = logr.Discard()
defaultLogger Logger = LogRLogger(discardLogger)
pkgLogger Logger = LogRLogger(discardLogger)
)
// InitFromConfig initializes a Zap-based logger
func InitFromConfig(conf *Config, name string) {
l, err := NewZapLogger(conf)
if err == nil {
SetLogger(l, name)
slog.SetDefault(slog.New(ToSlogHandler(l)))
}
}
// GetLogger returns the logger that was set with SetLogger with an extra depth of 1
func GetLogger() Logger {
return defaultLogger
}
// SetLogger lets you use a custom logger. Pass in a logr.Logger with default depth
func SetLogger(l Logger, name string) {
defaultLogger = l.WithCallDepth(1).WithName(name)
// pkg wrapper needs to drop two levels of depth
pkgLogger = l.WithCallDepth(2).WithName(name)
}
func Debugw(msg string, keysAndValues ...interface{}) {
pkgLogger.Debugw(msg, keysAndValues...)
}
func Infow(msg string, keysAndValues ...interface{}) {
pkgLogger.Infow(msg, keysAndValues...)
}
func Warnw(msg string, err error, keysAndValues ...interface{}) {
pkgLogger.Warnw(msg, err, keysAndValues...)
}
func Errorw(msg string, err error, keysAndValues ...interface{}) {
pkgLogger.Errorw(msg, err, keysAndValues...)
}
func ParseZapLevel(level string) zapcore.Level {
lvl := zapcore.InfoLevel
if level != "" {
_ = lvl.UnmarshalText([]byte(level))
}
return lvl
}
type DeferredFieldResolver = zaputil.DeferredFieldResolver
type Logger interface {
Debugw(msg string, keysAndValues ...interface{})
Infow(msg string, keysAndValues ...interface{})
Warnw(msg string, err error, keysAndValues ...interface{})
Errorw(msg string, err error, keysAndValues ...interface{})
WithValues(keysAndValues ...interface{}) Logger
WithName(name string) Logger
// WithComponent creates a new logger with name as "<name>.<component>", and uses a log level as specified
WithComponent(component string) Logger
WithCallDepth(depth int) Logger
WithItemSampler() Logger
// WithoutSampler returns the original logger without sampling
WithoutSampler() Logger
WithDeferredValues() (Logger, DeferredFieldResolver)
}
type sharedConfig struct {
level zap.AtomicLevel
mu sync.Mutex
componentLevels map[string]zap.AtomicLevel
config *Config
}
func newSharedConfig(conf *Config) *sharedConfig {
sc := &sharedConfig{
level: zap.NewAtomicLevelAt(ParseZapLevel(conf.Level)),
config: conf,
componentLevels: make(map[string]zap.AtomicLevel),
}
conf.AddUpdateObserver(sc.onConfigUpdate)
_ = sc.onConfigUpdate(conf)
return sc
}
func (c *sharedConfig) onConfigUpdate(conf *Config) error {
// update log levels
c.level.SetLevel(ParseZapLevel(conf.Level))
// we have to update alla existing component levels
c.mu.Lock()
c.config = conf
for component, atomicLevel := range c.componentLevels {
effectiveLevel := c.level.Level()
parts := strings.Split(component, ".")
confSearch:
for len(parts) > 0 {
search := strings.Join(parts, ".")
if compLevel, ok := conf.ComponentLevels[search]; ok {
effectiveLevel = ParseZapLevel(compLevel)
break confSearch
}
parts = parts[:len(parts)-1]
}
atomicLevel.SetLevel(effectiveLevel)
}
c.mu.Unlock()
return nil
}
// ensure we have an atomic level in the map representing the full component path
// this makes it possible to update the log level after the fact
func (c *sharedConfig) ComponentLevel(component string) zap.AtomicLevel {
c.mu.Lock()
defer c.mu.Unlock()
if compLevel, ok := c.componentLevels[component]; ok {
return compLevel
}
// search up the hierarchy to find the first level that is set
atomicLevel := zap.NewAtomicLevelAt(c.level.Level())
c.componentLevels[component] = atomicLevel
parts := strings.Split(component, ".")
for len(parts) > 0 {
search := strings.Join(parts, ".")
if compLevel, ok := c.config.ComponentLevels[search]; ok {
atomicLevel.SetLevel(ParseZapLevel(compLevel))
return atomicLevel
}
parts = parts[:len(parts)-1]
}
return atomicLevel
}
type zapConfig struct {
conf *Config
sc *sharedConfig
writeEnablers *xsync.MapOf[string, *zaputil.WriteEnabler]
levelEnablers *xsync.MapOf[string, *zaputil.OrLevelEnabler]
tap *zaputil.WriteEnabler
}
type ZapLoggerOption func(*zapConfig)
func WithTap(tap *zaputil.WriteEnabler) ZapLoggerOption {
return func(zc *zapConfig) {
zc.tap = tap
}
}
type ZapComponentLeveler interface {
ComponentLevel(component string) zapcore.LevelEnabler
}
type ZapLogger interface {
Logger
ToZap() *zap.SugaredLogger
ComponentLeveler() ZapComponentLeveler
WithMinLevel(lvl zapcore.LevelEnabler) Logger
}
type zapLogger[T zaputil.Encoder[T]] struct {
zap *zap.SugaredLogger
*zapConfig
enc T
component string
deferred []*zaputil.Deferrer
sampler *zaputil.Sampler
minLevel zapcore.LevelEnabler
}
func FromZapLogger(log *zap.Logger, conf *Config, opts ...ZapLoggerOption) (ZapLogger, error) {
if log == nil {
log = zap.New(nil).WithOptions(zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
}
zap := log.Sugar()
zc := &zapConfig{
conf: conf,
sc: newSharedConfig(conf),
writeEnablers: xsync.NewMapOf[string, *zaputil.WriteEnabler](),
levelEnablers: xsync.NewMapOf[string, *zaputil.OrLevelEnabler](),
tap: zaputil.NewDiscardWriteEnabler(),
}
for _, opt := range opts {
opt(zc)
}
var sampler *zaputil.Sampler
if conf.Sample {
var initial = 20
var interval = 100
if conf.ItemSampleInitial != 0 {
initial = conf.ItemSampleInitial
}
if conf.ItemSampleInterval != 0 {
interval = conf.ItemSampleInterval
}
sampler = zaputil.NewSampler(time.Second, initial, interval)
}
if conf.JSON {
return newZapLogger(zap, zc, zaputil.NewProductionEncoder(), sampler), nil
} else {
return newZapLogger(zap, zc, zaputil.NewDevelopmentEncoder(), sampler), nil
}
}
func NewZapLogger(conf *Config, opts ...ZapLoggerOption) (ZapLogger, error) {
return FromZapLogger(nil, conf, opts...)
}
func newZapLogger[T zaputil.Encoder[T]](zap *zap.SugaredLogger, zc *zapConfig, enc T, sampler *zaputil.Sampler) ZapLogger {
l := &zapLogger[T]{
zap: zap,
zapConfig: zc,
enc: enc,
sampler: sampler,
}
l.zap = l.ToZap()
return l
}
func (l *zapLogger[T]) ToZap() *zap.SugaredLogger {
var console *zaputil.WriteEnabler
if l.minLevel == nil {
console, _ = l.writeEnablers.LoadOrCompute(l.component, func() *zaputil.WriteEnabler {
return zaputil.NewWriteEnabler(os.Stderr, l.sc.ComponentLevel(l.component))
})
} else {
enab := zaputil.OrLevelEnabler{l.minLevel, l.sc.ComponentLevel(l.component)}
console = zaputil.NewWriteEnabler(os.Stderr, enab)
}
c := l.enc.Core(console, l.tap)
for i := range l.deferred {
c = zaputil.NewDeferredValueCore(c, l.deferred[i])
}
if l.sampler != nil {
c = zaputil.NewSamplerCore(c, l.sampler)
}
return l.zap.WithOptions(zap.WrapCore(func(zapcore.Core) zapcore.Core { return c }))
}
type zapLoggerComponentLeveler[T zaputil.Encoder[T]] struct {
zl *zapLogger[T]
}
func (l zapLoggerComponentLeveler[T]) ComponentLevel(component string) zapcore.LevelEnabler {
if l.zl.component != "" {
component = l.zl.component + "." + component
}
enab, _ := l.zl.levelEnablers.LoadOrCompute(component, func() *zaputil.OrLevelEnabler {
return &zaputil.OrLevelEnabler{l.zl.sc.ComponentLevel(component), l.zl.tap}
})
return enab
}
func (l *zapLogger[T]) ComponentLeveler() ZapComponentLeveler {
return zapLoggerComponentLeveler[T]{l}
}
func (l *zapLogger[T]) Debugw(msg string, keysAndValues ...interface{}) {
l.zap.Debugw(msg, keysAndValues...)
}
func (l *zapLogger[T]) WithMinLevel(lvl zapcore.LevelEnabler) Logger {
dup := *l
dup.minLevel = lvl
dup.zap = dup.ToZap()
return &dup
}
func (l *zapLogger[T]) Infow(msg string, keysAndValues ...interface{}) {
l.zap.Infow(msg, keysAndValues...)
}
func (l *zapLogger[T]) Warnw(msg string, err error, keysAndValues ...interface{}) {
if err != nil {
keysAndValues = append(keysAndValues, "error", err)
}
l.zap.Warnw(msg, keysAndValues...)
}
func (l *zapLogger[T]) Errorw(msg string, err error, keysAndValues ...interface{}) {
if err != nil {
keysAndValues = append(keysAndValues, "error", err)
}
l.zap.Errorw(msg, keysAndValues...)
}
func (l *zapLogger[T]) WithValues(keysAndValues ...interface{}) Logger {
dup := *l
dup.enc = dup.enc.WithValues(keysAndValues...)
dup.zap = dup.ToZap()
return &dup
}
func (l *zapLogger[T]) WithName(name string) Logger {
dup := *l
dup.zap = dup.zap.Named(name)
return &dup
}
func (l *zapLogger[T]) WithComponent(component string) Logger {
dup := *l
dup.zap = dup.zap.Named(component)
if dup.component == "" {
dup.component = component
} else {
dup.component = dup.component + "." + component
}
dup.zap = dup.ToZap()
return &dup
}
func (l *zapLogger[T]) WithCallDepth(depth int) Logger {
dup := *l
dup.zap = dup.zap.WithOptions(zap.AddCallerSkip(depth))
return &dup
}
func (l *zapLogger[T]) WithItemSampler() Logger {
if l.conf.ItemSampleSeconds == 0 {
return l
}
dup := *l
dup.sampler = zaputil.NewSampler(
time.Duration(l.conf.ItemSampleSeconds)*time.Second,
l.conf.ItemSampleInitial,
l.conf.ItemSampleInterval,
)
dup.zap = dup.ToZap()
return &dup
}
func (l *zapLogger[T]) WithoutSampler() Logger {
dup := *l
dup.sampler = nil
dup.zap = dup.ToZap()
return &dup
}
func (l *zapLogger[T]) WithDeferredValues() (Logger, DeferredFieldResolver) {
dup := *l
def, resolve := zaputil.NewDeferrer()
dup.deferred = append(dup.deferred[0:len(dup.deferred):len(dup.deferred)], def)
dup.zap = dup.ToZap()
return &dup, resolve
}
type LogRLogger logr.Logger
func (l LogRLogger) toLogr() logr.Logger {
if logr.Logger(l).GetSink() == nil {
return discardLogger
}
return logr.Logger(l)
}
func (l LogRLogger) Debugw(msg string, keysAndValues ...interface{}) {
l.toLogr().V(1).Info(msg, keysAndValues...)
}
func (l LogRLogger) Infow(msg string, keysAndValues ...interface{}) {
l.toLogr().Info(msg, keysAndValues...)
}
func (l LogRLogger) Warnw(msg string, err error, keysAndValues ...interface{}) {
if err != nil {
keysAndValues = append(keysAndValues, "error", err)
}
l.toLogr().Info(msg, keysAndValues...)
}
func (l LogRLogger) Errorw(msg string, err error, keysAndValues ...interface{}) {
l.toLogr().Error(err, msg, keysAndValues...)
}
func (l LogRLogger) WithValues(keysAndValues ...interface{}) Logger {
return LogRLogger(l.toLogr().WithValues(keysAndValues...))
}
func (l LogRLogger) WithName(name string) Logger {
return LogRLogger(l.toLogr().WithName(name))
}
func (l LogRLogger) WithComponent(component string) Logger {
return LogRLogger(l.toLogr().WithName(component))
}
func (l LogRLogger) WithCallDepth(depth int) Logger {
return LogRLogger(l.toLogr().WithCallDepth(depth))
}
func (l LogRLogger) WithItemSampler() Logger {
// logr does not support sampling
return l
}
func (l LogRLogger) WithoutSampler() Logger {
return l
}
func (l LogRLogger) WithDeferredValues() (Logger, DeferredFieldResolver) {
return l, func(args ...any) {}
}

125
logger/logger_test.go Normal file
View File

@@ -0,0 +1,125 @@
package logger
import (
"bytes"
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/livekit/protocol/logger/zaputil"
)
func zapLoggerCore(l Logger) zapcore.Core {
return l.(ZapLogger).ToZap().Desugar().Core()
}
func TestLoggerComponent(t *testing.T) {
t.Run("inheriting parent level", func(t *testing.T) {
l, err := NewZapLogger(&Config{
Level: "info",
ComponentLevels: map[string]string{
"mycomponent": "warn",
},
})
require.NoError(t, err)
sub := zapLoggerCore(l.WithComponent("sub"))
require.True(t, sub.Enabled(zapcore.InfoLevel))
require.False(t, sub.Enabled(zapcore.DebugLevel))
compLogger := zapLoggerCore(l.WithComponent("mycomponent").WithComponent("level2"))
require.True(t, compLogger.Enabled(zapcore.WarnLevel))
require.False(t, compLogger.Enabled(zapcore.InfoLevel))
})
t.Run("obeys component override", func(t *testing.T) {
l, err := NewZapLogger(&Config{
Level: "info",
ComponentLevels: map[string]string{
"sub": "debug",
"sub2": "error",
},
})
require.NoError(t, err)
sub := zapLoggerCore(l.WithComponent("sub"))
sub2 := zapLoggerCore(l.WithComponent("sub2"))
require.True(t, sub.Enabled(zapcore.DebugLevel))
require.False(t, sub2.Enabled(zapcore.InfoLevel))
})
t.Run("updates dynamically", func(t *testing.T) {
config := &Config{
Level: "info",
ComponentLevels: map[string]string{
"sub": "debug",
"sub2": "error",
},
}
l, err := NewZapLogger(config)
require.NoError(t, err)
sub := zapLoggerCore(l.WithComponent("sub"))
sub2 := zapLoggerCore(l.WithComponent("sub2.test"))
err = config.Update(&Config{
Level: "debug",
ComponentLevels: map[string]string{
"sub": "info",
// sub2 removed
},
})
require.NoError(t, err)
require.True(t, zapLoggerCore(l).Enabled(zapcore.DebugLevel))
require.False(t, sub.Enabled(zapcore.DebugLevel))
require.True(t, sub.Enabled(zapcore.InfoLevel))
require.True(t, sub2.Enabled(zapcore.InfoLevel))
})
t.Run("log output matches expected values", func(t *testing.T) {
ws := &testBufferedWriteSyncer{}
l, err := NewZapLogger(&Config{}, WithTap(zaputil.NewWriteEnabler(ws, zapcore.DebugLevel)))
require.NoError(t, err)
l.Debugw("foo", "bar", "baz")
var log struct {
Level string
TS float64
Caller string
Msg string
Bar string
}
require.NoError(t, json.Unmarshal(ws.Bytes(), &log))
require.Equal(t, "debug", log.Level)
require.NotEqual(t, 0, log.TS)
require.NotEqual(t, "", log.Caller)
require.Equal(t, "foo", log.Msg)
require.Equal(t, "baz", log.Bar)
})
t.Run("component enabler for tapped logger returns lowest enabled level", func(t *testing.T) {
tapLevel := zap.NewAtomicLevel()
l, err := NewZapLogger(&Config{Level: "info"}, WithTap(zaputil.NewWriteEnabler(&testBufferedWriteSyncer{}, tapLevel)))
require.NoError(t, err)
lvl := l.ComponentLeveler().ComponentLevel("foo")
// check config level
require.False(t, lvl.Enabled(zapcore.DebugLevel))
require.True(t, lvl.Enabled(zapcore.InfoLevel))
// check tap level
tapLevel.SetLevel(zapcore.DebugLevel)
require.True(t, lvl.Enabled(zapcore.DebugLevel))
})
}
type testBufferedWriteSyncer struct {
bytes.Buffer
}
func (t *testBufferedWriteSyncer) Sync() error { return nil }

View File

@@ -0,0 +1,95 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pionlogger
import (
"fmt"
"github.com/livekit/protocol/logger"
)
// implements webrtc.LeveledLogger
type logAdapter struct {
logger logger.Logger
ignoredPrefixes *prefixSet
}
func (l *logAdapter) Trace(msg string) {
l.logger.Debugw(msg)
}
func (l *logAdapter) Tracef(format string, args ...interface{}) {
l.logger.Debugw(fmt.Sprintf(format, args...))
}
func (l *logAdapter) Debug(msg string) {
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Debugw(msg)
}
func (l *logAdapter) Debugf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Debugw(msg)
}
func (l *logAdapter) Info(msg string) {
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Infow(msg)
}
func (l *logAdapter) Infof(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Infow(msg)
}
func (l *logAdapter) Warn(msg string) {
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Warnw(msg, nil)
}
func (l *logAdapter) Warnf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Warnw(msg, nil)
}
func (l *logAdapter) Error(msg string) {
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Errorw(msg, nil)
}
func (l *logAdapter) Errorf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
if l.ignoredPrefixes.Match(msg) {
return
}
l.logger.Errorw(msg, nil)
}

103
logger/pionlogger/logger.go Normal file
View File

@@ -0,0 +1,103 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pionlogger
import (
"strings"
"github.com/pion/logging"
"github.com/livekit/protocol/logger"
)
var (
pionIgnoredPrefixes = map[string]*prefixSet{
"ice": {
"pingAllCandidates called with no candidate pairs",
"failed to send packet: io: read/write on closed pipe",
"Ignoring remote candidate with tcpType active",
"discard message from",
"Failed to discover mDNS candidate",
"Failed to read from candidate tcp",
"remote mDNS candidate added, but mDNS is disabled",
},
"pc": {
"Failed to accept RTCP stream is already closed",
"Failed to accept RTP stream is already closed",
"Incoming unhandled RTCP ssrc",
},
"tcp_mux": {
"Error reading first packet from",
"error closing connection",
},
"turn": {
"error when handling datagram",
"Failed to send ChannelData from allocation",
"Failed to handle datagram",
},
}
)
type prefixSet []string
func (s *prefixSet) Match(msg string) bool {
if s == nil {
return false
}
for _, prefix := range *s {
if strings.HasPrefix(msg, prefix) {
return true
}
}
return false
}
func NewLoggerFactory(l logger.Logger) logging.LoggerFactory {
if zl, ok := l.(logger.ZapLogger); ok {
return &zapLoggerFactory{zl}
}
return &loggerFactory{l}
}
// zapLoggerFactory implements logging.LoggerFactory interface for zap loggers
type zapLoggerFactory struct {
logger logger.ZapLogger
}
func (f *zapLoggerFactory) NewLogger(scope string) logging.LeveledLogger {
return &zapLogAdapter{
logger: f.logger,
level: f.logger.ComponentLeveler().ComponentLevel(formatComponent(scope)),
scope: scope,
ignoredPrefixes: pionIgnoredPrefixes[scope],
}
}
// loggerFactory implements logging.LoggerFactory interface for generic loggers
type loggerFactory struct {
logger logger.Logger
}
func (f *loggerFactory) NewLogger(scope string) logging.LeveledLogger {
return &logAdapter{
logger: f.logger.WithComponent(formatComponent(scope)).WithCallDepth(1),
ignoredPrefixes: pionIgnoredPrefixes[scope],
}
}
func formatComponent(scope string) string {
return "pion." + scope
}

View File

@@ -0,0 +1,139 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pionlogger
import (
"fmt"
"go.uber.org/atomic"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/livekit/protocol/logger"
)
const (
zapLogAdapterStateCreated = iota
zapLogAdapterStateBuilding
zapLogAdapterStateReady
)
// implements webrtc.LeveledLogger
type zapLogAdapter struct {
state atomic.Uint32
logger logger.Logger
level zapcore.LevelEnabler
scope string
ignoredPrefixes *prefixSet
}
func (l *zapLogAdapter) init() {
for l.state.Load() != zapLogAdapterStateReady {
if l.state.CompareAndSwap(zapLogAdapterStateCreated, zapLogAdapterStateBuilding) {
l.logger = l.logger.WithComponent(formatComponent(l.scope)).WithCallDepth(1)
l.state.Store(zapLogAdapterStateReady)
}
}
}
func (l *zapLogAdapter) Trace(msg string) {
if l.level.Enabled(zap.DebugLevel) {
l.init()
l.logger.Debugw(msg)
}
}
func (l *zapLogAdapter) Tracef(format string, args ...interface{}) {
if l.level.Enabled(zap.DebugLevel) {
l.init()
l.logger.Debugw(fmt.Sprintf(format, args...))
}
}
func (l *zapLogAdapter) Debug(msg string) {
if l.level.Enabled(zap.DebugLevel) {
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Debugw(msg)
}
}
}
func (l *zapLogAdapter) Debugf(format string, args ...interface{}) {
if l.level.Enabled(zap.DebugLevel) {
msg := fmt.Sprintf(format, args...)
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Debugw(msg)
}
}
}
func (l *zapLogAdapter) Info(msg string) {
if l.level.Enabled(zap.InfoLevel) {
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Infow(msg)
}
}
}
func (l *zapLogAdapter) Infof(format string, args ...interface{}) {
if l.level.Enabled(zap.InfoLevel) {
msg := fmt.Sprintf(format, args...)
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Infow(msg)
}
}
}
func (l *zapLogAdapter) Warn(msg string) {
if l.level.Enabled(zap.WarnLevel) {
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Warnw(msg, nil)
}
}
}
func (l *zapLogAdapter) Warnf(format string, args ...interface{}) {
if l.level.Enabled(zap.WarnLevel) {
msg := fmt.Sprintf(format, args...)
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Warnw(msg, nil)
}
}
}
func (l *zapLogAdapter) Error(msg string) {
if l.level.Enabled(zap.ErrorLevel) {
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Errorw(msg, nil)
}
}
}
func (l *zapLogAdapter) Errorf(format string, args ...interface{}) {
if l.level.Enabled(zap.ErrorLevel) {
msg := fmt.Sprintf(format, args...)
if !l.ignoredPrefixes.Match(msg) {
l.init()
l.logger.Errorw(msg, nil)
}
}
}

173
logger/proto.go Normal file
View File

@@ -0,0 +1,173 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logger
import (
"encoding/base64"
"fmt"
"strconv"
"go.uber.org/zap/zapcore"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
)
func Proto(val proto.Message) zapcore.ObjectMarshaler {
if val == nil {
return nil
}
return protoMarshaller{val.ProtoReflect()}
}
var _ zapcore.ObjectMarshaler = protoMarshaller{}
var _ zapcore.ObjectMarshaler = protoMapMarshaller{}
var _ zapcore.ArrayMarshaler = protoListMarshaller{}
type protoMarshaller struct {
m protoreflect.Message
}
func (p protoMarshaller) MarshalLogObject(e zapcore.ObjectEncoder) error {
fields := p.m.Descriptor().Fields()
for i := 0; i < fields.Len(); i++ {
f := fields.Get(i)
k := f.JSONName()
v := p.m.Get(f)
if f.IsMap() {
if m := v.Map(); m.IsValid() {
e.AddObject(k, protoMapMarshaller{f, m})
}
} else if f.IsList() {
if m := v.List(); m.IsValid() {
e.AddArray(k, protoListMarshaller{f, m})
}
} else {
marshalProtoField(k, f, v, e)
}
}
return nil
}
type protoMapMarshaller struct {
f protoreflect.FieldDescriptor
m protoreflect.Map
}
func (p protoMapMarshaller) MarshalLogObject(e zapcore.ObjectEncoder) error {
p.m.Range(func(ki protoreflect.MapKey, vi protoreflect.Value) bool {
var k string
switch p.f.MapKey().Kind() {
case protoreflect.BoolKind:
k = strconv.FormatBool(ki.Bool())
case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
k = strconv.FormatInt(ki.Int(), 10)
case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
k = strconv.FormatUint(ki.Uint(), 10)
case protoreflect.StringKind:
k = ki.String()
}
marshalProtoField(k, p.f.MapValue(), vi, e)
return true
})
return nil
}
type protoListMarshaller struct {
f protoreflect.FieldDescriptor
m protoreflect.List
}
func (p protoListMarshaller) MarshalLogArray(e zapcore.ArrayEncoder) error {
for i := 0; i < p.m.Len(); i++ {
v := p.m.Get(i)
switch p.f.Kind() {
case protoreflect.BoolKind:
e.AppendBool(v.Bool())
case protoreflect.EnumKind:
e.AppendInt32(int32(v.Enum()))
case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
e.AppendInt64(v.Int())
case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
e.AppendUint64(v.Uint())
case protoreflect.FloatKind, protoreflect.DoubleKind:
e.AppendFloat64(v.Float())
case protoreflect.StringKind:
e.AppendString(v.String())
case protoreflect.BytesKind:
e.AppendString(marshalProtoBytes(v.Bytes()))
case protoreflect.MessageKind:
e.AppendObject(protoMarshaller{v.Message()})
}
}
return nil
}
func marshalProtoField(k string, f protoreflect.FieldDescriptor, v protoreflect.Value, e zapcore.ObjectEncoder) {
switch f.Kind() {
case protoreflect.BoolKind:
if b := v.Bool(); b {
e.AddBool(k, b)
}
case protoreflect.EnumKind:
if n := v.Enum(); n != 0 {
e.AddInt32(k, int32(n))
}
case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind:
if n := v.Int(); n != 0 {
e.AddInt64(k, n)
}
case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind:
if n := v.Uint(); n != 0 {
e.AddUint64(k, n)
}
case protoreflect.FloatKind, protoreflect.DoubleKind:
if n := v.Float(); n != 0 {
e.AddFloat64(k, n)
}
case protoreflect.StringKind:
if s := v.String(); s != "" {
e.AddString(k, s)
}
case protoreflect.BytesKind:
if b := v.Bytes(); len(b) != 0 {
e.AddString(k, marshalProtoBytes(b))
}
case protoreflect.MessageKind:
if m := v.Message(); m.IsValid() {
e.AddObject(k, protoMarshaller{m})
}
}
}
func marshalProtoBytes(b []byte) string {
n := len(b)
if n > 64 {
b = b[:64]
}
s := base64.RawStdEncoding.EncodeToString(b)
switch {
case n <= 64:
return s
case n < 1<<10:
return fmt.Sprintf("%s... (%dbytes)", s, n)
case n < 1<<20:
return fmt.Sprintf("%s... (%.2fkB)", s, float64(n)/float64(1<<10))
case n < 1<<30:
return fmt.Sprintf("%s... (%.2fMB)", s, float64(n)/float64(1<<20))
default:
return fmt.Sprintf("%s... (%.2fGB)", s, float64(n)/float64(1<<30))
}
}

102
logger/slog.go Normal file
View File

@@ -0,0 +1,102 @@
package logger
import (
"context"
"log/slog"
"github.com/go-logr/logr"
"go.uber.org/zap/exp/zapslog"
)
// NewSlogDiscard creates a slog.Handler that discards all logs.
func NewSlogDiscard() slog.Handler {
return slogDiscard{}
}
// ToSlogHandler converts Logger to slog.Handler.
func ToSlogHandler(log Logger) slog.Handler {
switch log := log.(type) {
case ZapLogger:
zlog := log.ToZap().Desugar()
return zapslog.NewHandler(zlog.Core(), &zapslog.HandlerOptions{AddSource: true})
case LogRLogger:
return logr.ToSlogHandler(log.toLogr())
}
return slogHandler{log, ""}
}
type slogDiscard struct{}
func (_ slogDiscard) Enabled(ctx context.Context, level slog.Level) bool {
return false
}
func (_ slogDiscard) Handle(ctx context.Context, record slog.Record) error {
return nil
}
func (l slogDiscard) WithAttrs(attrs []slog.Attr) slog.Handler {
return l
}
func (l slogDiscard) WithGroup(name string) slog.Handler {
return l
}
type slogHandler struct {
log Logger
group string
}
func (l slogHandler) Enabled(ctx context.Context, level slog.Level) bool {
return true // so such method on Logger
}
func (l slogHandler) getGroup() string {
group := l.group
if group != "" {
group = group + "."
}
return group
}
func (l slogHandler) Handle(ctx context.Context, r slog.Record) error {
keysAndValues := make([]any, 0, r.NumAttrs()*2)
group := l.getGroup()
r.Attrs(func(attr slog.Attr) bool {
keysAndValues = append(keysAndValues, group+attr.Key, attr.Value.Resolve().Any())
return true
})
switch r.Level {
case slog.LevelDebug:
l.log.Debugw(r.Message, keysAndValues...)
default:
fallthrough
case slog.LevelInfo:
l.log.Infow(r.Message, keysAndValues...)
case slog.LevelWarn:
l.log.Warnw(r.Message, nil, keysAndValues...)
case slog.LevelError:
l.log.Errorw(r.Message, nil, keysAndValues...)
}
return nil
}
func (l slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
log := l.log
keysAndValues := make([]any, 0, len(attrs)*2)
group := l.getGroup()
for _, attr := range attrs {
keysAndValues = append(keysAndValues, group+attr.Key, attr.Value.Resolve().Any())
}
log = log.WithValues(keysAndValues...)
return slogHandler{log, l.group}
}
func (l slogHandler) WithGroup(name string) slog.Handler {
group := name
if l.group != "" {
group = l.group + "." + name
}
return slogHandler{l.log, group}
}

123
logger/zaputil/deferrer.go Normal file
View File

@@ -0,0 +1,123 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"sync"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type deferredWrite struct {
core zapcore.Core
ent zapcore.Entry
fields []zapcore.Field
}
type Deferrer struct {
mu sync.Mutex
ready bool
fields []zapcore.Field
writes []*deferredWrite
}
func (b *Deferrer) buffer(core zapcore.Core, ent zapcore.Entry, fields []zapcore.Field) bool {
b.mu.Lock()
defer b.mu.Unlock()
if b.ready {
return false
}
b.writes = append(b.writes, &deferredWrite{core, ent, fields})
return true
}
func (b *Deferrer) flush() {
b.mu.Lock()
b.ready = true
writes := b.writes
b.writes = nil
b.mu.Unlock()
var fields []zapcore.Field
for _, w := range writes {
fields = append(fields[:0], b.fields...)
fields = append(fields, w.fields...)
w.core.Write(w.ent, fields)
}
}
func (b *Deferrer) write(core zapcore.Core, ent zapcore.Entry, fields []zapcore.Field) error {
if !b.buffer(core, ent, fields) {
return core.Write(ent, append(fields[0:len(fields):len(fields)], b.fields...))
}
return nil
}
type DeferredFieldResolver func(args ...any)
func NewDeferrer() (*Deferrer, DeferredFieldResolver) {
buf := &Deferrer{}
var resolveOnce sync.Once
resolve := func(args ...any) {
resolveOnce.Do(func() {
fields := make([]zapcore.Field, 0, len(args))
for i := 0; i < len(args); i++ {
switch arg := args[i].(type) {
case zapcore.Field:
fields = append(fields, arg)
case string:
if i < len(args)-1 {
fields = append(fields, zap.Any(arg, args[i+1]))
i++
}
}
}
buf.fields = fields
buf.flush()
})
}
return buf, resolve
}
type deferredValueCore struct {
zapcore.Core
def *Deferrer
}
func NewDeferredValueCore(core zapcore.Core, def *Deferrer) zapcore.Core {
def.mu.Lock()
defer def.mu.Unlock()
return &deferredValueCore{core, def}
}
func (c *deferredValueCore) With(fields []zapcore.Field) zapcore.Core {
return &deferredValueCore{
Core: c.Core.With(fields),
def: c.def,
}
}
func (c *deferredValueCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(ent.Level) {
return ce.AddCore(ent, c)
}
return ce
}
func (c *deferredValueCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
return c.def.write(c.Core, ent, fields)
}

View File

@@ -0,0 +1,41 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)
func TestDeferredLogger(t *testing.T) {
c := &testCore{Core: zap.NewExample().Core()}
d, resolve := NewDeferrer()
dc := NewDeferredValueCore(c, d)
s := zap.New(dc).Sugar()
s.Infow("test")
require.Equal(t, 0, c.WriteCount())
s.With("a", "1").Infow("test")
require.Equal(t, 0, c.WriteCount())
resolve("b", "2")
require.Equal(t, 2, c.WriteCount())
s.With("c", "3").Infow("test")
require.Equal(t, 3, c.WriteCount())
}

114
logger/zaputil/encoder.go Normal file
View File

@@ -0,0 +1,114 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"go.uber.org/multierr"
"go.uber.org/zap/zapcore"
)
type WriteEnabler struct {
zapcore.WriteSyncer
zapcore.LevelEnabler
}
func NewWriteEnabler(ws zapcore.WriteSyncer, enab zapcore.LevelEnabler) *WriteEnabler {
return &WriteEnabler{ws, enab}
}
type discardWriteSyncer struct{}
func (discardWriteSyncer) Write(p []byte) (int, error) { return len(p), nil }
func (discardWriteSyncer) Sync() error { return nil }
func NewDiscardWriteEnabler() *WriteEnabler {
return NewWriteEnabler(discardWriteSyncer{}, zapcore.FatalLevel)
}
func NewEncoderCore(enc zapcore.Encoder, out ...*WriteEnabler) zapcore.Core {
return &encoderCore{
enc: enc,
out: out,
}
}
type encoderCore struct {
enc zapcore.Encoder
out []*WriteEnabler
}
func (c encoderCore) Level() zapcore.Level {
minLvl := zapcore.FatalLevel
for _, out := range c.out {
if lvl := zapcore.LevelOf(out); lvl < minLvl {
minLvl = lvl
}
}
return minLvl
}
func (c encoderCore) Enabled(lvl zapcore.Level) bool {
for _, out := range c.out {
if out.Enabled(lvl) {
return true
}
}
return false
}
func (c *encoderCore) With(fields []zapcore.Field) zapcore.Core {
dup := *c
dup.enc = dup.enc.Clone()
for _, f := range fields {
f.AddTo(dup.enc)
}
return &dup
}
func (c *encoderCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(ent.Level) {
return ce.AddCore(ent, c)
}
return ce
}
func (c *encoderCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
buf, err := c.enc.EncodeEntry(ent, fields)
if err != nil {
return err
}
for _, out := range c.out {
if out.Enabled(ent.Level) {
_, werr := out.Write(buf.Bytes())
err = multierr.Append(err, werr)
}
}
buf.Free()
if err != nil {
return err
}
if ent.Level > zapcore.ErrorLevel {
_ = c.Sync()
}
return nil
}
func (c *encoderCore) Sync() error {
var err error
for _, out := range c.out {
err = multierr.Append(err, out.Sync())
}
return err
}

View File

@@ -0,0 +1,151 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"fmt"
"math"
"reflect"
"sync/atomic"
"github.com/zeebo/xxh3"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type FieldSampleRate interface {
Threshold() uint64
}
func rateToThreshold(rate float64) uint64 {
return math.MaxUint64 / 10000 * uint64(math.Max(math.Min(rate, 1), 0)*10000)
}
type AtomicFieldSampleRate uint64
func NewAtomicFieldSampleRate(rate float64) *AtomicFieldSampleRate {
var r AtomicFieldSampleRate
r.SetRate(rate)
return &r
}
func (r *AtomicFieldSampleRate) SetRate(rate float64) {
atomic.StoreUint64((*uint64)(r), rateToThreshold(rate))
}
func (r *AtomicFieldSampleRate) Threshold() uint64 {
return uint64(atomic.LoadUint64((*uint64)(r)))
}
type FieldSamplerAction int
const (
OmitSampledLog FieldSamplerAction = iota
AnnotateSampledLog
)
type FieldSamplerConfig struct {
FieldName string
Rate FieldSampleRate
Action FieldSamplerAction
AnnotationFieldName string
}
func NewFieldSampler(core zapcore.Core, config FieldSamplerConfig) zapcore.Core {
return &fieldSampler{
Core: core,
config: config,
}
}
type fieldSampler struct {
zapcore.Core
config FieldSamplerConfig
hash uint64
}
var _ zapcore.Core = (*fieldSampler)(nil)
func (s *fieldSampler) With(fields []zapcore.Field) zapcore.Core {
hash := s.hash
if h, ok := s.hashSampleField(fields); ok {
hash = h
}
return &fieldSampler{
Core: s.Core.With(fields),
config: s.config,
hash: hash,
}
}
func (s *fieldSampler) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if s.Enabled(ent.Level) {
return ce.AddCore(ent, s)
}
return ce
}
func (s *fieldSampler) hashSampleField(fields []zapcore.Field) (uint64, bool) {
v, ok := s.findSampleField(fields)
if !ok {
return 0, false
}
return xxh3.HashString(v), true
}
func (s *fieldSampler) findSampleField(fields []zapcore.Field) (string, bool) {
for _, f := range fields {
if f.Key == s.config.FieldName {
switch f.Type {
case zapcore.StringType:
return f.String, true
case zapcore.ReflectType:
rv := reflect.ValueOf(f.Interface)
if rv.Kind() == reflect.String {
return rv.String(), true
}
case zapcore.StringerType:
if str, ok := f.Interface.(fmt.Stringer); ok {
return str.String(), true
}
}
return "", false
}
}
return "", false
}
func (s *fieldSampler) test(fields []zapcore.Field) bool {
if s.hash != 0 {
return s.hash > s.config.Rate.Threshold()
}
if h, ok := s.hashSampleField(fields); ok {
return h > s.config.Rate.Threshold()
}
return false
}
func (s *fieldSampler) Write(entry zapcore.Entry, fields []zapcore.Field) error {
if s.test(fields) {
switch s.config.Action {
case OmitSampledLog:
return nil
case AnnotateSampledLog:
fields = append(fields, zap.Bool(s.config.AnnotationFieldName, true))
}
}
return s.Core.Write(entry, fields)
}

View File

@@ -0,0 +1,83 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"fmt"
"math"
"testing"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/stretchr/testify/require"
)
func TestRoomSampleRate(t *testing.T) {
expectedRate := 0.50
n := 10000
c := &testCore{Core: zap.NewExample().Core()}
s := zap.New(NewFieldSampler(c, FieldSamplerConfig{
FieldName: "field",
Rate: NewAtomicFieldSampleRate(expectedRate),
})).Sugar()
for i := 0; i < n; i++ {
s.Debugw("test", "field", fmt.Sprintf("field_%d", i))
}
rate := float64(c.WriteCount()) / float64(n)
require.Greater(t, 0.01, math.Abs(rate-expectedRate))
}
func TestRoomSamplerWith(t *testing.T) {
c := &testCore{Core: zap.NewExample().Core()}
s := zap.New(NewFieldSampler(c, FieldSamplerConfig{
FieldName: "field",
Rate: NewAtomicFieldSampleRate(0),
}).(*fieldSampler)).Sugar()
s.Debugw("test", "field", "test")
require.Equal(t, 0, c.WriteCount())
s.With("field", "test").Debugw("test")
require.Equal(t, 0, c.WriteCount())
}
func TestRoomSampleFindSampleField(t *testing.T) {
s := NewFieldSampler(nil, FieldSamplerConfig{
FieldName: "field",
Rate: NewAtomicFieldSampleRate(1),
}).(*fieldSampler)
v, ok := s.findSampleField([]zapcore.Field{zap.String("field", "test")})
require.Equal(t, "test", v)
require.True(t, ok)
v, ok = s.findSampleField([]zapcore.Field{zap.Reflect("field", testStringLike("test"))})
require.Equal(t, "test", v)
require.True(t, ok)
v, ok = s.findSampleField([]zapcore.Field{zap.Stringer("field", testStringer("test"))})
require.Equal(t, "test", v)
require.True(t, ok)
_, ok = s.findSampleField([]zapcore.Field{zap.Int("field", 123)})
require.False(t, ok)
_, ok = s.findSampleField([]zapcore.Field{})
require.False(t, ok)
}

View File

@@ -0,0 +1,23 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import "go.uber.org/zap/zapcore"
type OrLevelEnabler [2]zapcore.LevelEnabler
func (e OrLevelEnabler) Enabled(lvl zapcore.Level) bool {
return e[0].Enabled(lvl) || e[1].Enabled(lvl)
}

130
logger/zaputil/sampler.go Normal file
View File

@@ -0,0 +1,130 @@
// Copyright (c) 2016-2022 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package zaputil
import (
"sync/atomic"
"time"
"github.com/zeebo/xxh3"
"go.uber.org/zap/zapcore"
)
// this is lifted almost entirely from zap but with one significant change -
// the state is injected into the sampler core to allow rebuilding the logger
// without resetting the counts.
const (
minLevel = zapcore.DebugLevel
maxLevel = zapcore.FatalLevel
numLevels = maxLevel - minLevel + 1
countersPerLevel = 4096
)
type counter struct {
resetAt atomic.Int64
counter atomic.Uint64
}
type counters [numLevels][countersPerLevel]counter
func newCounters() *counters {
return &counters{}
}
func (cs *counters) get(lvl zapcore.Level, key string) *counter {
i := lvl - minLevel
j := xxh3.HashString(key) % countersPerLevel
return &cs[i][j]
}
func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
tn := t.UnixNano()
resetAfter := c.resetAt.Load()
if resetAfter > tn {
return c.counter.Add(1)
}
c.counter.Store(1)
newResetAfter := tn + tick.Nanoseconds()
if !c.resetAt.CompareAndSwap(resetAfter, newResetAfter) {
// We raced with another goroutine trying to reset, and it also reset
// the counter to 1, so we need to reincrement the counter.
return c.counter.Add(1)
}
return 1
}
type Sampler struct {
counts *counters
tick time.Duration
first, thereafter uint64
}
func NewSampler(tick time.Duration, first, thereafter int) *Sampler {
return &Sampler{
tick: tick,
counts: newCounters(),
first: uint64(first),
thereafter: uint64(thereafter),
}
}
func NewSamplerCore(core zapcore.Core, s *Sampler) zapcore.Core {
return &sampler{
Core: core,
s: s,
}
}
type sampler struct {
zapcore.Core
s *Sampler
}
func (s *sampler) Level() zapcore.Level {
return zapcore.LevelOf(s.Core)
}
func (s *sampler) With(fields []zapcore.Field) zapcore.Core {
return &sampler{
Core: s.Core.With(fields),
s: s.s,
}
}
func (s *sampler) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if !s.Enabled(ent.Level) {
return ce
}
if ent.Level >= minLevel && ent.Level <= maxLevel {
counter := s.s.counts.get(ent.Level, ent.Message)
n := counter.IncCheckReset(ent.Time, s.s.tick)
if n > s.s.first && (s.s.thereafter == 0 || (n-s.s.first)%s.s.thereafter != 0) {
return ce
}
}
return s.Core.Check(ent, ce)
}

76
logger/zaputil/zaputil.go Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func encoderWithValues(enc zapcore.Encoder, kvs ...any) zapcore.Encoder {
clone := enc.Clone()
for i := 1; i < len(kvs); i += 2 {
if key, ok := kvs[i-1].(string); ok {
zap.Any(key, kvs[i]).AddTo(clone)
}
}
return clone
}
type Encoder[T any] interface {
WithValues(kvs ...any) T
Core(console, json *WriteEnabler) zapcore.Core
}
type DevelopmentEncoder struct {
console zapcore.Encoder
json zapcore.Encoder
}
func NewDevelopmentEncoder() DevelopmentEncoder {
return DevelopmentEncoder{
console: zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()),
json: zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
}
}
func (e DevelopmentEncoder) WithValues(kvs ...any) DevelopmentEncoder {
e.console = encoderWithValues(e.console, kvs...)
e.json = encoderWithValues(e.json, kvs...)
return e
}
func (e DevelopmentEncoder) Core(console, json *WriteEnabler) zapcore.Core {
return zapcore.NewTee(NewEncoderCore(e.console, console), NewEncoderCore(e.json, json))
}
type ProductionEncoder struct {
json zapcore.Encoder
}
func NewProductionEncoder() ProductionEncoder {
return ProductionEncoder{
json: zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
}
}
func (e ProductionEncoder) WithValues(kvs ...any) ProductionEncoder {
e.json = encoderWithValues(e.json, kvs...)
return e
}
func (e ProductionEncoder) Core(console, json *WriteEnabler) zapcore.Core {
return NewEncoderCore(e.json, console, json)
}

View File

@@ -0,0 +1,58 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zaputil
import (
"go.uber.org/atomic"
"go.uber.org/zap/zapcore"
)
type testStringer string
func (s testStringer) String() string {
return string(s)
}
type testStringLike string
type testCore struct {
zapcore.Core
writeCount *atomic.Int32
}
func (c *testCore) init() {
if c.writeCount == nil {
c.writeCount = &atomic.Int32{}
}
}
func (c *testCore) WriteCount() int {
c.init()
return int(c.writeCount.Load())
}
func (c *testCore) With(fields []zapcore.Field) zapcore.Core {
c.init()
return &testCore{
Core: c.Core.With(fields),
writeCount: c.writeCount,
}
}
func (s *testCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
s.init()
s.writeCount.Inc()
return nil
}

204
magefile.go Normal file
View File

@@ -0,0 +1,204 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build mage
// +build mage
package main
import (
"context"
"fmt"
"go/build"
"os"
"os/exec"
"path/filepath"
"github.com/livekit/mageutil"
"github.com/livekit/protocol/psrpc"
)
var Default = Proto
func Bootstrap() error {
return mageutil.Run(context.Background(),
"go install github.com/twitchtv/twirp/protoc-gen-twirp@latest",
"go install google.golang.org/protobuf/cmd/protoc-gen-go@latest",
"go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest",
"go install github.com/livekit/psrpc/protoc-gen-psrpc@latest",
)
}
// regenerate protobuf
func Proto() error {
twirpProtoFiles := []string{
"livekit_egress.proto",
"livekit_ingress.proto",
"livekit_room.proto",
"livekit_sip.proto",
}
protoFiles := []string{
"livekit_agent.proto",
"livekit_analytics.proto",
"livekit_internal.proto",
"livekit_models.proto",
"livekit_rtc.proto",
"livekit_webhook.proto",
}
grpcProtoFiles := []string{
"infra/link.proto",
"rpc/analytics.proto",
}
psrpcProtoFiles := []string{
"rpc/agent.proto",
"rpc/egress.proto",
"rpc/ingress.proto",
"rpc/io.proto",
"rpc/keepalive.proto",
"rpc/participant.proto",
"rpc/room.proto",
"rpc/signal.proto",
"rpc/sip.proto",
}
fmt.Println("generating protobuf")
target := "livekit"
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
protoc, err := getToolPath("protoc")
if err != nil {
return err
}
protocGoPath, err := getToolPath("protoc-gen-go")
if err != nil {
return err
}
twirpPath, err := getToolPath("protoc-gen-twirp")
if err != nil {
return err
}
protocGrpcGoPath, err := getToolPath("protoc-gen-go-grpc")
if err != nil {
return err
}
fmt.Println("generating twirp protobuf")
args := append([]string{
"--go_out", target,
"--twirp_out", target,
"--go_opt=paths=source_relative",
"--twirp_opt=paths=source_relative",
"--plugin=go=" + protocGoPath,
"--plugin=twirp=" + twirpPath,
"-I=./protobufs",
}, twirpProtoFiles...)
cmd := exec.Command(protoc, args...)
connectStd(cmd)
if err := cmd.Run(); err != nil {
return err
}
fmt.Println("generating protobuf")
args = append([]string{
"--go_out", target,
"--go-grpc_out", target,
"--go_opt=paths=source_relative",
"--go-grpc_opt=paths=source_relative",
"--plugin=go=" + protocGoPath,
"--plugin=go-grpc=" + protocGrpcGoPath,
"-I=./protobufs",
}, protoFiles...)
cmd = exec.Command(protoc, args...)
connectStd(cmd)
if err := cmd.Run(); err != nil {
return err
}
fmt.Println("generating grpc protobuf")
args = append([]string{
"--go_out", ".",
"--go-grpc_out", ".",
"--go_opt=paths=source_relative",
"--go-grpc_opt=paths=source_relative",
"--plugin=go=" + protocGoPath,
"--plugin=go-grpc=" + protocGrpcGoPath,
"-I=./protobufs",
}, grpcProtoFiles...)
cmd = exec.Command(protoc, args...)
connectStd(cmd)
if err := cmd.Run(); err != nil {
return err
}
fmt.Println("generating psrpc protobuf")
psrpcDir, err := mageutil.GetPkgDir("github.com/livekit/psrpc")
if err != nil {
return err
}
psrpcPath, err := mageutil.GetToolPath("protoc-gen-psrpc")
if err != nil {
return err
}
if err := psrpc.CheckCompilerVersion(psrpcPath); err != nil {
return err
}
args = append([]string{
"--go_out", ".",
"--psrpc_out", ".",
"--go_opt=paths=source_relative",
"--psrpc_opt=paths=source_relative",
"--plugin=go=" + protocGoPath,
"--plugin=psrpc=" + psrpcPath,
"-I" + psrpcDir + "/protoc-gen-psrpc/options",
"-I=./protobufs",
}, psrpcProtoFiles...)
cmd = exec.Command(protoc, args...)
mageutil.ConnectStd(cmd)
if err = cmd.Run(); err != nil {
return err
}
return nil
}
// run tests
func Test() error {
cmd := exec.Command("go", "test", "-race", "./...")
connectStd(cmd)
return cmd.Run()
}
// helpers
func getToolPath(name string) (string, error) {
if p, err := exec.LookPath(name); err == nil {
return p, nil
}
// check under gopath
gopath := os.Getenv("GOPATH")
if gopath == "" {
gopath = build.Default.GOPATH
}
p := filepath.Join(gopath, "bin", name)
if _, err := os.Stat(p); err != nil {
return "", err
}
return p, nil
}
func connectStd(cmd *exec.Cmd) {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}

View File

@@ -1,51 +0,0 @@
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/livekit-server/proto/livekit";
message Room {
string sid = 1;
string name = 2;
uint32 empty_timeout = 3;
uint32 max_participants = 4;
int64 creation_time = 5;
string turn_password = 6;
}
message ParticipantInfo {
enum State {
// websocket' connected, but not offered yet
JOINING = 0;
// server received client offer
JOINED = 1;
// ICE connectivity established
ACTIVE = 2;
// WS disconnected
DISCONNECTED = 3;
}
string sid = 1;
string identity = 2;
State state = 3;
repeated TrackInfo tracks = 4;
string metadata = 5;
}
enum TrackType {
AUDIO = 0;
VIDEO = 1;
DATA = 2;
}
message TrackInfo {
string sid = 1;
TrackType type = 2;
string name = 3;
bool muted = 4;
}
message DataMessage {
oneof value {
string text = 1;
bytes binary = 2;
}
}

13
package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "github.com/livekit/protocol",
"private": true,
"version": "1.19.1",
"scripts": {
"changeset": "changeset",
"ci:publish": "pnpm --filter @livekit/protocol run build && changeset publish"
},
"devDependencies": {
"@changesets/cli": "^2.27.1",
"@livekit/changesets-changelog-github": "^0.0.4"
}
}

3
packages/javascript/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules/
src/gen
!src/gen/version.d.ts

View File

@@ -0,0 +1,111 @@
# @livekit/protocol
## 1.19.1
### Patch Changes
- Add ErrorResponse - [#743](https://github.com/livekit/protocol/pull/743) ([@lukasIO](https://github.com/lukasIO))
## 1.19.0
### Minor Changes
- Add SIP grants. - [#745](https://github.com/livekit/protocol/pull/745) ([@dennwc](https://github.com/dennwc))
## 1.18.0
### Minor Changes
- Split SIP Trunk configuration to inbound and outbound parts. - [#738](https://github.com/livekit/protocol/pull/738) ([@dennwc](https://github.com/dennwc))
- add Participant attributes key/val storage - [#733](https://github.com/livekit/protocol/pull/733) ([@davidzhao](https://github.com/davidzhao))
## 1.17.0
### Minor Changes
- Add support for additional SIP transports. - [#719](https://github.com/livekit/protocol/pull/719) ([@dennwc](https://github.com/dennwc))
- Add ICERestartWHIPResource to RPC - [#716](https://github.com/livekit/protocol/pull/716) ([@Sean-Der](https://github.com/Sean-Der))
### Patch Changes
- Added error code field to EgressInfo - [#714](https://github.com/livekit/protocol/pull/714) ([@frostbyte73](https://github.com/frostbyte73))
- Include node_id with analytics events - [#727](https://github.com/livekit/protocol/pull/727) ([@davidzhao](https://github.com/davidzhao))
- Add notice to use participant identity from DataPacket for transcriptions. - [#706](https://github.com/livekit/protocol/pull/706) ([@dennwc](https://github.com/dennwc))
## 1.16.0
### Minor Changes
- - Add RedactAutoEncodedOutput to support redacting auto egress types - [#712](https://github.com/livekit/protocol/pull/712) ([@biglittlebigben](https://github.com/biglittlebigben))
- Redact image outputs
- Support AliOSS uploads for auto egress
- Allow inbound number filtering on SIP Dispatch Rules - [#707](https://github.com/livekit/protocol/pull/707) ([@dennwc](https://github.com/dennwc))
- Move egress request redacting routines to protocol - [#711](https://github.com/livekit/protocol/pull/711) ([@biglittlebigben](https://github.com/biglittlebigben))
## 1.15.0
### Minor Changes
- Add metadata to SIP trunks, dispatch rules and participants. Change SIP participant identity prefix to `sip_`. - [#696](https://github.com/livekit/protocol/pull/696) ([@dennwc](https://github.com/dennwc))
- Move language into TranscriptionSegment #703 - [#704](https://github.com/livekit/protocol/pull/704) ([@lukasIO](https://github.com/lukasIO))
## 1.14.0
### Minor Changes
- Added real-time Transcription protocol - [#686](https://github.com/livekit/protocol/pull/686) ([@davidzhao](https://github.com/davidzhao))
- WHIP protocol change - [#680](https://github.com/livekit/protocol/pull/680) ([@biglittlebigben](https://github.com/biglittlebigben))
Deprecate the bypass_transcoding property in all ingress APIs and introduce the optional enable_transcoding property. This property will default to false for WHIP and to true for all other ingress types.
### Patch Changes
- Add SIP participant name. - [#687](https://github.com/livekit/protocol/pull/687) ([@dennwc](https://github.com/dennwc))
## 1.13.0
### Minor Changes
- Add and option to play ringtone for SIP outbound calls. - [#671](https://github.com/livekit/protocol/pull/671) ([@dennwc](https://github.com/dennwc))
## 1.12.0
### Patch Changes
- Fixed bounds check when masking short SIP numbers. - [#650](https://github.com/livekit/protocol/pull/650) ([@dennwc](https://github.com/dennwc))
- Add signal requests for local track updates - [#651](https://github.com/livekit/protocol/pull/651) ([@lukasIO](https://github.com/lukasIO))
- Allow sending DTMF when creating SIP participant. - [#658](https://github.com/livekit/protocol/pull/658) ([@dennwc](https://github.com/dennwc))
## 1.11.0
### Minor Changes
- Align package version with manually tagged golang module - [#646](https://github.com/livekit/protocol/pull/646) ([@lukasIO](https://github.com/lukasIO))
## 1.10.4
### Patch Changes
- Fix granular export paths - [#642](https://github.com/livekit/protocol/pull/642) ([@lukasIO](https://github.com/lukasIO))
## 1.10.3
### Patch Changes
- Export room stubs from package - [#640](https://github.com/livekit/protocol/pull/640) ([@lukasIO](https://github.com/lukasIO))
## 1.10.2
### Patch Changes
- Fix import paths - [#635](https://github.com/livekit/protocol/pull/635) ([@lukasIO](https://github.com/lukasIO))

View File

@@ -0,0 +1,36 @@
{
"name": "@livekit/protocol",
"version": "1.19.1",
"description": "",
"type": "module",
"main": "src/index.js",
"types": "src/index.d.ts",
"files": [
"src"
],
"exports": {
".": {
"types": "./src/index.d.ts",
"default": "./src/index.js"
},
"./*": {
"types": "./src/gen/livekit_*_pb.d.ts",
"default": "./src/gen/livekit_*_pb.js"
}
},
"scripts": {
"generate:version": "genversion --esm --semi src/gen/version.js",
"generate:proto": "protoc --es_out src/gen --es_opt target=js+dts -I=../../protobufs ../../protobufs/livekit_room.proto ../../protobufs/livekit_rtc.proto ../../protobufs/livekit_models.proto ../../protobufs/livekit_agent.proto ../../protobufs/livekit_webhook.proto ../../protobufs/livekit_egress.proto ../../protobufs/livekit_ingress.proto ../../protobufs/livekit_sip.proto",
"build": "pnpm generate:version && pnpm generate:proto"
},
"keywords": [],
"author": "LiveKit",
"license": "Apache-2.0",
"devDependencies": {
"@bufbuild/protoc-gen-es": "^1.7.2",
"genversion": "^3.2.0"
},
"dependencies": {
"@bufbuild/protobuf": "^1.7.2"
}
}

View File

@@ -0,0 +1 @@
export declare const version: string;

10
packages/javascript/src/index.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
export * from "./gen/version.js";
export * from "./gen/livekit_room_pb.js";
export * from "./gen/livekit_agent_pb.js";
export * from "./gen/livekit_models_pb.js";
export * from "./gen/livekit_rtc_pb.js";
export * from "./gen/livekit_webhook_pb.js";
export * from "./gen/livekit_egress_pb.js";
export * from "./gen/livekit_ingress_pb.js";
export * from "./gen/livekit_sip_pb.js";
export { protoInt64 } from "@bufbuild/protobuf";

View File

@@ -0,0 +1,11 @@
// @ts-check
export * from "./gen/version.js";
export * from "./gen/livekit_room_pb.js";
export * from "./gen/livekit_agent_pb.js";
export * from "./gen/livekit_models_pb.js";
export * from "./gen/livekit_rtc_pb.js";
export * from "./gen/livekit_webhook_pb.js";
export * from "./gen/livekit_egress_pb.js";
export * from "./gen/livekit_ingress_pb.js";
export * from "./gen/livekit_sip_pb.js";
export { protoInt64 } from "@bufbuild/protobuf";

1269
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

3
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,3 @@
packages:
- "packages/javascript"
- "."

83
pprof/pprof.go Normal file
View File

@@ -0,0 +1,83 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pprof
import (
"bytes"
"context"
"runtime/pprof"
"time"
"github.com/livekit/psrpc"
)
const (
cpuProfileName = "cpu"
defaultTimeout = 30
)
var (
ErrProfileNotFound = psrpc.NewErrorf(psrpc.NotFound, "profile not found")
)
func GetProfileData(ctx context.Context, profileName string, timeout int, debug int) (b []byte, err error) {
switch profileName {
case cpuProfileName:
return GetCpuProfileData(ctx, timeout)
default:
return GetGenericProfileData(profileName, debug)
}
}
func GetCpuProfileData(ctx context.Context, timeout int) (b []byte, err error) {
if timeout == 0 {
timeout = defaultTimeout
}
buf := &bytes.Buffer{}
err = pprof.StartCPUProfile(buf)
if err != nil {
return nil, err
}
select {
case <-ctx.Done():
// finish async in order not to block, since we will not use the results
go pprof.StopCPUProfile()
return nil, context.Canceled
case <-time.After(time.Duration(timeout) * time.Second):
// break
}
pprof.StopCPUProfile()
return buf.Bytes(), nil
}
func GetGenericProfileData(profileName string, debug int) (b []byte, err error) {
pp := pprof.Lookup(profileName)
if pp == nil {
return nil, ErrProfileNotFound
}
buf := &bytes.Buffer{}
err = pp.WriteTo(buf, debug)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}

View File

@@ -0,0 +1,50 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package rpc;
import "google/protobuf/timestamp.proto";
option go_package = "github.com/livekit/protocol/infra";
service Link {
rpc WatchLocalLinks(WatchLocalLinksRequest) returns (stream WatchLocalLinksResponse);
rpc SimulateLinkState(SimulateLinkStateRequest) returns (SimulateLinkStateResponse);
}
message WatchLocalLinksRequest {}
message WatchLocalLinksResponse {
string local_region = 1;
string remote_region = 2;
int64 rtt = 3;
int64 jitter = 4;
double packet_loss = 5;
bool disabled = 6;
google.protobuf.Timestamp last_read = 7;
}
message SimulateLinkStateRequest {
string local_region = 1;
string remote_region = 2;
optional int64 rtt = 3;
optional int64 jitter = 4;
optional double packet_loss = 5;
optional bool disabled = 6;
int64 timeout = 7;
}
message SimulateLinkStateResponse {}

View File

@@ -0,0 +1,218 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_models.proto";
service AgentService {
rpc CreateAgentJobDefinition(CreateAgentJobDefinitionRequest) returns (JobDefinition);
rpc DeleteAgentJobDefinition(DeleteAgentJobDefinitionRequest) returns (JobDefinition);
rpc ListAgentJobDefinitions(ListAgentJobDefinitionsRequesst) returns (ListAgentJobDefinitionsResponse);
}
message CreateAgentJobDefinitionRequest {
JobType type = 1;
string room = 2;
repeated string participant_identity = 3;
string namespace = 4;
string metadata = 5;
}
message DeleteAgentJobDefinitionRequest {
string job_definition_id = 1;
}
message ListAgentJobDefinitionsRequesst {
string job_definition_id = 1; // if set, only the job definition whose id is given will be returned
string room = 2; // name of the room to list agents for. Must be set.
}
message ListAgentJobDefinitionsResponse {
repeated JobDefinition job_definitions = 1;
}
message JobDefinition {
string id = 1;
JobType type = 2;
string room = 3;
repeated string participant_identity = 4;
string namespace = 5;
string metadata = 6;
JobDefinitionState state = 7;
}
message JobDefinitionState {
// For job definitions of tyoe JT_ROOM, there will be at most 1 job.
// For job definitions of type JT_PUBLISHER, there will be 1 job per provided participant identity, or per publisher in the room if left empty.
repeated Job jobs = 1;
int64 created_at = 2;
int64 deleted_at = 3;
}
message Job {
string id = 1;
JobType type = 2;
Room room = 3;
optional ParticipantInfo participant = 4;
string namespace = 5;
string metadata = 6;
JobState state = 7;
}
message JobState {
JobStatus status = 1;
string error = 2;
int64 started_at = 3;
int64 ended_at = 4;
int64 updated_at = 5;
}
// from Worker to Server
message WorkerMessage {
oneof message {
// agent workers need to register themselves with the server first
RegisterWorkerRequest register = 1;
// worker confirms to server that it's available for a job, or declines it
AvailabilityResponse availability = 2;
// worker can update its status to the server, including taking itself out of the pool
UpdateWorkerStatus update_worker = 3;
// job can send status updates to the server, useful for tracking progress
UpdateJobStatus update_job = 4;
WorkerPing ping = 5;
SimulateJobRequest simulate_job = 6;
MigrateJobRequest migrate_job = 7;
};
}
// from Server to Worker
message ServerMessage {
oneof message {
// server confirms the registration, from this moment on, the worker is considered active
RegisterWorkerResponse register = 1;
// server asks worker to confirm availability for a job
AvailabilityRequest availability = 2;
JobAssignment assignment = 3;
JobTermination termination = 5;
WorkerPong pong = 4;
}
}
enum JobType {
JT_ROOM = 0;
JT_PUBLISHER = 1;
}
enum WorkerStatus {
WS_AVAILABLE = 0;
WS_FULL = 1;
}
enum JobStatus {
JS_PENDING = 0;
JS_RUNNING = 1;
JS_SUCCESS = 2;
JS_FAILED = 3;
}
message SimulateJobRequest {
JobType type = 1;
Room room = 2;
ParticipantInfo participant = 3;
}
message WorkerPing {
int64 timestamp = 1;
}
message WorkerPong {
int64 last_timestamp = 1;
int64 timestamp = 2;
}
message RegisterWorkerRequest {
JobType type = 1;
//string worker_id = 2;
string version = 3;
string name = 4;
uint32 ping_interval = 5;
optional string namespace = 6;
ParticipantPermission allowed_permissions = 7;
}
message RegisterWorkerResponse {
string worker_id = 1;
ServerInfo server_info = 3;
}
message MigrateJobRequest {
// string job_id = 1 [deprecated = true];
repeated string job_ids = 2;
}
message AvailabilityRequest {
Job job = 1;
// True when the job was previously assigned to another worker but has been
// migrated due to different reasons (e.g. worker failure, job migration)
bool resuming = 2;
}
message AvailabilityResponse {
string job_id = 1;
bool available = 2;
bool supports_resume = 3;
string participant_name = 4;
string participant_identity = 5;
string participant_metadata = 6;
}
message UpdateJobStatus {
string job_id = 1;
// The worker can indicate the job end by either specifying SUCCESS or FAILED
JobStatus status = 2;
// metadata shown on the dashboard, useful for debugging
string error = 3;
// the metadata can be updated multiple times
// optional string metadata = 4 [deprecated=true];
}
message UpdateWorkerStatus {
optional WorkerStatus status = 1;
// optional string metadata = 2 [deprecated=true];
float load = 3;
int32 job_count = 4;
}
message JobAssignment {
Job job = 1;
optional string url = 2;
string token = 3;
}
message JobTermination {
string job_id = 1;
}

View File

@@ -0,0 +1,185 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "google/protobuf/timestamp.proto";
import "livekit_models.proto";
import "livekit_egress.proto";
import "livekit_ingress.proto";
enum StreamType {
UPSTREAM = 0;
DOWNSTREAM = 1;
}
message AnalyticsVideoLayer {
int32 layer = 1;
uint32 packets = 2;
uint64 bytes = 3;
uint32 frames = 4;
}
message AnalyticsStream {
uint32 ssrc = 1;
uint32 primary_packets = 2;
uint64 primary_bytes = 3;
uint32 retransmit_packets = 4;
uint64 retransmit_bytes = 5;
uint32 padding_packets = 6;
uint64 padding_bytes = 7;
uint32 packets_lost = 8;
uint32 frames = 9;
uint32 rtt = 10;
uint32 jitter = 11;
uint32 nacks = 12;
uint32 plis = 13;
uint32 firs = 14;
repeated AnalyticsVideoLayer video_layers = 15;
google.protobuf.Timestamp start_time = 17;
google.protobuf.Timestamp end_time = 18;
}
message AnalyticsStat {
// unique id for this stat
string id = 14;
string analytics_key = 1;
StreamType kind = 2;
google.protobuf.Timestamp time_stamp = 3;
string node = 4;
string room_id = 5;
string room_name = 6;
string participant_id = 7;
string track_id = 8;
float score = 9; // average score
repeated AnalyticsStream streams = 10;
string mime = 11;
float min_score = 12;
float median_score = 13;
// NEXT_ID: 15
}
message AnalyticsStats {
repeated AnalyticsStat stats = 1;
}
enum AnalyticsEventType {
ROOM_CREATED = 0;
ROOM_ENDED = 1;
PARTICIPANT_JOINED = 2;
PARTICIPANT_LEFT = 3;
TRACK_PUBLISHED = 4;
TRACK_PUBLISH_REQUESTED = 20;
TRACK_UNPUBLISHED = 5;
TRACK_SUBSCRIBED = 6;
TRACK_SUBSCRIBE_REQUESTED = 21;
TRACK_SUBSCRIBE_FAILED = 25;
TRACK_UNSUBSCRIBED = 7;
TRACK_PUBLISHED_UPDATE = 10;
TRACK_MUTED = 23;
TRACK_UNMUTED = 24;
TRACK_PUBLISH_STATS = 26;
TRACK_SUBSCRIBE_STATS = 27;
PARTICIPANT_ACTIVE = 11;
PARTICIPANT_RESUMED = 22;
EGRESS_STARTED = 12;
EGRESS_ENDED = 13;
EGRESS_UPDATED = 28;
TRACK_MAX_SUBSCRIBED_VIDEO_QUALITY = 14;
RECONNECTED = 15;
INGRESS_CREATED = 18;
INGRESS_DELETED = 19;
INGRESS_STARTED = 16;
INGRESS_ENDED = 17;
INGRESS_UPDATED = 29;
// NEXT_ID: 30
}
message AnalyticsClientMeta {
string region = 1;
string node = 2;
string client_addr = 3;
uint32 client_connect_time = 4;
// udp, tcp, turn
string connection_type = 5;
ReconnectReason reconnect_reason = 6;
optional string geo_hash = 7;
optional string country = 8;
optional uint32 isp_asn = 9;
}
message AnalyticsEvent {
// unique id for this event
string id = 25;
AnalyticsEventType type = 1;
google.protobuf.Timestamp timestamp = 2;
string room_id = 3;
Room room = 4;
string participant_id = 5;
ParticipantInfo participant = 6;
string track_id = 7;
TrackInfo track = 8;
string analytics_key = 10;
ClientInfo client_info = 11;
AnalyticsClientMeta client_meta = 12;
string egress_id = 13;
string ingress_id = 19;
VideoQuality max_subscribed_video_quality = 14;
ParticipantInfo publisher = 15;
string mime = 16;
EgressInfo egress = 17;
IngressInfo ingress = 18;
string error = 20;
RTPStats rtp_stats = 21;
int32 video_layer = 22;
string node_id = 24;
// NEXT_ID: 26
}
message AnalyticsEvents {
repeated AnalyticsEvent events = 1;
}
message AnalyticsRoomParticipant {
string id = 1;
string identity = 2;
string name = 3;
ParticipantInfo.State state = 4;
google.protobuf.Timestamp joined_at = 5;
}
message AnalyticsRoom {
string id = 1;
string name = 2;
string project_id = 5;
google.protobuf.Timestamp created_at = 3;
repeated AnalyticsRoomParticipant participants = 4;
// NEXT_ID: 6
}
message AnalyticsNodeRooms {
string node_id = 1;
uint64 sequence_number = 2;
google.protobuf.Timestamp timestamp = 3;
repeated AnalyticsRoom rooms = 4;
}

View File

@@ -0,0 +1,419 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
import "livekit_models.proto";
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
service Egress {
// start recording or streaming a room, participant, or tracks
rpc StartRoomCompositeEgress(RoomCompositeEgressRequest) returns (EgressInfo);
rpc StartWebEgress(WebEgressRequest) returns (EgressInfo);
rpc StartParticipantEgress(ParticipantEgressRequest) returns (EgressInfo);
rpc StartTrackCompositeEgress(TrackCompositeEgressRequest) returns (EgressInfo);
rpc StartTrackEgress(TrackEgressRequest) returns (EgressInfo);
// update web composite layout
rpc UpdateLayout(UpdateLayoutRequest) returns (EgressInfo);
// add or remove stream endpoints
rpc UpdateStream(UpdateStreamRequest) returns (EgressInfo);
// list available egress
rpc ListEgress(ListEgressRequest) returns (ListEgressResponse);
// stop a recording or stream
rpc StopEgress(StopEgressRequest) returns (EgressInfo);
}
// composite using a web browser
message RoomCompositeEgressRequest {
string room_name = 1; // required
string layout = 2; // (optional)
bool audio_only = 3; // (default false)
bool video_only = 4; // (default false)
string custom_base_url = 5; // template base url (default https://recorder.livekit.io)
oneof output { // deprecated (use _output fields)
EncodedFileOutput file = 6 [deprecated = true];
StreamOutput stream = 7 [deprecated = true];
SegmentedFileOutput segments = 10 [deprecated = true];
}
oneof options {
EncodingOptionsPreset preset = 8; // (default H264_720P_30)
EncodingOptions advanced = 9; // (optional)
}
repeated EncodedFileOutput file_outputs = 11;
repeated StreamOutput stream_outputs = 12;
repeated SegmentedFileOutput segment_outputs = 13;
repeated ImageOutput image_outputs = 14;
}
// record any website
message WebEgressRequest {
string url = 1;
bool audio_only = 2;
bool video_only = 3;
bool await_start_signal = 12;
oneof output { // deprecated (use _output fields)
EncodedFileOutput file = 4 [deprecated = true];
StreamOutput stream = 5 [deprecated = true];
SegmentedFileOutput segments = 6 [deprecated = true];
}
oneof options {
EncodingOptionsPreset preset = 7;
EncodingOptions advanced = 8;
}
repeated EncodedFileOutput file_outputs = 9;
repeated StreamOutput stream_outputs = 10;
repeated SegmentedFileOutput segment_outputs = 11;
repeated ImageOutput image_outputs = 13;
}
// record audio and video from a single participant
message ParticipantEgressRequest {
string room_name = 1; // required
string identity = 2; // required
bool screen_share = 3; // (default false)
oneof options {
EncodingOptionsPreset preset = 4; // (default H264_720P_30)
EncodingOptions advanced = 5; // (optional)
}
repeated EncodedFileOutput file_outputs = 6;
repeated StreamOutput stream_outputs = 7;
repeated SegmentedFileOutput segment_outputs = 8;
repeated ImageOutput image_outputs = 9;
}
// containerize up to one audio and one video track
message TrackCompositeEgressRequest {
string room_name = 1; // required
string audio_track_id = 2; // (optional)
string video_track_id = 3; // (optional)
oneof output { // deprecated (use _output fields)
EncodedFileOutput file = 4 [deprecated = true];
StreamOutput stream = 5 [deprecated = true];
SegmentedFileOutput segments = 8 [deprecated = true];
}
oneof options {
EncodingOptionsPreset preset = 6; // (default H264_720P_30)
EncodingOptions advanced = 7; // (optional)
}
repeated EncodedFileOutput file_outputs = 11;
repeated StreamOutput stream_outputs = 12;
repeated SegmentedFileOutput segment_outputs = 13;
repeated ImageOutput image_outputs = 14;
}
// record tracks individually, without transcoding
message TrackEgressRequest {
string room_name = 1; // required
string track_id = 2; // required
oneof output { // required
DirectFileOutput file = 3;
string websocket_url = 4;
}
}
enum EncodedFileType {
DEFAULT_FILETYPE = 0; // file type chosen based on codecs
MP4 = 1;
OGG = 2;
}
message EncodedFileOutput {
EncodedFileType file_type = 1; // (optional)
string filepath = 2; // see egress docs for templating (default {room_name}-{time})
bool disable_manifest = 6; // disable upload of manifest file (default false)
oneof output {
S3Upload s3 = 3;
GCPUpload gcp = 4;
AzureBlobUpload azure = 5;
AliOSSUpload aliOSS = 7;
}
}
enum SegmentedFileProtocol {
DEFAULT_SEGMENTED_FILE_PROTOCOL = 0;
HLS_PROTOCOL = 1;
}
enum SegmentedFileSuffix {
INDEX = 0;
TIMESTAMP = 1;
}
// Used to generate HLS segments or other kind of segmented output
message SegmentedFileOutput {
SegmentedFileProtocol protocol = 1; // (optional)
string filename_prefix = 2; // (optional)
string playlist_name = 3; // (optional)
string live_playlist_name = 11; // (optional, disabled if not provided). Path of a live playlist
uint32 segment_duration = 4; // in seconds (optional)
SegmentedFileSuffix filename_suffix = 10; // (optional, default INDEX)
bool disable_manifest = 8; // disable upload of manifest file (default false)
oneof output { // required
S3Upload s3 = 5;
GCPUpload gcp = 6;
AzureBlobUpload azure = 7;
AliOSSUpload aliOSS = 9;
}
}
message DirectFileOutput {
string filepath = 1; // see egress docs for templating (default {track_id}-{time})
bool disable_manifest = 5; // disable upload of manifest file (default false)
oneof output {
S3Upload s3 = 2;
GCPUpload gcp = 3;
AzureBlobUpload azure = 4;
AliOSSUpload aliOSS = 6;
}
}
enum ImageFileSuffix {
IMAGE_SUFFIX_INDEX = 0;
IMAGE_SUFFIX_TIMESTAMP = 1;
}
message ImageOutput {
uint32 capture_interval = 1; // in seconds (required)
int32 width = 2; // (optional, defaults to track width)
int32 height = 3; // (optional, defaults to track height)
string filename_prefix = 4; // (optional)
ImageFileSuffix filename_suffix = 5; // (optional, default INDEX)
ImageCodec image_codec = 6; // (optional)
bool disable_manifest = 7; // disable upload of manifest file (default false)
oneof output { // required
S3Upload s3 = 8;
GCPUpload gcp = 9;
AzureBlobUpload azure = 10;
AliOSSUpload aliOSS = 11;
}
}
message S3Upload {
string access_key = 1;
string secret = 2;
string session_token = 11;
string region = 3;
string endpoint = 4;
string bucket = 5;
bool force_path_style = 6;
map<string, string> metadata = 7;
string tagging = 8;
string content_disposition = 9; // Content-Disposition header
ProxyConfig proxy = 10;
}
message GCPUpload {
// service account credentials serialized in JSON "credentials.json"
string credentials = 1;
string bucket = 2;
ProxyConfig proxy = 3;
}
message AzureBlobUpload {
string account_name = 1;
string account_key = 2;
string container_name = 3;
}
message AliOSSUpload {
string access_key = 1;
string secret = 2;
string region = 3;
string endpoint = 4;
string bucket = 5;
}
message ProxyConfig {
string url = 1;
string username = 2;
string password = 3;
}
enum StreamProtocol {
DEFAULT_PROTOCOL = 0; // protocol chosen based on urls
RTMP = 1;
}
message StreamOutput {
StreamProtocol protocol = 1; // required
repeated string urls = 2; // required
}
message EncodingOptions {
int32 width = 1; // (default 1920)
int32 height = 2; // (default 1080)
int32 depth = 3; // (default 24)
int32 framerate = 4; // (default 30)
AudioCodec audio_codec = 5; // (default OPUS)
int32 audio_bitrate = 6; // (default 128)
int32 audio_quality = 11; // quality setting on audio encoder
int32 audio_frequency = 7; // (default 44100)
VideoCodec video_codec = 8; // (default H264_MAIN)
int32 video_bitrate = 9; // (default 4500)
int32 video_quality = 12; // quality setting on video encoder
double key_frame_interval = 10; // in seconds (default 4s for streaming, segment duration for segmented output, encoder default for files)
}
enum EncodingOptionsPreset {
H264_720P_30 = 0; // 1280x720, 30fps, 3000kpbs, H.264_MAIN / OPUS
H264_720P_60 = 1; // 1280x720, 60fps, 4500kbps, H.264_MAIN / OPUS
H264_1080P_30 = 2; // 1920x1080, 30fps, 4500kbps, H.264_MAIN / OPUS
H264_1080P_60 = 3; // 1920x1080, 60fps, 6000kbps, H.264_MAIN / OPUS
PORTRAIT_H264_720P_30 = 4; // 720x1280, 30fps, 3000kpbs, H.264_MAIN / OPUS
PORTRAIT_H264_720P_60 = 5; // 720x1280, 60fps, 4500kbps, H.264_MAIN / OPUS
PORTRAIT_H264_1080P_30 = 6; // 1080x1920, 30fps, 4500kbps, H.264_MAIN / OPUS
PORTRAIT_H264_1080P_60 = 7; // 1080x1920, 60fps, 6000kbps, H.264_MAIN / OPUS
}
message UpdateLayoutRequest {
string egress_id = 1;
string layout = 2;
}
message UpdateStreamRequest {
string egress_id = 1;
repeated string add_output_urls = 2;
repeated string remove_output_urls = 3;
}
message ListEgressRequest {
string room_name = 1; // (optional, filter by room name)
string egress_id = 2; // (optional, filter by egress ID)
bool active = 3; // (optional, list active egress only)
}
message ListEgressResponse {
repeated EgressInfo items = 1;
}
message StopEgressRequest {
string egress_id = 1;
}
enum EgressStatus {
EGRESS_STARTING = 0;
EGRESS_ACTIVE = 1;
EGRESS_ENDING = 2;
EGRESS_COMPLETE = 3;
EGRESS_FAILED = 4;
EGRESS_ABORTED = 5;
EGRESS_LIMIT_REACHED = 6;
}
message EgressInfo {
string egress_id = 1;
string room_id = 2;
string room_name = 13;
EgressStatus status = 3;
int64 started_at = 10;
int64 ended_at = 11;
int64 updated_at = 18;
string details = 21;
string error = 9;
int32 error_code = 22;
oneof request {
RoomCompositeEgressRequest room_composite = 4;
WebEgressRequest web = 14;
ParticipantEgressRequest participant = 19;
TrackCompositeEgressRequest track_composite = 5;
TrackEgressRequest track = 6;
}
oneof result { // deprecated (use _result fields)
StreamInfoList stream = 7 [deprecated = true];
FileInfo file = 8 [deprecated = true];
SegmentsInfo segments = 12 [deprecated = true];
}
repeated StreamInfo stream_results = 15;
repeated FileInfo file_results = 16;
repeated SegmentsInfo segment_results = 17;
repeated ImagesInfo image_results = 20;
// next ID: 23
}
message StreamInfoList {
option deprecated = true;
repeated StreamInfo info = 1;
}
message StreamInfo {
enum Status {
ACTIVE = 0;
FINISHED = 1;
FAILED = 2;
}
string url = 1;
int64 started_at = 2;
int64 ended_at = 3;
int64 duration = 4;
Status status = 5;
string error = 6;
}
message FileInfo {
string filename = 1;
int64 started_at = 2;
int64 ended_at = 3;
int64 duration = 6;
int64 size = 4;
string location = 5;
}
message SegmentsInfo {
string playlist_name = 1;
string live_playlist_name = 8;
int64 duration = 2;
int64 size = 3;
string playlist_location = 4;
string live_playlist_location = 9;
int64 segment_count = 5;
int64 started_at = 6;
int64 ended_at = 7;
}
message ImagesInfo {
int64 image_count = 1;
int64 started_at = 2;
int64 ended_at = 3;
}
message AutoParticipantEgress {
oneof options {
EncodingOptionsPreset preset = 1; // (default H264_720P_30)
EncodingOptions advanced = 2; // (optional)
}
repeated EncodedFileOutput file_outputs = 3;
repeated SegmentedFileOutput segment_outputs = 4;
}
message AutoTrackEgress {
string filepath = 1; // see docs for templating (default {track_id}-{time})
bool disable_manifest = 5; // disables upload of json manifest file (default false)
oneof output {
S3Upload s3 = 2;
GCPUpload gcp = 3;
AzureBlobUpload azure = 4;
AliOSSUpload aliOSS = 6;
}
}

View File

@@ -0,0 +1,206 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
import "livekit_models.proto";
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
service Ingress {
// Create a new Ingress
rpc CreateIngress(CreateIngressRequest) returns (IngressInfo);
// Update an existing Ingress. Ingress can only be updated when it's in ENDPOINT_WAITING state.
rpc UpdateIngress(UpdateIngressRequest) returns (IngressInfo);
rpc ListIngress(ListIngressRequest) returns (ListIngressResponse);
rpc DeleteIngress(DeleteIngressRequest) returns (IngressInfo);
}
message CreateIngressRequest {
IngressInput input_type = 1;
// Where to pull media from, only for URL input type
string url = 9;
// User provided identifier for the ingress
string name = 2;
// room to publish to
string room_name = 3;
// publish as participant
string participant_identity = 4;
// name of publishing participant (used for display only)
string participant_name = 5;
// metadata associated with the publishing participant
string participant_metadata = 10;
// [depreacted ] whether to pass through the incoming media without transcoding, only compatible with some input types. Use `enable_transcoding` instead.
bool bypass_transcoding = 8 [deprecated = true];
// Whether to transcode the ingested media. Only WHIP supports disabling transcoding currently. WHIP will default to transcoding disabled. Replaces `bypass_transcoding.
optional bool enable_transcoding = 11;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
// NEXT_ID: 12
}
enum IngressInput {
RTMP_INPUT = 0;
WHIP_INPUT = 1;
URL_INPUT = 2; // Pull from the provided URL. Only HTTP url are supported, serving either a single media file or a HLS stream
// FILE_INPUT = 3;
// SRT_INPUT = 4;
}
message IngressAudioOptions {
string name = 1;
TrackSource source = 2;
oneof encoding_options {
IngressAudioEncodingPreset preset = 3;
IngressAudioEncodingOptions options = 4;
}
}
message IngressVideoOptions {
string name = 1;
TrackSource source = 2;
oneof encoding_options {
IngressVideoEncodingPreset preset = 3;
IngressVideoEncodingOptions options = 4;
}
}
enum IngressAudioEncodingPreset {
OPUS_STEREO_96KBPS = 0; // OPUS, 2 channels, 96kbps
OPUS_MONO_64KBS = 1; // OPUS, 1 channel, 64kbps
}
enum IngressVideoEncodingPreset {
H264_720P_30FPS_3_LAYERS = 0; // 1280x720, 30fps, 1900kbps main layer, 3 layers total
H264_1080P_30FPS_3_LAYERS = 1; // 1980x1080, 30fps, 3500kbps main layer, 3 layers total
H264_540P_25FPS_2_LAYERS = 2; // 960x540, 25fps, 1000kbps main layer, 2 layers total
H264_720P_30FPS_1_LAYER = 3; // 1280x720, 30fps, 1900kbps, no simulcast
H264_1080P_30FPS_1_LAYER = 4; // 1980x1080, 30fps, 3500kbps, no simulcast
H264_720P_30FPS_3_LAYERS_HIGH_MOTION = 5; // 1280x720, 30fps, 2500kbps main layer, 3 layers total, higher bitrate for high motion, harder to encode content
H264_1080P_30FPS_3_LAYERS_HIGH_MOTION = 6; // 1980x1080, 30fps, 4500kbps main layer, 3 layers total, higher bitrate for high motion, harder to encode content
H264_540P_25FPS_2_LAYERS_HIGH_MOTION = 7; // 960x540, 25fps, 1300kbps main layer, 2 layers total, higher bitrate for high motion, harder to encode content
H264_720P_30FPS_1_LAYER_HIGH_MOTION = 8; // 1280x720, 30fps, 2500kbps, no simulcast, higher bitrate for high motion, harder to encode content
H264_1080P_30FPS_1_LAYER_HIGH_MOTION = 9; // 1980x1080, 30fps, 4500kbps, no simulcast, higher bitrate for high motion, harder to encode content
}
message IngressAudioEncodingOptions {
// desired audio codec to publish to room
AudioCodec audio_codec = 1;
uint32 bitrate = 2;
bool disable_dtx = 3;
uint32 channels = 4;
}
message IngressVideoEncodingOptions {
// desired codec to publish to room
VideoCodec video_codec = 1;
double frame_rate = 2;
// simulcast layers to publish, when empty, should usually be set to layers at 1/2 and 1/4 of the dimensions
repeated VideoLayer layers = 3;
}
message IngressInfo {
string ingress_id = 1;
string name = 2;
string stream_key = 3;
string url = 4; // URL to point the encoder to for push (RTMP, WHIP), or location to pull media from for pull (URL)
// for RTMP input, it'll be a rtmp:// URL
// for FILE input, it'll be a http:// URL
// for SRT input, it'll be a srt:// URL
IngressInput input_type = 5;
bool bypass_transcoding = 13 [deprecated = true];
optional bool enable_transcoding = 15;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
string room_name = 8;
string participant_identity = 9;
string participant_name = 10;
string participant_metadata = 14;
bool reusable = 11;
IngressState state = 12; // Description of error/stream non compliance and debug info for publisher otherwise (received bitrate, resolution, bandwidth)
// NEXT_ID: 16
}
message IngressState {
enum Status {
ENDPOINT_INACTIVE = 0;
ENDPOINT_BUFFERING = 1;
ENDPOINT_PUBLISHING = 2;
ENDPOINT_ERROR = 3;
ENDPOINT_COMPLETE = 4;
}
Status status = 1;
string error = 2; // Error/non compliance description if any
InputVideoState video = 3;
InputAudioState audio = 4;
string room_id = 5; // ID of the current/previous room published to
int64 started_at = 7;
int64 ended_at = 8;
int64 updated_at = 10;
string resource_id = 9;
repeated TrackInfo tracks = 6;
// next ID: 11
}
message InputVideoState {
string mime_type = 1;
uint32 average_bitrate = 2;
uint32 width = 3;
uint32 height = 4;
double framerate = 5;
}
message InputAudioState {
string mime_type = 1;
uint32 average_bitrate = 2;
uint32 channels = 3;
uint32 sample_rate = 4;
}
message UpdateIngressRequest {
string ingress_id = 1;
string name = 2;
string room_name = 3;
string participant_identity = 4;
string participant_name = 5;
string participant_metadata = 9;
optional bool bypass_transcoding = 8 [deprecated = true];
optional bool enable_transcoding = 10;
IngressAudioOptions audio = 6;
IngressVideoOptions video = 7;
// NEXT_ID: 11
}
message ListIngressRequest {
// when blank, lists all ingress endpoints
string room_name = 1; // (optional, filter by room name)
string ingress_id = 2; // (optional, filter by ingress ID)
}
message ListIngressResponse {
repeated IngressInfo items = 1;
}
message DeleteIngressRequest {
string ingress_id = 1;
}

View File

@@ -0,0 +1,158 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
// internal protos, not exposed to clients
import "livekit_models.proto";
import "livekit_egress.proto";
import "livekit_agent.proto";
enum NodeType {
SERVER = 0;
CONTROLLER = 1;
MEDIA = 2;
TURN = 4;
SWEEPER = 5;
DIRECTOR = 6;
}
enum NodeState {
STARTING_UP = 0;
SERVING = 1;
SHUTTING_DOWN = 2;
}
message Node {
string id = 1;
string ip = 2;
uint32 num_cpus = 3;
NodeStats stats = 4;
NodeType type = 5;
NodeState state = 6;
string region = 7;
}
message NodeStats {
// when server was started
int64 started_at = 1;
// when server last reported its status
int64 updated_at = 2;
// room
int32 num_rooms = 3;
int32 num_clients = 4;
int32 num_tracks_in = 5;
int32 num_tracks_out = 6;
int32 num_track_publish_attempts = 36;
float track_publish_attempts_per_sec = 37;
int32 num_track_publish_success = 38;
float track_publish_success_per_sec = 39;
int32 num_track_subscribe_attempts = 40;
float track_subscribe_attempts_per_sec = 41;
int32 num_track_subscribe_success = 42;
float track_subscribe_success_per_sec = 43;
// packet
uint64 bytes_in = 7;
uint64 bytes_out = 8;
uint64 packets_in = 9;
uint64 packets_out = 10;
uint64 nack_total = 11;
float bytes_in_per_sec = 12;
float bytes_out_per_sec = 13;
float packets_in_per_sec = 14;
float packets_out_per_sec = 15;
float nack_per_sec = 16;
// system
uint32 num_cpus = 17;
float load_avg_last1min = 18;
float load_avg_last5min = 19;
float load_avg_last15min = 20;
float cpu_load = 21;
float memory_load = 33; // deprecated
uint64 memory_total = 34;
uint64 memory_used = 35;
uint32 sys_packets_out = 28;
uint32 sys_packets_dropped = 29;
float sys_packets_out_per_sec = 30;
float sys_packets_dropped_per_sec = 31;
float sys_packets_dropped_pct_per_sec = 32;
// retransmissions
uint64 retransmit_bytes_out = 22;
uint64 retransmit_packets_out = 23;
float retransmit_bytes_out_per_sec = 24;
float retransmit_packets_out_per_sec = 25;
// participant joins
uint64 participant_signal_connected = 26;
float participant_signal_connected_per_sec = 27;
uint64 participant_rtc_connected = 44;
float participant_rtc_connected_per_sec = 45;
uint64 participant_rtc_init = 46;
float participant_rtc_init_per_sec = 47;
// forward metrics
uint32 forward_latency = 48;
uint32 forward_jitter = 49;
// NEXT ID: 50
}
message StartSession {
string room_name = 1;
string identity = 2;
string connection_id = 3;
// if a client is reconnecting (i.e. resume instead of restart)
bool reconnect = 4;
bool auto_subscribe = 9;
bool hidden = 10;
ClientInfo client = 11;
bool recorder = 12;
string name = 13;
// A user's ClaimGrants serialized in JSON
string grants_json = 14;
bool adaptive_stream = 15;
//if reconnect, client will set current sid
string participant_id = 16;
ReconnectReason reconnect_reason = 17;
optional bool subscriber_allow_pause = 18;
}
// room info that should not be returned to clients
message RoomInternal {
AutoTrackEgress track_egress = 1;
AutoParticipantEgress participant_egress = 2;
PlayoutDelay playout_delay = 3;
repeated CreateAgentJobDefinitionRequest agents = 5;
bool sync_streams = 4;
}
enum ICECandidateType {
ICT_NONE = 0;
ICT_TCP = 1;
ICT_TLS = 2;
}
message ICEConfig {
ICECandidateType preference_subscriber = 1;
ICECandidateType preference_publisher = 2;
}

View File

@@ -0,0 +1,493 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "google/protobuf/timestamp.proto";
message Room {
string sid = 1;
string name = 2;
uint32 empty_timeout = 3;
uint32 departure_timeout = 14;
uint32 max_participants = 4;
int64 creation_time = 5;
string turn_password = 6;
repeated Codec enabled_codecs = 7;
string metadata = 8;
uint32 num_participants = 9;
uint32 num_publishers = 11;
bool active_recording = 10;
TimedVersion version = 13;
// NEXT-ID: 15
}
message Codec {
string mime = 1;
string fmtp_line = 2;
}
enum AudioCodec {
DEFAULT_AC = 0;
OPUS = 1;
AAC = 2;
}
enum VideoCodec {
DEFAULT_VC = 0;
H264_BASELINE = 1;
H264_MAIN = 2;
H264_HIGH = 3;
VP8 = 4;
}
enum ImageCodec {
IC_DEFAULT = 0;
IC_JPEG = 1;
}
message PlayoutDelay {
bool enabled = 1;
uint32 min = 2;
uint32 max = 3;
}
message ParticipantPermission {
// allow participant to subscribe to other tracks in the room
bool can_subscribe = 1;
// allow participant to publish new tracks to room
bool can_publish = 2;
// allow participant to publish data
bool can_publish_data = 3;
// sources that are allowed to be published
repeated TrackSource can_publish_sources = 9;
// indicates that it's hidden to others
bool hidden = 7;
// indicates it's a recorder instance
// deprecated: use ParticipantInfo.kind instead
bool recorder = 8 [deprecated=true];
// indicates that participant can update own metadata and attributes
bool can_update_metadata = 10;
// indicates that participant is an agent
// deprecated: use ParticipantInfo.kind instead
bool agent = 11 [deprecated=true];
// NEXT_ID: 12
}
message ParticipantInfo {
enum State {
// websocket' connected, but not offered yet
JOINING = 0;
// server received client offer
JOINED = 1;
// ICE connectivity established
ACTIVE = 2;
// WS disconnected
DISCONNECTED = 3;
}
enum Kind {
// standard participants, e.g. web clients
STANDARD = 0;
// only ingests streams
INGRESS = 1;
// only consumes streams
EGRESS = 2;
// SIP participants
SIP = 3;
// LiveKit agents
AGENT = 4;
}
string sid = 1;
string identity = 2;
State state = 3;
repeated TrackInfo tracks = 4;
string metadata = 5;
// timestamp when participant joined room, in seconds
int64 joined_at = 6;
string name = 9;
uint32 version = 10;
ParticipantPermission permission = 11;
string region = 12;
// indicates the participant has an active publisher connection
// and can publish to the server
bool is_publisher = 13;
Kind kind = 14;
map<string, string> attributes = 15;
}
enum TrackType {
AUDIO = 0;
VIDEO = 1;
DATA = 2;
}
enum TrackSource {
UNKNOWN = 0;
CAMERA = 1;
MICROPHONE = 2;
SCREEN_SHARE = 3;
SCREEN_SHARE_AUDIO = 4;
}
message Encryption {
enum Type {
NONE=0;
GCM=1;
CUSTOM=2;
}
}
message SimulcastCodecInfo {
string mime_type = 1;
string mid = 2;
string cid = 3;
repeated VideoLayer layers = 4;
}
message TrackInfo {
string sid = 1;
TrackType type = 2;
string name = 3;
bool muted = 4;
// original width of video (unset for audio)
// clients may receive a lower resolution version with simulcast
uint32 width = 5;
// original height of video (unset for audio)
uint32 height = 6;
// true if track is simulcasted
bool simulcast = 7;
// true if DTX (Discontinuous Transmission) is disabled for audio
bool disable_dtx = 8;
// source of media
TrackSource source = 9;
repeated VideoLayer layers = 10;
// mime type of codec
string mime_type = 11;
string mid = 12;
repeated SimulcastCodecInfo codecs = 13;
bool stereo = 14;
// true if RED (Redundant Encoding) is disabled for audio
bool disable_red = 15;
Encryption.Type encryption = 16;
string stream = 17;
TimedVersion version = 18;
repeated AudioTrackFeature audio_features = 19;
}
enum VideoQuality {
LOW = 0;
MEDIUM = 1;
HIGH = 2;
OFF = 3;
}
// provide information about available spatial layers
message VideoLayer {
// for tracks with a single layer, this should be HIGH
VideoQuality quality = 1;
uint32 width = 2;
uint32 height = 3;
// target bitrate in bit per second (bps), server will measure actual
uint32 bitrate = 4;
uint32 ssrc = 5;
}
// new DataPacket API
message DataPacket {
enum Kind {
RELIABLE = 0;
LOSSY = 1;
}
Kind kind = 1 [deprecated=true];
// participant identity of user that sent the message
string participant_identity = 4;
// identities of participants who will receive the message (sent to all by default)
repeated string destination_identities = 5;
oneof value {
UserPacket user = 2;
ActiveSpeakerUpdate speaker = 3 [deprecated=true];
SipDTMF sip_dtmf = 6;
Transcription transcription = 7;
}
// NEXT_ID: 8
}
message ActiveSpeakerUpdate {
repeated SpeakerInfo speakers = 1;
}
message SpeakerInfo {
string sid = 1;
// audio level, 0-1.0, 1 is loudest
float level = 2;
// true if speaker is currently active
bool active = 3;
}
message UserPacket {
// participant ID of user that sent the message
string participant_sid = 1 [deprecated=true];
string participant_identity = 5 [deprecated=true];
// user defined payload
bytes payload = 2;
// the ID of the participants who will receive the message (sent to all by default)
repeated string destination_sids = 3 [deprecated=true];
// identities of participants who will receive the message (sent to all by default)
repeated string destination_identities = 6 [deprecated=true];
// topic under which the message was published
optional string topic = 4;
// Unique ID to indentify the message
optional string id = 8;
// start and end time allow relating the message to specific media time
optional uint64 start_time = 9;
optional uint64 end_time = 10;
// NEXT_ID: 11
}
message SipDTMF {
uint32 code = 3;
string digit = 4;
}
message Transcription {
// Participant that got its speech transcribed
string transcribed_participant_identity = 2;
string track_id = 3;
repeated TranscriptionSegment segments = 4;
// NEXT_ID: 6
}
message TranscriptionSegment {
string id = 1;
string text = 2;
uint64 start_time = 3;
uint64 end_time = 4;
bool final = 5;
string language = 6;
}
enum ConnectionQuality {
POOR = 0;
GOOD = 1;
EXCELLENT = 2;
LOST = 3;
}
message ParticipantTracks {
// participant ID of participant to whom the tracks belong
string participant_sid = 1;
repeated string track_sids = 2;
}
// details about the server
message ServerInfo {
enum Edition {
Standard = 0;
Cloud = 1;
}
Edition edition = 1;
string version = 2;
int32 protocol = 3;
string region = 4;
string node_id = 5;
// additional debugging information. sent only if server is in development mode
string debug_info = 6;
int32 agent_protocol = 7;
}
// details about the client
message ClientInfo {
enum SDK {
UNKNOWN = 0;
JS = 1;
SWIFT = 2;
ANDROID = 3;
FLUTTER = 4;
GO = 5;
UNITY = 6;
REACT_NATIVE = 7;
RUST = 8;
PYTHON = 9;
CPP = 10;
}
SDK sdk = 1;
string version = 2;
int32 protocol = 3;
string os = 4;
string os_version = 5;
string device_model = 6;
string browser = 7;
string browser_version = 8;
string address = 9;
// wifi, wired, cellular, vpn, empty if not known
string network = 10;
}
// server provided client configuration
message ClientConfiguration {
VideoConfiguration video = 1;
VideoConfiguration screen = 2;
ClientConfigSetting resume_connection = 3;
DisabledCodecs disabled_codecs = 4;
ClientConfigSetting force_relay = 5;
}
enum ClientConfigSetting {
UNSET = 0;
DISABLED = 1;
ENABLED = 2;
}
message VideoConfiguration {
ClientConfigSetting hardware_encoder = 1;
}
message DisabledCodecs {
// disabled for both publish and subscribe
repeated Codec codecs = 1;
// only disable for publish
repeated Codec publish = 2;
}
enum DisconnectReason {
UNKNOWN_REASON = 0;
CLIENT_INITIATED = 1;
DUPLICATE_IDENTITY = 2;
SERVER_SHUTDOWN = 3;
PARTICIPANT_REMOVED = 4;
ROOM_DELETED = 5;
STATE_MISMATCH = 6;
JOIN_FAILURE = 7;
MIGRATION = 8;
SIGNAL_CLOSE = 9;
}
message RTPDrift {
google.protobuf.Timestamp start_time = 1;
google.protobuf.Timestamp end_time = 2;
double duration = 3;
uint64 start_timestamp = 4;
uint64 end_timestamp = 5;
uint64 rtp_clock_ticks = 6;
int64 drift_samples = 7;
double drift_ms = 8;
double clock_rate = 9;
}
message RTPStats {
google.protobuf.Timestamp start_time = 1;
google.protobuf.Timestamp end_time = 2;
double duration = 3;
uint32 packets = 4;
double packet_rate = 5;
uint64 bytes = 6;
uint64 header_bytes = 39;
double bitrate = 7;
uint32 packets_lost = 8;
double packet_loss_rate = 9;
float packet_loss_percentage = 10;
uint32 packets_duplicate = 11;
double packet_duplicate_rate = 12;
uint64 bytes_duplicate = 13;
uint64 header_bytes_duplicate = 40;
double bitrate_duplicate = 14;
uint32 packets_padding = 15;
double packet_padding_rate = 16;
uint64 bytes_padding = 17;
uint64 header_bytes_padding = 41;
double bitrate_padding = 18;
uint32 packets_out_of_order = 19;
uint32 frames = 20;
double frame_rate = 21;
double jitter_current = 22;
double jitter_max = 23;
map<int32, uint32> gap_histogram = 24;
uint32 nacks = 25;
uint32 nack_acks = 37;
uint32 nack_misses = 26;
uint32 nack_repeated = 38;
uint32 plis = 27;
google.protobuf.Timestamp last_pli = 28;
uint32 firs = 29;
google.protobuf.Timestamp last_fir = 30;
uint32 rtt_current = 31;
uint32 rtt_max = 32;
uint32 key_frames = 33;
google.protobuf.Timestamp last_key_frame = 34;
uint32 layer_lock_plis = 35;
google.protobuf.Timestamp last_layer_lock_pli = 36;
RTPDrift packet_drift = 44;
RTPDrift report_drift = 45;
RTPDrift rebased_report_drift = 46;
// NEXT_ID: 47
}
message TimedVersion {
int64 unix_micro = 1;
int32 ticks = 2;
}
enum ReconnectReason {
RR_UNKNOWN = 0;
RR_SIGNAL_DISCONNECTED = 1;
RR_PUBLISHER_FAILED = 2;
RR_SUBSCRIBER_FAILED = 3;
RR_SWITCH_CANDIDATE = 4;
}
enum SubscriptionError {
SE_UNKNOWN = 0;
SE_CODEC_UNSUPPORTED = 1;
SE_TRACK_NOTFOUND = 2;
}
enum AudioTrackFeature {
TF_STEREO = 0;
TF_NO_DTX = 1;
TF_AUTO_GAIN_CONTROL = 2;
TF_ECHO_CANCELLATION = 3;
TF_NOISE_SUPPRESSION = 4;
TF_ENHANCED_NOISE_CANCELLATION = 5;
}

View File

@@ -0,0 +1,226 @@
// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package livekit;
option go_package = "github.com/livekit/protocol/livekit";
option csharp_namespace = "LiveKit.Proto";
option ruby_package = "LiveKit::Proto";
import "livekit_models.proto";
import "livekit_egress.proto";
import "livekit_agent.proto";
// Room service that can be performed on any node
// they are Twirp-based HTTP req/responses
service RoomService {
// Creates a room with settings. Requires `roomCreate` permission.
// This method is optional; rooms are automatically created when clients connect to them for the first time.
rpc CreateRoom(CreateRoomRequest) returns (Room);
// List rooms that are active on the server. Requires `roomList` permission.
rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse);
// Deletes an existing room by name or id. Requires `roomCreate` permission.
// DeleteRoom will disconnect all participants that are currently in the room.
rpc DeleteRoom(DeleteRoomRequest) returns (DeleteRoomResponse);
// Lists participants in a room, Requires `roomAdmin`
rpc ListParticipants(ListParticipantsRequest) returns (ListParticipantsResponse);
// Get information on a specific participant, Requires `roomAdmin`
rpc GetParticipant(RoomParticipantIdentity) returns (ParticipantInfo);
// Removes a participant from room. Requires `roomAdmin`
rpc RemoveParticipant(RoomParticipantIdentity) returns (RemoveParticipantResponse);
// Mute/unmute a participant's track, Requires `roomAdmin`
rpc MutePublishedTrack(MuteRoomTrackRequest) returns (MuteRoomTrackResponse);
// Update participant metadata, will cause updates to be broadcasted to everyone in the room. Requires `roomAdmin`
rpc UpdateParticipant(UpdateParticipantRequest) returns (ParticipantInfo);
// Subscribes or unsubscribe a participant from tracks. Requires `roomAdmin`
rpc UpdateSubscriptions(UpdateSubscriptionsRequest) returns (UpdateSubscriptionsResponse);
// Send data over data channel to participants in a room, Requires `roomAdmin`
rpc SendData(SendDataRequest) returns (SendDataResponse);
// Update room metadata, will cause updates to be broadcasted to everyone in the room, Requires `roomAdmin`
rpc UpdateRoomMetadata (UpdateRoomMetadataRequest) returns (Room);
}
message CreateRoomRequest {
// name of the room
string name = 1;
// configuration to use for this room parameters. Setting parameters below override the config defaults.
string config_name = 12;
// number of seconds to keep the room open if no one joins
uint32 empty_timeout = 2;
// number of seconds to keep the room open after everyone leaves
uint32 departure_timeout = 10;
// limit number of participants that can be in a room
uint32 max_participants = 3;
// override the node room is allocated to, for debugging
string node_id = 4;
// metadata of room
string metadata = 5;
// egress
RoomEgress egress = 6;
// agent
RoomAgent agent = 11;
// playout delay of subscriber
uint32 min_playout_delay = 7;
uint32 max_playout_delay = 8;
// improves A/V sync when playout_delay set to a value larger than 200ms. It will disables transceiver re-use
// so not recommended for rooms with frequent subscription changes
bool sync_streams = 9;
// NEXT-ID: 13
}
message RoomEgress {
RoomCompositeEgressRequest room = 1;
AutoParticipantEgress participant = 3;
AutoTrackEgress tracks = 2;
}
message RoomAgent {
repeated CreateAgentJobDefinitionRequest agents = 1;
}
message ListRoomsRequest {
// when set, will only return rooms with name match
repeated string names = 1;
}
message ListRoomsResponse {
repeated Room rooms = 1;
}
message DeleteRoomRequest {
// name of the room
string room = 1;
}
message DeleteRoomResponse {
}
message ListParticipantsRequest {
// name of the room
string room = 1;
}
message ListParticipantsResponse {
repeated ParticipantInfo participants = 1;
}
message RoomParticipantIdentity {
// name of the room
string room = 1;
// identity of the participant
string identity = 2;
}
message RemoveParticipantResponse {
}
message MuteRoomTrackRequest {
// name of the room
string room = 1;
string identity = 2;
// sid of the track to mute
string track_sid = 3;
// set to true to mute, false to unmute
bool muted = 4;
}
message MuteRoomTrackResponse {
TrackInfo track = 1;
}
message UpdateParticipantRequest {
string room = 1;
string identity = 2;
// metadata to update. skipping updates if left empty
string metadata = 3;
// set to update the participant's permissions
ParticipantPermission permission = 4;
// display name to update
string name = 5;
// attributes to update. it only updates attributes that have been set
// to delete attributes, set the value to an empty string
map<string, string> attributes = 6;
}
message UpdateSubscriptionsRequest {
string room = 1;
string identity = 2;
// list of sids of tracks
repeated string track_sids = 3;
// set to true to subscribe, false to unsubscribe from tracks
bool subscribe = 4;
// list of participants and their tracks
repeated ParticipantTracks participant_tracks = 5;
}
message UpdateSubscriptionsResponse {
// empty for now
}
message SendDataRequest {
string room = 1;
bytes data = 2;
DataPacket.Kind kind = 3;
// mark deprecated
repeated string destination_sids = 4 [deprecated=true];
// when set, only forward to these identities
repeated string destination_identities = 6;
optional string topic = 5;
// NEXT_ID: 7
}
message SendDataResponse {
//
}
message UpdateRoomMetadataRequest {
string room = 1;
// metadata to update. skipping updates if left empty
string metadata = 2;
}
message RoomConfiguration {
string name = 1; // Used as ID, must be unique
// number of seconds to keep the room open if no one joins
uint32 empty_timeout = 2;
// number of seconds to keep the room open after everyone leaves
uint32 departure_timeout = 3;
// limit number of participants that can be in a room
uint32 max_participants = 4;
// egress
RoomEgress egress = 5;
// agent
RoomAgent agent = 6;
// playout delay of subscriber
uint32 min_playout_delay = 7;
uint32 max_playout_delay = 8;
// improves A/V sync when playout_delay set to a value larger than 200ms. It will disables transceiver re-use
// so not recommended for rooms with frequent subscription changes
bool sync_streams = 9;
}

Some files were not shown because too many files have changed in this diff Show More