added TURN support
This commit is contained in:
parent
bed8d156dc
commit
7190086673
|
@ -116,3 +116,7 @@ The dependency `gstreamer` is licensed under the GNU Lesser General Public Licen
|
|||
Any kinds of contributions are welcome as a pull request.
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
`gst-meet` development is sponsored by [AVStack](https://www.avstack.io/). We provide globally-distributed, scalable, managed Jitsi Meet backends.
|
|
@ -21,12 +21,7 @@ use xmpp_parsers::{
|
|||
BareJid, Element, FullJid, Jid,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
jingle::JingleSession,
|
||||
source::MediaType,
|
||||
stanza_filter::StanzaFilter,
|
||||
xmpp,
|
||||
};
|
||||
use crate::{jingle::JingleSession, source::MediaType, stanza_filter::StanzaFilter, xmpp};
|
||||
|
||||
static DISCO_INFO: Lazy<DiscoInfoResult> = Lazy::new(|| DiscoInfoResult {
|
||||
node: None,
|
||||
|
@ -36,7 +31,6 @@ static DISCO_INFO: Lazy<DiscoInfoResult> = Lazy::new(|| DiscoInfoResult {
|
|||
Feature::new(ns::JINGLE_RTP_VIDEO),
|
||||
Feature::new(ns::JINGLE_ICE_UDP),
|
||||
Feature::new(ns::JINGLE_DTLS),
|
||||
|
||||
// not supported yet: rtx
|
||||
// Feature::new("urn:ietf:rfc:4588"),
|
||||
|
||||
|
|
|
@ -280,7 +280,9 @@ impl JitsiConnection {
|
|||
}
|
||||
|
||||
let iq = Iq::from_get(generate_id(), xmpp::extdisco::ServicesQuery {})
|
||||
.with_from(Jid::Full(locked_inner.jid.as_ref().context("missing jid")?.clone()))
|
||||
.with_from(Jid::Full(
|
||||
locked_inner.jid.as_ref().context("missing jid")?.clone(),
|
||||
))
|
||||
.with_to(Jid::Bare(locked_inner.xmpp_domain.clone()));
|
||||
tx.send(iq.into()).await?;
|
||||
locked_inner.state = DiscoveringExternalServices;
|
||||
|
|
|
@ -34,6 +34,7 @@ use crate::{
|
|||
};
|
||||
|
||||
const DEFAULT_STUN_PORT: u16 = 3478;
|
||||
const DEFAULT_TURNS_PORT: u16 = 5349;
|
||||
|
||||
pub(crate) struct JingleSession {
|
||||
pipeline: gstreamer::Pipeline,
|
||||
|
@ -198,7 +199,10 @@ impl JingleSession {
|
|||
}
|
||||
|
||||
if let Some(remote_fingerprint) = dtls_fingerprint {
|
||||
warn!("Remote DTLS fingerprint (verification not implemented yet): {:?}", remote_fingerprint);
|
||||
warn!(
|
||||
"Remote DTLS fingerprint (verification not implemented yet): {:?}",
|
||||
remote_fingerprint
|
||||
);
|
||||
}
|
||||
|
||||
let mut dtls_cert_params = CertificateParams::new(vec!["gst-meet".to_owned()]);
|
||||
|
@ -225,36 +229,63 @@ impl JingleSession {
|
|||
debug!("audio SSRC: {}", audio_ssrc);
|
||||
debug!("video SSRC: {}", video_ssrc);
|
||||
|
||||
let ice_agent = nice::Agent::new(&conference.glib_main_context, nice::Compatibility::Rfc5245);
|
||||
ice_agent.set_ice_tcp(false);
|
||||
ice_agent.set_upnp(false);
|
||||
let ice_stream_id = ice_agent.add_stream(1);
|
||||
let ice_component_id = 1;
|
||||
|
||||
let maybe_stun = conference
|
||||
.external_services
|
||||
.iter()
|
||||
.find(|svc| svc.r#type == "stun");
|
||||
|
||||
let stun_addr = if let Some(stun) = maybe_stun {
|
||||
lookup_host(format!("{}:{}", stun.host, stun.port.unwrap_or(DEFAULT_STUN_PORT)))
|
||||
.await?
|
||||
.next()
|
||||
lookup_host(format!(
|
||||
"{}:{}",
|
||||
stun.host,
|
||||
stun.port.unwrap_or(DEFAULT_STUN_PORT)
|
||||
))
|
||||
.await?
|
||||
.next()
|
||||
}
|
||||
else {
|
||||
None
|
||||
};
|
||||
debug!("STUN address: {:?}", stun_addr);
|
||||
|
||||
let ice_agent = nice::Agent::new(&conference.glib_main_context, nice::Compatibility::Rfc5245);
|
||||
ice_agent.set_ice_tcp(false);
|
||||
if let Some((stun_addr, stun_port)) = stun_addr.map(|sa| (sa.ip().to_string(), sa.port())) {
|
||||
ice_agent.set_stun_server(Some(&stun_addr));
|
||||
ice_agent.set_stun_server_port(stun_port as u32);
|
||||
}
|
||||
ice_agent.set_upnp(false);
|
||||
ice_agent.connect_component_state_changed(|_, a, b, c| {
|
||||
debug!("ICE component-state-changed {} {} {}", a, b, c);
|
||||
});
|
||||
ice_agent.connect_new_selected_pair(|_, a, b, c, d| {
|
||||
debug!("ICE new-selected-pair {} {} {} {}", a, b, c, d);
|
||||
});
|
||||
let ice_stream_id = ice_agent.add_stream(1);
|
||||
let ice_component_id = 1;
|
||||
|
||||
let maybe_turn = conference
|
||||
.external_services
|
||||
.iter()
|
||||
.find(|svc| svc.r#type == "turns");
|
||||
|
||||
if let Some(turn_server) = maybe_turn {
|
||||
let maybe_addr = lookup_host(format!(
|
||||
"{}:{}",
|
||||
turn_server.host,
|
||||
turn_server.port.unwrap_or(DEFAULT_TURNS_PORT)
|
||||
))
|
||||
.await?
|
||||
.next();
|
||||
|
||||
if let Some(addr) = maybe_addr {
|
||||
debug!("TURN address: {:?}", addr);
|
||||
ice_agent.set_relay_info(
|
||||
ice_stream_id,
|
||||
ice_component_id,
|
||||
&addr.ip().to_string(),
|
||||
addr.port() as u32,
|
||||
turn_server.username.as_deref().unwrap_or_default(),
|
||||
turn_server.password.as_deref().unwrap_or_default(),
|
||||
nice::RelayType::Tls,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !ice_agent.attach_recv(
|
||||
ice_stream_id,
|
||||
|
@ -716,13 +747,12 @@ impl JingleSession {
|
|||
});
|
||||
description.ssrcs = vec![ssrc];
|
||||
|
||||
let mut transport = IceUdpTransport::new()
|
||||
.with_fingerprint(Fingerprint {
|
||||
hash: Algo::Sha_256,
|
||||
setup: Some(Setup::Active),
|
||||
value: fingerprint.clone(),
|
||||
required: Some(true.to_string()),
|
||||
});
|
||||
let mut transport = IceUdpTransport::new().with_fingerprint(Fingerprint {
|
||||
hash: Algo::Sha_256,
|
||||
setup: Some(Setup::Active),
|
||||
value: fingerprint.clone(),
|
||||
required: Some(true.to_string()),
|
||||
});
|
||||
transport.ufrag = Some(ice_local_ufrag.clone());
|
||||
transport.pwd = Some(ice_local_pwd.clone());
|
||||
transport.candidates = vec![];
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
pub mod conference;
|
||||
pub mod connection;
|
||||
mod jingle;
|
||||
mod xmpp;
|
||||
mod pinger;
|
||||
pub mod source;
|
||||
mod stanza_filter;
|
||||
mod util;
|
||||
mod xmpp;
|
||||
|
||||
pub use crate::{
|
||||
conference::{JitsiConference, JitsiConferenceConfig, Participant},
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use xmpp_parsers::{
|
||||
Element,
|
||||
iq::IqGetPayload,
|
||||
};
|
||||
use xmpp_parsers::{iq::IqGetPayload, Element};
|
||||
|
||||
use crate::xmpp::ns;
|
||||
|
||||
|
@ -56,17 +53,21 @@ impl TryFrom<Element> for ServicesResult {
|
|||
Ok(ServicesResult {
|
||||
services: elem
|
||||
.children()
|
||||
.map(|child| Ok(Service {
|
||||
r#type: child.attr("type").context("missing type attr")?.to_owned(),
|
||||
name: child.attr("name").map(ToOwned::to_owned),
|
||||
host: child.attr("host").context("missing host attr")?.to_owned(),
|
||||
port: child.attr("port").map(|p| p.parse()).transpose()?,
|
||||
transport: child.attr("transport").map(ToOwned::to_owned),
|
||||
restricted: child.attr("restricted").map(|b| b.to_lowercase() == "parse" || b == "1"),
|
||||
username: child.attr("username").map(ToOwned::to_owned),
|
||||
password: child.attr("password").map(ToOwned::to_owned),
|
||||
expires: child.attr("expires").map(ToOwned::to_owned),
|
||||
}))
|
||||
.map(|child| {
|
||||
Ok(Service {
|
||||
r#type: child.attr("type").context("missing type attr")?.to_owned(),
|
||||
name: child.attr("name").map(ToOwned::to_owned),
|
||||
host: child.attr("host").context("missing host attr")?.to_owned(),
|
||||
port: child.attr("port").map(|p| p.parse()).transpose()?,
|
||||
transport: child.attr("transport").map(ToOwned::to_owned),
|
||||
restricted: child
|
||||
.attr("restricted")
|
||||
.map(|b| b.to_lowercase() == "parse" || b == "1"),
|
||||
username: child.attr("username").map(ToOwned::to_owned),
|
||||
password: child.attr("password").map(ToOwned::to_owned),
|
||||
expires: child.attr("expires").map(ToOwned::to_owned),
|
||||
})
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue