OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/devtools_bridge/session_dependency_factory.h" | |
6 | |
7 #include "components/devtools_bridge/abstract_data_channel.h" | |
8 #include "components/devtools_bridge/abstract_peer_connection.h" | |
9 #include "components/devtools_bridge/rtc_configuration.h" | |
10 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface .h" | |
11 #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h " | |
12 #include "third_party/webrtc/base/bind.h" | |
13 #include "third_party/webrtc/base/ssladapter.h" | |
14 #include "third_party/webrtc/base/thread.h" | |
15 | |
16 namespace devtools_bridge { | |
17 | |
18 class RTCConfiguration::Impl | |
19 : public RTCConfiguration, | |
20 public webrtc::PeerConnectionInterface::RTCConfiguration { | |
21 public: | |
22 | |
23 virtual void AddIceServer( | |
24 std::string const& uri, | |
25 std::string const& username, | |
26 std::string const& credential) override { | |
27 webrtc::PeerConnectionInterface::IceServer server; | |
28 server.uri = uri; | |
29 server.username = username; | |
30 server.password = credential; | |
31 servers.push_back(server); | |
32 } | |
33 | |
34 Impl const& impl() const override { | |
mnaganov (inactive)
2014/11/10 18:10:26
Also "const& Impl"
SeRya
2014/11/11 08:08:19
Done.
| |
35 return *this; | |
36 } | |
37 | |
38 private: | |
39 webrtc::PeerConnectionInterface::RTCConfiguration base_; | |
40 }; | |
41 | |
42 namespace { | |
43 | |
44 template <typename T> | |
45 void CheckedRelease(rtc::scoped_refptr<T>* ptr) { | |
46 CHECK_EQ(0, ptr->release()->Release()); | |
47 } | |
48 | |
49 class MediaConstraints | |
50 : public webrtc::MediaConstraintsInterface { | |
51 public: | |
52 virtual ~MediaConstraints() {} | |
53 | |
54 virtual const Constraints& GetMandatory() const override { | |
55 return mandatory_; | |
56 } | |
57 | |
58 virtual const Constraints& GetOptional() const override { | |
59 return optional_; | |
60 } | |
61 | |
62 void AddMandatory(std::string const& key, std::string const& value) { | |
63 mandatory_.push_back(Constraint(key, value)); | |
64 } | |
65 | |
66 private: | |
67 Constraints mandatory_; | |
68 Constraints optional_; | |
69 }; | |
70 | |
71 class DataChannelImpl : public AbstractDataChannel { | |
72 public: | |
73 explicit DataChannelImpl( | |
74 rtc::scoped_refptr<webrtc::DataChannelInterface> impl) : impl_(impl) { | |
75 } | |
76 | |
77 // TODO(serya): Implement. | |
78 | |
79 private: | |
80 rtc::scoped_refptr<webrtc::DataChannelInterface> const impl_; | |
81 }; | |
82 | |
83 class PeerConnectionObserverImpl | |
84 : public webrtc::PeerConnectionObserver { | |
85 public: | |
86 PeerConnectionObserverImpl(AbstractPeerConnection::Delegate* delegate) | |
87 : delegate_(delegate), | |
88 connected_(false) { | |
89 } | |
90 | |
91 virtual void OnAddStream(webrtc::MediaStreamInterface* stream) override {} | |
92 | |
93 virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) override {} | |
94 | |
95 virtual void OnDataChannel(webrtc::DataChannelInterface* data_channel) | |
96 override {} | |
97 | |
98 virtual void OnRenegotiationNeeded() override {} | |
99 | |
100 virtual void OnSignalingChange( | |
101 webrtc::PeerConnectionInterface::SignalingState new_state) override { | |
102 } | |
103 | |
104 virtual void OnIceConnectionChange( | |
105 webrtc::PeerConnectionInterface::IceConnectionState new_state) override { | |
106 bool connected = | |
107 new_state == webrtc::PeerConnectionInterface::kIceConnectionConnected || | |
108 new_state == webrtc::PeerConnectionInterface::kIceConnectionCompleted; | |
109 | |
110 if (connected != connected_) { | |
111 connected_ = connected; | |
112 delegate_->OnIceConnectionChange(connected_); | |
113 } | |
114 } | |
115 | |
116 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) | |
117 override { | |
118 std::string sdp; | |
119 candidate->ToString(&sdp); | |
120 | |
121 delegate_->OnIceCandidate( | |
122 candidate->sdp_mid(), candidate->sdp_mline_index(), sdp); | |
123 } | |
124 | |
125 private: | |
126 AbstractPeerConnection::Delegate* const delegate_; | |
127 bool connected_; | |
128 }; | |
129 | |
130 /** | |
131 * Helper object which may outlive PeerConnectionImpl. Provides access | |
132 * to the connection and the delegate to operaion callback objects | |
133 * in a safe way. Always accessible on the signaling thread. | |
134 */ | |
135 class PeerConnectionHolder : public rtc::RefCountInterface { | |
136 public: | |
137 PeerConnectionHolder( | |
138 rtc::Thread* signaling_thread, | |
139 webrtc::PeerConnectionInterface* connection, | |
140 AbstractPeerConnection::Delegate* delegate) | |
141 : signaling_thread_(signaling_thread), | |
mnaganov (inactive)
2014/11/10 18:10:26
I think indentation is a bit odd here.
SeRya
2014/11/11 08:08:19
Done.
| |
142 connection_(connection), | |
143 delegate_(delegate), | |
144 disposed_(false) { | |
145 } | |
146 | |
147 virtual ~PeerConnectionHolder() { | |
148 DCHECK(disposed_); | |
149 } | |
150 | |
151 void Dispose() { | |
152 DCHECK(!IsDisposed()); | |
153 disposed_ = true; | |
154 } | |
155 | |
156 webrtc::PeerConnectionInterface* connection() { | |
157 DCHECK(!IsDisposed()); | |
158 return connection_; | |
159 } | |
160 | |
161 AbstractPeerConnection::Delegate* delegate() { | |
162 DCHECK(!IsDisposed()); | |
163 return delegate_; | |
164 } | |
165 | |
166 bool IsDisposed() { | |
167 DCHECK(signaling_thread_->IsCurrent()); | |
168 return disposed_; | |
169 } | |
170 | |
171 private: | |
172 rtc::Thread* const signaling_thread_; | |
173 webrtc::PeerConnectionInterface* const connection_; | |
174 AbstractPeerConnection::Delegate* const delegate_; | |
175 bool disposed_; | |
176 }; | |
177 | |
178 class CreateAndSetHandler | |
179 : public webrtc::CreateSessionDescriptionObserver, | |
180 public webrtc::SetSessionDescriptionObserver { | |
181 public: | |
182 explicit CreateAndSetHandler( | |
183 rtc::scoped_refptr<PeerConnectionHolder> holder) | |
184 : holder_(holder) { | |
185 } | |
186 | |
187 virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { | |
188 if (holder_->IsDisposed()) return; | |
189 | |
190 type_ = desc->type(); | |
191 if (desc->ToString(&description_)) { | |
192 holder_->connection()->SetLocalDescription(this, desc); | |
193 } else { | |
194 OnFailure("Can't serialize session description"); | |
195 } | |
196 } | |
197 | |
198 virtual void OnSuccess() override { | |
199 if (holder_->IsDisposed()) return; | |
200 | |
201 if (type_ == webrtc::SessionDescriptionInterface::kOffer) { | |
202 holder_->delegate()->OnLocalOfferCreatedAndSetSet(description_); | |
203 } else { | |
204 DCHECK_EQ(webrtc::SessionDescriptionInterface::kAnswer, type_); | |
205 | |
206 holder_->delegate()->OnLocalAnswerCreatedAndSetSet(description_); | |
207 } | |
208 } | |
209 | |
210 virtual void OnFailure(const std::string& error) override { | |
211 if (holder_->IsDisposed()) return; | |
212 | |
213 holder_->delegate()->OnFailure(error); | |
214 } | |
215 | |
216 private: | |
217 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
218 std::string type_; | |
219 std::string description_; | |
220 }; | |
221 | |
222 class SetRemoteDescriptionHandler | |
223 : public webrtc::SetSessionDescriptionObserver { | |
224 public: | |
225 SetRemoteDescriptionHandler( | |
226 rtc::scoped_refptr<PeerConnectionHolder> holder) | |
227 : holder_(holder) { | |
228 } | |
229 | |
230 virtual void OnSuccess() override { | |
231 if (holder_->IsDisposed()) return; | |
232 | |
233 holder_->delegate()->OnRemoteDescriptionSet(); | |
234 } | |
235 | |
236 virtual void OnFailure(const std::string& error) override { | |
237 if (holder_->IsDisposed()) return; | |
238 | |
239 holder_->delegate()->OnFailure(error); | |
240 } | |
241 | |
242 private: | |
243 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
244 }; | |
245 | |
246 class PeerConnectionImpl : public AbstractPeerConnection { | |
247 public: | |
248 PeerConnectionImpl( | |
249 rtc::Thread* signaling_thread, | |
250 rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection, | |
251 scoped_ptr<PeerConnectionObserverImpl> observer, | |
252 scoped_ptr<AbstractPeerConnection::Delegate> delegate) | |
253 : holder_(new rtc::RefCountedObject<PeerConnectionHolder>( | |
254 signaling_thread, connection.get(), delegate.get())), | |
255 signaling_thread_(signaling_thread), | |
256 connection_(connection), | |
257 observer_(observer.Pass()), | |
258 delegate_(delegate.Pass()) { | |
259 } | |
260 | |
261 virtual ~PeerConnectionImpl() { | |
262 signaling_thread_->Invoke<void>(rtc::Bind( | |
263 &PeerConnectionImpl::DisposeOnSignalingThread, this)); | |
264 } | |
265 | |
266 virtual void CreateAndSetLocalOffer() override { | |
267 connection_->CreateOffer(MakeCreateAndSetHandler(), NULL); | |
268 } | |
269 | |
270 virtual void CreateAndSetLocalAnswer() override { | |
271 connection_->CreateAnswer(MakeCreateAndSetHandler(), NULL); | |
272 } | |
273 | |
274 virtual void SetRemoteOffer(std::string const& description) override { | |
275 SetRemoteDescription( | |
276 webrtc::SessionDescriptionInterface::kOffer, description); | |
277 } | |
278 | |
279 virtual void SetRemoteAnswer(std::string const& description) override { | |
280 SetRemoteDescription( | |
281 webrtc::SessionDescriptionInterface::kAnswer, description); | |
282 } | |
283 | |
284 void SetRemoteDescription( | |
285 std::string const& type, std::string const& description) { | |
286 webrtc::SdpParseError error; | |
287 scoped_ptr<webrtc::SessionDescriptionInterface> value( | |
288 webrtc::CreateSessionDescription(type, description, &error)); | |
289 if (value == NULL) { | |
290 OnParseError(error); | |
291 return; | |
292 } | |
293 // Takes ownership on |value|. | |
294 connection_->SetRemoteDescription( | |
295 new rtc::RefCountedObject<SetRemoteDescriptionHandler>(holder_), | |
296 value.release()); | |
297 } | |
298 | |
299 virtual void AddIceCandidate( | |
300 std::string const& sdp_mid, | |
301 int sdp_mline_index, | |
302 std::string const& sdp) override { | |
303 webrtc::SdpParseError error; | |
304 auto candidate = webrtc::CreateIceCandidate( | |
305 sdp_mid, sdp_mline_index, sdp, &error); | |
306 if (candidate == NULL) { | |
307 OnParseError(error); | |
308 return; | |
309 } | |
310 // Doesn't takes ownership. | |
311 connection_->AddIceCandidate(candidate); | |
312 delete candidate; | |
313 } | |
314 | |
315 virtual scoped_ptr<AbstractDataChannel> CreateDataChannel( | |
316 int channelId) override { | |
317 webrtc::DataChannelInit init; | |
318 init.reliable = true; | |
319 init.ordered = true; | |
320 init.negotiated = true; | |
321 init.id = channelId; | |
322 | |
323 return make_scoped_ptr(new DataChannelImpl( | |
324 connection_->CreateDataChannel("", &init))); | |
325 } | |
326 | |
327 private: | |
328 webrtc::CreateSessionDescriptionObserver* MakeCreateAndSetHandler() { | |
329 return new rtc::RefCountedObject<CreateAndSetHandler>(holder_); | |
330 } | |
331 | |
332 void DisposeOnSignalingThread() { | |
333 DCHECK(signaling_thread_->IsCurrent()); | |
334 | |
335 CheckedRelease(&connection_); | |
336 holder_->Dispose(); | |
337 } | |
338 | |
339 void OnParseError(webrtc::SdpParseError const& error) { | |
340 // TODO(serya): Send on signaling thread. | |
341 } | |
342 | |
343 rtc::scoped_refptr<PeerConnectionHolder> const holder_; | |
344 rtc::Thread* const signaling_thread_; | |
345 rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection_; | |
346 scoped_ptr<PeerConnectionObserverImpl> const observer_; | |
347 scoped_ptr<AbstractPeerConnection::Delegate> const delegate_; | |
348 }; | |
349 | |
350 class SessionDependencyFactoryImpl : public SessionDependencyFactory { | |
351 public: | |
352 SessionDependencyFactoryImpl( | |
353 base::Closure const& cleanup_on_signaling_thread) | |
354 : cleanup_on_signaling_thread_(cleanup_on_signaling_thread) { | |
355 signaling_thread_.SetName("signaling_thread", NULL); | |
356 signaling_thread_.Start(); | |
357 worker_thread_.SetName("worker_thread", NULL); | |
358 worker_thread_.Start(); | |
359 | |
360 factory_ = webrtc::CreatePeerConnectionFactory( | |
361 &worker_thread_, &signaling_thread_, NULL, NULL, NULL); | |
362 } | |
363 | |
364 virtual ~SessionDependencyFactoryImpl() { | |
365 signaling_thread_.Invoke<void>(rtc::Bind( | |
366 &SessionDependencyFactoryImpl::DisposeOnSignalingThread, this)); | |
367 } | |
368 | |
369 virtual scoped_ptr<AbstractPeerConnection> CreatePeerConnection( | |
370 scoped_ptr<RTCConfiguration> config, | |
371 scoped_ptr<AbstractPeerConnection::Delegate> delegate) override { | |
372 auto observer = make_scoped_ptr( | |
373 new PeerConnectionObserverImpl(delegate.get())); | |
374 | |
375 MediaConstraints constraints; | |
376 constraints.AddMandatory( | |
377 MediaConstraints::kEnableDtlsSrtp, MediaConstraints::kValueTrue); | |
378 | |
379 auto connection = factory_->CreatePeerConnection( | |
380 config->impl(), &constraints, NULL, NULL, observer.get()); | |
381 | |
382 return make_scoped_ptr(new PeerConnectionImpl( | |
383 &signaling_thread_, connection, observer.Pass(), delegate.Pass())); | |
384 } | |
385 | |
386 private: | |
387 void DisposeOnSignalingThread() { | |
388 DCHECK(signaling_thread_.IsCurrent()); | |
389 CheckedRelease(&factory_); | |
390 if (!cleanup_on_signaling_thread_.is_null()) { | |
391 cleanup_on_signaling_thread_.Run(); | |
392 } | |
393 } | |
394 | |
395 base::Closure cleanup_on_signaling_thread_; | |
396 rtc::Thread signaling_thread_; | |
397 rtc::Thread worker_thread_; | |
398 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory_; | |
399 }; | |
400 | |
401 } // namespace | |
402 | |
403 // RTCCOnfiguration | |
404 | |
405 // static | |
406 scoped_ptr<RTCConfiguration> RTCConfiguration::CreateInstance() { | |
407 return make_scoped_ptr(new RTCConfiguration::Impl()); | |
408 } | |
409 | |
410 // SessionDependencyFactory | |
411 | |
412 // static | |
413 bool SessionDependencyFactory::InitializeSSL() { | |
414 return rtc::InitializeSSL(); | |
415 } | |
416 | |
417 // static | |
418 bool SessionDependencyFactory::CleanupSSL() { | |
419 return rtc::CleanupSSL(); | |
420 } | |
421 | |
422 // static | |
423 scoped_ptr<SessionDependencyFactory> SessionDependencyFactory::CreateInstance( | |
424 base::Closure const& cleanup_on_signaling_thread) { | |
425 return make_scoped_ptr(new SessionDependencyFactoryImpl( | |
426 cleanup_on_signaling_thread)); | |
427 } | |
428 | |
429 } // namespace devtools_bridge | |
OLD | NEW |