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_packet_socket_factory.h" | 5 #include "remoting/client/plugin/pepper_packet_socket_factory.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "net/base/io_buffer.h" | 9 #include "net/base/io_buffer.h" |
| 10 #include "ppapi/cpp/net_address.h" | 10 #include "ppapi/cpp/net_address.h" |
| 11 #include "ppapi/cpp/udp_socket.h" | 11 #include "ppapi/cpp/udp_socket.h" |
| 12 #include "ppapi/utility/completion_callback_factory.h" | 12 #include "ppapi/utility/completion_callback_factory.h" |
| 13 #include "remoting/client/plugin/pepper_util.h" | 13 #include "remoting/client/plugin/pepper_util.h" |
| 14 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" | 14 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" |
| 15 | 15 |
| 16 namespace remoting { | 16 namespace remoting { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 // Size of the buffer to allocate for RecvFrom(). | 20 // Size of the buffer to allocate for RecvFrom(). |
| 21 const int kReceiveBufferSize = 65536; | 21 const int kReceiveBufferSize = 65536; |
| 22 | 22 |
| 23 // Maximum amount of data in the send buffers. This is necessary to | 23 // Maximum amount of data in the send buffers. This is necessary to |
| 24 // prevent out-of-memory crashes if the caller sends data faster than | 24 // prevent out-of-memory crashes if the caller sends data faster than |
| 25 // Pepper's UDP API can handle it. This maximum should never be | 25 // Pepper's UDP API can handle it. This maximum should never be |
| 26 // reached under normal conditions. | 26 // reached under normal conditions. |
| 27 const int kMaxSendBufferSize = 256 * 1024; | 27 const int kMaxSendBufferSize = 256 * 1024; |
| 28 | 28 |
| 29 // Enum for different actions that can be taken after sendto() returns an error. | |
| 30 enum ErrorAction { | |
| 31 ERROR_ACTION_FAIL, | |
| 32 ERROR_ACTION_IGNORE, | |
| 33 ERROR_ACTION_RETRY, | |
| 34 }; | |
| 35 | |
| 36 // Returns ErrorAction that must be taken after |error| returned from sendto(). | |
|
Wez
2014/06/17 02:34:10
nit: is returned (which triggers line-wrap, so I'd
Sergey Ulanov
2014/06/17 02:54:13
Done.
| |
| 37 ErrorAction GetErrorAction(int error) { | |
| 38 switch (error) { | |
| 39 // These errors are returned when one of the previous datagrams was sent to | |
| 40 // an unreachable address. | |
|
Wez
2014/06/17 02:34:10
nit: Be explicit that the error could correspond t
Sergey Ulanov
2014/06/17 02:54:13
Done, though I think the previous comment is expli
| |
| 41 case PP_ERROR_ADDRESS_UNREACHABLE: | |
| 42 case PP_ERROR_CONNECTION_RESET: | |
| 43 return ERROR_ACTION_RETRY; | |
| 44 | |
| 45 // Target address is invalid. | |
| 46 case PP_ERROR_ADDRESS_INVALID: | |
| 47 return ERROR_ACTION_IGNORE; | |
|
Wez
2014/06/17 02:34:10
Again, it would be good to clarify why we want to
Sergey Ulanov
2014/06/17 02:54:13
Done.
| |
| 48 | |
| 49 // May be returned when the packet is blocked by local firewall (see | |
| 50 // https://code.google.com/p/webrtc/issues/detail?id=1207). The error is | |
| 51 // transient because the firewall may block only some target addresses. | |
|
Wez
2014/06/17 02:34:10
nit: Suggest for the second sentence "The firewall
Sergey Ulanov
2014/06/17 02:54:13
Done.
| |
| 52 case PP_ERROR_NOACCESS: | |
| 53 return ERROR_ACTION_IGNORE; | |
| 54 | |
| 55 // Indicates that the buffer in the network adapter is full. The socket is | |
| 56 // still usable. | |
|
Wez
2014/06/17 02:34:10
nit: Suggest extending second sentence ".... is fu
Sergey Ulanov
2014/06/17 02:54:13
Done.
| |
| 57 case PP_ERROR_NOMEMORY: | |
| 58 return ERROR_ACTION_IGNORE; | |
| 59 | |
| 60 default: | |
| 61 return ERROR_ACTION_FAIL; | |
| 62 } | |
| 63 } | |
| 64 | |
| 29 class UdpPacketSocket : public talk_base::AsyncPacketSocket { | 65 class UdpPacketSocket : public talk_base::AsyncPacketSocket { |
| 30 public: | 66 public: |
| 31 explicit UdpPacketSocket(const pp::InstanceHandle& instance); | 67 explicit UdpPacketSocket(const pp::InstanceHandle& instance); |
| 32 virtual ~UdpPacketSocket(); | 68 virtual ~UdpPacketSocket(); |
| 33 | 69 |
| 34 // |min_port| and |max_port| are set to zero if the port number | 70 // |min_port| and |max_port| are set to zero if the port number |
| 35 // should be assigned by the OS. | 71 // should be assigned by the OS. |
| 36 bool Init(const talk_base::SocketAddress& local_address, | 72 bool Init(const talk_base::SocketAddress& local_address, |
| 37 int min_port, | 73 int min_port, |
| 38 int max_port); | 74 int max_port); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 54 virtual void SetError(int error) OVERRIDE; | 90 virtual void SetError(int error) OVERRIDE; |
| 55 | 91 |
| 56 private: | 92 private: |
| 57 struct PendingPacket { | 93 struct PendingPacket { |
| 58 PendingPacket(const void* buffer, | 94 PendingPacket(const void* buffer, |
| 59 int buffer_size, | 95 int buffer_size, |
| 60 const pp::NetAddress& address); | 96 const pp::NetAddress& address); |
| 61 | 97 |
| 62 scoped_refptr<net::IOBufferWithSize> data; | 98 scoped_refptr<net::IOBufferWithSize> data; |
| 63 pp::NetAddress address; | 99 pp::NetAddress address; |
| 100 bool retried; | |
| 64 }; | 101 }; |
| 65 | 102 |
| 66 void OnBindCompleted(int error); | 103 void OnBindCompleted(int error); |
| 67 | 104 |
| 68 void DoSend(); | 105 void DoSend(); |
| 69 void OnSendCompleted(int result); | 106 void OnSendCompleted(int result); |
| 70 | 107 |
| 71 void DoRead(); | 108 void DoRead(); |
| 72 void OnReadCompleted(int result, pp::NetAddress address); | 109 void OnReadCompleted(int result, pp::NetAddress address); |
| 73 void HandleReadResult(int result, pp::NetAddress address); | 110 void HandleReadResult(int result, pp::NetAddress address); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 95 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_; | 132 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_; |
| 96 | 133 |
| 97 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); | 134 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); |
| 98 }; | 135 }; |
| 99 | 136 |
| 100 UdpPacketSocket::PendingPacket::PendingPacket( | 137 UdpPacketSocket::PendingPacket::PendingPacket( |
| 101 const void* buffer, | 138 const void* buffer, |
| 102 int buffer_size, | 139 int buffer_size, |
| 103 const pp::NetAddress& address) | 140 const pp::NetAddress& address) |
| 104 : data(new net::IOBufferWithSize(buffer_size)), | 141 : data(new net::IOBufferWithSize(buffer_size)), |
| 105 address(address) { | 142 address(address), |
| 143 retried(true) { | |
| 106 memcpy(data->data(), buffer, buffer_size); | 144 memcpy(data->data(), buffer, buffer_size); |
| 107 } | 145 } |
| 108 | 146 |
| 109 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance) | 147 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance) |
| 110 : instance_(instance), | 148 : instance_(instance), |
| 111 socket_(instance), | 149 socket_(instance), |
| 112 state_(STATE_CLOSED), | 150 state_(STATE_CLOSED), |
| 113 error_(0), | 151 error_(0), |
| 114 min_port_(0), | 152 min_port_(0), |
| 115 max_port_(0), | 153 max_port_(0), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 ++min_port_; | 208 ++min_port_; |
| 171 pp::NetAddress pp_local_address; | 209 pp::NetAddress pp_local_address; |
| 172 if (SocketAddressToPpNetAddressWithPort( | 210 if (SocketAddressToPpNetAddressWithPort( |
| 173 instance_, local_address_, &pp_local_address, min_port_)) { | 211 instance_, local_address_, &pp_local_address, min_port_)) { |
| 174 pp::CompletionCallback callback = | 212 pp::CompletionCallback callback = |
| 175 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); | 213 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); |
| 176 int result = socket_.Bind(pp_local_address, callback); | 214 int result = socket_.Bind(pp_local_address, callback); |
| 177 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | 215 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); |
| 178 } | 216 } |
| 179 } else { | 217 } else { |
| 180 LOG(ERROR) << "Failed to bind UDP socket: " << result; | 218 LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString() |
| 219 << ", error: " << result; | |
| 181 } | 220 } |
| 182 } | 221 } |
| 183 | 222 |
| 184 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const { | 223 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const { |
| 185 DCHECK_EQ(state_, STATE_BOUND); | 224 DCHECK_EQ(state_, STATE_BOUND); |
| 186 return local_address_; | 225 return local_address_; |
| 187 } | 226 } |
| 188 | 227 |
| 189 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const { | 228 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const { |
| 190 // UDP sockets are not connected - this method should never be called. | 229 // UDP sockets are not connected - this method should never be called. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 if (result == PP_ERROR_ABORTED) { | 313 if (result == PP_ERROR_ABORTED) { |
| 275 // Send is aborted when the socket is being destroyed. | 314 // Send is aborted when the socket is being destroyed. |
| 276 // |send_queue_| may be already destroyed, it's not safe to access | 315 // |send_queue_| may be already destroyed, it's not safe to access |
| 277 // it here. | 316 // it here. |
| 278 return; | 317 return; |
| 279 } | 318 } |
| 280 | 319 |
| 281 send_pending_ = false; | 320 send_pending_ = false; |
| 282 | 321 |
| 283 if (result < 0) { | 322 if (result < 0) { |
| 284 LOG(ERROR) << "Send failed on a UDP socket: " << result; | 323 ErrorAction action = GetErrorAction(result); |
| 324 switch (action) { | |
| 325 case ERROR_ACTION_FAIL: | |
| 326 LOG(ERROR) << "Send failed on a UDP socket: " << result; | |
| 327 error_ = EINVAL; | |
| 328 return; | |
| 285 | 329 |
| 286 // OS (e.g. OSX) may return EHOSTUNREACH when the peer has the | 330 case ERROR_ACTION_RETRY: |
| 287 // same subnet address as the local host but connected to a | 331 // Retry resending only once. |
| 288 // different network. That error must be ingored because the | 332 if (!send_queue_.front().retried) { |
| 289 // socket may still be useful for other ICE canidadates (e.g. for | 333 send_queue_.front().retried = true; |
| 290 // STUN candidates with a different address). Unfortunately pepper | 334 DoSend(); |
| 291 // interface currently returns PP_ERROR_FAILED for any error (see | 335 return; |
| 292 // crbug.com/136406). It's not possible to distinguish that case | 336 } |
| 293 // from other errors and so we have to ingore all of them. This | 337 break; |
| 294 // behavior matchers the libjingle's AsyncUDPSocket used by the | |
| 295 // host. | |
| 296 // | |
| 297 // TODO(sergeyu): Once implementation of the Pepper UDP interface | |
| 298 // is fixed, uncomment the code below, but ignore | |
| 299 // host-unreacheable error. | |
| 300 | 338 |
| 301 // error_ = EINVAL; | 339 case ERROR_ACTION_IGNORE: |
| 302 // return; | 340 break; |
| 341 } | |
| 303 } | 342 } |
| 304 | 343 |
| 305 send_queue_size_ -= send_queue_.front().data->size(); | 344 send_queue_size_ -= send_queue_.front().data->size(); |
| 306 send_queue_.pop_front(); | 345 send_queue_.pop_front(); |
| 307 DoSend(); | 346 DoSend(); |
| 308 } | 347 } |
| 309 | 348 |
| 310 void UdpPacketSocket::DoRead() { | 349 void UdpPacketSocket::DoRead() { |
| 311 receive_buffer_.resize(kReceiveBufferSize); | 350 receive_buffer_.resize(kReceiveBufferSize); |
| 312 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = | 351 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 376 return NULL; | 415 return NULL; |
| 377 } | 416 } |
| 378 | 417 |
| 379 talk_base::AsyncResolverInterface* | 418 talk_base::AsyncResolverInterface* |
| 380 PepperPacketSocketFactory::CreateAsyncResolver() { | 419 PepperPacketSocketFactory::CreateAsyncResolver() { |
| 381 NOTREACHED(); | 420 NOTREACHED(); |
| 382 return NULL; | 421 return NULL; |
| 383 } | 422 } |
| 384 | 423 |
| 385 } // namespace remoting | 424 } // namespace remoting |
| OLD | NEW |