OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/port_allocator_base.h" | 5 #include "remoting/protocol/port_allocator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
14 #include "net/base/escape.h" | 14 #include "net/base/escape.h" |
| 15 #include "net/http/http_status_code.h" |
15 #include "remoting/protocol/network_settings.h" | 16 #include "remoting/protocol/network_settings.h" |
16 #include "remoting/protocol/transport_context.h" | 17 #include "remoting/protocol/transport_context.h" |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 typedef std::map<std::string, std::string> StringMap; | 21 typedef std::map<std::string, std::string> StringMap; |
21 | 22 |
22 // Parses the lines in the result of the HTTP request that are of the form | 23 // Parses the lines in the result of the HTTP request that are of the form |
23 // 'a=b' and returns them in a map. | 24 // 'a=b' and returns them in a map. |
24 StringMap ParseMap(const std::string& string) { | 25 StringMap ParseMap(const std::string& string) { |
25 StringMap map; | 26 StringMap map; |
26 base::StringPairs pairs; | 27 base::StringPairs pairs; |
27 base::SplitStringIntoKeyValuePairs(string, '=', '\n', &pairs); | 28 base::SplitStringIntoKeyValuePairs(string, '=', '\n', &pairs); |
28 | 29 |
29 for (auto& pair : pairs) { | 30 for (auto& pair : pairs) { |
30 map[pair.first] = pair.second; | 31 map[pair.first] = pair.second; |
31 } | 32 } |
32 return map; | 33 return map; |
33 } | 34 } |
34 | 35 |
| 36 const int kNumRetries = 5; |
| 37 |
35 } // namespace | 38 } // namespace |
36 | 39 |
37 namespace remoting { | 40 namespace remoting { |
38 namespace protocol { | 41 namespace protocol { |
39 | 42 |
40 const int PortAllocatorBase::kNumRetries = 5; | 43 PortAllocator::PortAllocator( |
41 | |
42 PortAllocatorBase::PortAllocatorBase( | |
43 scoped_ptr<rtc::NetworkManager> network_manager, | 44 scoped_ptr<rtc::NetworkManager> network_manager, |
44 scoped_ptr<rtc::PacketSocketFactory> socket_factory, | 45 scoped_ptr<rtc::PacketSocketFactory> socket_factory, |
45 scoped_refptr<TransportContext> transport_context) | 46 scoped_refptr<TransportContext> transport_context) |
46 : BasicPortAllocator(network_manager.get(), socket_factory.get()), | 47 : BasicPortAllocator(network_manager.get(), socket_factory.get()), |
47 network_manager_(std::move(network_manager)), | 48 network_manager_(std::move(network_manager)), |
48 socket_factory_(std::move(socket_factory)), | 49 socket_factory_(std::move(socket_factory)), |
49 transport_context_(transport_context) { | 50 transport_context_(transport_context) { |
50 // We always use PseudoTcp to provide a reliable channel. It provides poor | 51 // We always use PseudoTcp to provide a reliable channel. It provides poor |
51 // performance when combined with TCP-based transport, so we have to disable | 52 // performance when combined with TCP-based transport, so we have to disable |
52 // TCP ports. ENABLE_SHARED_UFRAG flag is specified so that the same username | 53 // TCP ports. ENABLE_SHARED_UFRAG flag is specified so that the same username |
53 // fragment is shared between all candidates. | 54 // fragment is shared between all candidates. |
54 int flags = cricket::PORTALLOCATOR_DISABLE_TCP | | 55 int flags = cricket::PORTALLOCATOR_DISABLE_TCP | |
55 cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | | 56 cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | |
56 cricket::PORTALLOCATOR_ENABLE_IPV6; | 57 cricket::PORTALLOCATOR_ENABLE_IPV6; |
57 | 58 |
58 NetworkSettings network_settings = transport_context_->network_settings(); | 59 NetworkSettings network_settings = transport_context_->network_settings(); |
59 | 60 |
60 if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_STUN)) | 61 if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_STUN)) |
61 flags |= cricket::PORTALLOCATOR_DISABLE_STUN; | 62 flags |= cricket::PORTALLOCATOR_DISABLE_STUN; |
62 | 63 |
63 if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_RELAY)) | 64 if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_RELAY)) |
64 flags |= cricket::PORTALLOCATOR_DISABLE_RELAY; | 65 flags |= cricket::PORTALLOCATOR_DISABLE_RELAY; |
65 | 66 |
66 set_flags(flags); | 67 set_flags(flags); |
67 SetPortRange(network_settings.port_range.min_port, | 68 SetPortRange(network_settings.port_range.min_port, |
68 network_settings.port_range.max_port); | 69 network_settings.port_range.max_port); |
69 } | 70 } |
70 | 71 |
71 PortAllocatorBase::~PortAllocatorBase() {} | 72 PortAllocator::~PortAllocator() {} |
72 | 73 |
73 PortAllocatorSessionBase::PortAllocatorSessionBase( | 74 cricket::PortAllocatorSession* PortAllocator::CreateSessionInternal( |
74 PortAllocatorBase* allocator, | |
75 const std::string& content_name, | 75 const std::string& content_name, |
76 int component, | 76 int component, |
77 const std::string& ice_ufrag, | 77 const std::string& ice_username_fragment, |
78 const std::string& ice_pwd) | 78 const std::string& ice_password) { |
| 79 return new PortAllocatorSession(this, content_name, component, |
| 80 ice_username_fragment, ice_password); |
| 81 } |
| 82 |
| 83 PortAllocatorSession::PortAllocatorSession(PortAllocator* allocator, |
| 84 const std::string& content_name, |
| 85 int component, |
| 86 const std::string& ice_ufrag, |
| 87 const std::string& ice_pwd) |
79 : BasicPortAllocatorSession(allocator, | 88 : BasicPortAllocatorSession(allocator, |
80 content_name, | 89 content_name, |
81 component, | 90 component, |
82 ice_ufrag, | 91 ice_ufrag, |
83 ice_pwd), | 92 ice_pwd), |
84 transport_context_(allocator->transport_context()), | 93 transport_context_(allocator->transport_context()), |
85 weak_factory_(this) {} | 94 weak_factory_(this) {} |
86 | 95 |
87 PortAllocatorSessionBase::~PortAllocatorSessionBase() {} | 96 PortAllocatorSession::~PortAllocatorSession() {} |
88 | 97 |
89 void PortAllocatorSessionBase::GetPortConfigurations() { | 98 void PortAllocatorSession::GetPortConfigurations() { |
90 transport_context_->GetJingleInfo(base::Bind( | 99 transport_context_->GetJingleInfo(base::Bind( |
91 &PortAllocatorSessionBase::OnJingleInfo, weak_factory_.GetWeakPtr())); | 100 &PortAllocatorSession::OnJingleInfo, weak_factory_.GetWeakPtr())); |
92 } | 101 } |
93 | 102 |
94 void PortAllocatorSessionBase::OnJingleInfo( | 103 void PortAllocatorSession::OnJingleInfo( |
95 std::vector<rtc::SocketAddress> stun_hosts, | 104 std::vector<rtc::SocketAddress> stun_hosts, |
96 std::vector<std::string> relay_hosts, | 105 std::vector<std::string> relay_hosts, |
97 std::string relay_token) { | 106 std::string relay_token) { |
98 stun_hosts_ = stun_hosts; | 107 stun_hosts_ = stun_hosts; |
99 relay_hosts_ = relay_hosts; | 108 relay_hosts_ = relay_hosts; |
100 relay_token_ = relay_token; | 109 relay_token_ = relay_token; |
101 | 110 |
102 // Creating relay sessions can take time and is done asynchronously. | 111 // Creating relay sessions can take time and is done asynchronously. |
103 // Creating stun sessions could also take time and could be done aysnc also, | 112 // Creating stun sessions could also take time and could be done aysnc also, |
104 // but for now is done here and added to the initial config. Note any later | 113 // but for now is done here and added to the initial config. Note any later |
105 // configs will have unresolved stun ips and will be discarded by the | 114 // configs will have unresolved stun ips and will be discarded by the |
106 // AllocationSequence. | 115 // AllocationSequence. |
107 cricket::ServerAddresses hosts; | 116 cricket::ServerAddresses hosts; |
108 for (const auto& host : stun_hosts_) { | 117 for (const auto& host : stun_hosts_) { |
109 hosts.insert(host); | 118 hosts.insert(host); |
110 } | 119 } |
111 | 120 |
112 cricket::PortConfiguration* config = | 121 cricket::PortConfiguration* config = |
113 new cricket::PortConfiguration(hosts, username(), password()); | 122 new cricket::PortConfiguration(hosts, username(), password()); |
114 ConfigReady(config); | 123 ConfigReady(config); |
115 TryCreateRelaySession(); | 124 TryCreateRelaySession(); |
116 } | 125 } |
117 | 126 |
118 void PortAllocatorSessionBase::TryCreateRelaySession() { | 127 void PortAllocatorSession::TryCreateRelaySession() { |
119 if (flags() & cricket::PORTALLOCATOR_DISABLE_RELAY) | 128 if (flags() & cricket::PORTALLOCATOR_DISABLE_RELAY) |
120 return; | 129 return; |
121 | 130 |
122 if (attempts_ == PortAllocatorBase::kNumRetries) { | 131 if (attempts_ == kNumRetries) { |
123 LOG(ERROR) << "PortAllocator: maximum number of requests reached; " | 132 LOG(ERROR) << "PortAllocator: maximum number of requests reached; " |
124 << "giving up on relay."; | 133 << "giving up on relay."; |
125 return; | 134 return; |
126 } | 135 } |
127 | 136 |
128 if (relay_hosts_.empty()) { | 137 if (relay_hosts_.empty()) { |
129 LOG(ERROR) << "PortAllocator: no relay hosts configured."; | 138 LOG(ERROR) << "PortAllocator: no relay hosts configured."; |
130 return; | 139 return; |
131 } | 140 } |
132 | 141 |
133 if (relay_token_.empty()){ | 142 if (relay_token_.empty()){ |
134 LOG(WARNING) << "No relay auth token found."; | 143 LOG(WARNING) << "No relay auth token found."; |
135 return; | 144 return; |
136 } | 145 } |
137 | 146 |
138 // Choose the next host to try. | 147 // Choose the next host to try. |
139 std::string host = relay_hosts_[attempts_ % relay_hosts_.size()]; | 148 std::string host = relay_hosts_[attempts_ % relay_hosts_.size()]; |
140 attempts_++; | 149 attempts_++; |
141 SendSessionRequest(host); | 150 |
| 151 DCHECK(!username().empty()); |
| 152 DCHECK(!password().empty()); |
| 153 std::string url = "https://" + host + "/create_session?username=" + |
| 154 net::EscapeUrlEncodedData(username(), false) + |
| 155 "&password=" + |
| 156 net::EscapeUrlEncodedData(password(), false) + "&sn=1"; |
| 157 scoped_ptr<UrlRequest> url_request = |
| 158 transport_context_->url_request_factory()->CreateUrlRequest(url); |
| 159 url_request->AddHeader("X-Talk-Google-Relay-Auth: " + relay_token()); |
| 160 url_request->AddHeader("X-Google-Relay-Auth: " + relay_token()); |
| 161 url_request->AddHeader("X-Stream-Type: chromoting"); |
| 162 url_request->Start(base::Bind(&PortAllocatorSession::OnSessionRequestResult, |
| 163 base::Unretained(this))); |
| 164 url_requests_.insert(std::move(url_request)); |
142 } | 165 } |
143 | 166 |
144 std::string PortAllocatorSessionBase::GetSessionRequestUrl() { | 167 void PortAllocatorSession::OnSessionRequestResult( |
145 ASSERT(!username().empty()); | 168 const UrlRequest::Result& result) { |
146 ASSERT(!password().empty()); | 169 if (!result.success || result.status != net::HTTP_OK) { |
147 return "/create_session?username=" + | 170 LOG(WARNING) << "Received error when allocating relay session: " |
148 net::EscapeUrlEncodedData(username(), false) + "&password=" + | 171 << result.status; |
149 net::EscapeUrlEncodedData(password(), false); | 172 TryCreateRelaySession(); |
150 } | 173 return; |
| 174 } |
151 | 175 |
152 void PortAllocatorSessionBase::ReceiveSessionResponse( | 176 StringMap map = ParseMap(result.response_body); |
153 const std::string& response) { | |
154 StringMap map = ParseMap(response); | |
155 | 177 |
156 if (!username().empty() && map["username"] != username()) { | 178 if (!username().empty() && map["username"] != username()) { |
157 LOG(WARNING) << "Received unexpected username value from relay server."; | 179 LOG(WARNING) << "Received unexpected username value from relay server."; |
158 } | 180 } |
159 if (!password().empty() && map["password"] != password()) { | 181 if (!password().empty() && map["password"] != password()) { |
160 LOG(WARNING) << "Received unexpected password value from relay server."; | 182 LOG(WARNING) << "Received unexpected password value from relay server."; |
161 } | 183 } |
162 | 184 |
163 cricket::ServerAddresses hosts; | 185 cricket::ServerAddresses hosts; |
164 for (const auto& host : stun_hosts_) { | 186 for (const auto& host : stun_hosts_) { |
(...skipping 14 matching lines...) Expand all Loading... |
179 relay_config.ports.push_back( | 201 relay_config.ports.push_back( |
180 cricket::ProtocolAddress(address, cricket::PROTO_UDP)); | 202 cricket::ProtocolAddress(address, cricket::PROTO_UDP)); |
181 config->AddRelay(relay_config); | 203 config->AddRelay(relay_config); |
182 } | 204 } |
183 | 205 |
184 ConfigReady(config); | 206 ConfigReady(config); |
185 } | 207 } |
186 | 208 |
187 } // namespace protocol | 209 } // namespace protocol |
188 } // namespace remoting | 210 } // namespace remoting |
OLD | NEW |