Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/webrtc_transport.h" | 5 #include "remoting/protocol/webrtc_transport.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_split.h" | |
| 16 #include "base/strings/string_util.h" | |
| 15 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
| 16 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| 17 #include "jingle/glue/thread_wrapper.h" | 19 #include "jingle/glue/thread_wrapper.h" |
| 18 #include "remoting/protocol/authenticator.h" | 20 #include "remoting/protocol/authenticator.h" |
| 19 #include "remoting/protocol/port_allocator_factory.h" | 21 #include "remoting/protocol/port_allocator_factory.h" |
| 20 #include "remoting/protocol/stream_message_pipe_adapter.h" | 22 #include "remoting/protocol/stream_message_pipe_adapter.h" |
| 21 #include "remoting/protocol/transport_context.h" | 23 #include "remoting/protocol/transport_context.h" |
| 22 #include "third_party/webrtc/api/test/fakeconstraints.h" | 24 #include "third_party/webrtc/api/test/fakeconstraints.h" |
| 23 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | 25 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" |
| 24 #include "third_party/webrtc/modules/audio_device/include/fake_audio_device.h" | 26 #include "third_party/webrtc/modules/audio_device/include/fake_audio_device.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 38 | 40 |
| 39 // XML namespace for the transport elements. | 41 // XML namespace for the transport elements. |
| 40 const char kTransportNamespace[] = "google:remoting:webrtc"; | 42 const char kTransportNamespace[] = "google:remoting:webrtc"; |
| 41 | 43 |
| 42 #if !defined(NDEBUG) | 44 #if !defined(NDEBUG) |
| 43 // Command line switch used to disable signature verification. | 45 // Command line switch used to disable signature verification. |
| 44 // TODO(sergeyu): Remove this flag. | 46 // TODO(sergeyu): Remove this flag. |
| 45 const char kDisableAuthenticationSwitchName[] = "disable-authentication"; | 47 const char kDisableAuthenticationSwitchName[] = "disable-authentication"; |
| 46 #endif | 48 #endif |
| 47 | 49 |
| 50 // Normalizes the SDP message to make sure the text used for HMAC signatures | |
| 51 // verifications is the same that was signed on the sending side.This is | |
|
kelvinp
2016/03/31 01:09:38
Nit: missing space after .
Sergey Ulanov
2016/03/31 16:52:18
Done.
| |
| 52 // necessary because WebRTC generates SDP with CRLF line endings which are | |
| 53 // sometimes converted to LF after passing the signaling channel. | |
| 54 std::string NormalizeSessionDescription(const std::string& sdp) { | |
| 55 // Split SDP lines. The CR symbols is removed by the TRIM_WHITESPACE flag. | |
| 56 std::vector<std::string> lines = | |
| 57 SplitString(sdp, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 58 return base::JoinString(lines, "\n") + "\n"; | |
| 59 } | |
| 60 | |
| 48 // A webrtc::CreateSessionDescriptionObserver implementation used to receive the | 61 // A webrtc::CreateSessionDescriptionObserver implementation used to receive the |
| 49 // results of creating descriptions for this end of the PeerConnection. | 62 // results of creating descriptions for this end of the PeerConnection. |
| 50 class CreateSessionDescriptionObserver | 63 class CreateSessionDescriptionObserver |
| 51 : public webrtc::CreateSessionDescriptionObserver { | 64 : public webrtc::CreateSessionDescriptionObserver { |
| 52 public: | 65 public: |
| 53 typedef base::Callback<void( | 66 typedef base::Callback<void( |
| 54 scoped_ptr<webrtc::SessionDescriptionInterface> description, | 67 scoped_ptr<webrtc::SessionDescriptionInterface> description, |
| 55 const std::string& error)> ResultCallback; | 68 const std::string& error)> ResultCallback; |
| 56 | 69 |
| 57 static CreateSessionDescriptionObserver* Create( | 70 static CreateSessionDescriptionObserver* Create( |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 webrtc::PeerConnectionInterface::SignalingState expected_state = | 212 webrtc::PeerConnectionInterface::SignalingState expected_state = |
| 200 transport_context_->role() == TransportRole::CLIENT | 213 transport_context_->role() == TransportRole::CLIENT |
| 201 ? webrtc::PeerConnectionInterface::kStable | 214 ? webrtc::PeerConnectionInterface::kStable |
| 202 : webrtc::PeerConnectionInterface::kHaveLocalOffer; | 215 : webrtc::PeerConnectionInterface::kHaveLocalOffer; |
| 203 if (peer_connection_->signaling_state() != expected_state) { | 216 if (peer_connection_->signaling_state() != expected_state) { |
| 204 LOG(ERROR) << "Received unexpected WebRTC session_description."; | 217 LOG(ERROR) << "Received unexpected WebRTC session_description."; |
| 205 return false; | 218 return false; |
| 206 } | 219 } |
| 207 | 220 |
| 208 std::string type = session_description->Attr(QName(std::string(), "type")); | 221 std::string type = session_description->Attr(QName(std::string(), "type")); |
| 209 std::string sdp = session_description->BodyText(); | 222 std::string sdp = |
| 223 NormalizeSessionDescription(session_description->BodyText()); | |
| 210 if (type.empty() || sdp.empty()) { | 224 if (type.empty() || sdp.empty()) { |
| 211 LOG(ERROR) << "Incorrect session description format."; | 225 LOG(ERROR) << "Incorrect session description format."; |
| 212 return false; | 226 return false; |
| 213 } | 227 } |
| 214 | 228 |
| 215 std::string signature_base64 = | 229 std::string signature_base64 = |
| 216 session_description->Attr(QName(std::string(), "signature")); | 230 session_description->Attr(QName(std::string(), "signature")); |
| 217 std::string signature; | 231 std::string signature; |
| 218 if (!base::Base64Decode(signature_base64, &signature) || | 232 if (!base::Base64Decode(signature_base64, &signature) || |
| 219 !handshake_hmac_.Verify(sdp, signature)) { | 233 !handshake_hmac_.Verify(sdp, signature)) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 Close(CHANNEL_CONNECTION_ERROR); | 314 Close(CHANNEL_CONNECTION_ERROR); |
| 301 return; | 315 return; |
| 302 } | 316 } |
| 303 | 317 |
| 304 std::string description_sdp; | 318 std::string description_sdp; |
| 305 if (!description->ToString(&description_sdp)) { | 319 if (!description->ToString(&description_sdp)) { |
| 306 LOG(ERROR) << "Failed to serialize description."; | 320 LOG(ERROR) << "Failed to serialize description."; |
| 307 Close(CHANNEL_CONNECTION_ERROR); | 321 Close(CHANNEL_CONNECTION_ERROR); |
| 308 return; | 322 return; |
| 309 } | 323 } |
| 324 description_sdp = NormalizeSessionDescription(description_sdp); | |
| 310 | 325 |
| 311 // Format and send the session description to the peer. | 326 // Format and send the session description to the peer. |
| 312 scoped_ptr<XmlElement> transport_info( | 327 scoped_ptr<XmlElement> transport_info( |
| 313 new XmlElement(QName(kTransportNamespace, "transport"), true)); | 328 new XmlElement(QName(kTransportNamespace, "transport"), true)); |
| 314 XmlElement* offer_tag = | 329 XmlElement* offer_tag = |
| 315 new XmlElement(QName(kTransportNamespace, "session-description")); | 330 new XmlElement(QName(kTransportNamespace, "session-description")); |
| 316 transport_info->AddElement(offer_tag); | 331 transport_info->AddElement(offer_tag); |
| 317 offer_tag->SetAttr(QName(std::string(), "type"), description->type()); | 332 offer_tag->SetAttr(QName(std::string(), "type"), description->type()); |
| 318 offer_tag->SetBodyText(description_sdp); | 333 offer_tag->SetBodyText(description_sdp); |
| 319 | 334 |
| 320 std::string digest; | 335 std::string digest; |
| 321 digest.resize(handshake_hmac_.DigestLength()); | 336 digest.resize(handshake_hmac_.DigestLength()); |
| 322 CHECK(handshake_hmac_.Sign(description_sdp, | 337 CHECK(handshake_hmac_.Sign(description_sdp, |
| 323 reinterpret_cast<uint8_t*>(&(digest[0])), | 338 reinterpret_cast<uint8_t*>(&(digest[0])), |
| 324 digest.size())); | 339 digest.size())); |
| 325 std::string digest_base64; | 340 std::string digest_base64; |
| 326 base::Base64Encode(digest, &digest_base64); | 341 base::Base64Encode(digest, &digest_base64); |
| 327 offer_tag->SetAttr(QName(std::string(), "signature"), digest_base64); | 342 offer_tag->SetAttr(QName(std::string(), "signature"), digest_base64); |
| 328 | 343 |
| 329 send_transport_info_callback_.Run(std::move(transport_info)); | 344 send_transport_info_callback_.Run(std::move(transport_info)); |
| 330 | 345 |
| 331 peer_connection_->SetLocalDescription( | 346 peer_connection_->SetLocalDescription( |
| 332 SetSessionDescriptionObserver::Create(base::Bind( | 347 SetSessionDescriptionObserver::Create(base::Bind( |
| 333 &WebrtcTransport::OnLocalDescriptionSet, weak_factory_.GetWeakPtr())), | 348 &WebrtcTransport::OnLocalDescriptionSet, weak_factory_.GetWeakPtr())), |
| 334 description.release()); | 349 description.release()); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 peer_connection_->Close(); | 544 peer_connection_->Close(); |
| 530 peer_connection_ = nullptr; | 545 peer_connection_ = nullptr; |
| 531 peer_connection_factory_ = nullptr; | 546 peer_connection_factory_ = nullptr; |
| 532 | 547 |
| 533 if (error != OK) | 548 if (error != OK) |
| 534 event_handler_->OnWebrtcTransportError(error); | 549 event_handler_->OnWebrtcTransportError(error); |
| 535 } | 550 } |
| 536 | 551 |
| 537 } // namespace protocol | 552 } // namespace protocol |
| 538 } // namespace remoting | 553 } // namespace remoting |
| OLD | NEW |