Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding disconnect reason #507

Merged
merged 3 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>,
davidzhao marked this conversation as resolved.
Show resolved Hide resolved
/// 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
Loading