Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/p2p/quic/quictransport.h" | |
| 12 | |
| 13 namespace cricket { | |
| 14 | |
| 15 QuicTransport::QuicTransport( | |
| 16 const std::string& name, | |
| 17 PortAllocator* allocator, | |
| 18 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) | |
| 19 : Transport(name, allocator), | |
| 20 certificate_(certificate), | |
| 21 secure_role_(rtc::SSL_CLIENT) {} | |
| 22 | |
| 23 QuicTransport::~QuicTransport() { | |
| 24 DestroyAllChannels(); // Must be called to avoid assertion error. | |
| 25 } | |
| 26 | |
| 27 void QuicTransport::SetLocalCertificate( | |
| 28 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | |
| 29 certificate_ = certificate; | |
| 30 } | |
| 31 bool QuicTransport::GetLocalCertificate( | |
| 32 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
| 33 if (!certificate_) | |
| 34 return false; | |
| 35 | |
| 36 *certificate = certificate_; | |
| 37 return true; | |
| 38 } | |
| 39 | |
| 40 bool QuicTransport::ApplyLocalTransportDescription( | |
| 41 TransportChannelImpl* channel, | |
| 42 std::string* error_desc) { | |
| 43 rtc::SSLFingerprint* local_fp = | |
| 44 local_description()->identity_fingerprint.get(); | |
| 45 | |
| 46 if (local_fp) { | |
| 47 // Sanity check local fingerprint. | |
| 48 if (certificate_) { | |
| 49 rtc::scoped_ptr<rtc::SSLFingerprint> local_fp_tmp( | |
| 50 rtc::SSLFingerprint::Create(local_fp->algorithm, | |
| 51 certificate_->identity())); | |
| 52 ASSERT(local_fp_tmp.get() != NULL); | |
| 53 if (!(*local_fp_tmp == *local_fp)) { | |
| 54 std::ostringstream desc; | |
| 55 desc << "Local fingerprint does not match identity. Expected: "; | |
| 56 desc << local_fp_tmp->ToString(); | |
| 57 desc << " Got: " << local_fp->ToString(); | |
| 58 return BadTransportDescription(desc.str(), error_desc); | |
| 59 } | |
| 60 } else { | |
| 61 return BadTransportDescription( | |
| 62 "Local fingerprint provided but no identity available.", error_desc); | |
| 63 } | |
| 64 } else { | |
| 65 certificate_ = nullptr; | |
| 66 } | |
| 67 | |
| 68 if (!channel->SetLocalCertificate(certificate_)) { | |
| 69 return BadTransportDescription("Failed to set local identity.", error_desc); | |
| 70 } | |
| 71 | |
| 72 return Transport::ApplyLocalTransportDescription(channel, error_desc); | |
| 73 } | |
| 74 | |
| 75 bool QuicTransport::NegotiateTransportDescription(ContentAction local_role, | |
| 76 std::string* error_desc) { | |
| 77 if (!local_description() || !remote_description()) { | |
| 78 const std::string msg = | |
| 79 "Local and Remote description must be set before " | |
| 80 "transport descriptions are negotiated"; | |
| 81 return BadTransportDescription(msg, error_desc); | |
| 82 } | |
| 83 | |
| 84 rtc::SSLFingerprint* remote_fp = | |
| 85 remote_description()->identity_fingerprint.get(); | |
| 86 | |
| 87 if (!remote_fp) { | |
| 88 return BadTransportDescription("Remote fingerprint not supplied.", | |
| 89 error_desc); | |
| 90 } | |
| 91 | |
| 92 remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp)); | |
| 93 | |
| 94 // TODO(pthatcher): Move all the negotiation up into PeerConnection and | |
| 95 // out of the Transport code. Just have a SetRole or similar method here. | |
| 96 ConnectionRole local_connection_role = local_description()->connection_role; | |
| 97 ConnectionRole remote_connection_role = remote_description()->connection_role; | |
| 98 | |
| 99 bool is_remote_server = false; | |
| 100 if (local_role == CA_OFFER) { | |
| 101 if (local_connection_role != CONNECTIONROLE_ACTPASS) { | |
| 102 return BadTransportDescription( | |
| 103 "Offerer must use actpass value for setup attribute.", error_desc); | |
| 104 } | |
| 105 | |
| 106 if (remote_connection_role == CONNECTIONROLE_ACTIVE || | |
| 107 remote_connection_role == CONNECTIONROLE_PASSIVE || | |
| 108 remote_connection_role == CONNECTIONROLE_NONE) { | |
| 109 is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE); | |
| 110 } else { | |
| 111 const std::string msg = | |
| 112 "Answerer must use either active or passive value " | |
| 113 "for setup attribute."; | |
| 114 return BadTransportDescription(msg, error_desc); | |
| 115 } | |
| 116 // If remote is NONE or ACTIVE it will act as client. | |
| 117 } else { | |
| 118 if (remote_connection_role != CONNECTIONROLE_ACTPASS && | |
| 119 remote_connection_role != CONNECTIONROLE_NONE) { | |
| 120 return BadTransportDescription( | |
| 121 "Offerer must use actpass value for setup attribute.", error_desc); | |
| 122 } | |
| 123 | |
| 124 if (local_connection_role != CONNECTIONROLE_ACTIVE && | |
| 125 local_connection_role != CONNECTIONROLE_PASSIVE) { | |
| 126 const std::string msg = | |
| 127 "Answerer must use either active or passive value " | |
| 128 "for setup attribute."; | |
| 129 return BadTransportDescription(msg, error_desc); | |
| 130 } | |
| 131 // If local is passive, local will act as server. | |
| 132 is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE); | |
| 133 } | |
| 134 | |
| 135 secure_role_ = is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER; | |
| 136 | |
| 137 // Now run the negotiation for the Transport class. | |
| 138 return Transport::NegotiateTransportDescription(local_role, error_desc); | |
|
Taylor Brandstetter
2016/04/05 22:13:49
There's a lot of duplicated code here. Would it ma
mikescarlett
2016/04/06 18:43:44
To avoid code duplication, another solution is tha
Taylor Brandstetter
2016/04/06 19:27:41
That sounds like a good idea. Though the advantage
mikescarlett
2016/04/06 21:18:14
Good point. My main concern with inheritance is th
mikescarlett
2016/04/12 00:06:38
Peter and I discussed this offline. He says that d
| |
| 139 } | |
| 140 | |
| 141 QuicTransportChannel* QuicTransport::CreateTransportChannel(int component) { | |
| 142 P2PTransportChannel* ice_channel = | |
| 143 new P2PTransportChannel(name(), component, port_allocator()); | |
| 144 QuicTransportChannel* quic_channel = new QuicTransportChannel(ice_channel); | |
| 145 ice_channel_by_quic_channel_[quic_channel] = ice_channel; | |
| 146 return quic_channel; | |
| 147 } | |
| 148 | |
| 149 void QuicTransport::DestroyTransportChannel(TransportChannelImpl* channel) { | |
| 150 const auto& kv = ice_channel_by_quic_channel_.find(channel); | |
| 151 RTC_DCHECK(kv != ice_channel_by_quic_channel_.end()); | |
| 152 delete kv->first; | |
| 153 delete kv->second; | |
| 154 } | |
| 155 | |
| 156 bool QuicTransport::GetSslRole(rtc::SSLRole* ssl_role) const { | |
| 157 ASSERT(ssl_role != NULL); | |
| 158 *ssl_role = secure_role_; | |
| 159 return true; | |
| 160 } | |
| 161 | |
| 162 bool QuicTransport::ApplyNegotiatedTransportDescription( | |
| 163 TransportChannelImpl* channel, | |
| 164 std::string* error_desc) { | |
| 165 // Set ssl role and remote fingerprint. These are required for QUIC setup. | |
| 166 if (!channel->SetSslRole(secure_role_)) { | |
| 167 return BadTransportDescription("Failed to set ssl role for the channel.", | |
| 168 error_desc); | |
| 169 } | |
| 170 // Apply remote fingerprint. | |
| 171 if (!channel->SetRemoteFingerprint( | |
| 172 remote_fingerprint_->algorithm, | |
| 173 reinterpret_cast<const uint8_t*>(remote_fingerprint_->digest.data()), | |
| 174 remote_fingerprint_->digest.size())) { | |
| 175 return BadTransportDescription("Failed to apply remote fingerprint.", | |
| 176 error_desc); | |
| 177 } | |
| 178 return Transport::ApplyNegotiatedTransportDescription(channel, error_desc); | |
| 179 } | |
| 180 | |
| 181 } // namespace cricket | |
| OLD | NEW |