1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
use rcgen::RcgenError;
use std::future::Future;
use std::num::ParseIntError;
use std::pin::Pin;
use std::string::FromUtf8Error;
use thiserror::Error;
use tokio::sync::mpsc::error::SendError as MpscSendError;
use crate::peer_connection::sdp::sdp_type::RTCSdpType;
use crate::peer_connection::signaling_state::RTCSignalingState;
use crate::rtp_transceiver::rtp_receiver;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug, PartialEq)]
#[non_exhaustive]
pub enum Error {
#[error("unknown")]
ErrUnknownType,
#[error("connection closed")]
ErrConnectionClosed,
#[error("data channel not open")]
ErrDataChannelNotOpen,
#[error("x509Cert expired")]
ErrCertificateExpired,
#[error("turn server credentials required")]
ErrNoTurnCredentials,
#[error("invalid turn server credentials")]
ErrTurnCredentials,
#[error("track already exists")]
ErrExistingTrack,
#[error("private key type not supported")]
ErrPrivateKeyType,
#[error("peerIdentity cannot be modified")]
ErrModifyingPeerIdentity,
#[error("certificates cannot be modified")]
ErrModifyingCertificates,
#[error("no certificate")]
ErrNonCertificate,
#[error("bundle policy cannot be modified")]
ErrModifyingBundlePolicy,
#[error("rtcp mux policy cannot be modified")]
ErrModifyingRTCPMuxPolicy,
#[error("ice candidate pool size cannot be modified")]
ErrModifyingICECandidatePoolSize,
#[error("data channel label exceeds size limit")]
ErrStringSizeLimit,
#[error("maximum number ID for datachannel specified")]
ErrMaxDataChannelID,
#[error("negotiated set without channel id")]
ErrNegotiatedWithoutID,
#[error("both max_packet_life_time and max_retransmits was set")]
ErrRetransmitsOrPacketLifeTime,
#[error("codec not found")]
ErrCodecNotFound,
#[error("remote description is not set")]
ErrNoRemoteDescription,
#[error("offer SDP semantics does not match configuration")]
ErrIncorrectSDPSemantics,
#[error("operation can not be run in current signaling state")]
ErrIncorrectSignalingState,
#[error("protocol is larger then 65535 bytes")]
ErrProtocolTooLarge,
#[error("RtpSender not created by this PeerConnection")]
ErrSenderNotCreatedByConnection,
#[error("RtpSender's initial_track_id has already been set")]
ErrSenderInitialTrackIdAlreadySet,
#[error("set_remote_description called with no fingerprint")]
ErrSessionDescriptionNoFingerprint,
#[error("set_remote_description called with an invalid fingerprint")]
ErrSessionDescriptionInvalidFingerprint,
#[error("set_remote_description called with multiple conflicting fingerprint")]
ErrSessionDescriptionConflictingFingerprints,
#[error("set_remote_description called with no ice-ufrag")]
ErrSessionDescriptionMissingIceUfrag,
#[error("set_remote_description called with no ice-pwd")]
ErrSessionDescriptionMissingIcePwd,
#[error("set_remote_description called with multiple conflicting ice-ufrag values")]
ErrSessionDescriptionConflictingIceUfrag,
#[error("set_remote_description called with multiple conflicting ice-pwd values")]
ErrSessionDescriptionConflictingIcePwd,
#[error("DTLS Handshake completed and no SRTP Protection Profile was chosen")]
ErrNoSRTPProtectionProfile,
#[error("failed to generate certificate fingerprint")]
ErrFailedToGenerateCertificateFingerprint,
#[error("operation failed no codecs are available")]
ErrNoCodecsAvailable,
#[error("unable to start track, codec is not supported by remote")]
ErrUnsupportedCodec,
#[error("unable to populate media section, RTPSender created with no codecs")]
ErrSenderWithNoCodecs,
#[error("new track must be of the same kind as previous")]
ErrRTPSenderNewTrackHasIncorrectKind,
#[error("failed to unbind TrackLocal from PeerConnection")]
ErrUnbindFailed,
#[error("the requested codec does not have a payloader")]
ErrNoPayloaderForCodec,
#[error("a header extension must be registered as 'recvonly', 'sendonly' or both")]
ErrRegisterHeaderExtensionInvalidDirection,
#[error("no header extension ID was free to use(this means the maximum of 15 extensions have been registered)")]
ErrRegisterHeaderExtensionNoFreeID,
#[error("simulcast probe limit has been reached, new SSRC has been discarded")]
ErrSimulcastProbeOverflow,
#[error("enable detaching by calling webrtc.DetachDataChannels()")]
ErrDetachNotEnabled,
#[error("datachannel not opened yet, try calling Detach from OnOpen")]
ErrDetachBeforeOpened,
#[error("the DTLS transport has not started yet")]
ErrDtlsTransportNotStarted,
#[error("failed extracting keys from DTLS for SRTP")]
ErrDtlsKeyExtractionFailed,
#[error("failed to start SRTP")]
ErrFailedToStartSRTP,
#[error("failed to start SRTCP")]
ErrFailedToStartSRTCP,
#[error("attempted to start DTLSTransport that is not in new state")]
ErrInvalidDTLSStart,
#[error("peer didn't provide certificate via DTLS")]
ErrNoRemoteCertificate,
#[error("identity provider is not implemented")]
ErrIdentityProviderNotImplemented,
#[error("remote certificate does not match any fingerprint")]
ErrNoMatchingCertificateFingerprint,
#[error("unsupported fingerprint algorithm")]
ErrUnsupportedFingerprintAlgorithm,
#[error("ICE connection not started")]
ErrICEConnectionNotStarted,
#[error("unknown candidate type")]
ErrICECandidateTypeUnknown,
#[error("cannot convert ice.CandidateType into webrtc.ICECandidateType, invalid type")]
ErrICEInvalidConvertCandidateType,
#[error("ICEAgent does not exist")]
ErrICEAgentNotExist,
#[error("unable to convert ICE candidates to ICECandidates")]
ErrICECandiatesCoversionFailed,
#[error("unknown ICE Role")]
ErrICERoleUnknown,
#[error("unknown protocol")]
ErrICEProtocolUnknown,
#[error("gatherer not started")]
ErrICEGathererNotStarted,
#[error("unknown network type")]
ErrNetworkTypeUnknown,
#[error("new sdp does not match previous offer")]
ErrSDPDoesNotMatchOffer,
#[error("new sdp does not match previous answer")]
ErrSDPDoesNotMatchAnswer,
#[error("provided value is not a valid enum value of type SDPType")]
ErrPeerConnSDPTypeInvalidValue,
#[error("invalid state change op")]
ErrPeerConnStateChangeInvalid,
#[error("unhandled state change op")]
ErrPeerConnStateChangeUnhandled,
#[error("invalid SDP type supplied to SetLocalDescription()")]
ErrPeerConnSDPTypeInvalidValueSetLocalDescription,
#[error("remoteDescription contained media section without mid value")]
ErrPeerConnRemoteDescriptionWithoutMidValue,
#[error("remoteDescription has not been set yet")]
ErrPeerConnRemoteDescriptionNil,
#[error("single media section has an explicit SSRC")]
ErrPeerConnSingleMediaSectionHasExplicitSSRC,
#[error("could not add transceiver for remote SSRC")]
ErrPeerConnRemoteSSRCAddTransceiver,
#[error("mid RTP Extensions required for Simulcast")]
ErrPeerConnSimulcastMidRTPExtensionRequired,
#[error("stream id RTP Extensions required for Simulcast")]
ErrPeerConnSimulcastStreamIDRTPExtensionRequired,
#[error("incoming SSRC failed Simulcast probing")]
ErrPeerConnSimulcastIncomingSSRCFailed,
#[error("failed collecting stats")]
ErrPeerConnStatsCollectionFailed,
#[error("add_transceiver_from_kind only accepts one RTPTransceiverInit")]
ErrPeerConnAddTransceiverFromKindOnlyAcceptsOne,
#[error("add_transceiver_from_track only accepts one RTPTransceiverInit")]
ErrPeerConnAddTransceiverFromTrackOnlyAcceptsOne,
#[error("add_transceiver_from_kind currently only supports recvonly")]
ErrPeerConnAddTransceiverFromKindSupport,
#[error("add_transceiver_from_track currently only supports sendonly and sendrecv")]
ErrPeerConnAddTransceiverFromTrackSupport,
#[error("TODO set_identity_provider")]
ErrPeerConnSetIdentityProviderNotImplemented,
#[error("write_rtcp failed to open write_stream")]
ErrPeerConnWriteRTCPOpenWriteStream,
#[error("cannot find transceiver with mid")]
ErrPeerConnTranscieverMidNil,
#[error("DTLSTransport must not be nil")]
ErrRTPReceiverDTLSTransportNil,
#[error("Receive has already been called")]
ErrRTPReceiverReceiveAlreadyCalled,
#[error("unable to find stream for Track with SSRC")]
ErrRTPReceiverWithSSRCTrackStreamNotFound,
#[error("no trackStreams found for SSRC")]
ErrRTPReceiverForSSRCTrackStreamNotFound,
#[error("no trackStreams found for RID")]
ErrRTPReceiverForRIDTrackStreamNotFound,
#[error("invalid RTP Receiver transition from {from} to {to}")]
ErrRTPReceiverStateChangeInvalid {
from: rtp_receiver::State,
to: rtp_receiver::State,
},
#[error("Track must not be nil")]
ErrRTPSenderTrackNil,
#[error("RTPSender must not be nil")]
ErrRTPSenderNil,
#[error("RTPReceiver must not be nil")]
ErrRTPReceiverNil,
#[error("DTLSTransport must not be nil")]
ErrRTPSenderDTLSTransportNil,
#[error("Send has already been called")]
ErrRTPSenderSendAlreadyCalled,
#[error("errRTPSenderTrackNil")]
ErrRTPTransceiverCannotChangeMid,
#[error("invalid state change in RTPTransceiver.setSending")]
ErrRTPTransceiverSetSendingInvalidState,
#[error("unsupported codec type by this transceiver")]
ErrRTPTransceiverCodecUnsupported,
#[error("DTLS not established")]
ErrSCTPTransportDTLS,
#[error("add_transceiver_sdp() called with 0 transceivers")]
ErrSDPZeroTransceivers,
#[error("invalid Media Section. Media + DataChannel both enabled")]
ErrSDPMediaSectionMediaDataChanInvalid,
#[error(
"invalid Media Section. Can not have multiple tracks in one MediaSection in UnifiedPlan"
)]
ErrSDPMediaSectionMultipleTrackInvalid,
#[error("set_answering_dtlsrole must DTLSRoleClient or DTLSRoleServer")]
ErrSettingEngineSetAnsweringDTLSRole,
#[error("can't rollback from stable state")]
ErrSignalingStateCannotRollback,
#[error(
"invalid proposed signaling state transition from {} applying {} {}",
from,
if *is_local { "local" } else { "remote" },
applying
)]
ErrSignalingStateProposedTransitionInvalid {
from: RTCSignalingState,
applying: RTCSdpType,
is_local: bool,
},
#[error("cannot convert to StatsICECandidatePairStateSucceeded invalid ice candidate state")]
ErrStatsICECandidateStateInvalid,
#[error("ICETransport can only be called in ICETransportStateNew")]
ErrICETransportNotInNew,
#[error("bad Certificate PEM format")]
ErrCertificatePEMFormatError,
#[error("SCTP is not established")]
ErrSCTPNotEstablished,
#[error("DataChannel is not opened")]
ErrClosedPipe,
#[error("Interceptor is not bind")]
ErrInterceptorNotBind,
#[error("excessive retries in CreateOffer")]
ErrExcessiveRetries,
#[error("not long enough to be a RTP Packet")]
ErrRTPTooShort,
#[error("{0}")]
Util(#[from] util::Error),
#[error("{0}")]
Ice(#[from] ice::Error),
#[error("{0}")]
Srtp(#[from] srtp::Error),
#[error("{0}")]
Dtls(#[from] dtls::Error),
#[error("{0}")]
Data(#[from] data::Error),
#[error("{0}")]
Sctp(#[from] sctp::Error),
#[error("{0}")]
Sdp(#[from] sdp::Error),
#[error("{0}")]
Interceptor(#[from] interceptor::Error),
#[error("{0}")]
Rtcp(#[from] rtcp::Error),
#[error("{0}")]
Rtp(#[from] rtp::Error),
#[error("utf-8 error: {0}")]
Utf8(#[from] FromUtf8Error),
#[error("{0}")]
RcGen(#[from] RcgenError),
#[error("mpsc send: {0}")]
MpscSend(String),
#[error("parse int: {0}")]
ParseInt(#[from] ParseIntError),
#[error("parse url: {0}")]
ParseUrl(#[from] url::ParseError),
#[allow(non_camel_case_types)]
#[error("{0}")]
new(String),
}
pub type OnErrorHdlrFn =
Box<dyn (FnMut(Error) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>) + Send + Sync>;
impl<T> From<MpscSendError<T>> for Error {
fn from(e: MpscSendError<T>) -> Self {
Error::MpscSend(e.to_string())
}
}
impl From<Error> for interceptor::Error {
fn from(e: Error) -> Self {
interceptor::Error::Util(util::Error::from_std(e))
}
}
impl PartialEq<ice::Error> for Error {
fn eq(&self, other: &ice::Error) -> bool {
if let Error::Ice(e) = self {
return e == other;
}
false
}
}
pub fn flatten_errs(errs: Vec<impl Into<Error>>) -> Result<()> {
if errs.is_empty() {
Ok(())
} else {
let errs_strs: Vec<String> = errs.into_iter().map(|e| e.into().to_string()).collect();
Err(Error::new(errs_strs.join("\n")))
}
}