WebRTC: Make MediaEndpointPeerConnection handle remotely assigned mids correctly
[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         }
307     }
308
309     return sourceMap;
310 }
311
312 void MediaEndpointPeerConnection::setLocalDescription(RTCSessionDescription& description, VoidPromise&& promise)
313 {
314     runTask([this, protectedDescription = RefPtr<RTCSessionDescription>(&description), protectedPromise = WTFMove(promise)]() mutable {
315         setLocalDescriptionTask(WTFMove(protectedDescription), protectedPromise);
316     });
317 }
318
319 void MediaEndpointPeerConnection::setLocalDescriptionTask(RefPtr<RTCSessionDescription>&& description, VoidPromise& promise)
320 {
321     if (m_client->internalSignalingState() == SignalingState::Closed)
322         return;
323
324     auto result = MediaEndpointSessionDescription::create(WTFMove(description), *m_sdpProcessor);
325     if (result.hasException()) {
326         promise.reject(result.releaseException());
327         return;
328     }
329     auto newDescription = result.releaseReturnValue();
330
331     if (!localDescriptionTypeValidForState(newDescription->type())) {
332         promise.reject(INVALID_STATE_ERR, "Description type incompatible with current signaling state");
333         return;
334     }
335
336     const RtpTransceiverVector& transceivers = m_client->getTransceivers();
337     const MediaDescriptionVector& mediaDescriptions = newDescription->configuration()->mediaDescriptions();
338     MediaEndpointSessionDescription* localDescription = internalLocalDescription();
339     unsigned previousNumberOfMediaDescriptions = localDescription ? localDescription->configuration()->mediaDescriptions().size() : 0;
340     bool hasNewMediaDescriptions = mediaDescriptions.size() > previousNumberOfMediaDescriptions;
341     bool isInitiator = newDescription->type() == RTCSessionDescription::SdpType::Offer;
342
343     if (hasNewMediaDescriptions) {
344         MediaEndpoint::UpdateResult result = m_mediaEndpoint->updateReceiveConfiguration(newDescription->configuration(), isInitiator);
345
346         if (result == MediaEndpoint::UpdateResult::SuccessWithIceRestart) {
347             if (m_client->internalIceGatheringState() != IceGatheringState::Gathering)
348                 m_client->updateIceGatheringState(IceGatheringState::Gathering);
349
350             if (m_client->internalIceConnectionState() != IceConnectionState::Completed)
351                 m_client->updateIceConnectionState(IceConnectionState::Connected);
352
353             LOG_ERROR("ICE restart is not implemented");
354             notImplemented();
355
356         } else if (result == MediaEndpoint::UpdateResult::Failed) {
357             promise.reject(OperationError, "Unable to apply session description");
358             return;
359         }
360
361         // Associate media descriptions with transceivers (set provisional mid to 'final' mid).
362         for (unsigned i = previousNumberOfMediaDescriptions; i < mediaDescriptions.size(); ++i) {
363             PeerMediaDescription& mediaDescription = *mediaDescriptions[i];
364
365             RTCRtpTransceiver* transceiver = matchTransceiver(transceivers, [&mediaDescription] (RTCRtpTransceiver& current) {
366                 return current.provisionalMid() == mediaDescription.mid();
367             });
368             if (transceiver)
369                 transceiver->setMid(transceiver->provisionalMid());
370         }
371     }
372
373     if (internalRemoteDescription()) {
374         MediaEndpointSessionConfiguration* remoteConfiguration = internalRemoteDescription()->configuration();
375         RealtimeMediaSourceMap sendSourceMap = createSourceMap(remoteConfiguration->mediaDescriptions(), mediaDescriptions.size(), transceivers);
376
377         if (m_mediaEndpoint->updateSendConfiguration(remoteConfiguration, sendSourceMap, isInitiator) == MediaEndpoint::UpdateResult::Failed) {
378             promise.reject(OperationError, "Unable to apply session description");
379             return;
380         }
381     }
382
383     if (!hasUnassociatedTransceivers(transceivers))
384         clearNegotiationNeededState();
385
386     SignalingState newSignalingState;
387
388     // Update state and local descriptions according to setLocal/RemoteDescription processing model
389     switch (newDescription->type()) {
390     case RTCSessionDescription::SdpType::Offer:
391         m_pendingLocalDescription = WTFMove(newDescription);
392         newSignalingState = SignalingState::HaveLocalOffer;
393         break;
394
395     case RTCSessionDescription::SdpType::Answer:
396         m_currentLocalDescription = WTFMove(newDescription);
397         m_currentRemoteDescription = m_pendingRemoteDescription;
398         m_pendingLocalDescription = nullptr;
399         m_pendingRemoteDescription = nullptr;
400         newSignalingState = SignalingState::Stable;
401         break;
402
403     case RTCSessionDescription::SdpType::Rollback:
404         m_pendingLocalDescription = nullptr;
405         newSignalingState = SignalingState::Stable;
406         break;
407
408     case RTCSessionDescription::SdpType::Pranswer:
409         m_pendingLocalDescription = WTFMove(newDescription);
410         newSignalingState = SignalingState::HaveLocalPrAnswer;
411         break;
412     }
413
414     if (newSignalingState != m_client->internalSignalingState()) {
415         m_client->setSignalingState(newSignalingState);
416         m_client->fireEvent(Event::create(eventNames().signalingstatechangeEvent, false, false));
417     }
418
419     if (m_client->internalIceGatheringState() == IceGatheringState::New && mediaDescriptions.size())
420         m_client->updateIceGatheringState(IceGatheringState::Gathering);
421
422     if (m_client->internalSignalingState() == SignalingState::Stable && m_negotiationNeeded)
423         m_client->scheduleNegotiationNeededEvent();
424
425     promise.resolve(nullptr);
426 }
427
428 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::localDescription() const
429 {
430     return createRTCSessionDescription(internalLocalDescription());
431 }
432
433 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::currentLocalDescription() const
434 {
435     return createRTCSessionDescription(m_currentLocalDescription.get());
436 }
437
438 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::pendingLocalDescription() const
439 {
440     return createRTCSessionDescription(m_pendingLocalDescription.get());
441 }
442
443 void MediaEndpointPeerConnection::setRemoteDescription(RTCSessionDescription& description, VoidPromise&& promise)
444 {
445     runTask([this, protectedDescription = RefPtr<RTCSessionDescription>(&description), protectedPromise = WTFMove(promise)]() mutable {
446         setRemoteDescriptionTask(WTFMove(protectedDescription), protectedPromise);
447     });
448 }
449
450 void MediaEndpointPeerConnection::setRemoteDescriptionTask(RefPtr<RTCSessionDescription>&& description, VoidPromise& promise)
451 {
452     if (m_client->internalSignalingState() == SignalingState::Closed)
453         return;
454
455     auto result = MediaEndpointSessionDescription::create(WTFMove(description), *m_sdpProcessor);
456     if (result.hasException()) {
457         promise.reject(result.releaseException());
458         return;
459     }
460     auto newDescription = result.releaseReturnValue();
461
462     if (!remoteDescriptionTypeValidForState(newDescription->type())) {
463         promise.reject(INVALID_STATE_ERR, "Description type incompatible with current signaling state");
464         return;
465     }
466
467     const MediaDescriptionVector& mediaDescriptions = newDescription->configuration()->mediaDescriptions();
468     for (auto& mediaDescription : mediaDescriptions) {
469         if (mediaDescription->type() != "audio" && mediaDescription->type() != "video")
470             continue;
471
472         mediaDescription->setPayloads(m_mediaEndpoint->filterPayloads(mediaDescription->payloads(),
473             mediaDescription->type() == "audio" ? m_defaultAudioPayloads : m_defaultVideoPayloads));
474     }
475
476     bool isInitiator = newDescription->type() == RTCSessionDescription::SdpType::Answer;
477     const RtpTransceiverVector& transceivers = m_client->getTransceivers();
478
479     RealtimeMediaSourceMap sendSourceMap;
480     if (internalLocalDescription())
481         sendSourceMap = createSourceMap(mediaDescriptions, internalLocalDescription()->configuration()->mediaDescriptions().size(), transceivers);
482
483     if (m_mediaEndpoint->updateSendConfiguration(newDescription->configuration(), sendSourceMap, isInitiator) == MediaEndpoint::UpdateResult::Failed) {
484         promise.reject(OperationError, "Unable to apply session description");
485         return;
486     }
487
488     // One legacy MediaStreamEvent will be fired for every new MediaStream created as this remote description is set.
489     Vector<RefPtr<MediaStreamEvent>> legacyMediaStreamEvents;
490
491     for (auto mediaDescription : mediaDescriptions) {
492         RTCRtpTransceiver* transceiver = matchTransceiverByMid(transceivers, mediaDescription->mid());
493         if (!transceiver) {
494             bool receiveOnlyFlag = false;
495
496             if (mediaDescription->mode() == "sendrecv" || mediaDescription->mode() == "recvonly") {
497                 // Try to match an existing transceiver.
498                 transceiver = matchTransceiver(transceivers, [&mediaDescription] (RTCRtpTransceiver& current) {
499                     return !current.stopped() && current.mid().isNull() && current.sender()->trackKind() == mediaDescription->type();
500                 });
501
502                 if (transceiver) {
503                     // This transceiver was created locally with a provisional mid. Its real mid will now be set by the remote
504                     // description so we need to update the mid of the transceiver's muted source to preserve the association.
505                     transceiver->setMid(mediaDescription->mid());
506                     m_mediaEndpoint->replaceMutedRemoteSourceMid(transceiver->provisionalMid(), mediaDescription->mid());
507                 } else
508                     receiveOnlyFlag = true;
509             }
510
511             if (!transceiver) {
512                 auto sender = RTCRtpSender::create(mediaDescription->type(), Vector<String>(), m_client->senderClient());
513                 auto receiver = createReceiver(mediaDescription->mid(), mediaDescription->type(), mediaDescription->mediaStreamTrackId());
514
515                 auto newTransceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver));
516                 newTransceiver->setMid(mediaDescription->mid());
517                 if (receiveOnlyFlag)
518                     newTransceiver->disableSendingDirection();
519
520                 transceiver = newTransceiver.ptr();
521                 m_client->addTransceiver(WTFMove(newTransceiver));
522             }
523         }
524
525         if (mediaDescription->mode() == "sendrecv" || mediaDescription->mode() == "sendonly") {
526             RTCRtpReceiver& receiver = *transceiver->receiver();
527             if (receiver.isDispatched())
528                 continue;
529             receiver.setDispatched(true);
530
531             Vector<String> mediaStreamIds;
532             if (!mediaDescription->mediaStreamId().isEmpty())
533                 mediaStreamIds.append(mediaDescription->mediaStreamId());
534
535             // A remote track can be associated with 0..* MediaStreams. We create a new stream for
536             // a track in case of an unrecognized stream id, or just add the track if the stream
537             // already exists.
538             HashMap<String, RefPtr<MediaStream>> trackEventMediaStreams;
539             for (auto& id : mediaStreamIds) {
540                 if (m_remoteStreamMap.contains(id)) {
541                     RefPtr<MediaStream> stream = m_remoteStreamMap.get(id);
542                     stream->addTrack(*receiver.track());
543                     trackEventMediaStreams.add(id, WTFMove(stream));
544                 } else {
545                     auto newStream = MediaStream::create(*m_client->scriptExecutionContext(), MediaStreamTrackVector({ receiver.track() }));
546                     m_remoteStreamMap.add(id, newStream.copyRef());
547                     legacyMediaStreamEvents.append(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, newStream.copyRef()));
548                     trackEventMediaStreams.add(id, WTFMove(newStream));
549                 }
550             }
551
552             Vector<RefPtr<MediaStream>> streams;
553             copyValuesToVector(trackEventMediaStreams, streams);
554
555             m_client->fireEvent(RTCTrackEvent::create(eventNames().trackEvent, false, false,
556                 &receiver, receiver.track(), WTFMove(streams), transceiver));
557         }
558     }
559
560     // Fire legacy addstream events.
561     for (auto& event : legacyMediaStreamEvents)
562         m_client->fireEvent(*event);
563
564     SignalingState newSignalingState;
565
566     // Update state and local descriptions according to setLocal/RemoteDescription processing model
567     switch (newDescription->type()) {
568     case RTCSessionDescription::SdpType::Offer:
569         m_pendingRemoteDescription = WTFMove(newDescription);
570         newSignalingState = SignalingState::HaveRemoteOffer;
571         break;
572
573     case RTCSessionDescription::SdpType::Answer:
574         m_currentRemoteDescription = WTFMove(newDescription);
575         m_currentLocalDescription = m_pendingLocalDescription;
576         m_pendingRemoteDescription = nullptr;
577         m_pendingLocalDescription = nullptr;
578         newSignalingState = SignalingState::Stable;
579         break;
580
581     case RTCSessionDescription::SdpType::Rollback:
582         m_pendingRemoteDescription = nullptr;
583         newSignalingState = SignalingState::Stable;
584         break;
585
586     case RTCSessionDescription::SdpType::Pranswer:
587         m_pendingRemoteDescription = WTFMove(newDescription);
588         newSignalingState = SignalingState::HaveRemotePrAnswer;
589         break;
590     }
591
592     if (newSignalingState != m_client->internalSignalingState()) {
593         m_client->setSignalingState(newSignalingState);
594         m_client->fireEvent(Event::create(eventNames().signalingstatechangeEvent, false, false));
595     }
596
597     promise.resolve(nullptr);
598 }
599
600 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::remoteDescription() const
601 {
602     return createRTCSessionDescription(internalRemoteDescription());
603 }
604
605 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::currentRemoteDescription() const
606 {
607     return createRTCSessionDescription(m_currentRemoteDescription.get());
608 }
609
610 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::pendingRemoteDescription() const
611 {
612     return createRTCSessionDescription(m_pendingRemoteDescription.get());
613 }
614
615 void MediaEndpointPeerConnection::setConfiguration(RTCConfiguration& configuration)
616 {
617     Vector<RefPtr<IceServerInfo>> iceServers;
618     for (auto& server : configuration.iceServers())
619         iceServers.append(IceServerInfo::create(server->urls(), server->credential(), server->username()));
620
621     m_mediaEndpoint->setConfiguration(MediaEndpointConfiguration::create(iceServers, configuration.iceTransportPolicy(), configuration.bundlePolicy()));
622 }
623
624 void MediaEndpointPeerConnection::addIceCandidate(RTCIceCandidate& rtcCandidate, PeerConnection::VoidPromise&& promise)
625 {
626     runTask([this, protectedCandidate = RefPtr<RTCIceCandidate>(&rtcCandidate), protectedPromise = WTFMove(promise)]() mutable {
627         addIceCandidateTask(*protectedCandidate, protectedPromise);
628     });
629 }
630
631 void MediaEndpointPeerConnection::addIceCandidateTask(RTCIceCandidate& rtcCandidate, PeerConnection::VoidPromise& promise)
632 {
633     if (m_client->internalSignalingState() == SignalingState::Closed)
634         return;
635
636     if (!internalRemoteDescription()) {
637         promise.reject(INVALID_STATE_ERR, "No remote description set");
638         return;
639     }
640
641     const MediaDescriptionVector& remoteMediaDescriptions = internalRemoteDescription()->configuration()->mediaDescriptions();
642     PeerMediaDescription* targetMediaDescription = nullptr;
643
644     // When identifying the target media description, sdpMid takes precedence over sdpMLineIndex
645     // if both are present.
646     if (!rtcCandidate.sdpMid().isNull()) {
647         const String& mid = rtcCandidate.sdpMid();
648         for (auto& description : remoteMediaDescriptions) {
649             if (description->mid() == mid) {
650                 targetMediaDescription = description.get();
651                 break;
652             }
653         }
654
655         if (!targetMediaDescription) {
656             promise.reject(OperationError, "sdpMid did not match any media description");
657             return;
658         }
659     } else if (rtcCandidate.sdpMLineIndex()) {
660         unsigned short sdpMLineIndex = rtcCandidate.sdpMLineIndex().value();
661         if (sdpMLineIndex >= remoteMediaDescriptions.size()) {
662             promise.reject(OperationError, "sdpMLineIndex is out of range");
663             return;
664         }
665         targetMediaDescription = remoteMediaDescriptions[sdpMLineIndex].get();
666     } else {
667         ASSERT_NOT_REACHED();
668         return;
669     }
670
671     RefPtr<IceCandidate> candidate;
672     SDPProcessor::Result result = m_sdpProcessor->parseCandidateLine(rtcCandidate.candidate(), candidate);
673     if (result != SDPProcessor::Result::Success) {
674         if (result == SDPProcessor::Result::ParseError)
675             promise.reject(OperationError, "Invalid candidate content");
676         else
677             LOG_ERROR("SDPProcessor internal error");
678         return;
679     }
680
681     targetMediaDescription->addIceCandidate(candidate.copyRef());
682
683     m_mediaEndpoint->addRemoteCandidate(*candidate, targetMediaDescription->mid(), targetMediaDescription->iceUfrag(),
684         targetMediaDescription->icePassword());
685
686     promise.resolve(nullptr);
687 }
688
689 void MediaEndpointPeerConnection::getStats(MediaStreamTrack*, PeerConnection::StatsPromise&& promise)
690 {
691     notImplemented();
692
693     promise.reject(NOT_SUPPORTED_ERR);
694 }
695
696 Vector<RefPtr<MediaStream>> MediaEndpointPeerConnection::getRemoteStreams() const
697 {
698     Vector<RefPtr<MediaStream>> remoteStreams;
699     copyValuesToVector(m_remoteStreamMap, remoteStreams);
700     return remoteStreams;
701 }
702
703 RefPtr<RTCRtpReceiver> MediaEndpointPeerConnection::createReceiver(const String& transceiverMid, const String& trackKind, const String& trackId)
704 {
705     RealtimeMediaSource::Type sourceType = trackKind == "audio" ? RealtimeMediaSource::Type::Audio : RealtimeMediaSource::Type::Video;
706
707     // Create a muted remote source that will be unmuted once media starts arriving.
708     auto remoteSource = m_mediaEndpoint->createMutedRemoteSource(transceiverMid, sourceType);
709     auto remoteTrackPrivate = MediaStreamTrackPrivate::create(WTFMove(remoteSource), trackId);
710     auto remoteTrack = MediaStreamTrack::create(*m_client->scriptExecutionContext(), *remoteTrackPrivate);
711
712     return RTCRtpReceiver::create(WTFMove(remoteTrack));
713 }
714
715 void MediaEndpointPeerConnection::replaceTrack(RTCRtpSender& sender, RefPtr<MediaStreamTrack>&& withTrack, PeerConnection::VoidPromise&& promise)
716 {
717     RTCRtpTransceiver* transceiver = matchTransceiver(m_client->getTransceivers(), [&sender] (RTCRtpTransceiver& current) {
718         return current.sender() == &sender;
719     });
720     ASSERT(transceiver);
721
722     const String& mid = transceiver->mid();
723     if (mid.isNull()) {
724         // Transceiver is not associated with a media description yet.
725         sender.setTrack(WTFMove(withTrack));
726         promise.resolve(nullptr);
727         return;
728     }
729
730     runTask([this, protectedSender = RefPtr<RTCRtpSender>(&sender), mid, protectedTrack = WTFMove(withTrack), protectedPromise = WTFMove(promise)]() mutable {
731         replaceTrackTask(*protectedSender, mid, WTFMove(protectedTrack), protectedPromise);
732     });
733 }
734
735 void MediaEndpointPeerConnection::replaceTrackTask(RTCRtpSender& sender, const String& mid, RefPtr<MediaStreamTrack>&& withTrack, PeerConnection::VoidPromise& promise)
736 {
737     if (m_client->internalSignalingState() == SignalingState::Closed)
738         return;
739
740     m_mediaEndpoint->replaceSendSource(withTrack->source(), mid);
741
742     sender.setTrack(WTFMove(withTrack));
743     promise.resolve(nullptr);
744 }
745
746 void MediaEndpointPeerConnection::stop()
747 {
748     notImplemented();
749 }
750
751 void MediaEndpointPeerConnection::markAsNeedingNegotiation()
752 {
753     if (m_negotiationNeeded)
754         return;
755
756     m_negotiationNeeded = true;
757
758     if (m_client->internalSignalingState() == SignalingState::Stable)
759         m_client->scheduleNegotiationNeededEvent();
760 }
761
762 void MediaEndpointPeerConnection::emulatePlatformEvent(const String& action)
763 {
764     m_mediaEndpoint->emulatePlatformEvent(action);
765 }
766
767 bool MediaEndpointPeerConnection::localDescriptionTypeValidForState(RTCSessionDescription::SdpType type) const
768 {
769     switch (m_client->internalSignalingState()) {
770     case SignalingState::Stable:
771         return type == RTCSessionDescription::SdpType::Offer;
772     case SignalingState::HaveLocalOffer:
773         return type == RTCSessionDescription::SdpType::Offer;
774     case SignalingState::HaveRemoteOffer:
775         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
776     case SignalingState::HaveLocalPrAnswer:
777         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
778     default:
779         return false;
780     };
781
782     ASSERT_NOT_REACHED();
783     return false;
784 }
785
786 bool MediaEndpointPeerConnection::remoteDescriptionTypeValidForState(RTCSessionDescription::SdpType type) const
787 {
788     switch (m_client->internalSignalingState()) {
789     case SignalingState::Stable:
790         return type == RTCSessionDescription::SdpType::Offer;
791     case SignalingState::HaveLocalOffer:
792         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
793     case SignalingState::HaveRemoteOffer:
794         return type == RTCSessionDescription::SdpType::Offer;
795     case SignalingState::HaveRemotePrAnswer:
796         return type == RTCSessionDescription::SdpType::Answer || type == RTCSessionDescription::SdpType::Pranswer;
797     default:
798         return false;
799     };
800
801     ASSERT_NOT_REACHED();
802     return false;
803 }
804
805 MediaEndpointSessionDescription* MediaEndpointPeerConnection::internalLocalDescription() const
806 {
807     return m_pendingLocalDescription ? m_pendingLocalDescription.get() : m_currentLocalDescription.get();
808 }
809
810 MediaEndpointSessionDescription* MediaEndpointPeerConnection::internalRemoteDescription() const
811 {
812     return m_pendingRemoteDescription ? m_pendingRemoteDescription.get() : m_currentRemoteDescription.get();
813 }
814
815 RefPtr<RTCSessionDescription> MediaEndpointPeerConnection::createRTCSessionDescription(MediaEndpointSessionDescription* description) const
816 {
817     return description ? description->toRTCSessionDescription(*m_sdpProcessor) : nullptr;
818 }
819
820 void MediaEndpointPeerConnection::gotDtlsFingerprint(const String& fingerprint, const String& fingerprintFunction)
821 {
822     ASSERT(isMainThread());
823
824     m_dtlsFingerprint = fingerprint;
825     m_dtlsFingerprintFunction = fingerprintFunction;
826
827     startRunningTasks();
828 }
829
830 void MediaEndpointPeerConnection::gotIceCandidate(const String& mid, RefPtr<IceCandidate>&& candidate)
831 {
832     ASSERT(isMainThread());
833
834     const MediaDescriptionVector& mediaDescriptions = internalLocalDescription()->configuration()->mediaDescriptions();
835     size_t mediaDescriptionIndex = notFound;
836
837     for (size_t i = 0; i < mediaDescriptions.size(); ++i) {
838         if (mediaDescriptions[i]->mid() == mid) {
839             mediaDescriptionIndex = i;
840             break;
841         }
842     }
843     ASSERT(mediaDescriptionIndex != notFound);
844
845     PeerMediaDescription& mediaDescription = *mediaDescriptions[mediaDescriptionIndex];
846     mediaDescription.addIceCandidate(candidate.copyRef());
847
848     String candidateLine;
849     SDPProcessor::Result result = m_sdpProcessor->generateCandidateLine(*candidate, candidateLine);
850     if (result != SDPProcessor::Result::Success) {
851         LOG_ERROR("SDPProcessor internal error");
852         return;
853     }
854
855     RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(candidateLine, mid, mediaDescriptionIndex);
856
857     m_client->fireEvent(RTCIceCandidateEvent::create(false, false, WTFMove(iceCandidate)));
858 }
859
860 void MediaEndpointPeerConnection::doneGatheringCandidates(const String& mid)
861 {
862     ASSERT(isMainThread());
863
864     RtpTransceiverVector transceivers = RtpTransceiverVector(m_client->getTransceivers());
865     RTCRtpTransceiver* notifyingTransceiver = matchTransceiverByMid(transceivers, mid);
866     ASSERT(notifyingTransceiver);
867
868     notifyingTransceiver->iceTransport().setGatheringState(RTCIceTransport::GatheringState::Complete);
869
870     // Don't notify the script if there are transceivers still gathering.
871     RTCRtpTransceiver* stillGatheringTransceiver = matchTransceiver(transceivers, [] (RTCRtpTransceiver& current) {
872         return !current.stopped() && !current.mid().isNull()
873             && current.iceTransport().gatheringState() != RTCIceTransport::GatheringState::Complete;
874     });
875     if (!stillGatheringTransceiver) {
876         m_client->fireEvent(RTCIceCandidateEvent::create(false, false, nullptr));
877         m_client->updateIceGatheringState(IceGatheringState::Complete);
878     }
879 }
880
881 static RTCIceTransport::TransportState deriveAggregatedIceConnectionState(const Vector<RTCIceTransport::TransportState>& states)
882 {
883     unsigned newCount = 0;
884     unsigned checkingCount = 0;
885     unsigned connectedCount = 0;
886     unsigned completedCount = 0;
887     unsigned failedCount = 0;
888     unsigned disconnectedCount = 0;
889     unsigned closedCount = 0;
890
891     for (auto& state : states) {
892         switch (state) {
893         case RTCIceTransport::TransportState::New: ++newCount; break;
894         case RTCIceTransport::TransportState::Checking: ++checkingCount; break;
895         case RTCIceTransport::TransportState::Connected: ++connectedCount; break;
896         case RTCIceTransport::TransportState::Completed: ++completedCount; break;
897         case RTCIceTransport::TransportState::Failed: ++failedCount; break;
898         case RTCIceTransport::TransportState::Disconnected: ++disconnectedCount; break;
899         case RTCIceTransport::TransportState::Closed: ++closedCount; break;
900         }
901     }
902
903     // The aggregated RTCIceConnectionState is derived from the RTCIceTransportState of all RTCIceTransports.
904     if ((newCount > 0 && !checkingCount && !failedCount && !disconnectedCount) || (closedCount == states.size()))
905         return RTCIceTransport::TransportState::New;
906
907     if (checkingCount > 0 && !failedCount && !disconnectedCount)
908         return RTCIceTransport::TransportState::Checking;
909
910     if ((connectedCount + completedCount + closedCount) == states.size() && connectedCount > 0)
911         return RTCIceTransport::TransportState::Connected;
912
913     if ((completedCount + closedCount) == states.size() && completedCount > 0)
914         return RTCIceTransport::TransportState::Completed;
915
916     if (failedCount > 0)
917         return RTCIceTransport::TransportState::Failed;
918
919     if (disconnectedCount > 0) // Any failed caught above.
920         return RTCIceTransport::TransportState::Disconnected;
921
922     ASSERT_NOT_REACHED();
923     return RTCIceTransport::TransportState::New;
924 }
925
926 void MediaEndpointPeerConnection::iceTransportStateChanged(const String& mid, MediaEndpoint::IceTransportState mediaEndpointIceTransportState)
927 {
928     ASSERT(isMainThread());
929
930     RTCRtpTransceiver* transceiver = matchTransceiverByMid(m_client->getTransceivers(), mid);
931     ASSERT(transceiver);
932
933     RTCIceTransport::TransportState transportState = static_cast<RTCIceTransport::TransportState>(mediaEndpointIceTransportState);
934     transceiver->iceTransport().setTransportState(transportState);
935
936     // Determine if the script needs to be notified.
937     Vector<RTCIceTransport::TransportState> transportStates;
938     for (auto& transceiver : m_client->getTransceivers())
939         transportStates.append(transceiver->iceTransport().transportState());
940
941     RTCIceTransport::TransportState derivedState = deriveAggregatedIceConnectionState(transportStates);
942     m_client->updateIceConnectionState(static_cast<IceConnectionState>(derivedState));
943 }
944
945 } // namespace WebCore
946
947 #endif // ENABLE(WEB_RTC)