blob: 8663647c307836d0fa91a59638b3978853019e8c [file] [log] [blame]
sergeyu0b6c1c8d2015-10-28 20:48:431// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
sergeyu309771b2015-10-31 01:41:375#include "remoting/protocol/ice_transport.h"
sergeyu0b6c1c8d2015-10-28 20:48:436
sergeyua7749062015-10-28 21:57:457#include "base/bind.h"
sergeyu0b6c1c8d2015-10-28 20:48:438#include "remoting/protocol/channel_authenticator.h"
9#include "remoting/protocol/channel_multiplexer.h"
sergeyu0b6c1c8d2015-10-28 20:48:4310#include "remoting/protocol/pseudotcp_channel_factory.h"
11#include "remoting/protocol/secure_channel_factory.h"
12#include "remoting/protocol/stream_channel_factory.h"
sergeyu786463e2016-02-04 18:46:1013#include "remoting/protocol/stream_message_pipe_adapter.h"
sergeyu86030f382015-12-16 22:45:0014#include "remoting/protocol/transport_context.h"
sergeyu0b6c1c8d2015-10-28 20:48:4315
16namespace remoting {
17namespace protocol {
18
19// Delay after candidate creation before sending transport-info message to
20// accumulate multiple candidates. This is an optimization to reduce number of
21// transport-info messages.
22const int kTransportInfoSendDelayMs = 20;
23
24// Name of the multiplexed channel.
25static const char kMuxChannelName[] = "mux";
26
sergeyue5767602015-12-28 19:49:0327IceTransport::IceTransport(scoped_refptr<TransportContext> transport_context,
Yuwei Huang5bc831e2019-07-12 21:30:2728 EventHandler* event_handler)
Jeremy Roman7c5cfabd2019-08-12 15:45:2729 : transport_context_(transport_context), event_handler_(event_handler) {
sergeyu86030f382015-12-16 22:45:0030 transport_context->Prepare();
31}
sergeyu0b6c1c8d2015-10-28 20:48:4332
sergeyu309771b2015-10-31 01:41:3733IceTransport::~IceTransport() {
sergeyu0b6c1c8d2015-10-28 20:48:4334 channel_multiplexer_.reset();
35 DCHECK(channels_.empty());
36}
37
sergeyue5767602015-12-28 19:49:0338void IceTransport::Start(
39 Authenticator* authenticator,
40 SendTransportInfoCallback send_transport_info_callback) {
41 DCHECK(!pseudotcp_channel_factory_);
sergeyua7749062015-10-28 21:57:4542
sergeyue5767602015-12-28 19:49:0343 send_transport_info_callback_ = std::move(send_transport_info_callback);
sergeyu0b6c1c8d2015-10-28 20:48:4344 pseudotcp_channel_factory_.reset(new PseudoTcpChannelFactory(this));
45 secure_channel_factory_.reset(new SecureChannelFactory(
46 pseudotcp_channel_factory_.get(), authenticator));
sergeyu786463e2016-02-04 18:46:1047 message_channel_factory_.reset(new StreamMessageChannelFactoryAdapter(
48 secure_channel_factory_.get(),
49 base::Bind(&IceTransport::OnChannelError, weak_factory_.GetWeakPtr())));
sergeyu0b6c1c8d2015-10-28 20:48:4350}
51
Mirko Bonadei80d1cea2019-01-18 22:22:1752bool IceTransport::ProcessTransportInfo(jingle_xmpp::XmlElement* transport_info_xml) {
sergeyu0b6c1c8d2015-10-28 20:48:4353 IceTransportInfo transport_info;
54 if (!transport_info.ParseXml(transport_info_xml))
55 return false;
56
57 for (auto it = transport_info.ice_credentials.begin();
58 it != transport_info.ice_credentials.end(); ++it) {
jdoerried0539eeb2018-10-02 20:54:2959 auto channel = channels_.find(it->channel);
sergeyu0b6c1c8d2015-10-28 20:48:4360 if (channel != channels_.end()) {
61 channel->second->SetRemoteCredentials(it->ufrag, it->password);
62 } else {
63 // Transport info was received before the channel was created.
64 // This could happen due to messages being reordered on the wire.
65 pending_remote_ice_credentials_.push_back(*it);
66 }
67 }
68
69 for (auto it = transport_info.candidates.begin();
70 it != transport_info.candidates.end(); ++it) {
jdoerried0539eeb2018-10-02 20:54:2971 auto channel = channels_.find(it->name);
sergeyu0b6c1c8d2015-10-28 20:48:4372 if (channel != channels_.end()) {
73 channel->second->AddRemoteCandidate(it->candidate);
74 } else {
75 // Transport info was received before the channel was created.
76 // This could happen due to messages being reordered on the wire.
77 pending_remote_candidates_.push_back(*it);
78 }
79 }
80
81 return true;
82}
83
sergeyu786463e2016-02-04 18:46:1084MessageChannelFactory* IceTransport::GetChannelFactory() {
85 return message_channel_factory_.get();
sergeyu0b6c1c8d2015-10-28 20:48:4386}
87
sergeyu786463e2016-02-04 18:46:1088MessageChannelFactory* IceTransport::GetMultiplexedChannelFactory() {
89 if (!channel_multiplexer_) {
sergeyu0b6c1c8d2015-10-28 20:48:4390 channel_multiplexer_.reset(
sergeyu786463e2016-02-04 18:46:1091 new ChannelMultiplexer(secure_channel_factory_.get(), kMuxChannelName));
92 mux_channel_factory_.reset(new StreamMessageChannelFactoryAdapter(
93 channel_multiplexer_.get(),
94 base::Bind(&IceTransport::OnChannelError, weak_factory_.GetWeakPtr())));
sergeyu0b6c1c8d2015-10-28 20:48:4395 }
sergeyu786463e2016-02-04 18:46:1096 return mux_channel_factory_.get();
sergeyu0b6c1c8d2015-10-28 20:48:4397}
98
sergeyu309771b2015-10-31 01:41:3799void IceTransport::CreateChannel(const std::string& name,
100 const ChannelCreatedCallback& callback) {
sergeyu0b6c1c8d2015-10-28 20:48:43101 DCHECK(!channels_[name]);
102
dcheng0765c492016-04-06 22:41:53103 std::unique_ptr<IceTransportChannel> channel(
sergeyu86030f382015-12-16 22:45:00104 new IceTransportChannel(transport_context_));
sergeyu0b6c1c8d2015-10-28 20:48:43105 channel->Connect(name, this, callback);
106 AddPendingRemoteTransportInfo(channel.get());
107 channels_[name] = channel.release();
108}
109
sergeyu309771b2015-10-31 01:41:37110void IceTransport::CancelChannelCreation(const std::string& name) {
jdoerried0539eeb2018-10-02 20:54:29111 auto it = channels_.find(name);
sergeyu0b6c1c8d2015-10-28 20:48:43112 if (it != channels_.end()) {
113 DCHECK(!it->second->is_connected());
114 delete it->second;
115 DCHECK(channels_.find(name) == channels_.end());
116 }
117}
118
sergeyu309771b2015-10-31 01:41:37119void IceTransport::AddPendingRemoteTransportInfo(IceTransportChannel* channel) {
jdoerried0539eeb2018-10-02 20:54:29120 auto credentials = pending_remote_ice_credentials_.begin();
sergeyu0b6c1c8d2015-10-28 20:48:43121 while (credentials != pending_remote_ice_credentials_.end()) {
122 if (credentials->channel == channel->name()) {
123 channel->SetRemoteCredentials(credentials->ufrag, credentials->password);
124 credentials = pending_remote_ice_credentials_.erase(credentials);
125 } else {
126 ++credentials;
127 }
128 }
129
jdoerried0539eeb2018-10-02 20:54:29130 auto candidate = pending_remote_candidates_.begin();
sergeyu0b6c1c8d2015-10-28 20:48:43131 while (candidate != pending_remote_candidates_.end()) {
132 if (candidate->name == channel->name()) {
133 channel->AddRemoteCandidate(candidate->candidate);
134 candidate = pending_remote_candidates_.erase(candidate);
135 } else {
136 ++candidate;
137 }
138 }
139}
140
sergeyue5767602015-12-28 19:49:03141void IceTransport::OnChannelIceCredentials(IceTransportChannel* channel,
142 const std::string& ufrag,
143 const std::string& password) {
sergeyu0b6c1c8d2015-10-28 20:48:43144 EnsurePendingTransportInfoMessage();
145 pending_transport_info_message_->ice_credentials.push_back(
sergeyua7749062015-10-28 21:57:45146 IceTransportInfo::IceCredentials(channel->name(), ufrag, password));
sergeyu0b6c1c8d2015-10-28 20:48:43147}
148
sergeyue5767602015-12-28 19:49:03149void IceTransport::OnChannelCandidate(IceTransportChannel* channel,
150 const cricket::Candidate& candidate) {
sergeyu0b6c1c8d2015-10-28 20:48:43151 EnsurePendingTransportInfoMessage();
152 pending_transport_info_message_->candidates.push_back(
sergeyua7749062015-10-28 21:57:45153 IceTransportInfo::NamedCandidate(channel->name(), candidate));
sergeyu0b6c1c8d2015-10-28 20:48:43154}
155
sergeyue5767602015-12-28 19:49:03156void IceTransport::OnChannelRouteChange(IceTransportChannel* channel,
157 const TransportRoute& route) {
sergeyu0b6c1c8d2015-10-28 20:48:43158 if (event_handler_)
sergeyue5767602015-12-28 19:49:03159 event_handler_->OnIceTransportRouteChange(channel->name(), route);
sergeyu0b6c1c8d2015-10-28 20:48:43160}
161
sergeyue5767602015-12-28 19:49:03162void IceTransport::OnChannelFailed(IceTransportChannel* channel) {
163 event_handler_->OnIceTransportError(CHANNEL_CONNECTION_ERROR);
sergeyu0b6c1c8d2015-10-28 20:48:43164}
165
sergeyue5767602015-12-28 19:49:03166void IceTransport::OnChannelDeleted(IceTransportChannel* channel) {
jdoerried0539eeb2018-10-02 20:54:29167 auto it = channels_.find(channel->name());
sergeyua7749062015-10-28 21:57:45168 DCHECK_EQ(it->second, channel);
sergeyu0b6c1c8d2015-10-28 20:48:43169 channels_.erase(it);
170}
171
sergeyu309771b2015-10-31 01:41:37172void IceTransport::EnsurePendingTransportInfoMessage() {
sergeyu0b6c1c8d2015-10-28 20:48:43173 // |transport_info_timer_| must be running iff
174 // |pending_transport_info_message_| exists.
175 DCHECK_EQ(pending_transport_info_message_ != nullptr,
176 transport_info_timer_.IsRunning());
177
178 if (!pending_transport_info_message_) {
179 pending_transport_info_message_.reset(new IceTransportInfo());
180 // Delay sending the new candidates in case we get more candidates
181 // that we can send in one message.
182 transport_info_timer_.Start(
183 FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
sergeyu309771b2015-10-31 01:41:37184 this, &IceTransport::SendTransportInfo);
sergeyu0b6c1c8d2015-10-28 20:48:43185 }
186}
187
sergeyu309771b2015-10-31 01:41:37188void IceTransport::SendTransportInfo() {
sergeyu0b6c1c8d2015-10-28 20:48:43189 DCHECK(pending_transport_info_message_);
sergeyue5767602015-12-28 19:49:03190
Mirko Bonadei80d1cea2019-01-18 22:22:17191 std::unique_ptr<jingle_xmpp::XmlElement> transport_info_xml =
sergeyue5767602015-12-28 19:49:03192 pending_transport_info_message_->ToXml();
sergeyu0b6c1c8d2015-10-28 20:48:43193 pending_transport_info_message_.reset();
sergeyue5767602015-12-28 19:49:03194 send_transport_info_callback_.Run(std::move(transport_info_xml));
sergeyu86030f382015-12-16 22:45:00195}
196
sergeyu786463e2016-02-04 18:46:10197void IceTransport::OnChannelError(int error) {
198 LOG(ERROR) << "Data channel failed, error=" << error;
joedow92f2a8c2017-02-22 07:35:39199 event_handler_->OnIceTransportError(error ? CHANNEL_CONNECTION_ERROR : OK);
sergeyu786463e2016-02-04 18:46:10200}
201
sergeyu0b6c1c8d2015-10-28 20:48:43202} // namespace protocol
203} // namespace remoting