xref: /webrtc/webrtc/src/api/setting_engine/mod.rs (revision 03a147ee)
1 #[cfg(test)]
2 mod setting_engine_test;
3 
4 use crate::dtls_transport::dtls_role::DTLSRole;
5 use crate::ice_transport::ice_candidate_type::RTCIceCandidateType;
6 use dtls::extension::extension_use_srtp::SrtpProtectionProfile;
7 use ice::agent::agent_config::{InterfaceFilterFn, IpFilterFn};
8 use ice::mdns::MulticastDnsMode;
9 use ice::network_type::NetworkType;
10 use ice::udp_network::UDPNetwork;
11 
12 use crate::error::{Error, Result};
13 
14 use crate::RECEIVE_MTU;
15 use std::sync::Arc;
16 use tokio::time::Duration;
17 use util::vnet::net::*;
18 
19 #[derive(Default, Clone)]
20 pub struct Detach {
21     pub data_channels: bool,
22 }
23 
24 #[derive(Default, Clone)]
25 pub struct Timeout {
26     pub ice_disconnected_timeout: Option<Duration>,
27     pub ice_failed_timeout: Option<Duration>,
28     pub ice_keepalive_interval: Option<Duration>,
29     pub ice_host_acceptance_min_wait: Option<Duration>,
30     pub ice_srflx_acceptance_min_wait: Option<Duration>,
31     pub ice_prflx_acceptance_min_wait: Option<Duration>,
32     pub ice_relay_acceptance_min_wait: Option<Duration>,
33 }
34 
35 #[derive(Default, Clone)]
36 pub struct Candidates {
37     pub ice_lite: bool,
38     pub ice_network_types: Vec<NetworkType>,
39     pub interface_filter: Arc<Option<InterfaceFilterFn>>,
40     pub ip_filter: Arc<Option<IpFilterFn>>,
41     pub nat_1to1_ips: Vec<String>,
42     pub nat_1to1_ip_candidate_type: RTCIceCandidateType,
43     pub multicast_dns_mode: MulticastDnsMode,
44     pub multicast_dns_host_name: String,
45     pub username_fragment: String,
46     pub password: String,
47 }
48 
49 #[derive(Default, Clone)]
50 pub struct ReplayProtection {
51     pub dtls: usize,
52     pub srtp: usize,
53     pub srtcp: usize,
54 }
55 
56 /// SettingEngine allows influencing behavior in ways that are not
57 /// supported by the WebRTC API. This allows us to support additional
58 /// use-cases without deviating from the WebRTC API elsewhere.
59 #[derive(Default, Clone)]
60 pub struct SettingEngine {
61     pub(crate) detach: Detach,
62     pub(crate) timeout: Timeout,
63     pub(crate) candidates: Candidates,
64     pub(crate) replay_protection: ReplayProtection,
65     pub(crate) sdp_media_level_fingerprints: bool,
66     pub(crate) answering_dtls_role: DTLSRole,
67     pub(crate) disable_certificate_fingerprint_verification: bool,
68     pub(crate) allow_insecure_verification_algorithm: bool,
69     pub(crate) disable_srtp_replay_protection: bool,
70     pub(crate) disable_srtcp_replay_protection: bool,
71     pub(crate) vnet: Option<Arc<Net>>,
72     //BufferFactory                             :func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser,
73     //iceTCPMux                                 :ice.TCPMux,?
74     //iceProxyDialer                            :proxy.Dialer,?
75     pub(crate) udp_network: UDPNetwork,
76     pub(crate) disable_media_engine_copy: bool,
77     pub(crate) srtp_protection_profiles: Vec<SrtpProtectionProfile>,
78     pub(crate) receive_mtu: usize,
79     pub(crate) mid_generator: Option<Arc<dyn Fn(isize) -> String + Send + Sync>>,
80 }
81 
82 impl SettingEngine {
83     /// get_receive_mtu returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default
get_receive_mtu(&self) -> usize84     pub(crate) fn get_receive_mtu(&self) -> usize {
85         if self.receive_mtu != 0 {
86             self.receive_mtu
87         } else {
88             RECEIVE_MTU
89         }
90     }
91     /// detach_data_channels enables detaching data channels. When enabled
92     /// data channels have to be detached in the OnOpen callback using the
93     /// DataChannel.Detach method.
detach_data_channels(&mut self)94     pub fn detach_data_channels(&mut self) {
95         self.detach.data_channels = true;
96     }
97 
98     /// set_srtp_protection_profiles allows the user to override the default srtp Protection Profiles
99     /// The default srtp protection profiles are provided by the function `defaultSrtpProtectionProfiles`
set_srtp_protection_profiles(&mut self, profiles: Vec<SrtpProtectionProfile>)100     pub fn set_srtp_protection_profiles(&mut self, profiles: Vec<SrtpProtectionProfile>) {
101         self.srtp_protection_profiles = profiles
102     }
103 
104     /// set_ice_timeouts sets the behavior around ICE Timeouts
105     /// * disconnected_timeout is the duration without network activity before a Agent is considered disconnected. Default is 5 Seconds
106     /// * failed_timeout is the duration without network activity before a Agent is considered failed after disconnected. Default is 25 Seconds
107     /// * keep_alive_interval is how often the ICE Agent sends extra traffic if there is no activity, if media is flowing no traffic will be sent. Default is 2 seconds
set_ice_timeouts( &mut self, disconnected_timeout: Option<Duration>, failed_timeout: Option<Duration>, keep_alive_interval: Option<Duration>, )108     pub fn set_ice_timeouts(
109         &mut self,
110         disconnected_timeout: Option<Duration>,
111         failed_timeout: Option<Duration>,
112         keep_alive_interval: Option<Duration>,
113     ) {
114         self.timeout.ice_disconnected_timeout = disconnected_timeout;
115         self.timeout.ice_failed_timeout = failed_timeout;
116         self.timeout.ice_keepalive_interval = keep_alive_interval;
117     }
118 
119     /// set_host_acceptance_min_wait sets the icehost_acceptance_min_wait
set_host_acceptance_min_wait(&mut self, t: Option<Duration>)120     pub fn set_host_acceptance_min_wait(&mut self, t: Option<Duration>) {
121         self.timeout.ice_host_acceptance_min_wait = t;
122     }
123 
124     /// set_srflx_acceptance_min_wait sets the icesrflx_acceptance_min_wait
set_srflx_acceptance_min_wait(&mut self, t: Option<Duration>)125     pub fn set_srflx_acceptance_min_wait(&mut self, t: Option<Duration>) {
126         self.timeout.ice_srflx_acceptance_min_wait = t;
127     }
128 
129     /// set_prflx_acceptance_min_wait sets the iceprflx_acceptance_min_wait
set_prflx_acceptance_min_wait(&mut self, t: Option<Duration>)130     pub fn set_prflx_acceptance_min_wait(&mut self, t: Option<Duration>) {
131         self.timeout.ice_prflx_acceptance_min_wait = t;
132     }
133 
134     /// set_relay_acceptance_min_wait sets the icerelay_acceptance_min_wait
set_relay_acceptance_min_wait(&mut self, t: Option<Duration>)135     pub fn set_relay_acceptance_min_wait(&mut self, t: Option<Duration>) {
136         self.timeout.ice_relay_acceptance_min_wait = t;
137     }
138 
139     /// set_udp_network allows ICE traffic to come through Ephemeral or UDPMux.
140     /// UDPMux drastically simplifying deployments where ports will need to be opened/forwarded.
141     /// UDPMux should be started prior to creating PeerConnections.
set_udp_network(&mut self, udp_network: UDPNetwork)142     pub fn set_udp_network(&mut self, udp_network: UDPNetwork) {
143         self.udp_network = udp_network;
144     }
145 
146     /// set_lite configures whether or not the ice agent should be a lite agent
set_lite(&mut self, lite: bool)147     pub fn set_lite(&mut self, lite: bool) {
148         self.candidates.ice_lite = lite;
149     }
150 
151     /// set_network_types configures what types of candidate networks are supported
152     /// during local and server reflexive gathering.
set_network_types(&mut self, candidate_types: Vec<NetworkType>)153     pub fn set_network_types(&mut self, candidate_types: Vec<NetworkType>) {
154         self.candidates.ice_network_types = candidate_types;
155     }
156 
157     /// set_interface_filter sets the filtering functions when gathering ICE candidates
158     /// This can be used to exclude certain network interfaces from ICE. Which may be
159     /// useful if you know a certain interface will never succeed, or if you wish to reduce
160     /// the amount of information you wish to expose to the remote peer
set_interface_filter(&mut self, filter: InterfaceFilterFn)161     pub fn set_interface_filter(&mut self, filter: InterfaceFilterFn) {
162         self.candidates.interface_filter = Arc::new(Some(filter));
163     }
164 
165     /// set_ip_filter sets the filtering functions when gathering ICE candidates
166     /// This can be used to exclude certain ip from ICE. Which may be
167     /// useful if you know a certain ip will never succeed, or if you wish to reduce
168     /// the amount of information you wish to expose to the remote peer
set_ip_filter(&mut self, filter: IpFilterFn)169     pub fn set_ip_filter(&mut self, filter: IpFilterFn) {
170         self.candidates.ip_filter = Arc::new(Some(filter));
171     }
172 
173     /// set_nat_1to1_ips sets a list of external IP addresses of 1:1 (D)NAT
174     /// and a candidate type for which the external IP address is used.
175     /// This is useful when you are host a server using Pion on an AWS EC2 instance
176     /// which has a private address, behind a 1:1 DNAT with a public IP (e.g.
177     /// Elastic IP). In this case, you can give the public IP address so that
178     /// Pion will use the public IP address in its candidate instead of the private
179     /// IP address. The second argument, candidate_type, is used to tell Pion which
180     /// type of candidate should use the given public IP address.
181     /// Two types of candidates are supported:
182     ///
183     /// ICECandidateTypeHost:
184     ///   The public IP address will be used for the host candidate in the SDP.
185     /// ICECandidateTypeSrflx:
186     ///   A server reflexive candidate with the given public IP address will be added
187     /// to the SDP.
188     ///
189     /// Please note that if you choose ICECandidateTypeHost, then the private IP address
190     /// won't be advertised with the peer. Also, this option cannot be used along with mDNS.
191     ///
192     /// If you choose ICECandidateTypeSrflx, it simply adds a server reflexive candidate
193     /// with the public IP. The host candidate is still available along with mDNS
194     /// capabilities unaffected. Also, you cannot give STUN server URL at the same time.
195     /// It will result in an error otherwise.
set_nat_1to1_ips(&mut self, ips: Vec<String>, candidate_type: RTCIceCandidateType)196     pub fn set_nat_1to1_ips(&mut self, ips: Vec<String>, candidate_type: RTCIceCandidateType) {
197         self.candidates.nat_1to1_ips = ips;
198         self.candidates.nat_1to1_ip_candidate_type = candidate_type;
199     }
200 
201     /// set_answering_dtls_role sets the dtls_transport role that is selected when offering
202     /// The dtls_transport role controls if the WebRTC Client as a client or server. This
203     /// may be useful when interacting with non-compliant clients or debugging issues.
204     ///
205     /// DTLSRoleActive:
206     ///   Act as dtls_transport Client, send the ClientHello and starts the handshake
207     /// DTLSRolePassive:
208     ///   Act as dtls_transport Server, wait for ClientHello
set_answering_dtls_role(&mut self, role: DTLSRole) -> Result<()>209     pub fn set_answering_dtls_role(&mut self, role: DTLSRole) -> Result<()> {
210         if role != DTLSRole::Client && role != DTLSRole::Server {
211             return Err(Error::ErrSettingEngineSetAnsweringDTLSRole);
212         }
213 
214         self.answering_dtls_role = role;
215         Ok(())
216     }
217 
218     /// set_vnet sets the VNet instance that is passed to ice
219     /// VNet is a virtual network layer, allowing users to simulate
220     /// different topologies, latency, loss and jitter. This can be useful for
221     /// learning WebRTC concepts or testing your application in a lab environment
set_vnet(&mut self, vnet: Option<Arc<Net>>)222     pub fn set_vnet(&mut self, vnet: Option<Arc<Net>>) {
223         self.vnet = vnet;
224     }
225 
226     /// set_ice_multicast_dns_mode controls if ice queries and generates mDNS ICE Candidates
set_ice_multicast_dns_mode(&mut self, multicast_dns_mode: ice::mdns::MulticastDnsMode)227     pub fn set_ice_multicast_dns_mode(&mut self, multicast_dns_mode: ice::mdns::MulticastDnsMode) {
228         self.candidates.multicast_dns_mode = multicast_dns_mode
229     }
230 
231     /// set_multicast_dns_host_name sets a static HostName to be used by ice instead of generating one on startup
232     /// This should only be used for a single PeerConnection. Having multiple PeerConnections with the same HostName will cause
233     /// undefined behavior
set_multicast_dns_host_name(&mut self, host_name: String)234     pub fn set_multicast_dns_host_name(&mut self, host_name: String) {
235         self.candidates.multicast_dns_host_name = host_name;
236     }
237 
238     /// set_ice_credentials sets a staic uFrag/uPwd to be used by ice
239     /// This is useful if you want to do signalless WebRTC session, or having a reproducible environment with static credentials
set_ice_credentials(&mut self, username_fragment: String, password: String)240     pub fn set_ice_credentials(&mut self, username_fragment: String, password: String) {
241         self.candidates.username_fragment = username_fragment;
242         self.candidates.password = password;
243     }
244 
245     /// disable_certificate_fingerprint_verification disables fingerprint verification after dtls_transport Handshake has finished
disable_certificate_fingerprint_verification(&mut self, is_disabled: bool)246     pub fn disable_certificate_fingerprint_verification(&mut self, is_disabled: bool) {
247         self.disable_certificate_fingerprint_verification = is_disabled;
248     }
249 
250     /// allow_insecure_verification_algorithm allows the usage of certain signature verification
251     /// algorithm that are known to be vulnerable or deprecated.
allow_insecure_verification_algorithm(&mut self, is_allowed: bool)252     pub fn allow_insecure_verification_algorithm(&mut self, is_allowed: bool) {
253         self.allow_insecure_verification_algorithm = is_allowed;
254     }
255     /// set_dtls_replay_protection_window sets a replay attack protection window size of dtls_transport connection.
set_dtls_replay_protection_window(&mut self, n: usize)256     pub fn set_dtls_replay_protection_window(&mut self, n: usize) {
257         self.replay_protection.dtls = n;
258     }
259 
260     /// set_srtp_replay_protection_window sets a replay attack protection window size of srtp session.
set_srtp_replay_protection_window(&mut self, n: usize)261     pub fn set_srtp_replay_protection_window(&mut self, n: usize) {
262         self.disable_srtp_replay_protection = false;
263         self.replay_protection.srtp = n;
264     }
265 
266     /// set_srtcp_replay_protection_window sets a replay attack protection window size of srtcp session.
set_srtcp_replay_protection_window(&mut self, n: usize)267     pub fn set_srtcp_replay_protection_window(&mut self, n: usize) {
268         self.disable_srtcp_replay_protection = false;
269         self.replay_protection.srtcp = n;
270     }
271 
272     /// disable_srtp_replay_protection disables srtp replay protection.
disable_srtp_replay_protection(&mut self, is_disabled: bool)273     pub fn disable_srtp_replay_protection(&mut self, is_disabled: bool) {
274         self.disable_srtp_replay_protection = is_disabled;
275     }
276 
277     /// disable_srtcp_replay_protection disables srtcp replay protection.
disable_srtcp_replay_protection(&mut self, is_disabled: bool)278     pub fn disable_srtcp_replay_protection(&mut self, is_disabled: bool) {
279         self.disable_srtcp_replay_protection = is_disabled;
280     }
281 
282     /// set_sdp_media_level_fingerprints configures the logic for dtls_transport Fingerprint insertion
283     /// If true, fingerprints will be inserted in the sdp at the fingerprint
284     /// level, instead of the session level. This helps with compatibility with
285     /// some webrtc implementations.
set_sdp_media_level_fingerprints(&mut self, sdp_media_level_fingerprints: bool)286     pub fn set_sdp_media_level_fingerprints(&mut self, sdp_media_level_fingerprints: bool) {
287         self.sdp_media_level_fingerprints = sdp_media_level_fingerprints;
288     }
289 
290     // SetICETCPMux enables ICE-TCP when set to a non-nil value. Make sure that
291     // NetworkTypeTCP4 or NetworkTypeTCP6 is enabled as well.
292     //pub fn SetICETCPMux(&mut self, tcpMux ice.TCPMux) {
293     //    self.iceTCPMux = tcpMux
294     //}
295 
296     // SetICEProxyDialer sets the proxy dialer interface based on golang.org/x/net/proxy.
297     //pub fn SetICEProxyDialer(&mut self, d proxy.Dialer) {
298     //    self.iceProxyDialer = d
299     //}
300 
301     /// disable_media_engine_copy stops the MediaEngine from being copied. This allows a user to modify
302     /// the MediaEngine after the PeerConnection has been constructed. This is useful if you wish to
303     /// modify codecs after signaling. Make sure not to share MediaEngines between PeerConnections.
disable_media_engine_copy(&mut self, is_disabled: bool)304     pub fn disable_media_engine_copy(&mut self, is_disabled: bool) {
305         self.disable_media_engine_copy = is_disabled;
306     }
307 
308     /// set_receive_mtu sets the size of read buffer that copies incoming packets. This is optional.
309     /// Leave this 0 for the default receive_mtu
set_receive_mtu(&mut self, receive_mtu: usize)310     pub fn set_receive_mtu(&mut self, receive_mtu: usize) {
311         self.receive_mtu = receive_mtu;
312     }
313 
314     /// Sets a callback used to generate mid for transceivers created by this side of the RTCPeerconnection.
315     /// By having separate "naming schemes" for mids generated by either side of a connection, it's
316     /// possible to reduce complexity when handling SDP offers/answers clashing.
317     ///
318     /// The `isize` argument is currently greatest seen _numeric_ mid. Since mids don't need to be numeric
319     /// this doesn't necessarily indicating anything.
320     ///
321     /// Note that the spec says: All MID values MUST be generated in a fashion that does not leak user
322     /// information, e.g., randomly or using a per-PeerConnection counter, and SHOULD be 3 bytes or less,
323     /// to allow them to efficiently fit into the RTP header extension
set_mid_generator(&mut self, f: impl Fn(isize) -> String + Send + Sync + 'static)324     pub fn set_mid_generator(&mut self, f: impl Fn(isize) -> String + Send + Sync + 'static) {
325         self.mid_generator = Some(Arc::new(f));
326     }
327 }
328