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 const std::string& uri, |
| 25 const std::string& username, |
| 26 const std::string& 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 const Impl& impl() const override { |
| 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(const std::string& key, const std::string& 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 const rtc::scoped_refptr<webrtc::DataChannelInterface> 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), |
| 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 const rtc::scoped_refptr<PeerConnectionHolder> 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 const rtc::scoped_refptr<PeerConnectionHolder> 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(const std::string& description) override { |
| 275 SetRemoteDescription( |
| 276 webrtc::SessionDescriptionInterface::kOffer, description); |
| 277 } |
| 278 |
| 279 virtual void SetRemoteAnswer(const std::string& description) override { |
| 280 SetRemoteDescription( |
| 281 webrtc::SessionDescriptionInterface::kAnswer, description); |
| 282 } |
| 283 |
| 284 void SetRemoteDescription( |
| 285 const std::string& type, const std::string& 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 const std::string& sdp_mid, |
| 301 int sdp_mline_index, |
| 302 const std::string& 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(const webrtc::SdpParseError& error) { |
| 340 // TODO(serya): Send on signaling thread. |
| 341 } |
| 342 |
| 343 const rtc::scoped_refptr<PeerConnectionHolder> holder_; |
| 344 rtc::Thread* const signaling_thread_; |
| 345 rtc::scoped_refptr<webrtc::PeerConnectionInterface> connection_; |
| 346 const scoped_ptr<PeerConnectionObserverImpl> observer_; |
| 347 const scoped_ptr<AbstractPeerConnection::Delegate> delegate_; |
| 348 }; |
| 349 |
| 350 class SessionDependencyFactoryImpl : public SessionDependencyFactory { |
| 351 public: |
| 352 SessionDependencyFactoryImpl( |
| 353 const base::Closure& 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 const base::Closure& cleanup_on_signaling_thread) { |
| 425 return make_scoped_ptr(new SessionDependencyFactoryImpl( |
| 426 cleanup_on_signaling_thread)); |
| 427 } |
| 428 |
| 429 } // namespace devtools_bridge |
OLD | NEW |