Skip to content

Commit

Permalink
Merge branch 'main' into mk/pnpm-up
Browse files Browse the repository at this point in the history
  • Loading branch information
matkam committed Nov 12, 2024
2 parents 6515586 + 391b78f commit 628a628
Show file tree
Hide file tree
Showing 103 changed files with 7,986 additions and 8,270 deletions.
6 changes: 6 additions & 0 deletions .changeset/mean-glasses-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@livekit/protocol": minor
"github.com/livekit/protocol": minor
---

Add disconnect reason for SIP failures.
5 changes: 5 additions & 0 deletions .changeset/unlucky-apples-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"github.com/livekit/protocol": patch
---

Annotate SIP errors with Twirp codes.
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
# github.com/livekit/protocol

## 1.27.1

### Patch Changes

- Add extra fields to SIP analytics events - [#872](https://github.com/livekit/protocol/pull/872) ([@biglittlebigben](https://github.com/biglittlebigben))

## 1.27.0

### Minor Changes

- Support for room configuration and agent dispatches - [#864](https://github.com/livekit/protocol/pull/864) ([@davidzhao](https://github.com/davidzhao))

### Patch Changes

- added manifest details to egress info - [#862](https://github.com/livekit/protocol/pull/862) ([@frostbyte73](https://github.com/frostbyte73))

- Type safe IP checks for SIP Trunks. - [#857](https://github.com/livekit/protocol/pull/857) ([@dennwc](https://github.com/dennwc))

- enable krisp SIP setting - [#866](https://github.com/livekit/protocol/pull/866) ([@frostbyte73](https://github.com/frostbyte73))

## 1.26.0

### Minor Changes

- allow Agents to pass through initial attributes - [#852](https://github.com/livekit/protocol/pull/852) ([@davidzhao](https://github.com/davidzhao))

## 1.25.0

### Minor Changes

- Add ringing timeout and max call duration setting for SIP. - [#844](https://github.com/livekit/protocol/pull/844) ([@dennwc](https://github.com/dennwc))

## 1.24.0

### Minor Changes

- Add disconnect reasons for SIP. - [#828](https://github.com/livekit/protocol/pull/828) ([@dennwc](https://github.com/dennwc))

### Patch Changes

- Add missing SIP status attribute. - [#833](https://github.com/livekit/protocol/pull/833) ([@dennwc](https://github.com/dennwc))

- Validate SipCallTo in CreateSIPParticipantRequest. - [#823](https://github.com/livekit/protocol/pull/823) ([@dennwc](https://github.com/dennwc))

## 1.23.0

### Patch Changes

- Add protocols for client metrics - [#821](https://github.com/livekit/protocol/pull/821) ([@davidliu](https://github.com/davidliu))

- Add other_sdks field to ClientInfo - [#804](https://github.com/livekit/protocol/pull/804) ([@bcherry](https://github.com/bcherry))

## 1.22.0

### Minor Changes
Expand Down
9 changes: 7 additions & 2 deletions agent/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import (
"github.com/livekit/protocol/livekit"
)

func BuildAgentToken(apiKey, secret, roomName, participantIdentity, participantName, participantMetadata string, permissions *livekit.ParticipantPermission) (string, error) {
func BuildAgentToken(
apiKey, secret, roomName, participantIdentity, participantName, participantMetadata string,
participantAttributes map[string]string,
permissions *livekit.ParticipantPermission,
) (string, error) {
grant := &auth.VideoGrant{
RoomJoin: true,
Agent: true,
Expand All @@ -26,7 +30,8 @@ func BuildAgentToken(apiKey, secret, roomName, participantIdentity, participantN
SetName(participantName).
SetKind(livekit.ParticipantInfo_AGENT).
SetValidFor(1 * time.Hour).
SetMetadata(participantMetadata)
SetMetadata(participantMetadata).
SetAttributes(participantAttributes)

return at.ToJWT()
}
37 changes: 37 additions & 0 deletions auth/accesstoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,22 @@ func (t *AccessToken) SetKind(kind livekit.ParticipantInfo_Kind) *AccessToken {
return t
}

// Deprecated: use SetVideoGrant instead
func (t *AccessToken) AddGrant(grant *VideoGrant) *AccessToken {
return t.SetVideoGrant(grant)
}

func (t *AccessToken) SetVideoGrant(grant *VideoGrant) *AccessToken {
t.grant.Video = grant
return t
}

// Deprecated: use SetSIPGrant instead
func (t *AccessToken) AddSIPGrant(grant *SIPGrant) *AccessToken {
return t.SetSIPGrant(grant)
}

func (t *AccessToken) SetSIPGrant(grant *SIPGrant) *AccessToken {
t.grant.SIP = grant
return t
}
Expand Down Expand Up @@ -95,6 +105,33 @@ func (t *AccessToken) SetSha256(sha string) *AccessToken {
return t
}

func (t *AccessToken) SetRoomPreset(preset string) *AccessToken {
t.grant.RoomPreset = preset
return t
}

func (t *AccessToken) SetRoomConfig(config *livekit.RoomConfiguration) *AccessToken {
if config == nil {
t.grant.RoomConfig = nil
} else {
t.grant.RoomConfig = (*RoomConfiguration)(config)
}
return t
}

// SetAgents is a shortcut for setting agents in room configuration
func (t *AccessToken) SetAgents(agents ...*livekit.RoomAgentDispatch) *AccessToken {
if t.grant.RoomConfig == nil {
t.grant.RoomConfig = &RoomConfiguration{}
}
t.grant.RoomConfig.Agents = agents
return t
}

func (t *AccessToken) GetGrants() *ClaimGrants {
return &t.grant
}

func (t *AccessToken) ToJWT() (string, error) {
if t.apiKey == "" || t.secret == "" {
return "", ErrKeysMissing
Expand Down
73 changes: 73 additions & 0 deletions auth/accesstoken_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package auth

import (
"encoding/base64"
"encoding/json"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -101,6 +103,77 @@ func TestAccessToken(t *testing.T) {
// default validity
require.True(t, claim.Expiry.Time().Sub(claim.IssuedAt.Time()) > time.Minute)
})

t.Run("room configuration serialization and deserialization", func(t *testing.T) {
apiKey, secret := apiKeypair()
roomConfig := &livekit.RoomConfiguration{
Agents: []*livekit.RoomAgentDispatch{{
AgentName: "agent1",
Metadata: "metadata1",
}},
SyncStreams: true,
Egress: &livekit.RoomEgress{
Room: &livekit.RoomCompositeEgressRequest{
FileOutputs: []*livekit.EncodedFileOutput{{
DisableManifest: true,
}},
},
},
}
videoGrant := &VideoGrant{RoomJoin: true, Room: "test-room"}
at := NewAccessToken(apiKey, secret).
SetVideoGrant(videoGrant).
SetRoomConfig(roomConfig)

value, err := at.ToJWT()
require.NoError(t, err)

// Parse and verify the token
token, err := jwt.ParseSigned(value)
require.NoError(t, err)

decodedGrant := ClaimGrants{}
err = token.UnsafeClaimsWithoutVerification(&decodedGrant)
require.NoError(t, err)

// Check if the room configuration was correctly serialized and deserialized
roomDecoded := (*livekit.RoomConfiguration)(decodedGrant.RoomConfig)
require.NotNil(t, roomDecoded)
agents := roomDecoded.Agents
require.NotNil(t, agents)
require.Len(t, agents, 1)
require.Equal(t, "agent1", agents[0].AgentName)
require.Equal(t, "metadata1", agents[0].Metadata)
egress := roomDecoded.Egress
require.NotNil(t, egress)
require.Equal(t, true, egress.Room.FileOutputs[0].DisableManifest)

// Ensure that we are encoding room configuration with camelCase
parts := strings.Split(value, ".")
require.Equal(t, 3, len(parts), "JWT should have three parts")
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
require.NoError(t, err)

// Parse the JSON
var jsonPayload map[string]interface{}
err = json.Unmarshal(payload, &jsonPayload)
require.NoError(t, err)

// Navigate to the agents array
room, ok := jsonPayload["roomConfig"].(map[string]interface{})
require.True(t, ok, "room should be a map")
agentsJSON, ok := room["agents"].([]interface{})
require.True(t, ok, "agents should be an array")
require.Len(t, agents, 1, "there should be one agent")

// Check if agentName is in camelCase
agent, ok := agentsJSON[0].(map[string]interface{})
require.True(t, ok, "agent should be a map")
_, hasAgentName := agent["agentName"]
require.True(t, hasAgentName, "agentName should be present in camelCase")
_, hasAgentNameSnakeCase := agent["agent_name"]
require.False(t, hasAgentNameSnakeCase, "agent_name should not be present in snake_case")
})
}

func apiKeypair() (string, string) {
Expand Down
43 changes: 38 additions & 5 deletions auth/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,44 @@ import (
"strings"

"golang.org/x/exp/slices"
"google.golang.org/protobuf/encoding/protojson"

"github.com/livekit/protocol/livekit"
"github.com/livekit/protocol/utils"
)

type RoomConfiguration livekit.RoomConfiguration

var tokenMarshaler = protojson.MarshalOptions{
EmitDefaultValues: false,
}

func (c *RoomConfiguration) Clone() *RoomConfiguration {
if c == nil {
return nil
}
return (*RoomConfiguration)(utils.CloneProto((*livekit.RoomConfiguration)(c)))
}

func (c *RoomConfiguration) MarshalJSON() ([]byte, error) {
return tokenMarshaler.Marshal((*livekit.RoomConfiguration)(c))
}

func (c *RoomConfiguration) UnmarshalJSON(data []byte) error {
return protojson.Unmarshal(data, (*livekit.RoomConfiguration)(c))
}

type ClaimGrants struct {
Identity string `json:"-"`
Name string `json:"name,omitempty"`
Kind string `json:"kind,omitempty"`
Video *VideoGrant `json:"video,omitempty"`
SIP *SIPGrant `json:"sip,omitempty"`
// Room configuration to use if this participant initiates the room
RoomConfig *RoomConfiguration `json:"roomConfig,omitempty"`
// Cloud-only, config preset to use
// when both room and roomPreset are set, parameters in room overrides the preset
RoomPreset string `json:"roomPreset,omitempty"`
// for verifying integrity of the message body
Sha256 string `json:"sha256,omitempty"`
Metadata string `json:"metadata,omitempty"`
Expand All @@ -44,6 +72,13 @@ func (c *ClaimGrants) GetParticipantKind() livekit.ParticipantInfo_Kind {
return kindToProto(c.Kind)
}

func (c *ClaimGrants) GetRoomConfiguration() *livekit.RoomConfiguration {
if c.RoomConfig == nil {
return nil
}
return (*livekit.RoomConfiguration)(c.RoomConfig)
}

func (c *ClaimGrants) Clone() *ClaimGrants {
if c == nil {
return nil
Expand All @@ -53,6 +88,7 @@ func (c *ClaimGrants) Clone() *ClaimGrants {
clone.Video = c.Video.Clone()
clone.SIP = c.SIP.Clone()
clone.Attributes = maps.Clone(c.Attributes)
clone.RoomConfig = c.RoomConfig.Clone()

return &clone
}
Expand All @@ -69,8 +105,6 @@ type VideoGrant struct {
RoomAdmin bool `json:"roomAdmin,omitempty"`
RoomJoin bool `json:"roomJoin,omitempty"`
Room string `json:"room,omitempty"`
// Name of the room configuration to apply to the room if created
RoomConfiguration string `json:"roomConfiguration,omitempty"`

// permissions within a room, if none of the permissions are set explicitly
// it will be granted with all publish and subscribe permissions
Expand All @@ -91,7 +125,6 @@ type VideoGrant struct {
// 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"`

// if a participant can subscribe to metrics
Expand Down Expand Up @@ -317,7 +350,7 @@ func sourceToString(source livekit.TrackSource) string {
}

func sourceToProto(sourceStr string) livekit.TrackSource {
switch sourceStr {
switch strings.ToLower(sourceStr) {
case "camera":
return livekit.TrackSource_CAMERA
case "microphone":
Expand All @@ -336,7 +369,7 @@ func kindFromProto(source livekit.ParticipantInfo_Kind) string {
}

func kindToProto(sourceStr string) livekit.ParticipantInfo_Kind {
switch sourceStr {
switch strings.ToLower(sourceStr) {
case "", "standard":
return livekit.ParticipantInfo_STANDARD
case "ingress":
Expand Down
6 changes: 2 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.22
require (
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.12
github.com/fsnotify/fsnotify v1.7.0
github.com/gammazero/deque v0.2.1
Expand All @@ -15,7 +14,7 @@ require (
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.20240616012458-ac39c8549a0a
github.com/livekit/psrpc v0.6.1-0.20240924010758-9f0a4268a3b9
github.com/mackerelio/go-osstat v0.2.4
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1
github.com/pion/logging v0.2.2
Expand All @@ -32,7 +31,7 @@ require (
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
go.uber.org/zap/exp v0.3.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/mod v0.19.0
google.golang.org/grpc v1.65.0
Expand All @@ -48,7 +47,6 @@ require (
github.com/cespare/xxhash/v2 v2.3.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/google/cel-go v0.20.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
Expand Down
Loading

0 comments on commit 628a628

Please sign in to comment.