Skip to content

Commit

Permalink
adding disconnect reason, pass through to FFI
Browse files Browse the repository at this point in the history
used for `ParticipantDisconnected` events
  • Loading branch information
davidzhao committed Dec 7, 2024
1 parent 8ff2071 commit 00c26a3
Show file tree
Hide file tree
Showing 14 changed files with 792 additions and 425 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions livekit-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ url = "2.3"
log = "0.4"
parking_lot = { version = "0.12" }
prost = "0.12"
pbjson-types = "0.6"

# webhooks
serde_json = { version = "1.0", optional = true }
Expand Down
123 changes: 62 additions & 61 deletions livekit-api/src/services/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@

use livekit_protocol as proto;
use std::collections::HashMap;
use std::time::Duration;

use crate::access_token::SIPGrants;
use crate::get_env_keys;
use crate::services::twirp_client::TwirpClient;
use crate::services::{ServiceBase, ServiceResult, LIVEKIT_PACKAGE};
use pbjson_types::Duration as ProtoDuration;

const SVC: &str = "SIP";

Expand Down Expand Up @@ -58,18 +60,24 @@ pub struct CreateSIPTrunkOptions {
#[derive(Default, Clone, Debug)]
pub struct CreateSIPInboundTrunkOptions {
/// Optional free-form metadata.
pub metadata: String,
pub metadata: Option<String>,
/// CIDR or IPs that traffic is accepted from
/// An empty list means all inbound traffic is accepted.
pub allowed_addresses: Vec<String>,
pub allowed_addresses: Option<Vec<String>>,
/// Accepted `To` values. This Trunk will only accept a call made to
/// these numbers. This allows you to have distinct Trunks for different phone
/// numbers at the same provider.
pub allowed_numbers: Vec<String>,
pub allowed_numbers: Option<Vec<String>>,
/// Username and password used to authenticate inbound SIP invites
/// May be empty to have no Authentication
pub auth_username: String,
pub auth_password: String,
pub auth_username: Option<String>,
pub auth_password: Option<String>,
pub headers: Option<HashMap<String, String>>,
pub headers_to_attributes: Option<HashMap<String, String>>,
pub attributes_to_headers: Option<HashMap<String, String>>,
pub max_call_duration: Option<Duration>,
pub ringing_timeout: Option<Duration>,
pub krisp_enabled: Option<bool>,
}

#[derive(Default, Clone, Debug)]
Expand All @@ -81,6 +89,10 @@ pub struct CreateSIPOutboundTrunkOptions {
/// May be empty to have no Authentication
pub auth_username: String,
pub auth_password: String,

pub headers: Option<HashMap<String, String>>,
pub headers_to_attributes: Option<HashMap<String, String>>,
pub attributes_to_headers: Option<HashMap<String, String>>,
}

#[deprecated]
Expand Down Expand Up @@ -119,16 +131,21 @@ pub struct CreateSIPParticipantOptions {
/// Optional identity of the participant in LiveKit room
pub participant_identity: String,
/// Optionally set the name of the participant in a LiveKit room
pub participant_name: String,
pub participant_name: Option<String>,
/// Optionally set the free-form metadata of the participant in a LiveKit room
pub participant_metadata: String,
pub participant_attributes: HashMap<String, String>,
pub participant_metadata: Option<String>,
pub participant_attributes: Option<HashMap<String, String>>,
// What number should be dialed via SIP
pub sip_number: Option<String>,
/// Optionally send following DTMF digits (extension codes) when making a call.
/// Character 'w' can be used to add a 0.5 sec delay.
pub dtmf: String,
/// Optionally play ringtone in the room as an audible indicator for existing participants
pub play_ringtone: bool,
pub hide_phone_number: bool,
pub dtmf: Option<String>,
/// Optionally play dialtone in the room as an audible indicator for existing participants
pub play_dialtone: Option<bool>,
pub hide_phone_number: Option<bool>,
pub ringing_timeout: Option<Duration>,
pub max_call_duration: Option<Duration>,
pub enable_krisp: Option<bool>,
}

impl SIPClient {
Expand All @@ -144,38 +161,8 @@ impl SIPClient {
Ok(Self::with_api_key(host, &api_key, &api_secret))
}

#[deprecated]
pub async fn create_sip_trunk(
&self,
number: String,
options: CreateSIPTrunkOptions,
) -> ServiceResult<proto::SipTrunkInfo> {
self.client
.request(
SVC,
"CreateSIPTrunk",
proto::CreateSipTrunkRequest {
name: options.name,
metadata: options.metadata,

outbound_number: number.to_owned(),
outbound_address: options.outbound_address.to_owned(),
outbound_username: options.outbound_username.to_owned(),
outbound_password: options.outbound_password.to_owned(),

inbound_numbers: options.inbound_numbers.to_owned(),
inbound_numbers_regex: Vec::new(),
inbound_addresses: options.inbound_addresses.to_owned(),
inbound_username: options.inbound_username.to_owned(),
inbound_password: options.inbound_password.to_owned(),
},
self.base.auth_header(
Default::default(),
Some(SIPGrants { admin: true, ..Default::default() }),
)?,
)
.await
.map_err(Into::into)
fn duration_to_proto(d: Option<Duration>) -> Option<ProtoDuration> {
d.map(|d| ProtoDuration { seconds: d.as_secs() as i64, nanos: d.subsec_nanos() as i32 })
}

pub async fn create_sip_inbound_trunk(
Expand All @@ -193,15 +180,17 @@ impl SIPClient {
sip_trunk_id: Default::default(),
name,
numbers,
metadata: options.metadata,

allowed_numbers: options.allowed_numbers.to_owned(),
allowed_addresses: options.allowed_addresses.to_owned(),
auth_username: options.auth_username.to_owned(),
auth_password: options.auth_password.to_owned(),

headers: Default::default(),
headers_to_attributes: Default::default(),
metadata: options.metadata.unwrap_or_default(),
allowed_numbers: options.allowed_numbers.unwrap_or_default(),
allowed_addresses: options.allowed_addresses.unwrap_or_default(),
auth_username: options.auth_username.unwrap_or_default(),
auth_password: options.auth_password.unwrap_or_default(),
headers: options.headers.unwrap_or_default(),
headers_to_attributes: options.headers_to_attributes.unwrap_or_default(),
attributes_to_headers: options.attributes_to_headers.unwrap_or_default(),
krisp_enabled: options.krisp_enabled.unwrap_or(false),
max_call_duration: Self::duration_to_proto(options.max_call_duration),
ringing_timeout: Self::duration_to_proto(options.ringing_timeout),
}),
},
self.base.auth_header(
Expand Down Expand Up @@ -236,8 +225,9 @@ impl SIPClient {
auth_username: options.auth_username.to_owned(),
auth_password: options.auth_password.to_owned(),

headers: Default::default(),
headers_to_attributes: Default::default(),
headers: options.headers.unwrap_or_default(),
headers_to_attributes: options.headers_to_attributes.unwrap_or_default(),
attributes_to_headers: options.attributes_to_headers.unwrap_or_default(),
}),
},
self.base.auth_header(
Expand Down Expand Up @@ -406,14 +396,25 @@ impl SIPClient {
proto::CreateSipParticipantRequest {
sip_trunk_id: sip_trunk_id.to_owned(),
sip_call_to: call_to.to_owned(),
sip_number: options.sip_number.to_owned().unwrap_or_default(),
room_name: room_name.to_owned(),
participant_identity: options.participant_identity.to_owned(),
participant_name: options.participant_name.to_owned(),
participant_metadata: options.participant_metadata.to_owned(),
participant_attributes: options.participant_attributes.to_owned(),
dtmf: options.dtmf.to_owned(),
play_ringtone: options.play_ringtone,
hide_phone_number: options.hide_phone_number,
participant_name: options.participant_name.to_owned().unwrap_or_default(),
participant_metadata: options
.participant_metadata
.to_owned()
.unwrap_or_default(),
participant_attributes: options
.participant_attributes
.to_owned()
.unwrap_or_default(),
dtmf: options.dtmf.to_owned().unwrap_or_default(),
play_ringtone: options.play_dialtone.unwrap_or(false),
play_dialtone: options.play_dialtone.unwrap_or(false),
hide_phone_number: options.hide_phone_number.unwrap_or(false),
max_call_duration: Self::duration_to_proto(options.max_call_duration),
ringing_timeout: Self::duration_to_proto(options.ringing_timeout),
enable_krisp: options.enable_krisp.unwrap_or(false),
},
self.base.auth_header(
Default::default(),
Expand Down
31 changes: 31 additions & 0 deletions livekit-ffi/protocol/participant.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ message ParticipantInfo {
required string metadata = 4;
map<string, string> attributes = 5;
required ParticipantKind kind = 6;
required DisconnectReason disconnect_reason = 7;
}

message OwnedParticipant {
Expand All @@ -39,4 +40,34 @@ enum ParticipantKind {
PARTICIPANT_KIND_EGRESS = 2;
PARTICIPANT_KIND_SIP = 3;
PARTICIPANT_KIND_AGENT = 4;
}

enum DisconnectReason {
UNKNOWN_REASON = 0;
// the client initiated the disconnect
CLIENT_INITIATED = 1;
// another participant with the same identity has joined the room
DUPLICATE_IDENTITY = 2;
// the server instance is shutting down
SERVER_SHUTDOWN = 3;
// RoomService.RemoveParticipant was called
PARTICIPANT_REMOVED = 4;
// RoomService.DeleteRoom was called
ROOM_DELETED = 5;
// the client is attempting to resume a session, but server is not aware of it
STATE_MISMATCH = 6;
// client was unable to connect fully
JOIN_FAILURE = 7;
// Cloud-only, the server requested Participant to migrate the connection elsewhere
MIGRATION = 8;
// the signal websocket was closed unexpectedly
SIGNAL_CLOSE = 9;
// the room was closed, due to all Standard and Ingress participants having left
ROOM_CLOSED = 10;
// SIP callee did not respond in time
USER_UNAVAILABLE = 11;
// SIP callee rejected the call (busy)
USER_REJECTED = 12;
// SIP protocol failure or unexpected response
SIP_TRUNK_FAILURE = 13;
}
36 changes: 6 additions & 30 deletions livekit-ffi/protocol/room.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ message ConnectCallback {
string error = 2;
Result result = 3;
}

}

// Disconnect from the a room
Expand All @@ -76,7 +76,7 @@ message PublishTrackCallback {
string error = 2;
OwnedTrackPublication publication = 3;
}

}

// Unpublish a track from the room
Expand Down Expand Up @@ -316,30 +316,6 @@ enum DataPacketKind {
KIND_RELIABLE = 1;
}

enum DisconnectReason {
UNKNOWN_REASON = 0;
// the client initiated the disconnect
CLIENT_INITIATED = 1;
// another participant with the same identity has joined the room
DUPLICATE_IDENTITY = 2;
// the server instance is shutting down
SERVER_SHUTDOWN = 3;
// RoomService.RemoveParticipant was called
PARTICIPANT_REMOVED = 4;
// RoomService.DeleteRoom was called
ROOM_DELETED = 5;
// the client is attempting to resume a session, but server is not aware of it
STATE_MISMATCH = 6;
// client was unable to connect fully
JOIN_FAILURE = 7;
// Cloud-only, the server requested Participant to migrate the connection elsewhere
MIGRATION = 8;
// the signal websocket was closed unexpectedly
SIGNAL_CLOSE = 9;
// the room was closed, due to all Standard and Ingress participants having left
ROOM_CLOSED = 10;
}

message TranscriptionSegment {
required string id = 1;
required string text = 2;
Expand Down Expand Up @@ -407,7 +383,7 @@ message OwnedRoom {

message ParticipantConnected { required OwnedParticipant info = 1; }

message ParticipantDisconnected {
message ParticipantDisconnected {
required string participant_identity = 1;
}

Expand Down Expand Up @@ -471,15 +447,15 @@ message E2eeStateChanged {

message ActiveSpeakersChanged { repeated string participant_identities = 1; }

message RoomMetadataChanged {
message RoomMetadataChanged {
required string metadata = 1;
}

message RoomSidChanged {
required string sid = 1;
}

message ParticipantMetadataChanged {
message ParticipantMetadataChanged {
required string participant_identity = 1;
required string metadata = 2;
}
Expand All @@ -490,7 +466,7 @@ message ParticipantAttributesChanged {
repeated AttributesEntry changed_attributes = 3;
}

message ParticipantNameChanged {
message ParticipantNameChanged {
required string participant_identity = 1;
required string name = 2;
}
Expand Down
24 changes: 24 additions & 0 deletions livekit-ffi/src/conversion/participant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use crate::{proto, server::participant::FfiParticipant};
use livekit::DisconnectReason;
use livekit::ParticipantKind;

impl From<&FfiParticipant> for proto::ParticipantInfo {
Expand All @@ -25,6 +26,8 @@ impl From<&FfiParticipant> for proto::ParticipantInfo {
metadata: participant.metadata(),
attributes: participant.attributes(),
kind: proto::ParticipantKind::from(participant.kind()).into(),
disconnect_reason: proto::DisconnectReason::from(participant.disconnect_reason())
.into(),
}
}
}
Expand All @@ -40,3 +43,24 @@ impl From<ParticipantKind> for proto::ParticipantKind {
}
}
}

impl From<DisconnectReason> for proto::DisconnectReason {
fn from(reason: DisconnectReason) -> Self {
match reason {
DisconnectReason::UnknownReason => proto::DisconnectReason::UnknownReason,
DisconnectReason::ClientInitiated => proto::DisconnectReason::ClientInitiated,
DisconnectReason::DuplicateIdentity => proto::DisconnectReason::DuplicateIdentity,
DisconnectReason::ServerShutdown => proto::DisconnectReason::ServerShutdown,
DisconnectReason::ParticipantRemoved => proto::DisconnectReason::ParticipantRemoved,
DisconnectReason::RoomDeleted => proto::DisconnectReason::RoomDeleted,
DisconnectReason::StateMismatch => proto::DisconnectReason::StateMismatch,
DisconnectReason::JoinFailure => proto::DisconnectReason::JoinFailure,
DisconnectReason::Migration => proto::DisconnectReason::Migration,
DisconnectReason::SignalClose => proto::DisconnectReason::SignalClose,
DisconnectReason::RoomClosed => proto::DisconnectReason::RoomClosed,
DisconnectReason::UserUnavailable => proto::DisconnectReason::UserUnavailable,
DisconnectReason::UserRejected => proto::DisconnectReason::UserRejected,
DisconnectReason::SipTrunkFailure => proto::DisconnectReason::SipTrunkFailure,
}
}
}
Loading

0 comments on commit 00c26a3

Please sign in to comment.