Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(993)

Unified Diff: webrtc/p2p/base/jseptransport.cc

Issue 2517883002: Refactoring that removes P2PTransport and DtlsTransport classes. (Closed)
Patch Set: Adding stub transport.h file for backwards compat. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/p2p/base/jseptransport.h ('k') | webrtc/p2p/base/jseptransport_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/p2p/base/jseptransport.cc
diff --git a/webrtc/p2p/base/transport.cc b/webrtc/p2p/base/jseptransport.cc
similarity index 62%
rename from webrtc/p2p/base/transport.cc
rename to webrtc/p2p/base/jseptransport.cc
index 7bd14c4cad1b8989755c7e6eba61f7ffcaf74c37..abfe0449a48f93e9d5a15806133f7d17e01e43be 100644
--- a/webrtc/p2p/base/transport.cc
+++ b/webrtc/p2p/base/jseptransport.cc
@@ -11,10 +11,12 @@
#include <memory>
#include <utility> // for std::pair
-#include "webrtc/p2p/base/transport.h"
+#include "webrtc/p2p/base/jseptransport.h"
#include "webrtc/p2p/base/candidate.h"
+#include "webrtc/p2p/base/dtlstransportchannel.h"
#include "webrtc/p2p/base/p2pconstants.h"
+#include "webrtc/p2p/base/p2ptransportchannel.h"
#include "webrtc/p2p/base/port.h"
#include "webrtc/p2p/base/transportchannelimpl.h"
#include "webrtc/base/bind.h"
@@ -58,37 +60,112 @@ bool IceCredentialsChanged(const std::string& old_ufrag,
return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
}
-Transport::Transport(const std::string& name, PortAllocator* allocator)
- : name_(name), allocator_(allocator) {}
+bool VerifyCandidate(const Candidate& cand, std::string* error) {
+ // No address zero.
+ if (cand.address().IsNil() || cand.address().IsAnyIP()) {
+ *error = "candidate has address of zero";
+ return false;
+ }
+
+ // Disallow all ports below 1024, except for 80 and 443 on public addresses.
+ int port = cand.address().port();
+ if (cand.protocol() == TCP_PROTOCOL_NAME &&
+ (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
+ // Expected for active-only candidates per
+ // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
+ // Libjingle clients emit port 0, in "active" mode.
+ return true;
+ }
+ if (port < 1024) {
+ if ((port != 80) && (port != 443)) {
+ *error = "candidate has port below 1024, but not 80 or 443";
+ return false;
+ }
+
+ if (cand.address().IsPrivateIP()) {
+ *error = "candidate has port of 80 or 443 with private IP address";
+ return false;
+ }
+ }
-Transport::~Transport() {
- RTC_DCHECK(channels_destroyed_);
+ return true;
}
-void Transport::SetIceRole(IceRole role) {
- ice_role_ = role;
- for (const auto& kv : channels_) {
- kv.second->SetIceRole(ice_role_);
+bool VerifyCandidates(const Candidates& candidates, std::string* error) {
+ for (const Candidate& candidate : candidates) {
+ if (!VerifyCandidate(candidate, error)) {
+ return false;
+ }
}
+ return true;
}
-std::unique_ptr<rtc::SSLCertificate> Transport::GetRemoteSSLCertificate() {
- if (channels_.empty()) {
- return nullptr;
+JsepTransport::JsepTransport(
+ const std::string& mid,
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
+ : mid_(mid), certificate_(certificate) {}
+
+bool JsepTransport::AddChannel(TransportChannelImpl* dtls, int component) {
+ if (channels_.find(component) != channels_.end()) {
+ LOG(LS_ERROR) << "Adding channel for component " << component << " twice.";
+ return false;
+ }
+ channels_[component] = dtls;
+ // Something's wrong if a channel is being added after a description is set.
+ // This may currently occur if rtcp-mux is negotiated, then a new m= section
+ // is added in a later offer/answer. But this is suboptimal and should be
+ // changed; we shouldn't support going from muxed to non-muxed.
+ // TODO(deadbeef): Once this is fixed, make the warning an error, and remove
+ // the calls to "ApplyXTransportDescription" below.
+ if (local_description_set_ || remote_description_set_) {
+ LOG(LS_WARNING) << "Adding new transport channel after "
+ "transport description already applied.";
+ }
+ bool ret = true;
+ std::string err;
+ if (local_description_set_) {
+ ret &= ApplyLocalTransportDescription(channels_[component], &err);
}
+ if (remote_description_set_) {
+ ret &= ApplyRemoteTransportDescription(channels_[component], &err);
+ }
+ if (local_description_set_ && remote_description_set_) {
+ ret &= ApplyNegotiatedTransportDescription(channels_[component], &err);
+ }
+ return ret;
+}
+
+bool JsepTransport::RemoveChannel(int component) {
+ auto it = channels_.find(component);
+ if (it == channels_.end()) {
+ LOG(LS_ERROR) << "Trying to remove channel for component " << component
+ << ", which doesn't exist.";
+ return false;
+ }
+ channels_.erase(component);
+ return true;
+}
- auto iter = channels_.begin();
- return iter->second->GetRemoteSSLCertificate();
+bool JsepTransport::HasChannels() const {
+ return !channels_.empty();
}
-void Transport::SetIceConfig(const IceConfig& config) {
- ice_config_ = config;
- for (const auto& kv : channels_) {
- kv.second->SetIceConfig(ice_config_);
+void JsepTransport::SetLocalCertificate(
+ const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
+ certificate_ = certificate;
+}
+
+bool JsepTransport::GetLocalCertificate(
+ rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const {
+ if (!certificate_) {
+ return false;
}
+
+ *certificate = certificate_;
+ return true;
}
-bool Transport::SetLocalTransportDescription(
+bool JsepTransport::SetLocalTransportDescription(
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
@@ -101,6 +178,16 @@ bool Transport::SetLocalTransportDescription(
local_description_.reset(new TransportDescription(description));
+ rtc::SSLFingerprint* local_fp =
+ local_description_->identity_fingerprint.get();
+
+ if (!local_fp) {
+ certificate_ = nullptr;
+ } else if (!VerifyCertificateFingerprint(certificate_.get(), local_fp,
+ error_desc)) {
+ return false;
+ }
+
for (const auto& kv : channels_) {
ret &= ApplyLocalTransportDescription(kv.second, error_desc);
}
@@ -119,7 +206,7 @@ bool Transport::SetLocalTransportDescription(
return ret;
}
-bool Transport::SetRemoteTransportDescription(
+bool JsepTransport::SetRemoteTransportDescription(
const TransportDescription& description,
ContentAction action,
std::string* error_desc) {
@@ -146,135 +233,18 @@ bool Transport::SetRemoteTransportDescription(
return ret;
}
-TransportChannelImpl* Transport::CreateChannel(int component) {
- TransportChannelImpl* channel;
-
- // Create the entry if it does not exist.
- bool channel_exists = false;
- auto iter = channels_.find(component);
- if (iter == channels_.end()) {
- channel = CreateTransportChannel(component);
- channels_.insert(std::pair<int, TransportChannelImpl*>(component, channel));
- } else {
- channel = iter->second;
- channel_exists = true;
- }
-
- channels_destroyed_ = false;
-
- if (channel_exists) {
- // If this is an existing channel, we should just return it.
- return channel;
- }
-
- // Push down our transport state to the new channel.
- channel->SetIceRole(ice_role_);
- channel->SetIceTiebreaker(tiebreaker_);
- channel->SetIceConfig(ice_config_);
- // TODO(ronghuawu): Change CreateChannel to be able to return error since
- // below Apply**Description calls can fail.
- if (local_description_)
- ApplyLocalTransportDescription(channel, nullptr);
- if (remote_description_)
- ApplyRemoteTransportDescription(channel, nullptr);
- if (local_description_ && remote_description_)
- ApplyNegotiatedTransportDescription(channel, nullptr);
-
- return channel;
-}
-
-TransportChannelImpl* Transport::GetChannel(int component) {
- auto iter = channels_.find(component);
- return (iter != channels_.end()) ? iter->second : nullptr;
-}
-
-bool Transport::HasChannels() {
- return !channels_.empty();
-}
-
-void Transport::DestroyChannel(int component) {
- auto iter = channels_.find(component);
- if (iter == channels_.end())
- return;
-
- TransportChannelImpl* channel = iter->second;
- channels_.erase(iter);
- DestroyTransportChannel(channel);
-}
-
-void Transport::MaybeStartGathering() {
- CallChannels(&TransportChannelImpl::MaybeStartGathering);
-}
-
-void Transport::DestroyAllChannels() {
- for (const auto& kv : channels_) {
- DestroyTransportChannel(kv.second);
- }
- channels_.clear();
- channels_destroyed_ = true;
-}
-
-void Transport::CallChannels(TransportChannelFunc func) {
- for (const auto& kv : channels_) {
- (kv.second->*func)();
- }
-}
-
-bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) {
- // No address zero.
- if (cand.address().IsNil() || cand.address().IsAnyIP()) {
- *error = "candidate has address of zero";
- return false;
- }
-
- // Disallow all ports below 1024, except for 80 and 443 on public addresses.
- int port = cand.address().port();
- if (cand.protocol() == TCP_PROTOCOL_NAME &&
- (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
- // Expected for active-only candidates per
- // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
- // Libjingle clients emit port 0, in "active" mode.
- return true;
- }
- if (port < 1024) {
- if ((port != 80) && (port != 443)) {
- *error = "candidate has port below 1024, but not 80 or 443";
- return false;
- }
-
- if (cand.address().IsPrivateIP()) {
- *error = "candidate has port of 80 or 443 with private IP address";
- return false;
- }
- }
-
- if (!HasChannel(cand.component())) {
- *error = "Candidate has an unknown component: " + cand.ToString() +
- " for content: " + name();
- return false;
- }
-
- return true;
-}
-
-bool Transport::VerifyCandidates(const Candidates& candidates,
- std::string* error) {
- for (const Candidate& candidate : candidates) {
- if (!VerifyCandidate(candidate, error)) {
- return false;
- }
- }
- return true;
+void JsepTransport::GetSslRole(rtc::SSLRole* ssl_role) const {
+ RTC_DCHECK(ssl_role);
+ *ssl_role = secure_role_;
}
-
-bool Transport::GetStats(TransportStats* stats) {
- stats->transport_name = name();
+bool JsepTransport::GetStats(TransportStats* stats) {
+ stats->transport_name = mid();
stats->channel_stats.clear();
- for (auto kv : channels_) {
+ for (auto& kv : channels_) {
TransportChannelImpl* channel = kv.second;
TransportChannelStats substats;
- substats.component = channel->component();
+ substats.component = kv.first;
channel->GetSrtpCryptoSuite(&substats.srtp_crypto_suite);
channel->GetSslCipherSuite(&substats.ssl_cipher_suite);
if (!channel->GetStats(&substats.connection_infos)) {
@@ -285,74 +255,95 @@ bool Transport::GetStats(TransportStats* stats) {
return true;
}
-bool Transport::AddRemoteCandidates(const std::vector<Candidate>& candidates,
- std::string* error) {
- ASSERT(!channels_destroyed_);
- // Verify each candidate before passing down to the transport layer.
- if (!VerifyCandidates(candidates, error)) {
- return false;
- }
-
- for (const Candidate& candidate : candidates) {
- TransportChannelImpl* channel = GetChannel(candidate.component());
- if (channel != nullptr) {
- channel->AddRemoteCandidate(candidate);
- }
+bool JsepTransport::VerifyCertificateFingerprint(
+ const rtc::RTCCertificate* certificate,
+ const rtc::SSLFingerprint* fingerprint,
+ std::string* error_desc) const {
+ if (!fingerprint) {
+ return BadTransportDescription("No fingerprint.", error_desc);
}
- return true;
-}
-
-bool Transport::RemoveRemoteCandidates(const std::vector<Candidate>& candidates,
- std::string* error) {
- ASSERT(!channels_destroyed_);
- // Verify each candidate before passing down to the transport layer.
- if (!VerifyCandidates(candidates, error)) {
- return false;
+ if (!certificate) {
+ return BadTransportDescription(
+ "Fingerprint provided but no identity available.", error_desc);
}
-
- for (const Candidate& candidate : candidates) {
- TransportChannelImpl* channel = GetChannel(candidate.component());
- if (channel != nullptr) {
- channel->RemoveRemoteCandidate(candidate);
- }
+ std::unique_ptr<rtc::SSLFingerprint> fp_tmp(rtc::SSLFingerprint::Create(
+ fingerprint->algorithm, certificate->identity()));
+ ASSERT(fp_tmp.get() != NULL);
+ if (*fp_tmp == *fingerprint) {
+ return true;
}
- return true;
+ std::ostringstream desc;
+ desc << "Local fingerprint does not match identity. Expected: ";
+ desc << fp_tmp->ToString();
+ desc << " Got: " << fingerprint->ToString();
+ return BadTransportDescription(desc.str(), error_desc);
}
-bool Transport::ApplyLocalTransportDescription(TransportChannelImpl* ch,
- std::string* error_desc) {
- ch->SetIceParameters(local_description_->GetIceParameters());
+bool JsepTransport::ApplyLocalTransportDescription(
+ TransportChannelImpl* channel,
+ std::string* error_desc) {
+ channel->SetIceParameters(local_description_->GetIceParameters());
return true;
}
-bool Transport::ApplyRemoteTransportDescription(TransportChannelImpl* ch,
- std::string* error_desc) {
- ch->SetRemoteIceParameters(remote_description_->GetIceParameters());
+bool JsepTransport::ApplyRemoteTransportDescription(
+ TransportChannelImpl* channel,
+ std::string* error_desc) {
+ // Currently, all ICE-related calls still go through this DTLS channel. But
+ // that will change once we get rid of TransportChannelImpl, and the DTLS
+ // channel interface no longer includes ICE-specific methods. Then this class
+ // will need to call dtls->ice()->SetIceRole(), for example, assuming the Dtls
+ // interface will expose its inner ICE channel.
+ channel->SetRemoteIceParameters(remote_description_->GetIceParameters());
+ channel->SetRemoteIceMode(remote_description_->ice_mode);
return true;
}
-bool Transport::ApplyNegotiatedTransportDescription(
+bool JsepTransport::ApplyNegotiatedTransportDescription(
TransportChannelImpl* channel,
std::string* error_desc) {
- channel->SetRemoteIceMode(remote_ice_mode_);
+ // Set SSL role. Role must be set before fingerprint is applied, which
+ // initiates DTLS setup.
+ if (!channel->SetSslRole(secure_role_)) {
+ return BadTransportDescription("Failed to set SSL role for the channel.",
+ error_desc);
+ }
+ // Apply remote fingerprint.
+ if (!channel->SetRemoteFingerprint(
+ remote_fingerprint_->algorithm,
+ reinterpret_cast<const uint8_t*>(remote_fingerprint_->digest.data()),
+ remote_fingerprint_->digest.size())) {
+ return BadTransportDescription("Failed to apply remote fingerprint.",
+ error_desc);
+ }
return true;
}
-bool Transport::NegotiateTransportDescription(ContentAction local_role,
- std::string* error_desc) {
- // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
- // P2PTransport.
-
- // If transport is in ICEROLE_CONTROLLED and remote end point supports only
- // ice_lite, this local end point should take CONTROLLING role.
- if (ice_role_ == ICEROLE_CONTROLLED &&
- remote_description_->ice_mode == ICEMODE_LITE) {
- SetIceRole(ICEROLE_CONTROLLING);
+bool JsepTransport::NegotiateTransportDescription(ContentAction local_role,
+ std::string* error_desc) {
+ if (!local_description_ || !remote_description_) {
+ const std::string msg =
+ "Applying an answer transport description "
+ "without applying any offer.";
+ return BadTransportDescription(msg, error_desc);
+ }
+ rtc::SSLFingerprint* local_fp =
+ local_description_->identity_fingerprint.get();
+ rtc::SSLFingerprint* remote_fp =
+ remote_description_->identity_fingerprint.get();
+ if (remote_fp && local_fp) {
+ remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp));
+ if (!NegotiateRole(local_role, &secure_role_, error_desc)) {
+ return false;
+ }
+ } else if (local_fp && (local_role == CA_ANSWER)) {
+ return BadTransportDescription(
+ "Local fingerprint supplied when caller didn't offer DTLS.",
+ error_desc);
+ } else {
+ // We are not doing DTLS
+ remote_fingerprint_.reset(new rtc::SSLFingerprint("", nullptr, 0));
}
-
- // Update remote ice_mode to all existing channels.
- remote_ice_mode_ = remote_description_->ice_mode;
-
// Now that we have negotiated everything, push it downward.
// Note that we cache the result so that if we have race conditions
// between future SetRemote/SetLocal invocations and new channel
@@ -366,35 +357,11 @@ bool Transport::NegotiateTransportDescription(ContentAction local_role,
return true;
}
-bool Transport::VerifyCertificateFingerprint(
- const rtc::RTCCertificate* certificate,
- const rtc::SSLFingerprint* fingerprint,
- std::string* error_desc) const {
- if (!fingerprint) {
- return BadTransportDescription("No fingerprint.", error_desc);
- }
- if (!certificate) {
- return BadTransportDescription(
- "Fingerprint provided but no identity available.", error_desc);
- }
- std::unique_ptr<rtc::SSLFingerprint> fp_tmp(rtc::SSLFingerprint::Create(
- fingerprint->algorithm, certificate->identity()));
- ASSERT(fp_tmp.get() != NULL);
- if (*fp_tmp == *fingerprint) {
- return true;
- }
- std::ostringstream desc;
- desc << "Local fingerprint does not match identity. Expected: ";
- desc << fp_tmp->ToString();
- desc << " Got: " << fingerprint->ToString();
- return BadTransportDescription(desc.str(), error_desc);
-}
-
-bool Transport::NegotiateRole(ContentAction local_role,
- rtc::SSLRole* ssl_role,
- std::string* error_desc) const {
+bool JsepTransport::NegotiateRole(ContentAction local_role,
+ rtc::SSLRole* ssl_role,
+ std::string* error_desc) const {
RTC_DCHECK(ssl_role);
- if (!local_description() || !remote_description()) {
+ if (!local_description_ || !remote_description_) {
const std::string msg =
"Local and Remote description must be set before "
"transport descriptions are negotiated";
@@ -424,8 +391,8 @@ bool Transport::NegotiateRole(ContentAction local_role,
// ClientHello over each flow (host/port quartet).
// IOW - actpass and passive modes should be treated as server and
// active as client.
- ConnectionRole local_connection_role = local_description()->connection_role;
- ConnectionRole remote_connection_role = remote_description()->connection_role;
+ ConnectionRole local_connection_role = local_description_->connection_role;
+ ConnectionRole remote_connection_role = remote_description_->connection_role;
bool is_remote_server = false;
if (local_role == CA_OFFER) {
« no previous file with comments | « webrtc/p2p/base/jseptransport.h ('k') | webrtc/p2p/base/jseptransport_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698