Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/client/plugin/pepper_port_allocator.h" | 5 #include "remoting/client/plugin/pepper_port_allocator.h" |
| 6 | 6 |
| 7 #include "base/string_number_conversions.h" | 7 #include "base/string_number_conversions.h" |
| 8 #include "net/base/net_util.h" | |
| 8 #include "ppapi/c/pp_errors.h" | 9 #include "ppapi/c/pp_errors.h" |
| 9 #include "ppapi/cpp/completion_callback.h" | 10 #include "ppapi/cpp/completion_callback.h" |
| 11 #include "ppapi/cpp/private/host_resolver_private.h" | |
| 10 #include "ppapi/cpp/url_loader.h" | 12 #include "ppapi/cpp/url_loader.h" |
| 11 #include "ppapi/cpp/url_request_info.h" | 13 #include "ppapi/cpp/url_request_info.h" |
| 12 #include "ppapi/cpp/url_response_info.h" | 14 #include "ppapi/cpp/url_response_info.h" |
| 13 #include "remoting/client/plugin/pepper_network_manager.h" | 15 #include "remoting/client/plugin/pepper_network_manager.h" |
| 14 #include "remoting/client/plugin/pepper_packet_socket_factory.h" | 16 #include "remoting/client/plugin/pepper_packet_socket_factory.h" |
| 17 #include "remoting/client/plugin/pepper_util.h" | |
| 15 | 18 |
| 16 namespace remoting { | 19 namespace remoting { |
| 17 | 20 |
| 18 namespace { | 21 namespace { |
| 19 | 22 |
| 23 // URL used to create a relay session. | |
| 24 const char kCreateRelaySessionURL[] = "/create_session"; | |
| 25 | |
| 20 // Read buffer we allocate per read when reading response from | 26 // Read buffer we allocate per read when reading response from |
| 21 // URLLoader. Normally the response from URL loader is smaller than 1kB. | 27 // URLLoader. Normally the response from URL loader is smaller than 1kB. |
| 22 const int kReadSize = 1024; | 28 const int kReadSize = 1024; |
| 23 | 29 |
| 24 class PepperPortAllocatorSession | 30 class PepperPortAllocatorSession |
| 25 : public cricket::HttpPortAllocatorSessionBase { | 31 : public cricket::HttpPortAllocatorSessionBase { |
| 26 public: | 32 public: |
| 27 PepperPortAllocatorSession( | 33 PepperPortAllocatorSession( |
| 28 cricket::HttpPortAllocatorBase* allocator, | 34 cricket::HttpPortAllocatorBase* allocator, |
| 29 const std::string& channel_name, | 35 const std::string& channel_name, |
| 30 int component, | 36 int component, |
| 31 const std::vector<talk_base::SocketAddress>& stun_hosts, | 37 const std::vector<talk_base::SocketAddress>& stun_hosts, |
| 32 const std::vector<std::string>& relay_hosts, | 38 const std::vector<std::string>& relay_hosts, |
| 33 const std::string& relay, | 39 const std::string& relay_token, |
| 34 const pp::InstanceHandle& instance); | 40 const pp::InstanceHandle& instance); |
| 35 virtual ~PepperPortAllocatorSession(); | 41 virtual ~PepperPortAllocatorSession(); |
| 36 | 42 |
| 37 // cricket::HttpPortAllocatorBase overrides. | 43 // cricket::HttpPortAllocatorBase overrides. |
| 38 virtual void ConfigReady(cricket::PortConfiguration* config) OVERRIDE; | 44 virtual void ConfigReady(cricket::PortConfiguration* config) OVERRIDE; |
| 45 virtual void GetPortConfigurations() OVERRIDE; | |
| 39 virtual void SendSessionRequest(const std::string& host, int port) OVERRIDE; | 46 virtual void SendSessionRequest(const std::string& host, int port) OVERRIDE; |
| 40 | 47 |
| 41 private: | 48 private: |
| 42 // Callback handlers for pp::URLLoader. | 49 // Callback handlers for Pepper APIs. |
| 50 static void HostResolverCallback(void* user_data, int32_t result); | |
| 43 static void UrlLoaderOpenCallback(void* user_data, int32_t result); | 51 static void UrlLoaderOpenCallback(void* user_data, int32_t result); |
| 44 static void UrlLoaderReadCallback(void* user_data, int32_t result); | 52 static void UrlLoaderReadCallback(void* user_data, int32_t result); |
| 45 | 53 |
| 54 void ResolveStunServerAddress(); | |
| 55 void OnStunAddressResolved(int32_t result); | |
| 56 void OnStunResolutionFinished(); | |
| 57 | |
| 46 void OnUrlOpened(int32_t result); | 58 void OnUrlOpened(int32_t result); |
| 47 void ReadResponseBody(); | 59 void ReadResponseBody(); |
| 48 void OnResponseBodyRead(int32_t result); | 60 void OnResponseBodyRead(int32_t result); |
| 49 | 61 |
| 50 pp::InstanceHandle instance_; | 62 pp::InstanceHandle instance_; |
| 51 | 63 |
| 52 scoped_ptr<pp::URLLoader> url_loader_; | 64 pp::HostResolverPrivate stun_address_resolver_; |
| 53 std::vector<char> body_; | 65 talk_base::SocketAddress unresolved_stun_address_; |
| 66 talk_base::SocketAddress stun_address_; | |
| 67 bool stun_address_resolved_; | |
|
Wez
2012/05/15 23:11:29
Why do you need |unresolved_stun_address_| and |st
Sergey Ulanov
2012/05/16 00:22:30
Removed both unresolved_stun_address_ and stun_add
| |
| 68 int stun_port_; | |
| 69 | |
| 70 scoped_ptr<pp::URLLoader> relay_url_loader_; | |
| 71 std::vector<char> relay_response_body_; | |
| 72 bool relay_response_received_; | |
| 54 | 73 |
| 55 DISALLOW_COPY_AND_ASSIGN(PepperPortAllocatorSession); | 74 DISALLOW_COPY_AND_ASSIGN(PepperPortAllocatorSession); |
| 56 }; | 75 }; |
| 57 | 76 |
| 58 PepperPortAllocatorSession::PepperPortAllocatorSession( | 77 PepperPortAllocatorSession::PepperPortAllocatorSession( |
| 59 cricket::HttpPortAllocatorBase* allocator, | 78 cricket::HttpPortAllocatorBase* allocator, |
| 60 const std::string& channel_name, | 79 const std::string& channel_name, |
| 61 int component, | 80 int component, |
| 62 const std::vector<talk_base::SocketAddress>& stun_hosts, | 81 const std::vector<talk_base::SocketAddress>& stun_hosts, |
| 63 const std::vector<std::string>& relay_hosts, | 82 const std::vector<std::string>& relay_hosts, |
| 64 const std::string& relay, | 83 const std::string& relay_token, |
| 65 const pp::InstanceHandle& instance) | 84 const pp::InstanceHandle& instance) |
| 66 : HttpPortAllocatorSessionBase( | 85 : cricket::HttpPortAllocatorSessionBase( |
| 67 allocator, channel_name, component, stun_hosts, relay_hosts, relay, ""), | 86 allocator, channel_name, component, stun_hosts, |
| 68 instance_(instance) { | 87 relay_hosts, relay_token, ""), |
| 88 instance_(instance), | |
| 89 stun_address_resolver_(instance_), | |
| 90 stun_address_resolved_(false), | |
| 91 stun_port_(0), | |
| 92 relay_response_received_(false) { | |
| 93 set_flags(cricket::PORTALLOCATOR_DISABLE_TCP); | |
|
Wez
2012/05/15 23:11:29
This doesn't look related to this CL's description
Sergey Ulanov
2012/05/16 00:22:30
Updated the description.
| |
| 94 if (stun_hosts.size() > 0) | |
| 95 unresolved_stun_address_ = stun_hosts[0]; | |
| 69 } | 96 } |
| 70 | 97 |
| 71 PepperPortAllocatorSession::~PepperPortAllocatorSession() { | 98 PepperPortAllocatorSession::~PepperPortAllocatorSession() { |
| 72 } | 99 } |
| 73 | 100 |
| 74 void PepperPortAllocatorSession::ConfigReady( | 101 void PepperPortAllocatorSession::ConfigReady( |
| 75 cricket::PortConfiguration* config) { | 102 cricket::PortConfiguration* config) { |
| 103 if (config->stun_address.IsUnresolved()) { | |
| 104 // Replace stun address with the resolved IP address. | |
| 105 config->stun_address = stun_address_; | |
| 106 } | |
| 107 | |
| 76 // Filter out non-UDP relay ports, so that we don't try using TCP. | 108 // Filter out non-UDP relay ports, so that we don't try using TCP. |
| 77 for (cricket::PortConfiguration::RelayList::iterator relay = | 109 for (cricket::PortConfiguration::RelayList::iterator relay = |
| 78 config->relays.begin(); relay != config->relays.end(); ++relay) { | 110 config->relays.begin(); relay != config->relays.end(); ++relay) { |
| 79 cricket::PortConfiguration::PortList filtered_ports; | 111 cricket::PortConfiguration::PortList filtered_ports; |
| 80 for (cricket::PortConfiguration::PortList::iterator port = | 112 for (cricket::PortConfiguration::PortList::iterator port = |
| 81 relay->ports.begin(); port != relay->ports.end(); ++port) { | 113 relay->ports.begin(); port != relay->ports.end(); ++port) { |
| 82 if (port->proto == cricket::PROTO_UDP) { | 114 if (port->proto == cricket::PROTO_UDP) { |
| 83 filtered_ports.push_back(*port); | 115 filtered_ports.push_back(*port); |
| 84 } | 116 } |
| 85 } | 117 } |
| 86 relay->ports = filtered_ports; | 118 relay->ports = filtered_ports; |
| 87 } | 119 } |
| 88 cricket::BasicPortAllocatorSession::ConfigReady(config); | 120 cricket::BasicPortAllocatorSession::ConfigReady(config); |
| 89 } | 121 } |
| 90 | 122 |
| 123 void PepperPortAllocatorSession::GetPortConfigurations() { | |
| 124 // Add an empty configuration synchronously, so a local connection | |
| 125 // can be started immediately. | |
| 126 ConfigReady(new cricket::PortConfiguration(talk_base::SocketAddress())); | |
| 127 | |
| 128 ResolveStunServerAddress(); | |
| 129 TryCreateRelaySession(); | |
| 130 } | |
| 131 | |
| 132 void PepperPortAllocatorSession::ResolveStunServerAddress() { | |
| 133 if (unresolved_stun_address_.IsNil()) { | |
| 134 OnStunResolutionFinished(); | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 if (!unresolved_stun_address_.IsUnresolved()) { | |
| 139 stun_address_ = unresolved_stun_address_; | |
| 140 OnStunResolutionFinished(); | |
| 141 return; | |
| 142 } | |
| 143 | |
| 144 std::string hostname = unresolved_stun_address_.hostname(); | |
| 145 uint16 port = unresolved_stun_address_.port(); | |
| 146 | |
| 147 PP_HostResolver_Private_Hint hint; | |
| 148 hint.flags = 0; | |
| 149 hint.family = PP_NETADDRESSFAMILY_IPV4; | |
| 150 int result = stun_address_resolver_.Resolve( | |
| 151 hostname, port, hint, pp::CompletionCallback( | |
| 152 &PepperPortAllocatorSession::HostResolverCallback, this)); | |
| 153 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | |
| 154 } | |
| 155 | |
| 156 void PepperPortAllocatorSession::OnStunAddressResolved(int32_t result) { | |
| 157 if (result < 0) { | |
| 158 LOG(ERROR) << "Failed to resolve stun address " | |
| 159 << unresolved_stun_address_.hostname() << ": " << result; | |
| 160 OnStunResolutionFinished(); | |
| 161 return; | |
| 162 } | |
| 163 | |
| 164 if (!stun_address_resolver_.GetSize()) { | |
| 165 LOG(WARNING) << "Received 0 addresses for stun server " | |
| 166 << unresolved_stun_address_.hostname(); | |
| 167 OnStunResolutionFinished(); | |
| 168 return; | |
| 169 } | |
| 170 | |
| 171 PP_NetAddress_Private address; | |
| 172 if (!stun_address_resolver_.GetNetAddress(0, &address) || | |
| 173 !PpAddressToSocketAddress(address, &stun_address_)) { | |
| 174 LOG(ERROR) << "Failed to get address for STUN server " | |
| 175 << unresolved_stun_address_.hostname(); | |
| 176 OnStunResolutionFinished(); | |
| 177 return; | |
| 178 } | |
| 179 | |
| 180 OnStunResolutionFinished(); | |
| 181 } | |
| 182 | |
| 183 void PepperPortAllocatorSession::OnStunResolutionFinished() { | |
| 184 stun_address_resolved_ = true; | |
| 185 if (!stun_address_.IsNil()) | |
|
Wez
2012/05/15 23:11:29
|!stun_address_.IsUnresolved()|?
Wez
2012/05/15 23:11:29
Use { } consistently with the other if(), below.
Sergey Ulanov
2012/05/16 00:22:30
STUN address may not be set. IsUnresolved returns
Sergey Ulanov
2012/05/16 00:22:30
Done.
Wez
2012/05/16 00:51:53
OK; consider adding a DCHECK() or even CHECK() for
Sergey Ulanov
2012/05/16 01:02:16
Done. Actually we don't need this method anymore,
| |
| 186 ConfigReady(new cricket::PortConfiguration(stun_address_)); | |
| 187 | |
| 188 if (relay_response_received_) { | |
|
Wez
2012/05/15 23:11:29
This never gets set anywhere. Do you actually nee
Sergey Ulanov
2012/05/16 00:22:30
It should be set in OnResponseBodyRead(). Fixed no
| |
| 189 ReceiveSessionResponse(std::string(relay_response_body_.begin(), | |
| 190 relay_response_body_.end())); | |
| 191 } | |
| 192 } | |
| 193 | |
| 91 void PepperPortAllocatorSession::SendSessionRequest( | 194 void PepperPortAllocatorSession::SendSessionRequest( |
| 92 const std::string& host, | 195 const std::string& host, |
| 93 int port) { | 196 int port) { |
| 94 url_loader_.reset(new pp::URLLoader(instance_)); | 197 relay_url_loader_.reset(new pp::URLLoader(instance_)); |
| 95 pp::URLRequestInfo request_info(instance_); | 198 pp::URLRequestInfo request_info(instance_); |
| 96 std::string url = "https://" + host + ":" + base::IntToString(port) + | 199 std::string url = "https://" + host + ":" + base::IntToString(port) + |
| 97 GetSessionRequestUrl() + "&sn=1"; | 200 GetSessionRequestUrl() + "&sn=1"; |
| 98 request_info.SetURL(url); | 201 request_info.SetURL(url); |
| 99 request_info.SetMethod("GET"); | 202 request_info.SetMethod("GET"); |
| 100 std::stringstream headers; | 203 std::stringstream headers; |
| 101 headers << "X-Talk-Google-Relay-Auth: " << relay_token() << "\n\r"; | 204 headers << "X-Talk-Google-Relay-Auth: " << relay_token() << "\n\r"; |
| 102 headers << "X-Google-Relay-Auth: " << relay_token() << "\n\r"; | 205 headers << "X-Google-Relay-Auth: " << relay_token() << "\n\r"; |
| 103 headers << "X-StreamType: " << channel_name() << "\n\r"; | 206 headers << "X-StreamType: " << channel_name() << "\n\r"; |
| 104 request_info.SetHeaders(headers.str()); | 207 request_info.SetHeaders(headers.str()); |
| 105 | 208 |
| 106 int result = url_loader_->Open(request_info, pp::CompletionCallback( | 209 int result = relay_url_loader_->Open(request_info, pp::CompletionCallback( |
| 107 &PepperPortAllocatorSession::UrlLoaderOpenCallback, this)); | 210 &PepperPortAllocatorSession::UrlLoaderOpenCallback, this)); |
| 108 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | 211 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); |
| 109 } | 212 } |
| 110 | 213 |
| 111 void PepperPortAllocatorSession::OnUrlOpened(int32_t result) { | 214 void PepperPortAllocatorSession::OnUrlOpened(int32_t result) { |
| 112 if (result == PP_ERROR_ABORTED) | 215 if (result == PP_ERROR_ABORTED) |
| 113 return; | 216 return; |
| 114 | 217 |
| 115 if (result < 0) { | 218 if (result < 0) { |
| 116 LOG(WARNING) << "URLLoader failed: " << result; | 219 LOG(WARNING) << "URLLoader failed: " << result; |
| 117 // Retry creating session. | 220 // Retry creating session. |
| 118 TryCreateRelaySession(); | 221 TryCreateRelaySession(); |
| 119 return; | 222 return; |
| 120 } | 223 } |
| 121 | 224 |
| 122 pp::URLResponseInfo response = url_loader_->GetResponseInfo(); | 225 pp::URLResponseInfo response = relay_url_loader_->GetResponseInfo(); |
| 123 DCHECK(!response.is_null()); | 226 DCHECK(!response.is_null()); |
| 124 if (response.GetStatusCode() != 200) { | 227 if (response.GetStatusCode() != 200) { |
| 125 LOG(WARNING) << "Received HTTP status code " << response.GetStatusCode(); | 228 LOG(WARNING) << "Received HTTP status code " << response.GetStatusCode(); |
| 126 // Retry creating session. | 229 // Retry creating session. |
| 127 TryCreateRelaySession(); | 230 TryCreateRelaySession(); |
| 128 return; | 231 return; |
| 129 } | 232 } |
| 130 | 233 |
| 131 body_.clear(); | 234 relay_response_body_.clear(); |
| 132 ReadResponseBody(); | 235 ReadResponseBody(); |
| 133 } | 236 } |
| 134 | 237 |
| 135 void PepperPortAllocatorSession::ReadResponseBody() { | 238 void PepperPortAllocatorSession::ReadResponseBody() { |
| 136 int pos = body_.size(); | 239 int pos = relay_response_body_.size(); |
| 137 body_.resize(pos + kReadSize); | 240 relay_response_body_.resize(pos + kReadSize); |
| 138 int result = url_loader_->ReadResponseBody( | 241 int result = relay_url_loader_->ReadResponseBody( |
| 139 &body_[pos], kReadSize, pp::CompletionCallback( | 242 &relay_response_body_[pos], kReadSize, pp::CompletionCallback( |
| 140 &PepperPortAllocatorSession::UrlLoaderReadCallback, this)); | 243 &PepperPortAllocatorSession::UrlLoaderReadCallback, this)); |
| 141 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | 244 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); |
| 142 } | 245 } |
| 143 | 246 |
| 144 void PepperPortAllocatorSession::OnResponseBodyRead(int32_t result) { | 247 void PepperPortAllocatorSession::OnResponseBodyRead(int32_t result) { |
| 145 if (result == PP_ERROR_ABORTED) | 248 if (result == PP_ERROR_ABORTED) |
| 146 return; | 249 return; |
| 147 | 250 |
| 148 if (result < 0) { | 251 if (result < 0) { |
| 149 LOG(WARNING) << "Failed to read HTTP response body when " | 252 LOG(WARNING) << "Failed to read HTTP response body when " |
| 150 "creating relay session: " << result; | 253 "creating relay session: " << result; |
| 151 // Retry creating session. | 254 // Retry creating session. |
| 152 TryCreateRelaySession(); | 255 TryCreateRelaySession(); |
| 153 return; | 256 return; |
| 154 } | 257 } |
| 155 | 258 |
| 156 // Resize the buffer in case we've read less than was requested. | 259 // Resize the buffer in case we've read less than was requested. |
| 157 CHECK_LE(result, kReadSize); | 260 CHECK_LE(result, kReadSize); |
| 158 CHECK_GE(static_cast<int>(body_.size()), kReadSize); | 261 CHECK_GE(static_cast<int>(relay_response_body_.size()), kReadSize); |
| 159 body_.resize(body_.size() - kReadSize + result); | 262 relay_response_body_.resize(relay_response_body_.size() - kReadSize + result); |
| 160 | 263 |
| 161 if (result == 0) { | 264 if (result == 0) { |
| 162 // Finished reading the response. | 265 // Finished reading the response. Submit it to |
| 163 ReceiveSessionResponse(std::string(body_.begin(), body_.end())); | 266 // HttpPortAllocatorSessionBase only after we've resolved STUN |
| 267 // address. This is necessary because STUN and Relay parameters | |
| 268 // are stored together in PortConfiguration and | |
| 269 // ReceiveSessionResponse() doesn't save relay session | |
| 270 // configuration for the case we resolve STUN address later. | |
| 271 // | |
| 272 // TODO(sergeyu): Refactor HttpPortAllocatorSessionBase to fix this. | |
| 273 if (stun_address_resolved_) { | |
| 274 ReceiveSessionResponse(std::string(relay_response_body_.begin(), | |
| 275 relay_response_body_.end())); | |
| 276 } | |
| 164 return; | 277 return; |
| 165 } | 278 } |
| 166 | 279 |
| 167 ReadResponseBody(); | 280 ReadResponseBody(); |
| 168 } | 281 } |
| 169 | 282 |
| 170 // static | 283 // static |
| 284 void PepperPortAllocatorSession::HostResolverCallback( | |
| 285 void* user_data, | |
| 286 int32_t result) { | |
| 287 PepperPortAllocatorSession* object = | |
| 288 static_cast<PepperPortAllocatorSession*>(user_data); | |
| 289 object->OnStunAddressResolved(result); | |
| 290 } | |
| 291 | |
| 292 // static | |
| 171 void PepperPortAllocatorSession::UrlLoaderOpenCallback( | 293 void PepperPortAllocatorSession::UrlLoaderOpenCallback( |
| 172 void* user_data, | 294 void* user_data, |
| 173 int32_t result) { | 295 int32_t result) { |
| 174 PepperPortAllocatorSession* object = | 296 PepperPortAllocatorSession* object = |
| 175 static_cast<PepperPortAllocatorSession*>(user_data); | 297 static_cast<PepperPortAllocatorSession*>(user_data); |
| 176 object->OnUrlOpened(result); | 298 object->OnUrlOpened(result); |
| 177 } | 299 } |
| 178 | 300 |
| 179 // static | 301 // static |
| 180 void PepperPortAllocatorSession::UrlLoaderReadCallback( | 302 void PepperPortAllocatorSession::UrlLoaderReadCallback( |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 208 network_manager_(network_manager.Pass()), | 330 network_manager_(network_manager.Pass()), |
| 209 socket_factory_(socket_factory.Pass()) { | 331 socket_factory_(socket_factory.Pass()) { |
| 210 } | 332 } |
| 211 | 333 |
| 212 PepperPortAllocator::~PepperPortAllocator() { | 334 PepperPortAllocator::~PepperPortAllocator() { |
| 213 } | 335 } |
| 214 | 336 |
| 215 cricket::PortAllocatorSession* PepperPortAllocator::CreateSession( | 337 cricket::PortAllocatorSession* PepperPortAllocator::CreateSession( |
| 216 const std::string& channel_name, | 338 const std::string& channel_name, |
| 217 int component) { | 339 int component) { |
| 218 return new PepperPortAllocatorSession( | 340 return new PepperPortAllocatorSession( |
| 219 this, channel_name, component, stun_hosts(), | 341 this, channel_name, component, stun_hosts(), |
| 220 relay_hosts(), relay_token(), instance_); | 342 relay_hosts(), relay_token(), instance_); |
| 221 } | 343 } |
| 222 | 344 |
| 223 } // namespace remoting | 345 } // namespace remoting |
| OLD | NEW |