4444a3a79bbfccbd0e037a5b203fcf08dcaf3b02
[WebKit-https.git] / Source / WebCore / Modules / mediastream / MediaEndpointPeerConnection.cpp
1 /*
2  * Copyright (C) 2015 Ericsson AB. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of Ericsson nor the names of its contributors
15  *    may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(WEB_RTC)
34 #include "MediaEndpointPeerConnection.h"
35
36 #include "EventNames.h"
37 #include "JSRTCSessionDescription.h"
38 #include "MediaEndpointSessionConfiguration.h"
39 #include "MediaStream.h"
40 #include "MediaStreamEvent.h"
41 #include "MediaStreamTrack.h"
42 #include "NotImplemented.h"
43 #include "PeerMediaDescription.h"
44 #include "RTCConfiguration.h"
45 #include "RTCIceCandidate.h"
46 #include "RTCIceCandidateEvent.h"
47 #include "RTCOfferAnswerOptions.h"
48 #include "RTCRtpTransceiver.h"
49 #include "RTCTrackEvent.h"
50 #include "SDPProcessor.h"
51 #include <wtf/MainThread.h>
52 #include <wtf/text/Base64.h>
53
54 namespace WebCore {
55
56 using namespace PeerConnection;
57 using namespace PeerConnectionStates;
58
59 // We use base64 to generate the random strings so we need a size that avoids padding to get ice-chars.
60 static const size_t cnameSize = 18;
61 // Size range from 4 to 256 ice-chars defined in RFC 5245.
62 static const size_t iceUfragSize = 6;
63 // Size range from 22 to 256 ice-chars defined in RFC 5245.
64 static const size_t icePasswordSize = 24;
65
66 static std::unique_ptr<PeerConnectionBackend> createMediaEndpointPeerConnection(PeerConnectionBackendClient* client)
67 {
68     return std::unique_ptr<PeerConnectionBackend>(new MediaEndpointPeerConnection(client));
69 }
70
71 CreatePeerConnectionBackend PeerConnectionBackend::create = createMediaEndpointPeerConnection;
72
73 static String randomString(size_t size)
74 {
75     unsigned char randomValues[size];
76     cryptographicallyRandomValues(randomValues, size);
77     return base64Encode(randomValues, size);
78 }
79
80 MediaEndpointPeerConnection::MediaEndpointPeerConnection(PeerConnectionBackendClient* client)
81     : m_client(client)
82     , m_mediaEndpoint(MediaEndpoint::create(*this))
83     , m_sdpProcessor(std::unique_ptr<SDPProcessor>(new SDPProcessor(m_client->scriptExecutionContext())))
84     , m_cname(randomString(cnameSize))
85     , m_iceUfrag(randomString(iceUfragSize))
86     , m_icePassword(randomString(icePasswordSize))
87 {
88     ASSERT(m_mediaEndpoint);
89
90     m_defaultAudioPayloads = m_mediaEndpoint->getDefaultAudioPayloads();
91     m_defaultVideoPayloads = m_mediaEndpoint->getDefaultVideoPayloads();
92
93     // Tasks (see runTask()) will be deferred until we get the DTLS fingerprint.
94     m_mediaEndpoint->generateDtlsInfo();
95 }
96
97 static RTCRtpTransceiver* matchTransceiver(const RtpTransceiverVector& transceivers, const std::function<bool(RTCRtpTransceiver&)>& matchFunction)
98 {
99     for (auto& transceiver : transceivers) {
100         if (matchFunction(*transceiver))
101             return transceiver.get();
102     }
103     return nullptr;
104 }
105
106 static RTCRtpTransceiver* matchTransceiverByMid(const RtpTransceiverVector& transceivers, const String& mid)
107 {
108     return matchTransceiver(transceivers, [&mid] (RTCRtpTransceiver& current) {
109         return current.mid() == mid;
110     });
111 }
112
113 static bool hasUnassociatedTransceivers(const RtpTransceiverVector& transceivers)
114 {
115     return matchTransceiver(transceivers, [] (RTCRtpTransceiver& current) {
116         return current.mid().isNull() && !current.stopped();
117     });
118 }
119
120 void MediaEndpointPeerConnection::runTask(Function<void ()>&& task)
121 {
122     if (m_dtlsFingerprint.isNull()) {
123         // Only one task needs to be deferred since it will hold off any others until completed.
124         ASSERT(!m_initialDeferredTask);
125         m_initialDeferredTask = WTFMove(task);
126     } else
127         callOnMainThread(WTFMove(task));
128 }
129
130 void MediaEndpointPeerConnection::startRunningTasks()
131 {
132     if (!m_initialDeferredTask)
133         return;
134
135     m_initialDeferredTask();
136     m_initialDeferredTask = nullptr;
137 }
138
139 void MediaEndpointPeerConnection::createOffer(RTCOfferOptions& options, SessionDescriptionPromise&& promise)
140 {
141     runTask([this, protectedOptions = RefPtr<RTCOfferOptions>(&options), protectedPromise = WTFMove(promise)]() mutable {
142         createOfferTask(*protectedOptions, protectedPromise);
143     });
144 }
145
146 void MediaEndpointPeerConnection::createOfferTask(RTCOfferOptions&, SessionDescriptionPromise& promise)
147 {
148     ASSERT(!m_dtlsFingerprint.isEmpty());
149
150     if (m_client->internalSignalingState() == SignalingState::Closed)
151         return;
152
153     MediaEndpointSessionDescription* localDescription = internalLocalDescription();
154     RefPtr<MediaEndpointSessionConfiguration> configurationSnapshot = localDescription ?
155         localDescription->configuration()->clone() : MediaEndpointSessionConfiguration::create();
156
157     configurationSnapshot->setSessionVersion(m_sdpOfferSessionVersion++);
158
159     auto transceivers = RtpTransceiverVector(m_client->getTransceivers());
160
161     // Remove any transceiver objects from transceivers that can be matched to an existing media description.
162     for (auto& mediaDescription : configurationSnapshot->mediaDescriptions()) {
163         if (!mediaDescription->port()) {
164             // This media description should be recycled.
165             continue;
166         }
167
168         RTCRtpTransceiver* transceiver = matchTransceiverByMid(transceivers, mediaDescription->mid());
169         if (!transceiver)
170             continue;
171
172         mediaDescription->setMode(transceiver->directionString());
173         if (transceiver->hasSendingDirection()) {
174             RTCRtpSender& sender = *transceiver->sender();
175
176             mediaDescription->setMediaStreamId(sender.mediaStreamIds()[0]);
177             mediaDescription->setMediaStreamTrackId(sender.trackId());
178         }
179
180         transceivers.removeFirst(transceiver);
181     }
182
183     // Add media descriptions for remaining transceivers.
184     for (auto& transceiver : transceivers) {
185         RefPtr<PeerMediaDescription> mediaDescription = PeerMediaDescription::create();
186         RTCRtpSender& sender = *transceiver->sender();
187
188         mediaDescription->setMode(transceiver->directionString());
189         mediaDescription->setMid(transceiver->provisionalMid());
190         mediaDescription->setMediaStreamId(sender.mediaStreamIds()[0]);
191         mediaDescription->setType(sender.trackKind());
192         mediaDescription->setPayloads(sender.trackKind() == "audio" ? m_defaultAudioPayloads : m_defaultVideoPayloads);
193         mediaDescription->setDtlsFingerprintHashFunction(m_dtlsFingerprintFunction);
194         mediaDescription->setDtlsFingerprint(m_dtlsFingerprint);
195         mediaDescription->setCname(m_cname);
196         mediaDescription->addSsrc(cryptographicallyRandomNumber());
197         mediaDescription->setIceUfrag(m_iceUfrag);
198         mediaDescription->setIcePassword(m_icePassword);
199
200         if (sender.track())
201             mediaDescription->setMediaStreamTrackId(sender.trackId());
202
203         configurationSnapshot->addMediaDescription(WTFMove(mediaDescription));
204     }
205
206     auto description = MediaEndpointSessionDescription::create(RTCSessionDescription::SdpType::Offer, WTFMove(configurationSnapshot));
207     promise.resolve(*description->toRTCSessionDescription(*m_sdpProcessor));
208 }
209
210 void MediaEndpointPeerConnection::createAnswer(RTCAnswerOptions& options, SessionDescriptionPromise&& promise)
211 {
212     runTask([this, protectedOptions = RefPtr<RTCAnswerOptions>(&options), protectedPromise = WTFMove(promise)]() mutable {
213         createAnswerTask(*protectedOptions, protectedPromise);
214     });
215 }
216
217 void MediaEndpointPeerConnection::createAnswerTask(RTCAnswerOptions&, SessionDescriptionPromise& promise)
218 {
219     ASSERT(!m_dtlsFingerprint.isEmpty());
220
221     if (m_client->internalSignalingState() == SignalingState::Closed)
222         return;
223
224     if (!internalRemoteDescription()) {
225         promise.reject(INVALID_STATE_ERR, "No remote description set");
226         return;
227     }
228
229     MediaEndpointSessionDescription* localDescription = internalLocalDescription();
230     RefPtr<MediaEndpointSessionConfiguration> configurationSnapshot = localDescription ?
231         localDescription->configuration()->clone() : MediaEndpointSessionConfiguration::create();
232
233     configurationSnapshot->setSessionVersion(m_sdpAnswerSessionVersion++);
234
235     auto transceivers = RtpTransceiverVector(m_client->getTransceivers());
236     const MediaDescriptionVector& remoteMediaDescriptions = internalRemoteDescription()->configuration()->mediaDescriptions();
237
238     for (unsigned i = 0; i < remoteMediaDescriptions.size(); ++i) {
239         PeerMediaDescription& remoteMediaDescription = *remoteMediaDescriptions[i];
240
241         RTCRtpTransceiver* transceiver = matchTransceiverByMid(transceivers, remoteMediaDescription.mid());
242         if (!transceiver) {
243             LOG_ERROR("Could not find a matching transceiver for remote description while creating answer");
244             continue;
245         }
246
247         if (i >= configurationSnapshot->mediaDescriptions().size()) {
248             auto newMediaDescription = PeerMediaDescription::create();
249
250             RTCRtpSender& sender = *transceiver->sender();
251             if (sender.track()) {
252                 if (sender.mediaStreamIds().size())
253                     newMediaDescription->setMediaStreamId(sender.mediaStreamIds()[0]);
254                 newMediaDescription->setMediaStreamTrackId(sender.trackId());
255                 newMediaDescription->addSsrc(cryptographicallyRandomNumber());
256             }
257
258             newMediaDescription->setMode(transceiver->directionString());
259             newMediaDescription->setType(remoteMediaDescription.type());
260             newMediaDescription->setMid(remoteMediaDescription.mid());
261             newMediaDescription->setDtlsSetup(remoteMediaDescription.dtlsSetup() == "active" ? "passive" : "active");
262             newMediaDescription->setDtlsFingerprintHashFunction(m_dtlsFingerprintFunction);
263             newMediaDescription->setDtlsFingerprint(m_dtlsFingerprint);
264             newMediaDescription->setCname(m_cname);
265             newMediaDescription->setIceUfrag(m_iceUfrag);
266             newMediaDescription->setIcePassword(m_icePassword);
267
268             configurationSnapshot->addMediaDescription(WTFMove(newMediaDescription));
269         }
270
271         PeerMediaDescription& localMediaDescription = *configurationSnapshot->mediaDescriptions()[i];
272
273         localMediaDescription.setPayloads(remoteMediaDescription.payloads());
274         localMediaDescription.setRtcpMux(remoteMediaDescription.rtcpMux());
275
276         if (!localMediaDescription.ssrcs().size())
277             localMediaDescription.addSsrc(cryptographicallyRandomNumber());
278
279         if (localMediaDescription.dtlsSetup() == "actpass")
280             localMediaDescription.setDtlsSetup("passive");
281
282         transceivers.removeFirst(transceiver);
283     }
284
285     // Unassociated (non-stopped) transceivers need to be negotiated in a follow-up offer.
286     if (hasUnassociatedTransceivers(transceivers))
287         markAsNeedingNegotiation();
288
289     auto description = MediaEndpointSessionDescription::create(RTCSessionDescription::SdpType::Answer, WTFMove(configurationSnapshot));
290     promise.resolve(*description->toRTCSessionDescription(*m_sdpProcessor));
291 }
292
293 static RealtimeMediaSourceMap createSourceMap(const MediaDescriptionVector& remoteMediaDescriptions, unsigned localMediaDescriptionCount, const RtpTransceiverVector& transceivers)
294 {
295     RealtimeMediaSourceMap sourceMap;
296
297     for (unsigned i = 0; i < remoteMediaDescriptions.size() && i < localMediaDescriptionCount; ++i) {
298         PeerMediaDescription& remoteMediaDescription = *remoteMediaDescriptions[i];
299         if (remoteMediaDescription.type() != "audio" && remoteMediaDescription.type() != "video")
300             continue;
301
302         RTCRtpTransceiver* transceiver = matchTransceiverByMid(transceivers, remoteMediaDescription.mid());
303         if (transceiver) {
304             if (transceiver->hasSendingDirection() && transceiver->sender()->track())
305                 sourceMap.set(transceiver->mid(), &transceiver->sender()->track()->source());
306             break;
307         }
308     }
309
310     return sourceMap;
311 }
312
313 void MediaEndpointPeerConnection::setLocalDescription(RTCSessionDescription& description, VoidPromise&& promise)
314 {
315     runTask([this, protectedDescription = RefPtr<RTCSessionDescription>(&description), protectedPromise = WTFMove(promise)]() mutable {
316         setLocalDescriptionTask(WTFMove(protectedDescription), protectedPromise);
317     });
318 }
319
320 void MediaEndpointPeerConnection::setLocalDescriptionTask(RefPtr<RTCSessionDescription>&& description, VoidPromise& promise)
321 {
322     if (m_client->internalSignalingState() == SignalingState::Closed)
323         return;
324
325     auto result = MediaEndpointSessionDescription::create(WTFMove(description), *m_sdpProcessor);
326     if (result.hasException()) {
327         promise.reject(result.releaseException());
328         return;
329     }
330     auto newDescription = result.releaseReturnValue();
331
332     if (!localDescriptionTypeValidForState(newDescription->type())) {
333         promise.reject(INVALID_STATE_ERR, "Description type incompatible with current signaling state");
334         return;
335     }
336
337     const RtpTransceiverVector& transceivers = m_client->getTransceivers();
338     const MediaDescriptionVector& mediaDescriptions = newDescription->configuration()->mediaDescriptions();
339     MediaEndpointSessionDescription* localDescription = internalLocalDescription();
340     unsigned previousNumberOfMediaDescriptions = localDescription ? localDescription->configuration()->mediaDescriptions().size() : 0;
341     bool hasNewMediaDescriptions = mediaDescriptions.size() > previousNumberOfMediaDescriptions;
342     bool isInitiator = newDescription->type() == RTCSessionDescription::SdpType::Offer;
343
344     if (hasNewMediaDescriptions) {
345         MediaEndpoint::UpdateResult result = m_mediaEndpoint->updateReceiveConfiguration(newDescription->configuration(), isInitiator);
346
347         if (result == MediaEndpoint::UpdateResult::SuccessWithIceRestart) {
348             if (m_client->internalIceGatheringState() != IceGatheringState::Gathering)
349                 m_client->updateIceGatheringState(IceGatheringState::Gathering);
350
351             if (m_client->internalIceConnectionState() != IceConnectionState::Completed)
352                 m_client->updateIceConnectionState(IceConnectionState::Connected);
353
354             LOG_ERROR("ICE restart is not implemented");
355             notImplemented();
356
357         } else if (result == MediaEndpoint::UpdateResult::Failed) {
358             promise.reject(OperationError, "Unable to apply session description");
359             return;
360         }
361
362         // Associate media descriptions with transceivers (set provisional mid to 'final' mid).
363         for (unsigned i = previousNumberOfMediaDescriptions; i < mediaDescriptions.size(); ++i) {
364             PeerMediaDescription& mediaDescription = *mediaDescriptions[i];
365
366             RTCRtpTransceiver* transceiver = matchTransceiver(transceivers, [&mediaDescription] (RTCRtpTransceiver& current) {
367                 return current.provisionalMid() == mediaDescription.mid();
368             });
369             if (transceiver)
370                 transceiver->setMid(transceiver->provisionalMid());
371         }
372     }
373
374     if (internalRemoteDescription()) {
375         MediaEndpointSessionConfiguration* remoteConfiguration = internalRemoteDescription()->configuration();
376         RealtimeMediaSourceMap sendSourceMap = createSourceMap(remoteConfiguration->mediaDescriptions(), mediaDescriptions.size(), transceivers);
377
378         if (m_mediaEndpoint->updateSendConfiguration(remoteConfiguration, sendSourceMap, isInitiator) == MediaEndpoint::UpdateResult::Failed) {
379             promise.reject(OperationError, "Unable to apply session description");
380             return;
381         }
382     }
383
384     if (!hasUnassociatedTransceivers(transceivers))
385         clearNegotiationNeededState();
386
387     SignalingState newSignalingState;
388
389     // Update state and local descriptions according to setLocal/RemoteDescription processing model
390     switch (newDescription->type()) {
391     case RTCSessionDescription::SdpType::Offer:
392         m_pendingLocalDescription = WTFMove(newDescription);
393         newSignalingState = SignalingState::HaveLocalOffer;
394         break;
395
396     case RTCSessionDescription::SdpType::Answer:
397         m_currentLocalDescription = WTFMove(newDescription);
398         m_currentRemoteDescription = m_pendingRemoteDescription;
399         m_pendingLocalDescription = nullptr;
400         m_pendingRemoteDescription = nullptr;
401         newSignalingState = SignalingState::Stable;
402         break;
403
404     case RTCSessionDescription::SdpType::Rollback:
405         m_pendingLocalDescription = nullptr;
406         newSignalingState = SignalingState::Stable;
407         break;
408
409     case RTCSessionDescription::SdpType::Pranswer:
410         m_pendingLocalDescription = WTFMove(newDescription);
411         newSignalingState = SignalingState::HaveLocalPrAnswer;
412         break;
413     }
414
415     if (newSignalingState != m_client->internalSignalingState()) {
416         m_client->setSignalingState(newSignalingState);
417         m_client->fireEvent(Event::create(eventNames().signalingstatechangeEvent, false, false));
418     }
419
420     if (m_client->internalIceGatheringState() == IceGatheringState::New && mediaDescriptions.size())
421         m_client->updateIceGatheringState(IceGatheringState::Gathering);
422
423     if (m_client->internalSignalingState() == SignalingState::Stable && m_negotiationNeeded)
424         m_client->scheduleNegotiationNeededEvent();
425
426     promise.resolve(nullptr);
427 }
428
429 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::localDescription() const
430 {
431     return createRTCSessionDescription(internalLocalDescription());
432 }
433
434 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::currentLocalDescription() const
435 {
436     return createRTCSessionDescription(m_currentLocalDescription.get());
437 }
438
439 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::pendingLocalDescription() const
440 {
441     return createRTCSessionDescription(m_pendingLocalDescription.get());
442 }
443
444 void MediaEndpointPeerConnection::setRemoteDescription(RTCSessionDescription& description, VoidPromise&& promise)
445 {
446     runTask([this, protectedDescription = RefPtr<RTCSessionDescription>(&description), protectedPromise = WTFMove(promise)]() mutable {
447         setRemoteDescriptionTask(WTFMove(protectedDescription), protectedPromise);
448     });
449 }
450
451 void MediaEndpointPeerConnection::setRemoteDescriptionTask(RefPtr<RTCSessionDescription>&& description, VoidPromise& promise)
452 {
453     if (m_client->internalSignalingState() == SignalingState::Closed)
454         return;
455
456     auto result = MediaEndpointSessionDescription::create(WTFMove(description), *m_sdpProcessor);
457     if (result.hasException()) {
458         promise.reject(result.releaseException());
459         return;
460     }
461     auto newDescription = result.releaseReturnValue();
462
463     if (!remoteDescriptionTypeValidForState(newDescription->type())) {
464         promise.reject(INVALID_STATE_ERR, "Description type incompatible with current signaling state");
465         return;
466     }
467
468     const MediaDescriptionVector& mediaDescriptions = newDescription->configuration()->mediaDescriptions();
469     for (auto& mediaDescription : mediaDescriptions) {
470         if (mediaDescription->type() != "audio" && mediaDescription->type() != "video")
471             continue;
472
473         mediaDescription->setPayloads(m_mediaEndpoint->filterPayloads(mediaDescription->payloads(),
474             mediaDescription->type() == "audio" ? m_defaultAudioPayloads : m_defaultVideoPayloads));
475     }
476
477     bool isInitiator = newDescription->type() == RTCSessionDescription::SdpType::Answer;
478     const RtpTransceiverVector& transceivers = m_client->getTransceivers();
479
480     RealtimeMediaSourceMap sendSourceMap;
481     if (internalLocalDescription())
482         sendSourceMap = createSourceMap(mediaDescriptions, internalLocalDescription()->configuration()->mediaDescriptions().size(), transceivers);
483
484     if (m_mediaEndpoint->updateSendConfiguration(newDescription->configuration(), sendSourceMap, isInitiator) == MediaEndpoint::UpdateResult::Failed) {
485         promise.reject(OperationError, "Unable to apply session description");
486         return;
487     }
488
489     // One legacy MediaStreamEvent will be fired for every new MediaStream created as this remote description is set.
490     Vector<RefPtr<MediaStreamEvent>> legacyMediaStreamEvents;
491
492     for (auto mediaDescription : mediaDescriptions) {
493         RTCRtpTransceiver* transceiver = matchTransceiverByMid(transceivers, mediaDescription->mid());
494         if (!transceiver) {
495             bool receiveOnlyFlag = false;
496
497             if (mediaDescription->mode() == "sendrecv" || mediaDescription->mode() == "recvonly") {
498                 // Try to match an existing transceiver.
499                 transceiver = matchTransceiver(transceivers, [&mediaDescription] (RTCRtpTransceiver& current) {
500                     return !current.stopped() && current.mid().isNull() && current.sender()->trackKind() == mediaDescription->type();
501                 });
502
503                 if (transceiver)
504                     transceiver->setMid(mediaDescription->mid());
505                 else
506                     receiveOnlyFlag = true;
507             }
508
509             if (!transceiver) {
510                 auto sender = RTCRtpSender::create(mediaDescription->type(), Vector<String>(), m_client->senderClient());
511                 auto receiver = createReceiver(mediaDescription->mid(), mediaDescription->type(), mediaDescription->mediaStreamTrackId());
512
513                 auto newTransceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver));
514                 newTransceiver->setMid(mediaDescription->mid());
515                 if (receiveOnlyFlag)
516                     newTransceiver->disableSendingDirection();
517
518                 transceiver = newTransceiver.ptr();
519                 m_client->addTransceiver(WTFMove(newTransceiver));
520             }
521         }
522
523         if (mediaDescription->mode() == "sendrecv" || mediaDescription->mode() == "sendonly") {
524             RTCRtpReceiver& receiver = *transceiver->receiver();
525             if (receiver.isDispatched())
526                 continue;
527             receiver.setDispatched(true);
528
529             Vector<String> mediaStreamIds;
530             if (!mediaDescription->mediaStreamId().isEmpty())
531                 mediaStreamIds.append(mediaDescription->mediaStreamId());
532
533             // A remote track can be associated with 0..* MediaStreams. We create a new stream for
534             // a track in case of an unrecognized stream id, or just add the track if the stream
535             // already exists.
536             HashMap<String, RefPtr<MediaStream>> trackEventMediaStreams;
537             for (auto& id : mediaStreamIds) {
538                 if (m_remoteStreamMap.contains(id)) {
539                     RefPtr<MediaStream> stream = m_remoteStreamMap.get(id);
540                     stream->addTrack(*receiver.track());
541                     trackEventMediaStreams.add(id, WTFMove(stream));
542                 } else {
543                     auto newStream = MediaStream::create(*m_client->scriptExecutionContext(), MediaStreamTrackVector({ receiver.track() }));
544                     m_remoteStreamMap.add(id, newStream.copyRef());
545                     legacyMediaStreamEvents.append(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, newStream.copyRef()));
546                     trackEventMediaStreams.add(id, WTFMove(newStream));
547                 }
548             }
549
550             Vector<RefPtr<MediaStream>> streams;
551             copyValuesToVector(trackEventMediaStreams, streams);
552
553             m_client->fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false,
554                 &receiver, receiver.track(), WTFMove(streams), transceiver));
555         }
556     }
557
558     // Fire legacy addstream events.
559     for (auto& event : legacyMediaStreamEvents)
560         m_client->fireEvent(*event);
561
562     SignalingState newSignalingState;
563
564     // Update state and local descriptions according to setLocal/RemoteDescription processing model
565     switch (newDescription->type()) {
566     case RTCSessionDescription::SdpType::Offer:
567         m_pendingRemoteDescription = WTFMove(newDescription);
568         newSignalingState = SignalingState::HaveRemoteOffer;
569         break;
570
571     case RTCSessionDescription::SdpType::Answer:
572         m_currentRemoteDescription = WTFMove(newDescription);
573         m_currentLocalDescription = m_pendingLocalDescription;
574         m_pendingRemoteDescription = nullptr;
575         m_pendingLocalDescription = nullptr;
576         newSignalingState = SignalingState::Stable;
577         break;
578
579     case RTCSessionDescription::SdpType::Rollback:
580         m_pendingRemoteDescription = nullptr;
581         newSignalingState = SignalingState::Stable;
582         break;
583
584     case RTCSessionDescription::SdpType::Pranswer:
585         m_pendingRemoteDescription = WTFMove(newDescription);
586         newSignalingState = SignalingState::HaveRemotePrAnswer;
587         break;
588     }
589
590     if (newSignalingState != m_client->internalSignalingState()) {
591         m_client->setSignalingState(newSignalingState);
592         m_client->fireEvent(Event::create(eventNames().signalingstatechangeEvent, false, false));
593     }
594
595     promise.resolve(nullptr);
596 }
597
598 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::remoteDescription() const
599 {
600     return createRTCSessionDescription(internalRemoteDescription());
601 }
602
603 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::currentRemoteDescription() const
604 {
605     return createRTCSessionDescription(m_currentRemoteDescription.get());
606 }
607
608 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::pendingRemoteDescription() const
609 {
610     return createRTCSessionDescription(m_pendingRemoteDescription.get());
611 }
612
613 void MediaEndpointPeerConnection::setConfiguration(RTCConfiguration& configuration)
614 {
615     Vector<RefPtr<IceServerInfo>> iceServers;
616     for (auto& server : configuration.iceServers())
617         iceServers.append(IceServerInfo::create(server->urls(), server->credential(), server->username()));
618
619     m_mediaEndpoint->setConfiguration(MediaEndpointConfiguration::create(iceServers, configuration.iceTransportPolicy(), configuration.bundlePolicy()));
620 }
621
622 void MediaEndpointPeerConnection::addIceCandidate(RTCIceCandidate& rtcCandidate, PeerConnection::VoidPromise&& promise)
623 {
624     runTask([this, protectedCandidate = RefPtr<RTCIceCandidate>(&rtcCandidate), protectedPromise = WTFMove(promise)]() mutable {
625         addIceCandidateTask(*protectedCandidate, protectedPromise);
626     });
627 }
628
629 void MediaEndpointPeerConnection::addIceCandidateTask(RTCIceCandidate& rtcCandidate, PeerConnection::VoidPromise& promise)
630 {
631     if (m_client->internalSignalingState() == SignalingState::Closed)
632         return;
633
634     if (!internalRemoteDescription()) {
635         promise.reject(INVALID_STATE_ERR, "No remote description set");
636         return;
637     }
638
639     const MediaDescriptionVector& remoteMediaDescriptions = internalRemoteDescription()->configuration()->mediaDescriptions();
640     PeerMediaDescription* targetMediaDescription = nullptr;
641
642     // When identifying the target media description, sdpMid takes precedence over sdpMLineIndex
643     // if both are present.
644     if (!rtcCandidate.sdpMid().isNull()) {
645         const String& mid = rtcCandidate.sdpMid();
646         for (auto& description : remoteMediaDescriptions) {
647             if (description->mid() == mid) {
648                 targetMediaDescription = description.get();
649                 break;
650             }
651         }
652
653         if (!targetMediaDescription) {
654             promise.reject(OperationError, "sdpMid did not match any media description");
655             return;
656         }
657     } else if (rtcCandidate.sdpMLineIndex()) {
658         unsigned short sdpMLineIndex = rtcCandidate.sdpMLineIndex().value();
659         if (sdpMLineIndex >= remoteMediaDescriptions.size()) {
660             promise.reject(OperationError, "sdpMLineIndex is out of range");
661             return;
662         }
663         targetMediaDescription = remoteMediaDescriptions[sdpMLineIndex].get();
664     } else {
665         ASSERT_NOT_REACHED();
666         return;
667     }
668
669     RefPtr<IceCandidate> candidate;
670     SDPProcessor::Result result = m_sdpProcessor->parseCandidateLine(rtcCandidate.candidate(), candidate);
671     if (result != SDPProcessor::Result::Success) {
672         if (result == SDPProcessor::Result::ParseError)
673             promise.reject(OperationError, "Invalid candidate content");
674         else
675             LOG_ERROR("SDPProcessor internal error");
676         return;
677     }
678
679     targetMediaDescription->addIceCandidate(candidate.copyRef());
680
681     m_mediaEndpoint->addRemoteCandidate(*candidate, targetMediaDescription->mid(), targetMediaDescription->iceUfrag(),
682         targetMediaDescription->icePassword());
683
684     promise.resolve(nullptr);
685 }
686
687 void MediaEndpointPeerConnection::getStats(MediaStreamTrack*, PeerConnection::StatsPromise&& promise)
688 {
689     notImplemented();
690
691     promise.reject(NOT_SUPPORTED_ERR);
692 }
693
694 Vector<RefPtr<MediaStream>> MediaEndpointPeerConnection::getRemoteStreams() const
695 {
696     Vector<RefPtr<MediaStream>> remoteStreams;
697     copyValuesToVector(m_remoteStreamMap, remoteStreams);
698     return remoteStreams;
699 }
700
701 RefPtr<RTCRtpReceiver> MediaEndpointPeerConnection::createReceiver(const String& transceiverMid, const String& trackKind, const String& trackId)
702 {
703     RealtimeMediaSource::Type sourceType = trackKind == "audio" ? RealtimeMediaSource::Type::Audio : RealtimeMediaSource::Type::Video;
704
705     // Create a muted remote source that will be unmuted once media starts arriving.
706     auto remoteSource = m_mediaEndpoint->createMutedRemoteSource(transceiverMid, sourceType);
707     auto remoteTrackPrivate = MediaStreamTrackPrivate::create(WTFMove(remoteSource), trackId);
708     auto remoteTrack = MediaStreamTrack::create(*m_client->scriptExecutionContext(), *remoteTrackPrivate);
709
710     return RTCRtpReceiver::create(WTFMove(remoteTrack));
711 }
712
713 void MediaEndpointPeerConnection::replaceTrack(RTCRtpSender& sender, RefPtr<MediaStreamTrack>&& withTrack, PeerConnection::VoidPromise&& promise)
714 {
715     RTCRtpTransceiver* transceiver = matchTransceiver(m_client->getTransceivers(), [&sender] (RTCRtpTransceiver& current) {
716         return current.sender() == &sender;
717     });
718     ASSERT(transceiver);
719
720     const String& mid = transceiver->mid();
721     if (mid.isNull()) {
722         // Transceiver is not associated with a media description yet.
723         sender.setTrack(WTFMove(withTrack));
724         promise.resolve(nullptr);
725         return;
726     }
727
728     runTask([this, protectedSender = RefPtr<RTCRtpSender>(&sender), mid, protectedTrack = WTFMove(withTrack), protectedPromise = WTFMove(promise)]() mutable {
729         replaceTrackTask(*protectedSender, mid, WTFMove(protectedTrack), protectedPromise);
730     });
731 }
732
733 void MediaEndpointPeerConnection::replaceTrackTask(RTCRtpSender& sender, const String& mid, RefPtr<MediaStreamTrack>&& withTrack, PeerConnection::VoidPromise& promise)
734 {
735     if (m_client->internalSignalingState() == SignalingState::Closed)
736         return;
737
738     m_mediaEndpoint->replaceSendSource(withTrack->source(), mid);
739
740     sender.setTrack(WTFMove(withTrack));
741     promise.resolve(nullptr);
742 }
743
744 void MediaEndpointPeerConnection::stop()
745 {
746     notImplemented();
747 }
748
749 void MediaEndpointPeerConnection::markAsNeedingNegotiation()
750 {
751     if (m_negotiationNeeded)
752         return;
753
754     m_negotiationNeeded = true;
755
756     if (m_client->internalSignalingState() == SignalingState::Stable)
757         m_client->scheduleNegotiationNeededEvent();
758 }
759
760 void MediaEndpointPeerConnection::emulatePlatformEvent(const String& action)
761 {
762     m_mediaEndpoint->emulatePlatformEvent(action);
763 }
764
765 bool MediaEndpointPeerConnection::localDescriptionTypeValidForState(RTCSessionDescription::SdpType type) const
766 {
767     switch (m_client->internalSignalingState()) {
768     case SignalingState::Stable:
769         return type == RTCSessionDescription::SdpType::Offer;
770     case SignalingState::HaveLocalOffer:
771         return type == RTCSessionDescription::SdpType::Offer;
772     case SignalingState::HaveRemoteOffer:
773         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
774     case SignalingState::HaveLocalPrAnswer:
775         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
776     default:
777         return false;
778     };
779
780     ASSERT_NOT_REACHED();
781     return false;
782 }
783
784 bool MediaEndpointPeerConnection::remoteDescriptionTypeValidForState(RTCSessionDescription::SdpType type) const
785 {
786     switch (m_client->internalSignalingState()) {
787     case SignalingState::Stable:
788         return type == RTCSessionDescription::SdpType::Offer;
789     case SignalingState::HaveLocalOffer:
790         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
791     case SignalingState::HaveRemoteOffer:
792         return type == RTCSessionDescription::SdpType::Offer;
793     case SignalingState::HaveRemotePrAnswer:
794         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
795     default:
796         return false;
797     };
798
799     ASSERT_NOT_REACHED();
800     return false;
801 }
802
803 MediaEndpointSessionDescription* MediaEndpointPeerConnection::internalLocalDescription() const
804 {
805     return m_pendingLocalDescription ? m_pendingLocalDescription.get() : m_currentLocalDescription.get();
806 }
807
808 MediaEndpointSessionDescription* MediaEndpointPeerConnection::internalRemoteDescription() const
809 {
810     return m_pendingRemoteDescription ? m_pendingRemoteDescription.get() : m_currentRemoteDescription.get();
811 }
812
813 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::createRTCSessionDescription(MediaEndpointSessionDescription* description) const
814 {
815     return description ? description->toRTCSessionDescription(*m_sdpProcessor) : nullptr;
816 }
817
818 void MediaEndpointPeerConnection::gotDtlsFingerprint(const String& fingerprint, const String& fingerprintFunction)
819 {
820     ASSERT(isMainThread());
821
822     m_dtlsFingerprint = fingerprint;
823     m_dtlsFingerprintFunction = fingerprintFunction;
824
825     startRunningTasks();
826 }
827
828 void MediaEndpointPeerConnection::gotIceCandidate(const String& mid, RefPtr<IceCandidate>&& candidate)
829 {
830     ASSERT(isMainThread());
831
832     const MediaDescriptionVector& mediaDescriptions = internalLocalDescription()->configuration()->mediaDescriptions();
833     size_t mediaDescriptionIndex = notFound;
834
835     for (size_t i = 0; i < mediaDescriptions.size(); ++i) {
836         if (mediaDescriptions[i]->mid() == mid) {
837             mediaDescriptionIndex = i;
838             break;
839         }
840     }
841     ASSERT(mediaDescriptionIndex != notFound);
842
843     PeerMediaDescription& mediaDescription = *mediaDescriptions[mediaDescriptionIndex];
844     mediaDescription.addIceCandidate(candidate.copyRef());
845
846     String candidateLine;
847     SDPProcessor::Result result = m_sdpProcessor->generateCandidateLine(*candidate, candidateLine);
848     if (result != SDPProcessor::Result::Success) {
849         LOG_ERROR("SDPProcessor internal error");
850         return;
851     }
852
853     RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(candidateLine, mid, mediaDescriptionIndex);
854
855     m_client->fireEvent(RTCIceCandidateEvent::create(false, false, WTFMove(iceCandidate)));
856 }
857
858 void MediaEndpointPeerConnection::doneGatheringCandidates(const String& mid)
859 {
860     ASSERT(isMainThread());
861
862     RtpTransceiverVector transceivers = RtpTransceiverVector(m_client->getTransceivers());
863     RTCRtpTransceiver* notifyingTransceiver = matchTransceiverByMid(transceivers, mid);
864     ASSERT(notifyingTransceiver);
865
866     notifyingTransceiver->iceTransport().setGatheringState(RTCIceTransport::GatheringState::Complete);
867
868     // Don't notify the script if there are transceivers still gathering.
869     RTCRtpTransceiver* stillGatheringTransceiver = matchTransceiver(transceivers, [] (RTCRtpTransceiver& current) {
870         return !current.stopped() && !current.mid().isNull()
871             && current.iceTransport().gatheringState() != RTCIceTransport::GatheringState::Complete;
872     });
873     if (!stillGatheringTransceiver) {
874         m_client->fireEvent(RTCIceCandidateEvent::create(false, false, nullptr));
875         m_client->updateIceGatheringState(IceGatheringState::Complete);
876     }
877 }
878
879 static RTCIceTransport::TransportState deriveAggregatedIceConnectionState(const Vector<RTCIceTransport::TransportState>& states)
880 {
881     unsigned newCount = 0;
882     unsigned checkingCount = 0;
883     unsigned connectedCount = 0;
884     unsigned completedCount = 0;
885     unsigned failedCount = 0;
886     unsigned disconnectedCount = 0;
887     unsigned closedCount = 0;
888
889     for (auto& state : states) {
890         switch (state) {
891         case RTCIceTransport::TransportState::New: ++newCount; break;
892         case RTCIceTransport::TransportState::Checking: ++checkingCount; break;
893         case RTCIceTransport::TransportState::Connected: ++connectedCount; break;
894         case RTCIceTransport::TransportState::Completed: ++completedCount; break;
895         case RTCIceTransport::TransportState::Failed: ++failedCount; break;
896         case RTCIceTransport::TransportState::Disconnected: ++disconnectedCount; break;
897         case RTCIceTransport::TransportState::Closed: ++closedCount; break;
898         }
899     }
900
901     // The aggregated RTCIceConnectionState is derived from the RTCIceTransportState of all RTCIceTransports.
902     if ((newCount > 0 && !checkingCount && !failedCount && !disconnectedCount) || (closedCount == states.size()))
903         return RTCIceTransport::TransportState::New;
904
905     if (checkingCount > 0 && !failedCount && !disconnectedCount)
906         return RTCIceTransport::TransportState::Checking;
907
908     if ((connectedCount + completedCount + closedCount) == states.size() && connectedCount > 0)
909         return RTCIceTransport::TransportState::Connected;
910
911     if ((completedCount + closedCount) == states.size() && completedCount > 0)
912         return RTCIceTransport::TransportState::Completed;
913
914     if (failedCount > 0)
915         return RTCIceTransport::TransportState::Failed;
916
917     if (disconnectedCount > 0) // Any failed caught above.
918         return RTCIceTransport::TransportState::Disconnected;
919
920     ASSERT_NOT_REACHED();
921     return RTCIceTransport::TransportState::New;
922 }
923
924 void MediaEndpointPeerConnection::iceTransportStateChanged(const String& mid, MediaEndpoint::IceTransportState mediaEndpointIceTransportState)
925 {
926     ASSERT(isMainThread());
927
928     RTCRtpTransceiver* transceiver = matchTransceiverByMid(m_client->getTransceivers(), mid);
929     ASSERT(transceiver);
930
931     RTCIceTransport::TransportState transportState = static_cast<RTCIceTransport::TransportState>(mediaEndpointIceTransportState);
932     transceiver->iceTransport().setTransportState(transportState);
933
934     // Determine if the script needs to be notified.
935     Vector<RTCIceTransport::TransportState> transportStates;
936     for (auto& transceiver : m_client->getTransceivers())
937         transportStates.append(transceiver->iceTransport().transportState());
938
939     RTCIceTransport::TransportState derivedState = deriveAggregatedIceConnectionState(transportStates);
940     m_client->updateIceConnectionState(static_cast<IceConnectionState>(derivedState));
941 }
942
943 } // namespace WebCore
944
945 #endif // ENABLE(WEB_RTC)