summaryrefslogtreecommitdiffstats
path: root/remoting/protocol
diff options
context:
space:
mode:
authorsergeyu <sergeyu@chromium.org>2015-04-23 11:59:12 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-23 18:59:56 +0000
commitb4b0927a2e02d6357f019aeb78576e7a8d84da47 (patch)
tree94448c68a7d18547dc542cadb12a1aaa702012f9 /remoting/protocol
parent616c2c3cedbe27df60a39ba14c566885af9513d7 (diff)
downloadchromium_src-b4b0927a2e02d6357f019aeb78576e7a8d84da47.zip
chromium_src-b4b0927a2e02d6357f019aeb78576e7a8d84da47.tar.gz
chromium_src-b4b0927a2e02d6357f019aeb78576e7a8d84da47.tar.bz2
Use standard ICE in Chromoting.
Previously we were using legacy, non-standard version of ICE. This change adds ICE version negotiation and enabled standard ICE by default, when both peers support it. BUG=473758 Committed: https://crrev.com/5a5854ee3e1c5760b422f26d31909bfb5dca631f Cr-Commit-Position: refs/heads/master@{#326560} Review URL: https://codereview.chromium.org/1085703003 Cr-Commit-Position: refs/heads/master@{#326600}
Diffstat (limited to 'remoting/protocol')
-rw-r--r--remoting/protocol/content_description.cc42
-rw-r--r--remoting/protocol/content_description.h7
-rw-r--r--remoting/protocol/fake_connection_to_host.cc2
-rw-r--r--remoting/protocol/fake_connection_to_host.h2
-rw-r--r--remoting/protocol/fake_session.cc6
-rw-r--r--remoting/protocol/fake_session.h4
-rw-r--r--remoting/protocol/jingle_messages.cc248
-rw-r--r--remoting/protocol/jingle_messages.h25
-rw-r--r--remoting/protocol/jingle_messages_unittest.cc119
-rw-r--r--remoting/protocol/jingle_session.cc130
-rw-r--r--remoting/protocol/jingle_session.h25
-rw-r--r--remoting/protocol/jingle_session_unittest.cc28
-rw-r--r--remoting/protocol/libjingle_transport_factory.cc83
-rw-r--r--remoting/protocol/libjingle_transport_factory.h4
-rw-r--r--remoting/protocol/protocol_mock_objects.h5
-rw-r--r--remoting/protocol/session.h2
-rw-r--r--remoting/protocol/session_config.cc187
-rw-r--r--remoting/protocol/session_config.h75
-rw-r--r--remoting/protocol/transport.h21
19 files changed, 716 insertions, 299 deletions
diff --git a/remoting/protocol/content_description.cc b/remoting/protocol/content_description.cc
index 5d8aaac..a48c57b 100644
--- a/remoting/protocol/content_description.cc
+++ b/remoting/protocol/content_description.cc
@@ -25,6 +25,7 @@ const char kDefaultNs[] = "";
// Following constants are used to format session description in XML.
const char kDescriptionTag[] = "description";
+const char kStandardIceTag[] = "standard-ice";
const char kControlTag[] = "control";
const char kEventTag[] = "event";
const char kVideoTag[] = "video";
@@ -121,17 +122,10 @@ ContentDescription::ContentDescription(
ContentDescription::~ContentDescription() { }
-ContentDescription* ContentDescription::Copy() const {
- if (!candidate_config_.get() || !authenticator_message_.get()) {
- return nullptr;
- }
- scoped_ptr<XmlElement> message(new XmlElement(*authenticator_message_));
- return new ContentDescription(candidate_config_->Clone(), message.Pass());
-}
-
// ToXml() creates content description for chromoting session. The
// description looks as follows:
// <description xmlns="google:remoting">
+// <standard-ice/>
// <control transport="stream" version="1" />
// <event transport="datagram" version="1" />
// <video transport="stream" codec="vp8" version="1" />
@@ -145,27 +139,25 @@ XmlElement* ContentDescription::ToXml() const {
XmlElement* root = new XmlElement(
QName(kChromotingXmlNamespace, kDescriptionTag), true);
- std::list<ChannelConfig>::const_iterator it;
+ if (config()->standard_ice()) {
+ root->AddElement(
+ new buzz::XmlElement(QName(kChromotingXmlNamespace, kStandardIceTag)));
+ }
- for (it = config()->control_configs().begin();
- it != config()->control_configs().end(); ++it) {
- root->AddElement(FormatChannelConfig(*it, kControlTag));
+ for (const ChannelConfig& channel_config : config()->control_configs()) {
+ root->AddElement(FormatChannelConfig(channel_config, kControlTag));
}
- for (it = config()->event_configs().begin();
- it != config()->event_configs().end(); ++it) {
- root->AddElement(FormatChannelConfig(*it, kEventTag));
+ for (const ChannelConfig& channel_config : config()->event_configs()) {
+ root->AddElement(FormatChannelConfig(channel_config, kEventTag));
}
- for (it = config()->video_configs().begin();
- it != config()->video_configs().end(); ++it) {
- root->AddElement(FormatChannelConfig(*it, kVideoTag));
+ for (const ChannelConfig& channel_config : config()->video_configs()) {
+ root->AddElement(FormatChannelConfig(channel_config, kVideoTag));
}
- for (it = config()->audio_configs().begin();
- it != config()->audio_configs().end(); ++it) {
- ChannelConfig config = *it;
- root->AddElement(FormatChannelConfig(config, kAudioTag));
+ for (const ChannelConfig& channel_config : config()->audio_configs()) {
+ root->AddElement(FormatChannelConfig(channel_config, kAudioTag));
}
// Older endpoints require an initial-resolution tag, but otherwise ignore it.
@@ -192,7 +184,6 @@ bool ContentDescription::ParseChannelConfigs(
bool codec_required,
bool optional,
std::list<ChannelConfig>* const configs) {
-
QName tag(kChromotingXmlNamespace, tag_name);
const XmlElement* child = element->FirstNamed(tag);
while (child) {
@@ -218,6 +209,11 @@ scoped_ptr<ContentDescription> ContentDescription::ParseXml(
}
scoped_ptr<CandidateSessionConfig> config(
CandidateSessionConfig::CreateEmpty());
+
+ config->set_standard_ice(
+ element->FirstNamed(QName(kChromotingXmlNamespace, kStandardIceTag)) !=
+ nullptr);
+
if (!ParseChannelConfigs(element, kControlTag, false, false,
config->mutable_control_configs()) ||
!ParseChannelConfigs(element, kEventTag, false, false,
diff --git a/remoting/protocol/content_description.h b/remoting/protocol/content_description.h
index 748b0f9..f12582f 100644
--- a/remoting/protocol/content_description.h
+++ b/remoting/protocol/content_description.h
@@ -10,7 +10,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/protocol/session_config.h"
-#include "third_party/webrtc/p2p/base/sessiondescription.h"
namespace buzz {
class XmlElement;
@@ -24,15 +23,13 @@ namespace protocol {
//
// This class also provides a type abstraction so that the Chromotocol Session
// interface does not need to depend on libjingle.
-class ContentDescription : public cricket::ContentDescription {
+class ContentDescription {
public:
static const char kChromotingContentName[];
ContentDescription(scoped_ptr<CandidateSessionConfig> config,
scoped_ptr<buzz::XmlElement> authenticator_message);
- ~ContentDescription() override;
-
- ContentDescription* Copy() const override;
+ ~ContentDescription();
const CandidateSessionConfig* config() const {
return candidate_config_.get();
diff --git a/remoting/protocol/fake_connection_to_host.cc b/remoting/protocol/fake_connection_to_host.cc
index 025f720..6567d92 100644
--- a/remoting/protocol/fake_connection_to_host.cc
+++ b/remoting/protocol/fake_connection_to_host.cc
@@ -85,7 +85,7 @@ void FakeConnectionToHost::SignalConnectionReady(bool ready) {
}
const protocol::SessionConfig& FakeConnectionToHost::config() {
- return session_config_;
+ return *session_config_;
}
protocol::ClipboardStub* FakeConnectionToHost::clipboard_forwarder() {
diff --git a/remoting/protocol/fake_connection_to_host.h b/remoting/protocol/fake_connection_to_host.h
index 8220a96..1c3fe40 100644
--- a/remoting/protocol/fake_connection_to_host.h
+++ b/remoting/protocol/fake_connection_to_host.h
@@ -54,7 +54,7 @@ class FakeConnectionToHost : public protocol::ConnectionToHost {
testing::NiceMock<protocol::MockClipboardStub> mock_clipboard_stub_;
testing::NiceMock<protocol::MockHostStub> mock_host_stub_;
testing::NiceMock<protocol::MockInputStub> mock_input_stub_;
- protocol::SessionConfig session_config_;
+ scoped_ptr<protocol::SessionConfig> session_config_;
DISALLOW_COPY_AND_ASSIGN(FakeConnectionToHost);
};
diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc
index ba6a5a9..68a78ca 100644
--- a/remoting/protocol/fake_session.cc
+++ b/remoting/protocol/fake_session.cc
@@ -36,11 +36,11 @@ const CandidateSessionConfig* FakeSession::candidate_config() {
}
const SessionConfig& FakeSession::config() {
- return config_;
+ return *config_;
}
-void FakeSession::set_config(const SessionConfig& config) {
- config_ = config;
+void FakeSession::set_config(scoped_ptr<SessionConfig> config) {
+ config_ = config.Pass();
}
StreamChannelFactory* FakeSession::GetTransportChannelFactory() {
diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h
index 2e5d5ce..e8ea472 100644
--- a/remoting/protocol/fake_session.h
+++ b/remoting/protocol/fake_session.h
@@ -39,7 +39,7 @@ class FakeSession : public Session {
const std::string& jid() override;
const CandidateSessionConfig* candidate_config() override;
const SessionConfig& config() override;
- void set_config(const SessionConfig& config) override;
+ void set_config(scoped_ptr<SessionConfig> config) override;
StreamChannelFactory* GetTransportChannelFactory() override;
StreamChannelFactory* GetMultiplexedChannelFactory() override;
void Close() override;
@@ -47,7 +47,7 @@ class FakeSession : public Session {
public:
EventHandler* event_handler_;
scoped_ptr<const CandidateSessionConfig> candidate_config_;
- SessionConfig config_;
+ scoped_ptr<SessionConfig> config_;
FakeStreamChannelFactory channel_factory_;
diff --git a/remoting/protocol/jingle_messages.cc b/remoting/protocol/jingle_messages.cc
index c2c9b80..7e4c21e 100644
--- a/remoting/protocol/jingle_messages.cc
+++ b/remoting/protocol/jingle_messages.cc
@@ -17,11 +17,16 @@ using buzz::XmlElement;
namespace remoting {
namespace protocol {
+namespace {
+
const char kJabberNamespace[] = "jabber:client";
const char kJingleNamespace[] = "urn:xmpp:jingle:1";
-const char kP2PTransportNamespace[] = "http://www.google.com/transport/p2p";
-namespace {
+// Namespace for transport messages for legacy GICE.
+const char kGiceTransportNamespace[] = "http://www.google.com/transport/p2p";
+
+// Namespace for transport messages when using standard ICE.
+const char kIceTransportNamespace[] = "google:remoting:ice";
const char kEmptyNamespace[] = "";
const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace";
@@ -45,9 +50,101 @@ const NameMapElement<JingleMessage::Reason> kReasons[] = {
{ JingleMessage::INCOMPATIBLE_PARAMETERS, "incompatible-parameters" },
};
-bool ParseCandidate(const buzz::XmlElement* element,
- JingleMessage::NamedCandidate* candidate) {
- DCHECK(element->Name() == QName(kP2PTransportNamespace, "candidate"));
+bool ParseIceCredentials(const buzz::XmlElement* element,
+ JingleMessage::IceCredentials* credentials) {
+ DCHECK(element->Name() == QName(kIceTransportNamespace, "credentials"));
+
+ const std::string& channel = element->Attr(QName(kEmptyNamespace, "channel"));
+ const std::string& ufrag =
+ element->Attr(QName(kEmptyNamespace, "ufrag"));
+ const std::string& password =
+ element->Attr(QName(kEmptyNamespace, "password"));
+
+ if (channel.empty() || ufrag.empty() || password.empty()) {
+ return false;
+ }
+
+ credentials->channel = channel;
+ credentials->ufrag = ufrag;
+ credentials->password = password;
+
+ return true;
+}
+
+bool ParseIceCandidate(const buzz::XmlElement* element,
+ JingleMessage::NamedCandidate* candidate) {
+ DCHECK(element->Name() == QName(kIceTransportNamespace, "candidate"));
+
+ const std::string& name = element->Attr(QName(kEmptyNamespace, "name"));
+ const std::string& foundation =
+ element->Attr(QName(kEmptyNamespace, "foundation"));
+ const std::string& address = element->Attr(QName(kEmptyNamespace, "address"));
+ const std::string& port_str = element->Attr(QName(kEmptyNamespace, "port"));
+ const std::string& type = element->Attr(QName(kEmptyNamespace, "type"));
+ const std::string& protocol =
+ element->Attr(QName(kEmptyNamespace, "protocol"));
+ const std::string& priority_str =
+ element->Attr(QName(kEmptyNamespace, "priority"));
+ const std::string& generation_str =
+ element->Attr(QName(kEmptyNamespace, "generation"));
+
+ int port;
+ unsigned priority;
+ int generation;
+ if (name.empty() || foundation.empty() || address.empty() ||
+ !base::StringToInt(port_str, &port) || port < kPortMin ||
+ port > kPortMax || type.empty() || protocol.empty() ||
+ !base::StringToUint(priority_str, &priority) ||
+ !base::StringToInt(generation_str, &generation)) {
+ return false;
+ }
+
+ candidate->name = name;
+
+ candidate->candidate.set_foundation(foundation);
+ candidate->candidate.set_address(rtc::SocketAddress(address, port));
+ candidate->candidate.set_type(type);
+ candidate->candidate.set_protocol(protocol);
+ candidate->candidate.set_priority(priority);
+ candidate->candidate.set_generation(generation);
+
+ return true;
+}
+
+bool ParseIceTransportInfo(
+ const buzz::XmlElement* element,
+ std::list<JingleMessage::IceCredentials>* ice_credentials,
+ std::list<JingleMessage::NamedCandidate>* candidates) {
+ DCHECK(element->Name() == QName(kIceTransportNamespace, "transport"));
+
+ ice_credentials->clear();
+ candidates->clear();
+
+ QName qn_credentials(kIceTransportNamespace, "credentials");
+ for (const XmlElement* credentials_tag = element->FirstNamed(qn_credentials);
+ credentials_tag;
+ credentials_tag = credentials_tag->NextNamed(qn_credentials)) {
+ JingleMessage::IceCredentials credentials;
+ if (!ParseIceCredentials(credentials_tag, &credentials))
+ return false;
+ ice_credentials->push_back(credentials);
+ }
+
+ QName qn_candidate(kIceTransportNamespace, "candidate");
+ for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate);
+ candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
+ JingleMessage::NamedCandidate candidate;
+ if (!ParseIceCandidate(candidate_tag, &candidate))
+ return false;
+ candidates->push_back(candidate);
+ }
+
+ return true;
+}
+
+bool ParseGiceCandidate(const buzz::XmlElement* element,
+ JingleMessage::NamedCandidate* candidate) {
+ DCHECK(element->Name() == QName(kGiceTransportNamespace, "candidate"));
const std::string& name = element->Attr(QName(kEmptyNamespace, "name"));
const std::string& address = element->Attr(QName(kEmptyNamespace, "address"));
@@ -88,9 +185,59 @@ bool ParseCandidate(const buzz::XmlElement* element,
return true;
}
-XmlElement* FormatCandidate(const JingleMessage::NamedCandidate& candidate) {
+bool ParseGiceTransportInfo(
+ const buzz::XmlElement* element,
+ std::list<JingleMessage::NamedCandidate>* candidates) {
+ DCHECK(element->Name() == QName(kGiceTransportNamespace, "transport"));
+
+ candidates->clear();
+
+ QName qn_candidate(kGiceTransportNamespace, "candidate");
+ for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate);
+ candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
+ JingleMessage::NamedCandidate candidate;
+ if (!ParseGiceCandidate(candidate_tag, &candidate))
+ return false;
+ candidates->push_back(candidate);
+ }
+
+ return true;
+}
+
+XmlElement* FormatIceCredentials(
+ const JingleMessage::IceCredentials& credentials) {
+ XmlElement* result =
+ new XmlElement(QName(kIceTransportNamespace, "credentials"));
+ result->SetAttr(QName(kEmptyNamespace, "channel"), credentials.channel);
+ result->SetAttr(QName(kEmptyNamespace, "ufrag"), credentials.ufrag);
+ result->SetAttr(QName(kEmptyNamespace, "password"), credentials.password);
+ return result;
+}
+
+XmlElement* FormatIceCandidate(const JingleMessage::NamedCandidate& candidate) {
+ XmlElement* result =
+ new XmlElement(QName(kIceTransportNamespace, "candidate"));
+ result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name);
+ result->SetAttr(QName(kEmptyNamespace, "foundation"),
+ candidate.candidate.foundation());
+ result->SetAttr(QName(kEmptyNamespace, "address"),
+ candidate.candidate.address().ipaddr().ToString());
+ result->SetAttr(QName(kEmptyNamespace, "port"),
+ base::IntToString(candidate.candidate.address().port()));
+ result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type());
+ result->SetAttr(QName(kEmptyNamespace, "protocol"),
+ candidate.candidate.protocol());
+ result->SetAttr(QName(kEmptyNamespace, "priority"),
+ base::DoubleToString(candidate.candidate.priority()));
+ result->SetAttr(QName(kEmptyNamespace, "generation"),
+ base::IntToString(candidate.candidate.generation()));
+ return result;
+}
+
+XmlElement* FormatGiceCandidate(
+ const JingleMessage::NamedCandidate& candidate) {
XmlElement* result =
- new XmlElement(QName(kP2PTransportNamespace, "candidate"));
+ new XmlElement(QName(kGiceTransportNamespace, "candidate"));
result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name);
result->SetAttr(QName(kEmptyNamespace, "address"),
candidate.candidate.address().ipaddr().ToString());
@@ -112,9 +259,6 @@ XmlElement* FormatCandidate(const JingleMessage::NamedCandidate& candidate) {
} // namespace
-JingleMessage::NamedCandidate::NamedCandidate() {
-}
-
JingleMessage::NamedCandidate::NamedCandidate(
const std::string& name,
const cricket::Candidate& candidate)
@@ -122,6 +266,12 @@ JingleMessage::NamedCandidate::NamedCandidate(
candidate(candidate) {
}
+JingleMessage::IceCredentials::IceCredentials(std::string channel,
+ std::string ufrag,
+ std::string password)
+ : channel(channel), ufrag(ufrag), password(password) {
+}
+
// static
bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) {
return stanza->Name() == QName(kJabberNamespace, "iq") &&
@@ -134,19 +284,13 @@ std::string JingleMessage::GetActionName(ActionType action) {
return ValueToName(kActionTypes, action);
}
-JingleMessage::JingleMessage()
- : action(UNKNOWN_ACTION),
- reason(UNKNOWN_REASON) {
+JingleMessage::JingleMessage() {
}
-JingleMessage::JingleMessage(
- const std::string& to_value,
- ActionType action_value,
- const std::string& sid_value)
- : to(to_value),
- action(action_value),
- sid(sid_value),
- reason(UNKNOWN_REASON) {
+JingleMessage::JingleMessage(const std::string& to,
+ ActionType action,
+ const std::string& sid)
+ : to(to), action(action), sid(sid) {
}
JingleMessage::~JingleMessage() {
@@ -240,21 +384,26 @@ bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
}
}
- candidates.clear();
- const XmlElement* transport_tag = content_tag->FirstNamed(
- QName(kP2PTransportNamespace, "transport"));
- if (transport_tag) {
- QName qn_candidate(kP2PTransportNamespace, "candidate");
- for (const XmlElement* candidate_tag =
- transport_tag->FirstNamed(qn_candidate);
- candidate_tag != nullptr;
- candidate_tag = candidate_tag->NextNamed(qn_candidate)) {
- NamedCandidate candidate;
- if (!ParseCandidate(candidate_tag, &candidate)) {
- *error = "Failed to parse candidates";
- return false;
- }
- candidates.push_back(candidate);
+ const XmlElement* ice_transport_tag = content_tag->FirstNamed(
+ QName(kIceTransportNamespace, "transport"));
+ const XmlElement* gice_transport_tag = content_tag->FirstNamed(
+ QName(kGiceTransportNamespace, "transport"));
+ if (ice_transport_tag && gice_transport_tag) {
+ *error = "ICE and GICE transport information is found in the same message";
+ return false;
+ } else if (ice_transport_tag) {
+ standard_ice = true;
+ if (!ParseIceTransportInfo(ice_transport_tag, &ice_credentials,
+ &candidates)) {
+ *error = "Failed to parse transport info";
+ return false;
+ }
+ } else if (gice_transport_tag) {
+ standard_ice = false;
+ ice_credentials.clear();
+ if (!ParseGiceTransportInfo(gice_transport_tag, &candidates)) {
+ *error = "Failed to parse transport info";
+ return false;
}
}
@@ -313,12 +462,27 @@ scoped_ptr<buzz::XmlElement> JingleMessage::ToXml() const {
if (description.get())
content_tag->AddElement(description->ToXml());
- XmlElement* transport_tag =
- new XmlElement(QName(kP2PTransportNamespace, "transport"), true);
- content_tag->AddElement(transport_tag);
- for (std::list<NamedCandidate>::const_iterator it = candidates.begin();
- it != candidates.end(); ++it) {
- transport_tag->AddElement(FormatCandidate(*it));
+ if (standard_ice) {
+ XmlElement* transport_tag =
+ new XmlElement(QName(kIceTransportNamespace, "transport"), true);
+ content_tag->AddElement(transport_tag);
+ for (std::list<IceCredentials>::const_iterator it =
+ ice_credentials.begin();
+ it != ice_credentials.end(); ++it) {
+ transport_tag->AddElement(FormatIceCredentials(*it));
+ }
+ for (std::list<NamedCandidate>::const_iterator it = candidates.begin();
+ it != candidates.end(); ++it) {
+ transport_tag->AddElement(FormatIceCandidate(*it));
+ }
+ } else {
+ XmlElement* transport_tag =
+ new XmlElement(QName(kGiceTransportNamespace, "transport"), true);
+ content_tag->AddElement(transport_tag);
+ for (std::list<NamedCandidate>::const_iterator it = candidates.begin();
+ it != candidates.end(); ++it) {
+ transport_tag->AddElement(FormatGiceCandidate(*it));
+ }
}
}
diff --git a/remoting/protocol/jingle_messages.h b/remoting/protocol/jingle_messages.h
index e12c854..c83776a 100644
--- a/remoting/protocol/jingle_messages.h
+++ b/remoting/protocol/jingle_messages.h
@@ -12,16 +12,11 @@
#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
#include "third_party/webrtc/p2p/base/candidate.h"
-
namespace remoting {
namespace protocol {
class ContentDescription;
-extern const char kJabberNamespace[];
-extern const char kJingleNamespace[];
-extern const char kP2PTransportNamespace[];
-
struct JingleMessage {
enum ActionType {
UNKNOWN_ACTION,
@@ -42,7 +37,7 @@ struct JingleMessage {
};
struct NamedCandidate {
- NamedCandidate();
+ NamedCandidate() = default;
NamedCandidate(const std::string& name,
const cricket::Candidate& candidate);
@@ -50,6 +45,17 @@ struct JingleMessage {
cricket::Candidate candidate;
};
+ struct IceCredentials {
+ IceCredentials() = default;
+ IceCredentials(std::string channel,
+ std::string ufrag,
+ std::string password);
+
+ std::string channel;
+ std::string ufrag;
+ std::string password;
+ };
+
JingleMessage();
JingleMessage(const std::string& to_value,
ActionType action_value,
@@ -68,12 +74,15 @@ struct JingleMessage {
std::string from;
std::string to;
- ActionType action;
+ ActionType action = UNKNOWN_ACTION;
std::string sid;
std::string initiator;
scoped_ptr<ContentDescription> description;
+
+ bool standard_ice = true;
+ std::list<IceCredentials> ice_credentials;
std::list<NamedCandidate> candidates;
// Content of session-info messages.
@@ -82,7 +91,7 @@ struct JingleMessage {
// Value from the <reason> tag if it is present in the
// message. Useful mainly for session-terminate messages, but Jingle
// spec allows it in any message.
- Reason reason;
+ Reason reason = UNKNOWN_REASON;
};
struct JingleMessageReply {
diff --git a/remoting/protocol/jingle_messages_unittest.cc b/remoting/protocol/jingle_messages_unittest.cc
index de58443..aa95d07 100644
--- a/remoting/protocol/jingle_messages_unittest.cc
+++ b/remoting/protocol/jingle_messages_unittest.cc
@@ -105,6 +105,7 @@ TEST(JingleMessageTest, SessionInitiate) {
"initiator='user@gmail.com/chromiumsy5C6A652D'>"
"<content name='chromoting' creator='initiator'>"
"<description xmlns='google:remoting'>"
+ "<standard-ice/>"
"<control transport='stream' version='2'/>"
"<event transport='stream' version='2'/>"
"<video transport='stream' version='2' codec='vp8'/>"
@@ -145,6 +146,7 @@ TEST(JingleMessageTest, SessionAccept) {
"xmlns='urn:xmpp:jingle:1'>i"
"<content creator='initiator' name='chromoting'>"
"<description xmlns='google:remoting'>"
+ "<standard-ice/>"
"<control transport='stream' version='2'/>"
"<event transport='stream' version='2'/>"
"<video codec='vp8' transport='stream' version='2'/>"
@@ -177,23 +179,112 @@ TEST(JingleMessageTest, SessionAccept) {
<< error;
}
-TEST(JingleMessageTest, TransportInfo) {
- const char* kTestTransportInfoMessage =
+TEST(JingleMessageTest, SessionAcceptNoIce) {
+ const char* kTestSessionAcceptMessage =
+ "<cli:iq from='user@gmail.com/chromoting016DBB07' "
+ "to='user@gmail.com/chromiumsy5C6A652D' type='set' "
+ "xmlns:cli='jabber:client'>"
+ "<jingle action='session-accept' sid='2227053353' "
+ "xmlns='urn:xmpp:jingle:1'>i"
+ "<content creator='initiator' name='chromoting'>"
+ "<description xmlns='google:remoting'>"
+ "<control transport='stream' version='2'/>"
+ "<event transport='stream' version='2'/>"
+ "<video codec='vp8' transport='stream' version='2'/>"
+ "<audio transport='stream' version='2' codec='verbatim'/>"
+ "<initial-resolution height='480' width='640'/>"
+ "<authentication><certificate>"
+ "MIICpjCCAY6gW0Cert0TANBgkqhkiG9w0BAQUFA="
+ "</certificate></authentication>"
+ "</description>"
+ "<transport xmlns='http://www.google.com/transport/p2p'/>"
+ "</content>"
+ "</jingle>"
+ "</cli:iq>";
+
+ scoped_ptr<XmlElement> source_message(
+ XmlElement::ForStr(kTestSessionAcceptMessage));
+ ASSERT_TRUE(source_message.get());
+
+ EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get()));
+
+ JingleMessage message;
+ std::string error;
+ EXPECT_TRUE(message.ParseXml(source_message.get(), &error)) << error;
+
+ EXPECT_EQ(message.action, JingleMessage::SESSION_ACCEPT);
+
+ scoped_ptr<XmlElement> formatted_message(message.ToXml());
+ ASSERT_TRUE(formatted_message.get());
+ EXPECT_TRUE(VerifyXml(source_message.get(), formatted_message.get(), &error))
+ << error;
+}
+
+TEST(JingleMessageTest, IceTransportInfo) {
+ const char* kTestIceTransportInfoMessage =
+ "<cli:iq to='user@gmail.com/chromoting016DBB07' type='set' "
+ "xmlns:cli='jabber:client'>"
+ "<jingle xmlns='urn:xmpp:jingle:1' action='transport-info' "
+ "sid='2227053353'>"
+ "<content name='chromoting' creator='initiator'>"
+ "<transport xmlns='google:remoting:ice'>"
+ "<credentials channel='event' ufrag='tPUyEAmQrEw3y7hi' "
+ "password='2iRdhLfawKZC5ydJ'/>"
+ "<credentials channel='video' ufrag='EPK3CXo5sTLJSez0' "
+ "password='eM0VUfUkZ+1Pyi0M'/>"
+ "<candidate name='event' foundation='725747215' "
+ "address='172.23.164.186' port='59089' type='local' "
+ "protocol='udp' priority='2122194688' generation='0'/>"
+ "<candidate name='video' foundation='3623806809' "
+ "address='172.23.164.186' port='57040' type='local' "
+ "protocol='udp' priority='2122194688' generation='0'/>"
+ "</transport>"
+ "</content>"
+ "</jingle>"
+ "</cli:iq>";
+
+ scoped_ptr<XmlElement> source_message(
+ XmlElement::ForStr(kTestIceTransportInfoMessage));
+ ASSERT_TRUE(source_message.get());
+
+ EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get()));
+
+ JingleMessage message;
+ std::string error;
+ EXPECT_TRUE(message.ParseXml(source_message.get(), &error)) << error;
+
+ EXPECT_EQ(message.action, JingleMessage::TRANSPORT_INFO);
+ EXPECT_EQ(message.candidates.size(), 2U);
+
+ scoped_ptr<XmlElement> formatted_message(message.ToXml());
+ ASSERT_TRUE(formatted_message.get());
+ EXPECT_TRUE(VerifyXml(source_message.get(), formatted_message.get(), &error))
+ << error;
+}
+
+TEST(JingleMessageTest, GiceTransportInfo) {
+ const char* kTestGiceTransportInfoMessage =
"<cli:iq to='user@gmail.com/chromoting016DBB07' type='set' "
- "xmlns:cli='jabber:client'><jingle xmlns='urn:xmpp:jingle:1' "
- "action='transport-info' sid='2227053353'><content name='chromoting' "
- "creator='initiator'><transport "
- "xmlns='http://www.google.com/transport/p2p'><candidate name='event' "
- "address='172.23.164.186' port='57040' preference='1' "
- "username='tPUyEAmQrEw3y7hi' protocol='udp' generation='0' "
- "password='2iRdhLfawKZC5ydJ' type='local'/><candidate name='video' "
- "address='172.23.164.186' port='42171' preference='1' "
- "username='EPK3CXo5sTLJSez0' protocol='udp' generation='0' "
- "password='eM0VUfUkZ+1Pyi0M' type='local'/></transport></content>"
- "</jingle></cli:iq>";
+ "xmlns:cli='jabber:client'>"
+ "<jingle xmlns='urn:xmpp:jingle:1' action='transport-info' "
+ "sid='2227053353'>"
+ "<content name='chromoting' creator='initiator'>"
+ "<transport xmlns='http://www.google.com/transport/p2p'>"
+ "<candidate name='event' address='172.23.164.186' port='57040' "
+ "preference='1' username='tPUyEAmQrEw3y7hi' "
+ "protocol='udp' generation='0' "
+ "password='2iRdhLfawKZC5ydJ' type='local'/>"
+ "<candidate name='video' address='172.23.164.186' port='42171' "
+ "preference='1' username='EPK3CXo5sTLJSez0' "
+ "protocol='udp' generation='0' "
+ "password='eM0VUfUkZ+1Pyi0M' type='local'/>"
+ "</transport>"
+ "</content>"
+ "</jingle>"
+ "</cli:iq>";
scoped_ptr<XmlElement> source_message(
- XmlElement::ForStr(kTestTransportInfoMessage));
+ XmlElement::ForStr(kTestGiceTransportInfoMessage));
ASSERT_TRUE(source_message.get());
EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get()));
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index edc48ee..0f4f0a2 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -32,12 +32,11 @@ namespace remoting {
namespace protocol {
namespace {
-// Delay after candidate creation before sending transport-info
-// message. This is neccessary to be able to pack multiple candidates
-// into one transport-info messages. The value needs to be greater
-// than zero because ports are opened asynchronously in the browser
-// process.
-const int kTransportInfoSendDelayMs = 2;
+
+// Delay after candidate creation before sending transport-info message to
+// accumulate multiple candidates. This is an optimization to reduce number of
+// transport-info messages.
+const int kTransportInfoSendDelayMs = 20;
// How long we should wait for a response from the other end. This value is used
// for all requests except |transport-info|.
@@ -74,7 +73,6 @@ JingleSession::JingleSession(JingleSessionManager* session_manager)
event_handler_(nullptr),
state_(INITIALIZING),
error_(OK),
- config_is_set_(false),
weak_factory_(this) {
}
@@ -149,7 +147,7 @@ void JingleSession::InitializeIncomingConnection(
void JingleSession::AcceptIncomingConnection(
const JingleMessage& initiate_message) {
- DCHECK(config_is_set_);
+ DCHECK(config_);
// Process the first authentication message.
const buzz::XmlElement* first_auth_message =
@@ -184,7 +182,7 @@ void JingleSession::ContinueAcceptIncomingConnection() {
auth_message = authenticator_->GetNextMessage();
message.description.reset(
- new ContentDescription(CandidateSessionConfig::CreateFrom(config_),
+ new ContentDescription(CandidateSessionConfig::CreateFrom(*config_),
auth_message.Pass()));
SendMessage(message);
@@ -213,14 +211,13 @@ const CandidateSessionConfig* JingleSession::candidate_config() {
const SessionConfig& JingleSession::config() {
DCHECK(CalledOnValidThread());
- return config_;
+ return *config_;
}
-void JingleSession::set_config(const SessionConfig& config) {
+void JingleSession::set_config(scoped_ptr<SessionConfig> config) {
DCHECK(CalledOnValidThread());
- DCHECK(!config_is_set_);
- config_ = config;
- config_is_set_ = true;
+ DCHECK(!config_);
+ config_ = config.Pass();
}
StreamChannelFactory* JingleSession::GetTransportChannelFactory() {
@@ -243,16 +240,26 @@ void JingleSession::Close() {
CloseInternal(OK);
}
-void JingleSession::AddPendingRemoteCandidates(Transport* channel,
- const std::string& name) {
- std::list<JingleMessage::NamedCandidate>::iterator it =
+void JingleSession::AddPendingRemoteTransportInfo(Transport* channel) {
+ std::list<JingleMessage::IceCredentials>::iterator credentials =
+ pending_remote_ice_credentials_.begin();
+ while (credentials != pending_remote_ice_credentials_.end()) {
+ if (credentials->channel == channel->name()) {
+ channel->SetRemoteCredentials(credentials->ufrag, credentials->password);
+ credentials = pending_remote_ice_credentials_.erase(credentials);
+ } else {
+ ++credentials;
+ }
+ }
+
+ std::list<JingleMessage::NamedCandidate>::iterator candidate =
pending_remote_candidates_.begin();
- while(it != pending_remote_candidates_.end()) {
- if (it->name == name) {
- channel->AddRemoteCandidate(it->candidate);
- it = pending_remote_candidates_.erase(it);
+ while (candidate != pending_remote_candidates_.end()) {
+ if (candidate->name == channel->name()) {
+ channel->AddRemoteCandidate(candidate->candidate);
+ candidate = pending_remote_candidates_.erase(candidate);
} else {
- ++it;
+ ++candidate;
}
}
}
@@ -263,8 +270,9 @@ void JingleSession::CreateChannel(const std::string& name,
scoped_ptr<Transport> channel =
session_manager_->transport_factory_->CreateTransport();
+ channel->SetUseStandardIce(config_->standard_ice());
channel->Connect(name, this, callback);
- AddPendingRemoteCandidates(channel.get(), name);
+ AddPendingRemoteTransportInfo(channel.get());
channels_[name] = channel.release();
}
@@ -277,18 +285,19 @@ void JingleSession::CancelChannelCreation(const std::string& name) {
}
}
+void JingleSession::OnTransportIceCredentials(Transport* transport,
+ const std::string& ufrag,
+ const std::string& password) {
+ EnsurePendingTransportInfoMessage();
+ pending_transport_info_message_->ice_credentials.push_back(
+ JingleMessage::IceCredentials(transport->name(), ufrag, password));
+}
+
void JingleSession::OnTransportCandidate(Transport* transport,
const cricket::Candidate& candidate) {
- pending_candidates_.push_back(JingleMessage::NamedCandidate(
- transport->name(), candidate));
-
- if (!transport_infos_timer_.IsRunning()) {
- // Delay sending the new candidates in case we get more candidates
- // that we can send in one message.
- transport_infos_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
- this, &JingleSession::SendTransportInfo);
- }
+ EnsurePendingTransportInfoMessage();
+ pending_transport_info_message_->candidates.push_back(
+ JingleMessage::NamedCandidate(transport->name(), candidate));
}
void JingleSession::OnTransportRouteChange(Transport* transport,
@@ -362,14 +371,33 @@ void JingleSession::OnMessageResponse(
}
}
+void JingleSession::EnsurePendingTransportInfoMessage() {
+ // |transport_info_timer_| must be running iff
+ // |pending_transport_info_message_| exists.
+ DCHECK_EQ(pending_transport_info_message_ != nullptr,
+ transport_info_timer_.IsRunning());
+
+ if (!pending_transport_info_message_) {
+ pending_transport_info_message_.reset(new JingleMessage(
+ peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_));
+ pending_transport_info_message_->standard_ice = config_->standard_ice();
+
+ // Delay sending the new candidates in case we get more candidates
+ // that we can send in one message.
+ transport_info_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
+ this, &JingleSession::SendTransportInfo);
+ }
+}
+
void JingleSession::SendTransportInfo() {
- JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_);
- message.candidates.swap(pending_candidates_);
+ DCHECK(pending_transport_info_message_);
scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq(
- message.ToXml(),
+ pending_transport_info_message_->ToXml(),
base::Bind(&JingleSession::OnTransportInfoResponse,
base::Unretained(this)));
+ pending_transport_info_message_.reset();
if (request) {
request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout));
transport_info_requests_.push_back(request.release());
@@ -463,9 +491,6 @@ void JingleSession::OnAccept(const JingleMessage& message,
return;
}
- // In case there is transport information in the accept message.
- ProcessTransportInfo(message);
-
SetState(CONNECTED);
DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
@@ -497,6 +522,27 @@ void JingleSession::OnSessionInfo(const JingleMessage& message,
}
void JingleSession::ProcessTransportInfo(const JingleMessage& message) {
+ // Check if the transport information version matches what was negotiated.
+ if (message.standard_ice != config_->standard_ice()) {
+ LOG(ERROR) << "Received transport-info message in format different from "
+ "negotiated.";
+ CloseInternal(INCOMPATIBLE_PROTOCOL);
+ return;
+ }
+
+ for (std::list<JingleMessage::IceCredentials>::const_iterator it =
+ message.ice_credentials.begin();
+ it != message.ice_credentials.end(); ++it) {
+ ChannelsMap::iterator channel = channels_.find(it->channel);
+ if (channel != channels_.end()) {
+ channel->second->SetRemoteCredentials(it->ufrag, it->password);
+ } else {
+ // Transport info was received before the channel was created.
+ // This could happen due to messages being reordered on the wire.
+ pending_remote_ice_credentials_.push_back(*it);
+ }
+ }
+
for (std::list<JingleMessage::NamedCandidate>::const_iterator it =
message.candidates.begin();
it != message.candidates.end(); ++it) {
@@ -555,12 +601,12 @@ void JingleSession::OnTerminate(const JingleMessage& message,
bool JingleSession::InitializeConfigFromDescription(
const ContentDescription* description) {
DCHECK(description);
-
- if (!description->config()->GetFinalConfig(&config_)) {
+ config_ = SessionConfig::GetFinalConfig(description->config());
+ if (!config_) {
LOG(ERROR) << "session-accept does not specify configuration";
return false;
}
- if (!candidate_config()->IsSupported(config_)) {
+ if (!candidate_config()->IsSupported(*config_)) {
LOG(ERROR) << "session-accept specifies an invalid configuration";
return false;
}
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index eb30e50..584aeae 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -51,7 +51,7 @@ class JingleSession : public base::NonThreadSafe,
const std::string& jid() override;
const CandidateSessionConfig* candidate_config() override;
const SessionConfig& config() override;
- void set_config(const SessionConfig& config) override;
+ void set_config(scoped_ptr<SessionConfig> config) override;
StreamChannelFactory* GetTransportChannelFactory() override;
StreamChannelFactory* GetMultiplexedChannelFactory() override;
void Close() override;
@@ -62,6 +62,9 @@ class JingleSession : public base::NonThreadSafe,
void CancelChannelCreation(const std::string& name) override;
// Transport::EventHandler interface.
+ void OnTransportIceCredentials(Transport* transport,
+ const std::string& ufrag,
+ const std::string& password) override;
void OnTransportCandidate(Transport* transport,
const cricket::Candidate& candidate) override;
void OnTransportRouteChange(Transport* transport,
@@ -82,8 +85,9 @@ class JingleSession : public base::NonThreadSafe,
scoped_ptr<Authenticator> authenticator,
scoped_ptr<CandidateSessionConfig> config);
- // Adds to a new channel the remote candidates received before it was created.
- void AddPendingRemoteCandidates(Transport* channel, const std::string& name);
+ // Passes transport info to a new |channel| in case it was received before the
+ // channel was created.
+ void AddPendingRemoteTransportInfo(Transport* channel);
// Called by JingleSessionManager for incoming connections.
void InitializeIncomingConnection(const JingleMessage& initiate_message,
@@ -100,6 +104,10 @@ class JingleSession : public base::NonThreadSafe,
IqRequest* request,
const buzz::XmlElement* response);
+ // Creates empty |pending_transport_info_message_| and schedules timer for
+ // SentTransportInfo() to sent the message later.
+ void EnsurePendingTransportInfoMessage();
+
// Sends transport-info message with candidates from |pending_candidates_|.
void SendTransportInfo();
@@ -158,8 +166,7 @@ class JingleSession : public base::NonThreadSafe,
State state_;
ErrorCode error_;
- SessionConfig config_;
- bool config_is_set_;
+ scoped_ptr<SessionConfig> config_;
scoped_ptr<Authenticator> authenticator_;
@@ -174,10 +181,12 @@ class JingleSession : public base::NonThreadSafe,
scoped_ptr<SecureChannelFactory> secure_channel_factory_;
scoped_ptr<ChannelMultiplexer> channel_multiplexer_;
- base::OneShotTimer<JingleSession> transport_infos_timer_;
- std::list<JingleMessage::NamedCandidate> pending_candidates_;
+ scoped_ptr<JingleMessage> pending_transport_info_message_;
+ base::OneShotTimer<JingleSession> transport_info_timer_;
- // Pending remote candidates, received before the local channels were created.
+ // Pending remote transport info received before the local channels were
+ // created.
+ std::list<JingleMessage::IceCredentials> pending_remote_ice_credentials_;
std::list<JingleMessage::NamedCandidate> pending_remote_candidates_;
base::WeakPtrFactory<JingleSession> weak_factory_;
diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc
index 9ec24b9..9eb829d 100644
--- a/remoting/protocol/jingle_session_unittest.cc
+++ b/remoting/protocol/jingle_session_unittest.cc
@@ -105,7 +105,8 @@ class JingleSessionTest : public testing::Test {
host_session_.reset(session);
host_session_->SetEventHandler(&host_session_event_handler_);
- session->set_config(SessionConfig::ForTest());
+ session->set_config(standard_ice_ ? SessionConfig::ForTest()
+ : SessionConfig::WithLegacyIceForTest());
}
void DeleteSession() {
@@ -153,7 +154,7 @@ class JingleSessionTest : public testing::Test {
scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory(
nullptr,
ChromiumPortAllocator::Create(nullptr, network_settings).Pass(),
- network_settings));
+ network_settings, TransportRole::SERVER));
host_server_.reset(new JingleSessionManager(host_transport.Pass()));
host_server_->Init(host_signal_strategy_.get(), &host_server_listener_);
@@ -167,7 +168,7 @@ class JingleSessionTest : public testing::Test {
scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory(
nullptr,
ChromiumPortAllocator::Create(nullptr, network_settings).Pass(),
- network_settings));
+ network_settings, TransportRole::CLIENT));
client_server_.reset(
new JingleSessionManager(client_transport.Pass()));
client_server_->Init(client_signal_strategy_.get(),
@@ -290,6 +291,8 @@ class JingleSessionTest : public testing::Test {
scoped_ptr<base::MessageLoopForIO> message_loop_;
+ bool standard_ice_ = true;
+
scoped_ptr<FakeSignalStrategy> host_signal_strategy_;
scoped_ptr<FakeSignalStrategy> client_signal_strategy_;
@@ -352,7 +355,7 @@ TEST_F(JingleSessionTest, Connect) {
const buzz::XmlElement* initiate_xml =
host_signal_strategy_->received_messages().front();
const buzz::XmlElement* jingle_element =
- initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle"));
+ initiate_xml->FirstNamed(buzz::QName("urn:xmpp:jingle:1", "jingle"));
ASSERT_TRUE(jingle_element);
ASSERT_EQ(kClientJid,
jingle_element->Attr(buzz::QName(std::string(), "initiator")));
@@ -391,6 +394,23 @@ TEST_F(JingleSessionTest, TestStreamChannel) {
tester.CheckResults();
}
+// Verify that we can still connect using legacy GICE transport.
+TEST_F(JingleSessionTest, TestLegacyIceConnection) {
+ standard_ice_ = false;
+
+ CreateSessionManagers(1, FakeAuthenticator::ACCEPT);
+ ASSERT_NO_FATAL_FAILURE(
+ InitiateConnection(1, FakeAuthenticator::ACCEPT, false));
+
+ ASSERT_NO_FATAL_FAILURE(CreateChannel());
+
+ StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
+ kMessageSize, kMessages);
+ tester.Start();
+ message_loop_->Run();
+ tester.CheckResults();
+}
+
TEST_F(JingleSessionTest, DeleteSessionOnIncomingConnection) {
CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
diff --git a/remoting/protocol/libjingle_transport_factory.cc b/remoting/protocol/libjingle_transport_factory.cc
index 151d329..10124bd 100644
--- a/remoting/protocol/libjingle_transport_factory.cc
+++ b/remoting/protocol/libjingle_transport_factory.cc
@@ -41,7 +41,7 @@ TransportRoute::RouteType CandidateTypeToTransportRouteType(
const std::string& candidate_type) {
if (candidate_type == "local") {
return TransportRoute::DIRECT;
- } else if (candidate_type == "stun") {
+ } else if (candidate_type == "stun" || candidate_type == "prflx") {
return TransportRoute::STUN;
} else if (candidate_type == "relay") {
return TransportRoute::RELAY;
@@ -57,7 +57,8 @@ class LibjingleTransport
public sigslot::has_slots<> {
public:
LibjingleTransport(cricket::PortAllocator* port_allocator,
- const NetworkSettings& network_settings);
+ const NetworkSettings& network_settings,
+ TransportRole role);
~LibjingleTransport() override;
// Called by JingleTransportFactory when it has fresh Jingle info.
@@ -67,9 +68,12 @@ class LibjingleTransport
void Connect(const std::string& name,
Transport::EventHandler* event_handler,
const Transport::ConnectedCallback& callback) override;
+ void SetRemoteCredentials(const std::string& ufrag,
+ const std::string& password) override;
void AddRemoteCandidate(const cricket::Candidate& candidate) override;
const std::string& name() const override;
bool is_connected() const override;
+ void SetUseStandardIce(bool use_standard_ice) override;
private:
void DoStart();
@@ -94,15 +98,19 @@ class LibjingleTransport
cricket::PortAllocator* port_allocator_;
NetworkSettings network_settings_;
+ TransportRole role_;
+
+ bool use_standard_ice_ = true;
std::string name_;
EventHandler* event_handler_;
Transport::ConnectedCallback callback_;
std::string ice_username_fragment_;
- std::string ice_password_;
bool can_start_;
+ std::string remote_ice_username_fragment_;
+ std::string remote_ice_password_;
std::list<cricket::Candidate> pending_candidates_;
scoped_ptr<cricket::P2PTransportChannel> channel_;
int connect_attempts_left_;
@@ -114,18 +122,18 @@ class LibjingleTransport
};
LibjingleTransport::LibjingleTransport(cricket::PortAllocator* port_allocator,
- const NetworkSettings& network_settings)
+ const NetworkSettings& network_settings,
+ TransportRole role)
: port_allocator_(port_allocator),
network_settings_(network_settings),
+ role_(role),
event_handler_(nullptr),
ice_username_fragment_(
rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH)),
- ice_password_(rtc::CreateRandomString(cricket::ICE_PWD_LENGTH)),
can_start_(false),
connect_attempts_left_(kMaxReconnectAttempts),
weak_factory_(this) {
DCHECK(!ice_username_fragment_.empty());
- DCHECK(!ice_password_.empty());
}
LibjingleTransport::~LibjingleTransport() {
@@ -149,9 +157,17 @@ void LibjingleTransport::OnCanStart() {
if (!callback_.is_null())
DoStart();
+ // Pass pending ICE credentials and candidates to the channel.
+ if (!remote_ice_username_fragment_.empty()) {
+ channel_->SetRemoteIceCredentials(remote_ice_username_fragment_,
+ remote_ice_password_);
+ }
+
while (!pending_candidates_.empty()) {
- channel_->SetRemoteIceCredentials(pending_candidates_.front().username(),
- pending_candidates_.front().password());
+ if (!use_standard_ice_) {
+ channel_->SetRemoteIceCredentials(pending_candidates_.front().username(),
+ pending_candidates_.front().password());
+ }
channel_->OnCandidate(pending_candidates_.front());
pending_candidates_.pop_front();
}
@@ -182,8 +198,18 @@ void LibjingleTransport::DoStart() {
// TODO(sergeyu): Specify correct component ID for the channel.
channel_.reset(new cricket::P2PTransportChannel(
std::string(), 0, nullptr, port_allocator_));
- channel_->SetIceProtocolType(cricket::ICEPROTO_GOOGLE);
- channel_->SetIceCredentials(ice_username_fragment_, ice_password_);
+ std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH);
+ if (use_standard_ice_) {
+ channel_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
+ channel_->SetIceRole((role_ == TransportRole::CLIENT)
+ ? cricket::ICEROLE_CONTROLLING
+ : cricket::ICEROLE_CONTROLLED);
+ event_handler_->OnTransportIceCredentials(this, ice_username_fragment_,
+ ice_password);
+ } else {
+ channel_->SetIceProtocolType(cricket::ICEPROTO_GOOGLE);
+ }
+ channel_->SetIceCredentials(ice_username_fragment_, ice_password);
channel_->SignalRequestSignaling.connect(
this, &LibjingleTransport::OnRequestSignaling);
channel_->SignalCandidateReady.connect(
@@ -218,6 +244,17 @@ void LibjingleTransport::NotifyConnected() {
base::ResetAndReturn(&callback_).Run(socket.Pass());
}
+void LibjingleTransport::SetRemoteCredentials(const std::string& ufrag,
+ const std::string& password) {
+ DCHECK(CalledOnValidThread());
+
+ remote_ice_username_fragment_ = ufrag;
+ remote_ice_password_ = password;
+
+ if (channel_)
+ channel_->SetRemoteIceCredentials(ufrag, password);
+}
+
void LibjingleTransport::AddRemoteCandidate(
const cricket::Candidate& candidate) {
DCHECK(CalledOnValidThread());
@@ -230,8 +267,10 @@ void LibjingleTransport::AddRemoteCandidate(
return;
if (channel_) {
- channel_->SetRemoteIceCredentials(candidate.username(),
- candidate.password());
+ if (!use_standard_ice_) {
+ channel_->SetRemoteIceCredentials(candidate.username(),
+ candidate.password());
+ }
channel_->OnCandidate(candidate);
} else {
pending_candidates_.push_back(candidate);
@@ -248,6 +287,12 @@ bool LibjingleTransport::is_connected() const {
return callback_.is_null();
}
+void LibjingleTransport::SetUseStandardIce(bool use_standard_ice) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!channel_);
+ use_standard_ice_ = use_standard_ice;
+}
+
void LibjingleTransport::OnRequestSignaling(
cricket::TransportChannelImpl* channel) {
DCHECK(CalledOnValidThread());
@@ -339,8 +384,10 @@ void LibjingleTransport::TryReconnect() {
--connect_attempts_left_;
// Restart ICE by resetting ICE password.
- ice_password_ = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH);
- channel_->SetIceCredentials(ice_username_fragment_, ice_password_);
+ std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH);
+ event_handler_->OnTransportIceCredentials(this, ice_username_fragment_,
+ ice_password);
+ channel_->SetIceCredentials(ice_username_fragment_, ice_password);
}
} // namespace
@@ -348,10 +395,12 @@ void LibjingleTransport::TryReconnect() {
LibjingleTransportFactory::LibjingleTransportFactory(
SignalStrategy* signal_strategy,
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator,
- const NetworkSettings& network_settings)
+ const NetworkSettings& network_settings,
+ TransportRole role)
: signal_strategy_(signal_strategy),
port_allocator_(port_allocator.Pass()),
- network_settings_(network_settings) {
+ network_settings_(network_settings),
+ role_(role) {
}
LibjingleTransportFactory::~LibjingleTransportFactory() {
@@ -368,7 +417,7 @@ void LibjingleTransportFactory::PrepareTokens() {
scoped_ptr<Transport> LibjingleTransportFactory::CreateTransport() {
scoped_ptr<LibjingleTransport> result(
- new LibjingleTransport(port_allocator_.get(), network_settings_));
+ new LibjingleTransport(port_allocator_.get(), network_settings_, role_));
EnsureFreshJingleInfo();
diff --git a/remoting/protocol/libjingle_transport_factory.h b/remoting/protocol/libjingle_transport_factory.h
index f6af301..1fd8855 100644
--- a/remoting/protocol/libjingle_transport_factory.h
+++ b/remoting/protocol/libjingle_transport_factory.h
@@ -41,7 +41,8 @@ class LibjingleTransportFactory : public TransportFactory {
LibjingleTransportFactory(
SignalStrategy* signal_strategy,
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator,
- const NetworkSettings& network_settings);
+ const NetworkSettings& network_settings,
+ TransportRole role);
~LibjingleTransportFactory() override;
@@ -58,6 +59,7 @@ class LibjingleTransportFactory : public TransportFactory {
SignalStrategy* signal_strategy_;
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator_;
NetworkSettings network_settings_;
+ TransportRole role_;
base::TimeTicks last_jingle_info_update_time_;
scoped_ptr<JingleInfoRequest> jingle_info_request_;
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index 2484e9a..b3fca8e 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -207,7 +207,10 @@ class MockSession : public Session {
MOCK_METHOD0(jid, const std::string&());
MOCK_METHOD0(candidate_config, const CandidateSessionConfig*());
MOCK_METHOD0(config, const SessionConfig&());
- MOCK_METHOD1(set_config, void(const SessionConfig& config));
+ MOCK_METHOD1(set_config_ptr, void(const SessionConfig* config));
+ void set_config(scoped_ptr<SessionConfig> config) override {
+ set_config_ptr(config.get());
+ }
MOCK_METHOD0(initiator_token, const std::string&());
MOCK_METHOD1(set_initiator_token, void(const std::string& initiator_token));
MOCK_METHOD0(receiver_token, const std::string&());
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h
index f806e21..b4a0d03 100644
--- a/remoting/protocol/session.h
+++ b/remoting/protocol/session.h
@@ -94,7 +94,7 @@ class Session {
// Set protocol configuration for an incoming session. Must be
// called on the host before the connection is accepted, from
// ChromotocolServer::IncomingConnectionCallback.
- virtual void set_config(const SessionConfig& config) = 0;
+ virtual void set_config(scoped_ptr<SessionConfig> config) = 0;
// GetTransportChannelFactory() returns a factory that creates a new transport
// channel for each logical channel. GetMultiplexedChannelFactory() channels
diff --git a/remoting/protocol/session_config.cc b/remoting/protocol/session_config.cc
index 460da28..f6163f4 100644
--- a/remoting/protocol/session_config.cc
+++ b/remoting/protocol/session_config.cc
@@ -9,6 +9,30 @@
namespace remoting {
namespace protocol {
+namespace {
+
+bool IsChannelConfigSupported(const std::list<ChannelConfig>& list,
+ const ChannelConfig& value) {
+ return std::find(list.begin(), list.end(), value) != list.end();
+}
+
+bool SelectCommonChannelConfig(const std::list<ChannelConfig>& host_configs,
+ const std::list<ChannelConfig>& client_configs,
+ ChannelConfig* config) {
+ // Usually each of these lists will contain just a few elements, so iterating
+ // over all of them is not a problem.
+ std::list<ChannelConfig>::const_iterator it;
+ for (it = client_configs.begin(); it != client_configs.end(); ++it) {
+ if (IsChannelConfigSupported(host_configs, *it)) {
+ *config = *it;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
const int kDefaultStreamVersion = 2;
const int kControlStreamVersion = 3;
@@ -16,12 +40,6 @@ ChannelConfig ChannelConfig::None() {
return ChannelConfig();
}
-ChannelConfig::ChannelConfig()
- : transport(TRANSPORT_NONE),
- version(0),
- codec(CODEC_UNDEFINED) {
-}
-
ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
: transport(transport),
version(version),
@@ -35,32 +53,93 @@ bool ChannelConfig::operator==(const ChannelConfig& b) const {
return transport == b.transport && version == b.version && codec == b.codec;
}
-SessionConfig::SessionConfig() {
+// static
+scoped_ptr<SessionConfig> SessionConfig::SelectCommon(
+ const CandidateSessionConfig* client_config,
+ const CandidateSessionConfig* host_config) {
+ scoped_ptr<SessionConfig> result(new SessionConfig());
+ ChannelConfig control_config;
+ ChannelConfig event_config;
+ ChannelConfig video_config;
+ ChannelConfig audio_config;
+
+ result->standard_ice_ =
+ host_config->standard_ice() && client_config->standard_ice();
+
+ if (!SelectCommonChannelConfig(host_config->control_configs(),
+ client_config->control_configs(),
+ &result->control_config_) ||
+ !SelectCommonChannelConfig(host_config->event_configs(),
+ client_config->event_configs(),
+ &result->event_config_) ||
+ !SelectCommonChannelConfig(host_config->video_configs(),
+ client_config->video_configs(),
+ &result->video_config_) ||
+ !SelectCommonChannelConfig(host_config->audio_configs(),
+ client_config->audio_configs(),
+ &result->audio_config_)) {
+ return nullptr;
+ }
+
+ return result;
}
// static
-SessionConfig SessionConfig::ForTest() {
- SessionConfig result;
- result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
+scoped_ptr<SessionConfig> SessionConfig::GetFinalConfig(
+ const CandidateSessionConfig* candidate_config) {
+ if (candidate_config->control_configs().size() != 1 ||
+ candidate_config->event_configs().size() != 1 ||
+ candidate_config->video_configs().size() != 1 ||
+ candidate_config->audio_configs().size() != 1) {
+ return nullptr;
+ }
+
+ scoped_ptr<SessionConfig> result(new SessionConfig());
+ result->standard_ice_ = candidate_config->standard_ice();
+ result->control_config_ = candidate_config->control_configs().front();
+ result->event_config_ = candidate_config->event_configs().front();
+ result->video_config_ = candidate_config->video_configs().front();
+ result->audio_config_ = candidate_config->audio_configs().front();
+
+ return result.Pass();
+}
+
+// static
+scoped_ptr<SessionConfig> SessionConfig::ForTest() {
+ scoped_ptr<SessionConfig> result(new SessionConfig());
+ result->standard_ice_ = true;
+ result->control_config_ = ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
kControlStreamVersion,
- ChannelConfig::CODEC_UNDEFINED));
- result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
+ ChannelConfig::CODEC_UNDEFINED);
+ result->event_config_ = ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
kDefaultStreamVersion,
- ChannelConfig::CODEC_UNDEFINED));
- result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
+ ChannelConfig::CODEC_UNDEFINED);
+ result->video_config_ = ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
kDefaultStreamVersion,
- ChannelConfig::CODEC_VP8));
- result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE,
+ ChannelConfig::CODEC_VP8);
+ result->audio_config_ = ChannelConfig(ChannelConfig::TRANSPORT_NONE,
kDefaultStreamVersion,
- ChannelConfig::CODEC_UNDEFINED));
- return result;
+ ChannelConfig::CODEC_UNDEFINED);
+ return result.Pass();
}
+// static
+scoped_ptr<SessionConfig> SessionConfig::WithLegacyIceForTest() {
+ scoped_ptr<SessionConfig> result = ForTest();
+ result->standard_ice_ = false;
+ return result.Pass();
+}
+
+SessionConfig::SessionConfig() {
+}
+
+
CandidateSessionConfig::CandidateSessionConfig() { }
CandidateSessionConfig::CandidateSessionConfig(
const CandidateSessionConfig& config)
- : control_configs_(config.control_configs_),
+ : standard_ice_(true),
+ control_configs_(config.control_configs_),
event_configs_(config.event_configs_),
video_configs_(config.video_configs_),
audio_configs_(config.audio_configs_) {
@@ -68,33 +147,6 @@ CandidateSessionConfig::CandidateSessionConfig(
CandidateSessionConfig::~CandidateSessionConfig() { }
-bool CandidateSessionConfig::Select(
- const CandidateSessionConfig* client_config,
- SessionConfig* result) {
- ChannelConfig control_config;
- ChannelConfig event_config;
- ChannelConfig video_config;
- ChannelConfig audio_config;
-
- if (!SelectCommonChannelConfig(
- control_configs_, client_config->control_configs_, &control_config) ||
- !SelectCommonChannelConfig(
- event_configs_, client_config->event_configs_, &event_config) ||
- !SelectCommonChannelConfig(
- video_configs_, client_config->video_configs_, &video_config) ||
- !SelectCommonChannelConfig(
- audio_configs_, client_config->audio_configs_, &audio_config)) {
- return false;
- }
-
- result->set_control_config(control_config);
- result->set_event_config(event_config);
- result->set_video_config(video_config);
- result->set_audio_config(audio_config);
-
- return true;
-}
-
bool CandidateSessionConfig::IsSupported(
const SessionConfig& config) const {
return
@@ -104,46 +156,6 @@ bool CandidateSessionConfig::IsSupported(
IsChannelConfigSupported(audio_configs_, config.audio_config());
}
-bool CandidateSessionConfig::GetFinalConfig(SessionConfig* result) const {
- if (control_configs_.size() != 1 ||
- event_configs_.size() != 1 ||
- video_configs_.size() != 1 ||
- audio_configs_.size() != 1) {
- return false;
- }
-
- result->set_control_config(control_configs_.front());
- result->set_event_config(event_configs_.front());
- result->set_video_config(video_configs_.front());
- result->set_audio_config(audio_configs_.front());
-
- return true;
-}
-
-// static
-bool CandidateSessionConfig::SelectCommonChannelConfig(
- const std::list<ChannelConfig>& host_configs,
- const std::list<ChannelConfig>& client_configs,
- ChannelConfig* config) {
- // Usually each of these vectors will contain just several elements,
- // so iterating over all of them is not a problem.
- std::list<ChannelConfig>::const_iterator it;
- for (it = client_configs.begin(); it != client_configs.end(); ++it) {
- if (IsChannelConfigSupported(host_configs, *it)) {
- *config = *it;
- return true;
- }
- }
- return false;
-}
-
-// static
-bool CandidateSessionConfig::IsChannelConfigSupported(
- const std::list<ChannelConfig>& vector,
- const ChannelConfig& value) {
- return std::find(vector.begin(), vector.end(), value) != vector.end();
-}
-
scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
return make_scoped_ptr(new CandidateSessionConfig(*this));
}
@@ -157,6 +169,7 @@ scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom(
const SessionConfig& config) {
scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
+ result->set_standard_ice(config.standard_ice());
result->mutable_control_configs()->push_back(config.control_config());
result->mutable_event_configs()->push_back(config.event_config());
result->mutable_video_configs()->push_back(config.video_config());
@@ -168,6 +181,8 @@ scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom(
scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() {
scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
+ result->set_standard_ice(true);
+
// Control channel.
result->mutable_control_configs()->push_back(
ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
diff --git a/remoting/protocol/session_config.h b/remoting/protocol/session_config.h
index c0313a0..acd3dba 100644
--- a/remoting/protocol/session_config.h
+++ b/remoting/protocol/session_config.h
@@ -42,7 +42,7 @@ struct ChannelConfig {
static ChannelConfig None();
// Default constructor. Equivalent to None().
- ChannelConfig();
+ ChannelConfig() = default;
// Creates a channel config with the specified parameters.
ChannelConfig(TransportType transport, int version, Codec codec);
@@ -51,42 +51,53 @@ struct ChannelConfig {
// std::list<ChannelConfig>.
bool operator==(const ChannelConfig& b) const;
- TransportType transport;
- int version;
- Codec codec;
+ TransportType transport = TRANSPORT_NONE;
+ int version = 0;
+ Codec codec = CODEC_UNDEFINED;
};
+class CandidateSessionConfig;
+
// SessionConfig is used by the chromoting Session to store negotiated
// chromotocol configuration.
class SessionConfig {
public:
- SessionConfig();
+ // Selects session configuration that is supported by both participants.
+ // nullptr is returned if such configuration doesn't exist. When selecting
+ // channel configuration priority is given to the configs listed first
+ // in |client_config|.
+ static scoped_ptr<SessionConfig> SelectCommon(
+ const CandidateSessionConfig* client_config,
+ const CandidateSessionConfig* host_config);
+
+ // Extracts final protocol configuration. Must be used for the description
+ // received in the session-accept stanza. If the selection is ambiguous
+ // (e.g. there is more than one configuration for one of the channel)
+ // or undefined (e.g. no configurations for a channel) then nullptr is
+ // returned.
+ static scoped_ptr<SessionConfig> GetFinalConfig(
+ const CandidateSessionConfig* candidate_config);
+
+ // Returns a suitable session configuration for use in tests.
+ static scoped_ptr<SessionConfig> ForTest();
+ static scoped_ptr<SessionConfig> WithLegacyIceForTest();
+
+ bool standard_ice() const { return standard_ice_; }
- void set_control_config(const ChannelConfig& control_config) {
- control_config_ = control_config;
- }
const ChannelConfig& control_config() const { return control_config_; }
- void set_event_config(const ChannelConfig& event_config) {
- event_config_ = event_config;
- }
const ChannelConfig& event_config() const { return event_config_; }
- void set_video_config(const ChannelConfig& video_config) {
- video_config_ = video_config;
- }
const ChannelConfig& video_config() const { return video_config_; }
- void set_audio_config(const ChannelConfig& audio_config) {
- audio_config_ = audio_config;
- }
const ChannelConfig& audio_config() const { return audio_config_; }
bool is_audio_enabled() const {
return audio_config_.transport != ChannelConfig::TRANSPORT_NONE;
}
- // Returns a suitable session configuration for use in tests.
- static SessionConfig ForTest();
-
private:
+ SessionConfig();
+
+ bool standard_ice_ = true;
+
ChannelConfig control_config_;
ChannelConfig event_config_;
ChannelConfig video_config_;
@@ -105,6 +116,9 @@ class CandidateSessionConfig {
~CandidateSessionConfig();
+ bool standard_ice() const { return standard_ice_; }
+ void set_standard_ice(bool standard_ice) { standard_ice_ = standard_ice; }
+
const std::list<ChannelConfig>& control_configs() const {
return control_configs_;
}
@@ -137,23 +151,9 @@ class CandidateSessionConfig {
return &audio_configs_;
}
- // Selects session configuration that is supported by both participants.
- // nullptr is returned if such configuration doesn't exist. When selecting
- // channel configuration priority is given to the configs listed first
- // in |client_config|.
- bool Select(const CandidateSessionConfig* client_config,
- SessionConfig* result);
-
// Returns true if |config| is supported.
bool IsSupported(const SessionConfig& config) const;
- // Extracts final protocol configuration. Must be used for the description
- // received in the session-accept stanza. If the selection is ambiguous
- // (e.g. there is more than one configuration for one of the channel)
- // or undefined (e.g. no configurations for a channel) then nullptr is
- // returned.
- bool GetFinalConfig(SessionConfig* result) const;
-
scoped_ptr<CandidateSessionConfig> Clone() const;
// Helpers for enabling/disabling specific features.
@@ -165,12 +165,7 @@ class CandidateSessionConfig {
explicit CandidateSessionConfig(const CandidateSessionConfig& config);
CandidateSessionConfig& operator=(const CandidateSessionConfig& b);
- static bool SelectCommonChannelConfig(
- const std::list<ChannelConfig>& host_configs_,
- const std::list<ChannelConfig>& client_configs_,
- ChannelConfig* config);
- static bool IsChannelConfigSupported(const std::list<ChannelConfig>& list,
- const ChannelConfig& value);
+ bool standard_ice_ = true;
std::list<ChannelConfig> control_configs_;
std::list<ChannelConfig> event_configs_;
diff --git a/remoting/protocol/transport.h b/remoting/protocol/transport.h
index d4c4b3f..4223796 100644
--- a/remoting/protocol/transport.h
+++ b/remoting/protocol/transport.h
@@ -44,6 +44,11 @@ namespace protocol {
class ChannelAuthenticator;
+enum class TransportRole {
+ SERVER,
+ CLIENT,
+};
+
struct TransportRoute {
enum RouteType {
DIRECT,
@@ -69,6 +74,12 @@ class Transport : public base::NonThreadSafe {
EventHandler() {};
virtual ~EventHandler() {};
+ // Called to pass ICE credentials to the session. Used only for STANDARD
+ // version of ICE, see SetIceVersion().
+ virtual void OnTransportIceCredentials(Transport* transport,
+ const std::string& ufrag,
+ const std::string& password) = 0;
+
// Called when the transport generates a new candidate that needs
// to be passed to the AddRemoteCandidate() method on the remote
// end of the connection.
@@ -97,6 +108,10 @@ class Transport : public base::NonThreadSafe {
Transport::EventHandler* event_handler,
const ConnectedCallback& callback) = 0;
+ // Sets remote ICE credentials.
+ virtual void SetRemoteCredentials(const std::string& ufrag,
+ const std::string& password) = 0;
+
// Adds |candidate| received from the peer.
virtual void AddRemoteCandidate(const cricket::Candidate& candidate) = 0;
@@ -108,6 +123,12 @@ class Transport : public base::NonThreadSafe {
// Returns true if the channel is already connected.
virtual bool is_connected() const = 0;
+ // Sets ICE version for the transport.
+ //
+ // TODO(sergeyu): Remove this when support for legacy ICE is removed.
+ // crbug.com/473758
+ virtual void SetUseStandardIce(bool use_standard_ice) {}
+
private:
DISALLOW_COPY_AND_ASSIGN(Transport);
};