OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/libjingle_transport_factory.h" | 5 #include "remoting/protocol/ice_transport_channel.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" |
12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
13 #include "base/timer/timer.h" | |
14 #include "jingle/glue/utils.h" | 13 #include "jingle/glue/utils.h" |
15 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
16 #include "remoting/protocol/channel_socket_adapter.h" | 15 #include "remoting/protocol/channel_socket_adapter.h" |
17 #include "remoting/protocol/network_settings.h" | |
18 #include "remoting/signaling/jingle_info_request.h" | |
19 #include "third_party/webrtc/base/network.h" | 16 #include "third_party/webrtc/base/network.h" |
20 #include "third_party/webrtc/p2p/base/constants.h" | 17 #include "third_party/webrtc/p2p/base/constants.h" |
21 #include "third_party/webrtc/p2p/base/p2ptransportchannel.h" | 18 #include "third_party/webrtc/p2p/base/p2ptransportchannel.h" |
22 #include "third_party/webrtc/p2p/base/port.h" | 19 #include "third_party/webrtc/p2p/base/port.h" |
23 #include "third_party/webrtc/p2p/client/httpportallocator.h" | 20 #include "third_party/webrtc/p2p/client/httpportallocator.h" |
24 | 21 |
25 namespace remoting { | 22 namespace remoting { |
26 namespace protocol { | 23 namespace protocol { |
27 | 24 |
28 namespace { | 25 namespace { |
29 | 26 |
30 // Try connecting ICE twice with timeout of 15 seconds for each attempt. | 27 // Try connecting ICE twice with timeout of 15 seconds for each attempt. |
31 const int kMaxReconnectAttempts = 2; | 28 const int kMaxReconnectAttempts = 2; |
32 const int kReconnectDelaySeconds = 15; | 29 const int kReconnectDelaySeconds = 15; |
33 | 30 |
34 // Get fresh STUN/Relay configuration every hour. | |
35 const int kJingleInfoUpdatePeriodSeconds = 3600; | |
36 | |
37 // Utility function to map a cricket::Candidate string type to a | 31 // Utility function to map a cricket::Candidate string type to a |
38 // TransportRoute::RouteType enum value. | 32 // TransportRoute::RouteType enum value. |
39 TransportRoute::RouteType CandidateTypeToTransportRouteType( | 33 TransportRoute::RouteType CandidateTypeToTransportRouteType( |
40 const std::string& candidate_type) { | 34 const std::string& candidate_type) { |
41 if (candidate_type == "local") { | 35 if (candidate_type == "local") { |
42 return TransportRoute::DIRECT; | 36 return TransportRoute::DIRECT; |
43 } else if (candidate_type == "stun" || candidate_type == "prflx") { | 37 } else if (candidate_type == "stun" || candidate_type == "prflx") { |
44 return TransportRoute::STUN; | 38 return TransportRoute::STUN; |
45 } else if (candidate_type == "relay") { | 39 } else if (candidate_type == "relay") { |
46 return TransportRoute::RELAY; | 40 return TransportRoute::RELAY; |
47 } else { | 41 } else { |
48 LOG(FATAL) << "Unknown candidate type: " << candidate_type; | 42 LOG(FATAL) << "Unknown candidate type: " << candidate_type; |
49 return TransportRoute::DIRECT; | 43 return TransportRoute::DIRECT; |
50 } | 44 } |
51 } | 45 } |
52 | 46 |
53 class LibjingleTransport | 47 } // namespace |
54 : public Transport, | |
55 public base::SupportsWeakPtr<LibjingleTransport>, | |
56 public sigslot::has_slots<> { | |
57 public: | |
58 LibjingleTransport(cricket::PortAllocator* port_allocator, | |
59 const NetworkSettings& network_settings, | |
60 TransportRole role); | |
61 ~LibjingleTransport() override; | |
62 | 48 |
63 // Called by JingleTransportFactory when it has fresh Jingle info. | 49 IceTransportChannel::IceTransportChannel(cricket::PortAllocator* port_allocator, |
64 void OnCanStart(); | |
65 | |
66 // Transport interface. | |
67 void Connect(const std::string& name, | |
68 Transport::EventHandler* event_handler, | |
69 const Transport::ConnectedCallback& callback) override; | |
70 void SetRemoteCredentials(const std::string& ufrag, | |
71 const std::string& password) override; | |
72 void AddRemoteCandidate(const cricket::Candidate& candidate) override; | |
73 const std::string& name() const override; | |
74 bool is_connected() const override; | |
75 | |
76 private: | |
77 void DoStart(); | |
78 void NotifyConnected(); | |
79 | |
80 // Signal handlers for cricket::TransportChannel. | |
81 void OnCandidateGathered(cricket::TransportChannelImpl* channel, | |
82 const cricket::Candidate& candidate); | |
83 void OnRouteChange(cricket::TransportChannel* channel, | |
84 const cricket::Candidate& candidate); | |
85 void OnReceivingState(cricket::TransportChannel* channel); | |
86 void OnWritableState(cricket::TransportChannel* channel); | |
87 | |
88 // Callback for TransportChannelSocketAdapter to notify when the socket is | |
89 // destroyed. | |
90 void OnChannelDestroyed(); | |
91 | |
92 void NotifyRouteChanged(); | |
93 | |
94 // Tries to connect by restarting ICE. Called by |reconnect_timer_|. | |
95 void TryReconnect(); | |
96 | |
97 cricket::PortAllocator* port_allocator_; | |
98 NetworkSettings network_settings_; | |
99 TransportRole role_; | |
100 | |
101 std::string name_; | |
102 EventHandler* event_handler_; | |
103 Transport::ConnectedCallback callback_; | |
104 std::string ice_username_fragment_; | |
105 | |
106 bool can_start_; | |
107 | |
108 std::string remote_ice_username_fragment_; | |
109 std::string remote_ice_password_; | |
110 std::list<cricket::Candidate> pending_candidates_; | |
111 scoped_ptr<cricket::P2PTransportChannel> channel_; | |
112 int connect_attempts_left_; | |
113 base::RepeatingTimer reconnect_timer_; | |
114 | |
115 base::WeakPtrFactory<LibjingleTransport> weak_factory_; | |
116 | |
117 DISALLOW_COPY_AND_ASSIGN(LibjingleTransport); | |
118 }; | |
119 | |
120 LibjingleTransport::LibjingleTransport(cricket::PortAllocator* port_allocator, | |
121 const NetworkSettings& network_settings, | 50 const NetworkSettings& network_settings, |
122 TransportRole role) | 51 TransportRole role) |
123 : port_allocator_(port_allocator), | 52 : port_allocator_(port_allocator), |
124 network_settings_(network_settings), | 53 network_settings_(network_settings), |
125 role_(role), | 54 role_(role), |
126 event_handler_(nullptr), | 55 delegate_(nullptr), |
127 ice_username_fragment_( | 56 ice_username_fragment_( |
128 rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH)), | 57 rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH)), |
129 can_start_(false), | 58 can_start_(false), |
130 connect_attempts_left_(kMaxReconnectAttempts), | 59 connect_attempts_left_(kMaxReconnectAttempts), |
131 weak_factory_(this) { | 60 weak_factory_(this) { |
132 DCHECK(!ice_username_fragment_.empty()); | 61 DCHECK(!ice_username_fragment_.empty()); |
133 } | 62 } |
134 | 63 |
135 LibjingleTransport::~LibjingleTransport() { | 64 IceTransportChannel::~IceTransportChannel() { |
136 DCHECK(event_handler_); | 65 DCHECK(delegate_); |
137 | 66 |
138 event_handler_->OnTransportDeleted(this); | 67 delegate_->OnTransportDeleted(this); |
139 | 68 |
140 if (channel_.get()) { | 69 if (channel_.get()) { |
141 base::ThreadTaskRunnerHandle::Get()->DeleteSoon( | 70 base::ThreadTaskRunnerHandle::Get()->DeleteSoon( |
142 FROM_HERE, channel_.release()); | 71 FROM_HERE, channel_.release()); |
143 } | 72 } |
144 } | 73 } |
145 | 74 |
146 void LibjingleTransport::OnCanStart() { | 75 void IceTransportChannel::OnCanStart() { |
147 DCHECK(CalledOnValidThread()); | 76 DCHECK(thread_checker_.CalledOnValidThread()); |
148 | 77 |
149 DCHECK(!can_start_); | 78 DCHECK(!can_start_); |
150 can_start_ = true; | 79 can_start_ = true; |
151 | 80 |
152 // If Connect() has been called then start connection. | 81 // If Connect() has been called then start connection. |
153 if (!callback_.is_null()) | 82 if (!callback_.is_null()) |
154 DoStart(); | 83 DoStart(); |
155 | 84 |
156 // Pass pending ICE credentials and candidates to the channel. | 85 // Pass pending ICE credentials and candidates to the channel. |
157 if (!remote_ice_username_fragment_.empty()) { | 86 if (!remote_ice_username_fragment_.empty()) { |
158 channel_->SetRemoteIceCredentials(remote_ice_username_fragment_, | 87 channel_->SetRemoteIceCredentials(remote_ice_username_fragment_, |
159 remote_ice_password_); | 88 remote_ice_password_); |
160 } | 89 } |
161 | 90 |
162 while (!pending_candidates_.empty()) { | 91 while (!pending_candidates_.empty()) { |
163 channel_->AddRemoteCandidate(pending_candidates_.front()); | 92 channel_->AddRemoteCandidate(pending_candidates_.front()); |
164 pending_candidates_.pop_front(); | 93 pending_candidates_.pop_front(); |
165 } | 94 } |
166 } | 95 } |
167 | 96 |
168 void LibjingleTransport::Connect( | 97 void IceTransportChannel::Connect(const std::string& name, |
169 const std::string& name, | 98 Delegate* delegate, |
170 Transport::EventHandler* event_handler, | 99 const ConnectedCallback& callback) { |
171 const Transport::ConnectedCallback& callback) { | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
172 DCHECK(CalledOnValidThread()); | |
173 DCHECK(!name.empty()); | 101 DCHECK(!name.empty()); |
174 DCHECK(event_handler); | 102 DCHECK(delegate); |
175 DCHECK(!callback.is_null()); | 103 DCHECK(!callback.is_null()); |
176 | 104 |
177 DCHECK(name_.empty()); | 105 DCHECK(name_.empty()); |
178 name_ = name; | 106 name_ = name; |
179 event_handler_ = event_handler; | 107 delegate_ = delegate; |
180 callback_ = callback; | 108 callback_ = callback; |
181 | 109 |
182 if (can_start_) | 110 if (can_start_) |
183 DoStart(); | 111 DoStart(); |
184 } | 112 } |
185 | 113 |
186 void LibjingleTransport::DoStart() { | 114 void IceTransportChannel::DoStart() { |
187 DCHECK(!channel_.get()); | 115 DCHECK(!channel_.get()); |
188 | 116 |
189 // Create P2PTransportChannel, attach signal handlers and connect it. | 117 // Create P2PTransportChannel, attach signal handlers and connect it. |
190 // TODO(sergeyu): Specify correct component ID for the channel. | 118 // TODO(sergeyu): Specify correct component ID for the channel. |
191 channel_.reset(new cricket::P2PTransportChannel( | 119 channel_.reset(new cricket::P2PTransportChannel( |
192 std::string(), 0, nullptr, port_allocator_)); | 120 std::string(), 0, nullptr, port_allocator_)); |
193 std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); | 121 std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); |
194 channel_->SetIceProtocolType(cricket::ICEPROTO_RFC5245); | 122 channel_->SetIceProtocolType(cricket::ICEPROTO_RFC5245); |
195 channel_->SetIceRole((role_ == TransportRole::CLIENT) | 123 channel_->SetIceRole((role_ == TransportRole::CLIENT) |
196 ? cricket::ICEROLE_CONTROLLING | 124 ? cricket::ICEROLE_CONTROLLING |
197 : cricket::ICEROLE_CONTROLLED); | 125 : cricket::ICEROLE_CONTROLLED); |
198 event_handler_->OnTransportIceCredentials(this, ice_username_fragment_, | 126 delegate_->OnTransportIceCredentials(this, ice_username_fragment_, |
199 ice_password); | 127 ice_password); |
200 channel_->SetIceCredentials(ice_username_fragment_, ice_password); | 128 channel_->SetIceCredentials(ice_username_fragment_, ice_password); |
201 channel_->SignalCandidateGathered.connect( | 129 channel_->SignalCandidateGathered.connect( |
202 this, &LibjingleTransport::OnCandidateGathered); | 130 this, &IceTransportChannel::OnCandidateGathered); |
203 channel_->SignalRouteChange.connect( | 131 channel_->SignalRouteChange.connect( |
204 this, &LibjingleTransport::OnRouteChange); | 132 this, &IceTransportChannel::OnRouteChange); |
205 channel_->SignalReceivingState.connect( | 133 channel_->SignalReceivingState.connect( |
206 this, &LibjingleTransport::OnReceivingState); | 134 this, &IceTransportChannel::OnReceivingState); |
207 channel_->SignalWritableState.connect( | 135 channel_->SignalWritableState.connect( |
208 this, &LibjingleTransport::OnWritableState); | 136 this, &IceTransportChannel::OnWritableState); |
209 channel_->set_incoming_only( | 137 channel_->set_incoming_only( |
210 !(network_settings_.flags & NetworkSettings::NAT_TRAVERSAL_OUTGOING)); | 138 !(network_settings_.flags & NetworkSettings::NAT_TRAVERSAL_OUTGOING)); |
211 | 139 |
212 channel_->Connect(); | 140 channel_->Connect(); |
213 channel_->MaybeStartGathering(); | 141 channel_->MaybeStartGathering(); |
214 | 142 |
215 --connect_attempts_left_; | 143 --connect_attempts_left_; |
216 | 144 |
217 // Start reconnection timer. | 145 // Start reconnection timer. |
218 reconnect_timer_.Start( | 146 reconnect_timer_.Start( |
219 FROM_HERE, base::TimeDelta::FromSeconds(kReconnectDelaySeconds), | 147 FROM_HERE, base::TimeDelta::FromSeconds(kReconnectDelaySeconds), |
220 this, &LibjingleTransport::TryReconnect); | 148 this, &IceTransportChannel::TryReconnect); |
221 } | 149 } |
222 | 150 |
223 void LibjingleTransport::NotifyConnected() { | 151 void IceTransportChannel::NotifyConnected() { |
224 // Create P2PDatagramSocket adapter for the P2PTransportChannel. | 152 // Create P2PDatagramSocket adapter for the P2PTransportChannel. |
225 scoped_ptr<TransportChannelSocketAdapter> socket( | 153 scoped_ptr<TransportChannelSocketAdapter> socket( |
226 new TransportChannelSocketAdapter(channel_.get())); | 154 new TransportChannelSocketAdapter(channel_.get())); |
227 socket->SetOnDestroyedCallback(base::Bind( | 155 socket->SetOnDestroyedCallback(base::Bind( |
228 &LibjingleTransport::OnChannelDestroyed, base::Unretained(this))); | 156 &IceTransportChannel::OnChannelDestroyed, base::Unretained(this))); |
229 base::ResetAndReturn(&callback_).Run(socket.Pass()); | 157 base::ResetAndReturn(&callback_).Run(socket.Pass()); |
230 } | 158 } |
231 | 159 |
232 void LibjingleTransport::SetRemoteCredentials(const std::string& ufrag, | 160 void IceTransportChannel::SetRemoteCredentials(const std::string& ufrag, |
233 const std::string& password) { | 161 const std::string& password) { |
234 DCHECK(CalledOnValidThread()); | 162 DCHECK(thread_checker_.CalledOnValidThread()); |
235 | 163 |
236 remote_ice_username_fragment_ = ufrag; | 164 remote_ice_username_fragment_ = ufrag; |
237 remote_ice_password_ = password; | 165 remote_ice_password_ = password; |
238 | 166 |
239 if (channel_) | 167 if (channel_) |
240 channel_->SetRemoteIceCredentials(ufrag, password); | 168 channel_->SetRemoteIceCredentials(ufrag, password); |
241 } | 169 } |
242 | 170 |
243 void LibjingleTransport::AddRemoteCandidate( | 171 void IceTransportChannel::AddRemoteCandidate( |
244 const cricket::Candidate& candidate) { | 172 const cricket::Candidate& candidate) { |
245 DCHECK(CalledOnValidThread()); | 173 DCHECK(thread_checker_.CalledOnValidThread()); |
246 | 174 |
247 // To enforce the no-relay setting, it's not enough to not produce relay | 175 // To enforce the no-relay setting, it's not enough to not produce relay |
248 // candidates. It's also necessary to discard remote relay candidates. | 176 // candidates. It's also necessary to discard remote relay candidates. |
249 bool relay_allowed = (network_settings_.flags & | 177 bool relay_allowed = (network_settings_.flags & |
250 NetworkSettings::NAT_TRAVERSAL_RELAY) != 0; | 178 NetworkSettings::NAT_TRAVERSAL_RELAY) != 0; |
251 if (!relay_allowed && candidate.type() == cricket::RELAY_PORT_TYPE) | 179 if (!relay_allowed && candidate.type() == cricket::RELAY_PORT_TYPE) |
252 return; | 180 return; |
253 | 181 |
254 if (channel_) { | 182 if (channel_) { |
255 channel_->AddRemoteCandidate(candidate); | 183 channel_->AddRemoteCandidate(candidate); |
256 } else { | 184 } else { |
257 pending_candidates_.push_back(candidate); | 185 pending_candidates_.push_back(candidate); |
258 } | 186 } |
259 } | 187 } |
260 | 188 |
261 const std::string& LibjingleTransport::name() const { | 189 const std::string& IceTransportChannel::name() const { |
262 DCHECK(CalledOnValidThread()); | 190 DCHECK(thread_checker_.CalledOnValidThread()); |
263 return name_; | 191 return name_; |
264 } | 192 } |
265 | 193 |
266 bool LibjingleTransport::is_connected() const { | 194 bool IceTransportChannel::is_connected() const { |
267 DCHECK(CalledOnValidThread()); | 195 DCHECK(thread_checker_.CalledOnValidThread()); |
268 return callback_.is_null(); | 196 return callback_.is_null(); |
269 } | 197 } |
270 | 198 |
271 void LibjingleTransport::OnCandidateGathered( | 199 void IceTransportChannel::OnCandidateGathered( |
272 cricket::TransportChannelImpl* channel, | 200 cricket::TransportChannelImpl* channel, |
273 const cricket::Candidate& candidate) { | 201 const cricket::Candidate& candidate) { |
274 DCHECK(CalledOnValidThread()); | 202 DCHECK(thread_checker_.CalledOnValidThread()); |
275 event_handler_->OnTransportCandidate(this, candidate); | 203 delegate_->OnTransportCandidate(this, candidate); |
276 } | 204 } |
277 | 205 |
278 void LibjingleTransport::OnRouteChange( | 206 void IceTransportChannel::OnRouteChange( |
279 cricket::TransportChannel* channel, | 207 cricket::TransportChannel* channel, |
280 const cricket::Candidate& candidate) { | 208 const cricket::Candidate& candidate) { |
281 // Ignore notifications if the channel is not writable. | 209 // Ignore notifications if the channel is not writable. |
282 if (channel_->writable()) | 210 if (channel_->writable()) |
283 NotifyRouteChanged(); | 211 NotifyRouteChanged(); |
284 } | 212 } |
285 | 213 |
286 void LibjingleTransport::OnReceivingState(cricket::TransportChannel* channel) { | 214 void IceTransportChannel::OnReceivingState(cricket::TransportChannel* channel) { |
287 DCHECK_EQ(channel, static_cast<cricket::TransportChannel*>(channel_.get())); | 215 DCHECK_EQ(channel, static_cast<cricket::TransportChannel*>(channel_.get())); |
288 | 216 |
289 if (channel->receiving() && !callback_.is_null()) | 217 if (channel->receiving() && !callback_.is_null()) |
290 NotifyConnected(); | 218 NotifyConnected(); |
291 } | 219 } |
292 | 220 |
293 void LibjingleTransport::OnWritableState(cricket::TransportChannel* channel) { | 221 void IceTransportChannel::OnWritableState(cricket::TransportChannel* channel) { |
294 DCHECK_EQ(channel, static_cast<cricket::TransportChannel*>(channel_.get())); | 222 DCHECK_EQ(channel, static_cast<cricket::TransportChannel*>(channel_.get())); |
295 | 223 |
296 if (channel->writable()) { | 224 if (channel->writable()) { |
297 connect_attempts_left_ = kMaxReconnectAttempts; | 225 connect_attempts_left_ = kMaxReconnectAttempts; |
298 reconnect_timer_.Stop(); | 226 reconnect_timer_.Stop(); |
299 | 227 |
300 // Route change notifications are ignored when the |channel_| is not | 228 // Route change notifications are ignored when the |channel_| is not |
301 // writable. Notify the event handler about the current route once the | 229 // writable. Notify the event handler about the current route once the |
302 // channel is writable. | 230 // channel is writable. |
303 NotifyRouteChanged(); | 231 NotifyRouteChanged(); |
304 } else { | 232 } else { |
305 reconnect_timer_.Reset(); | 233 reconnect_timer_.Reset(); |
306 TryReconnect(); | 234 TryReconnect(); |
307 } | 235 } |
308 } | 236 } |
309 | 237 |
310 void LibjingleTransport::OnChannelDestroyed() { | 238 void IceTransportChannel::OnChannelDestroyed() { |
311 // The connection socket is being deleted, so delete the transport too. | 239 // The connection socket is being deleted, so delete the transport too. |
312 delete this; | 240 delete this; |
313 } | 241 } |
314 | 242 |
315 void LibjingleTransport::NotifyRouteChanged() { | 243 void IceTransportChannel::NotifyRouteChanged() { |
316 TransportRoute route; | 244 TransportRoute route; |
317 | 245 |
318 DCHECK(channel_->best_connection()); | 246 DCHECK(channel_->best_connection()); |
319 const cricket::Connection* connection = channel_->best_connection(); | 247 const cricket::Connection* connection = channel_->best_connection(); |
320 | 248 |
321 // A connection has both a local and a remote candidate. For our purposes, the | 249 // A connection has both a local and a remote candidate. For our purposes, the |
322 // route type is determined by the most indirect candidate type. For example: | 250 // route type is determined by the most indirect candidate type. For example: |
323 // it's possible for the local candidate be a "relay" type, while the remote | 251 // it's possible for the local candidate be a "relay" type, while the remote |
324 // candidate is "local". In this case, we still want to report a RELAY route | 252 // candidate is "local". In this case, we still want to report a RELAY route |
325 // type. | 253 // type. |
326 static_assert(TransportRoute::DIRECT < TransportRoute::STUN && | 254 static_assert(TransportRoute::DIRECT < TransportRoute::STUN && |
327 TransportRoute::STUN < TransportRoute::RELAY, | 255 TransportRoute::STUN < TransportRoute::RELAY, |
328 "Route type enum values are ordered by 'indirectness'"); | 256 "Route type enum values are ordered by 'indirectness'"); |
329 route.type = std::max( | 257 route.type = std::max( |
330 CandidateTypeToTransportRouteType(connection->local_candidate().type()), | 258 CandidateTypeToTransportRouteType(connection->local_candidate().type()), |
331 CandidateTypeToTransportRouteType(connection->remote_candidate().type())); | 259 CandidateTypeToTransportRouteType(connection->remote_candidate().type())); |
332 | 260 |
333 if (!jingle_glue::SocketAddressToIPEndPoint( | 261 if (!jingle_glue::SocketAddressToIPEndPoint( |
334 connection->remote_candidate().address(), &route.remote_address)) { | 262 connection->remote_candidate().address(), &route.remote_address)) { |
335 LOG(FATAL) << "Failed to convert peer IP address."; | 263 LOG(FATAL) << "Failed to convert peer IP address."; |
336 } | 264 } |
337 | 265 |
338 const cricket::Candidate& local_candidate = | 266 const cricket::Candidate& local_candidate = |
339 channel_->best_connection()->local_candidate(); | 267 channel_->best_connection()->local_candidate(); |
340 if (!jingle_glue::SocketAddressToIPEndPoint( | 268 if (!jingle_glue::SocketAddressToIPEndPoint( |
341 local_candidate.address(), &route.local_address)) { | 269 local_candidate.address(), &route.local_address)) { |
342 LOG(FATAL) << "Failed to convert local IP address."; | 270 LOG(FATAL) << "Failed to convert local IP address."; |
343 } | 271 } |
344 | 272 |
345 event_handler_->OnTransportRouteChange(this, route); | 273 delegate_->OnTransportRouteChange(this, route); |
346 } | 274 } |
347 | 275 |
348 void LibjingleTransport::TryReconnect() { | 276 void IceTransportChannel::TryReconnect() { |
349 DCHECK(!channel_->writable()); | 277 DCHECK(!channel_->writable()); |
350 | 278 |
351 if (connect_attempts_left_ <= 0) { | 279 if (connect_attempts_left_ <= 0) { |
352 reconnect_timer_.Stop(); | 280 reconnect_timer_.Stop(); |
353 | 281 |
354 // Notify the caller that ICE connection has failed - normally that will | 282 // Notify the caller that ICE connection has failed - normally that will |
355 // terminate Jingle connection (i.e. the transport will be destroyed). | 283 // terminate Jingle connection (i.e. the transport will be destroyed). |
356 event_handler_->OnTransportFailed(this); | 284 delegate_->OnTransportFailed(this); |
357 return; | 285 return; |
358 } | 286 } |
359 --connect_attempts_left_; | 287 --connect_attempts_left_; |
360 | 288 |
361 // Restart ICE by resetting ICE password. | 289 // Restart ICE by resetting ICE password. |
362 std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); | 290 std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); |
363 event_handler_->OnTransportIceCredentials(this, ice_username_fragment_, | 291 delegate_->OnTransportIceCredentials(this, ice_username_fragment_, |
364 ice_password); | 292 ice_password); |
365 channel_->SetIceCredentials(ice_username_fragment_, ice_password); | 293 channel_->SetIceCredentials(ice_username_fragment_, ice_password); |
366 } | 294 } |
367 | 295 |
368 } // namespace | |
369 | |
370 LibjingleTransportFactory::LibjingleTransportFactory( | |
371 SignalStrategy* signal_strategy, | |
372 scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, | |
373 const NetworkSettings& network_settings, | |
374 TransportRole role) | |
375 : signal_strategy_(signal_strategy), | |
376 port_allocator_(port_allocator.Pass()), | |
377 network_settings_(network_settings), | |
378 role_(role) { | |
379 } | |
380 | |
381 LibjingleTransportFactory::~LibjingleTransportFactory() { | |
382 // This method may be called in response to a libjingle signal, so | |
383 // libjingle objects must be deleted asynchronously. | |
384 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | |
385 base::ThreadTaskRunnerHandle::Get(); | |
386 task_runner->DeleteSoon(FROM_HERE, port_allocator_.release()); | |
387 } | |
388 | |
389 void LibjingleTransportFactory::PrepareTokens() { | |
390 EnsureFreshJingleInfo(); | |
391 } | |
392 | |
393 scoped_ptr<Transport> LibjingleTransportFactory::CreateTransport() { | |
394 scoped_ptr<LibjingleTransport> result( | |
395 new LibjingleTransport(port_allocator_.get(), network_settings_, role_)); | |
396 | |
397 EnsureFreshJingleInfo(); | |
398 | |
399 // If there is a pending |jingle_info_request_| delay starting the new | |
400 // transport until the request is finished. | |
401 if (jingle_info_request_) { | |
402 on_jingle_info_callbacks_.push_back( | |
403 base::Bind(&LibjingleTransport::OnCanStart, | |
404 result->AsWeakPtr())); | |
405 } else { | |
406 result->OnCanStart(); | |
407 } | |
408 | |
409 return result.Pass(); | |
410 } | |
411 | |
412 void LibjingleTransportFactory::EnsureFreshJingleInfo() { | |
413 uint32 stun_or_relay_flags = NetworkSettings::NAT_TRAVERSAL_STUN | | |
414 NetworkSettings::NAT_TRAVERSAL_RELAY; | |
415 if (!(network_settings_.flags & stun_or_relay_flags) || | |
416 jingle_info_request_) { | |
417 return; | |
418 } | |
419 | |
420 if (last_jingle_info_update_time_.is_null() || | |
421 base::TimeTicks::Now() - last_jingle_info_update_time_ > | |
422 base::TimeDelta::FromSeconds(kJingleInfoUpdatePeriodSeconds)) { | |
423 jingle_info_request_.reset(new JingleInfoRequest(signal_strategy_)); | |
424 jingle_info_request_->Send(base::Bind( | |
425 &LibjingleTransportFactory::OnJingleInfo, base::Unretained(this))); | |
426 } | |
427 } | |
428 | |
429 void LibjingleTransportFactory::OnJingleInfo( | |
430 const std::string& relay_token, | |
431 const std::vector<std::string>& relay_hosts, | |
432 const std::vector<rtc::SocketAddress>& stun_hosts) { | |
433 if (!relay_token.empty() && !relay_hosts.empty()) { | |
434 port_allocator_->SetRelayHosts(relay_hosts); | |
435 port_allocator_->SetRelayToken(relay_token); | |
436 } | |
437 if (!stun_hosts.empty()) { | |
438 port_allocator_->SetStunHosts(stun_hosts); | |
439 } | |
440 | |
441 jingle_info_request_.reset(); | |
442 if ((!relay_token.empty() && !relay_hosts.empty()) || !stun_hosts.empty()) | |
443 last_jingle_info_update_time_ = base::TimeTicks::Now(); | |
444 | |
445 while (!on_jingle_info_callbacks_.empty()) { | |
446 on_jingle_info_callbacks_.begin()->Run(); | |
447 on_jingle_info_callbacks_.pop_front(); | |
448 } | |
449 } | |
450 | |
451 } // namespace protocol | 296 } // namespace protocol |
452 } // namespace remoting | 297 } // namespace remoting |
OLD | NEW |