Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: remoting/client/plugin/pepper_packet_socket_factory.cc

Issue 336113002: Avoid error messages from UDP sockets in Chromoting client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // Returns true if |error| must be ignored when returned from sendto(). |retry|
30 // is set when sendto() should be called for the same packet again.
31 bool IsTransientError(int error, bool* retry) {
Wez 2014/06/17 01:13:26 Adding a "retry" member to a function called IsTra
Wez 2014/06/17 01:13:26 This would be cleaner as a GetErrorAction(int erro
Sergey Ulanov 2014/06/17 02:12:02 Done.
Sergey Ulanov 2014/06/17 02:12:03 Done.
32 // Following error codes are returned when one of the previous datagrams was
33 // sent to an unreachable address.
Wez 2014/06/17 01:13:26 What's the point of retrying if we tried to send t
Sergey Ulanov 2014/06/17 02:12:03 PP_ERROR_ADDRESS_UNREACHABLE and PP_ERROR_CONNECTI
34 if (error == PP_ERROR_ADDRESS_UNREACHABLE ||
35 error == PP_ERROR_ADDRESS_INVALID ||
36 error == PP_ERROR_CONNECTION_RESET) {
37 *retry = true;
38 return true;
39 }
40
41 // PP_ERROR_NOACCESS may be returned when the packet is blocked by local
42 // firewall (see https://code.google.com/p/webrtc/issues/detail?id=1207). The
43 // error is transient because the firewall may block only some target
44 // addresses.
45 //
46 // PP_ERROR_NOMEMORY indicates that the buffer in the network adapter is full.
47 if (error == PP_ERROR_NOACCESS || error == PP_ERROR_NOMEMORY) {
48 *retry = false;
49 return true;
50 }
51
52 return false;
53 }
54
29 class UdpPacketSocket : public talk_base::AsyncPacketSocket { 55 class UdpPacketSocket : public talk_base::AsyncPacketSocket {
30 public: 56 public:
31 explicit UdpPacketSocket(const pp::InstanceHandle& instance); 57 explicit UdpPacketSocket(const pp::InstanceHandle& instance);
32 virtual ~UdpPacketSocket(); 58 virtual ~UdpPacketSocket();
33 59
34 // |min_port| and |max_port| are set to zero if the port number 60 // |min_port| and |max_port| are set to zero if the port number
35 // should be assigned by the OS. 61 // should be assigned by the OS.
36 bool Init(const talk_base::SocketAddress& local_address, 62 bool Init(const talk_base::SocketAddress& local_address,
37 int min_port, 63 int min_port,
38 int max_port); 64 int max_port);
(...skipping 15 matching lines...) Expand all
54 virtual void SetError(int error) OVERRIDE; 80 virtual void SetError(int error) OVERRIDE;
55 81
56 private: 82 private:
57 struct PendingPacket { 83 struct PendingPacket {
58 PendingPacket(const void* buffer, 84 PendingPacket(const void* buffer,
59 int buffer_size, 85 int buffer_size,
60 const pp::NetAddress& address); 86 const pp::NetAddress& address);
61 87
62 scoped_refptr<net::IOBufferWithSize> data; 88 scoped_refptr<net::IOBufferWithSize> data;
63 pp::NetAddress address; 89 pp::NetAddress address;
90 bool retried;
64 }; 91 };
65 92
66 void OnBindCompleted(int error); 93 void OnBindCompleted(int error);
67 94
68 void DoSend(); 95 void DoSend();
69 void OnSendCompleted(int result); 96 void OnSendCompleted(int result);
70 97
71 void DoRead(); 98 void DoRead();
72 void OnReadCompleted(int result, pp::NetAddress address); 99 void OnReadCompleted(int result, pp::NetAddress address);
73 void HandleReadResult(int result, pp::NetAddress address); 100 void HandleReadResult(int result, pp::NetAddress address);
(...skipping 21 matching lines...) Expand all
95 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_; 122 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_;
96 123
97 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); 124 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket);
98 }; 125 };
99 126
100 UdpPacketSocket::PendingPacket::PendingPacket( 127 UdpPacketSocket::PendingPacket::PendingPacket(
101 const void* buffer, 128 const void* buffer,
102 int buffer_size, 129 int buffer_size,
103 const pp::NetAddress& address) 130 const pp::NetAddress& address)
104 : data(new net::IOBufferWithSize(buffer_size)), 131 : data(new net::IOBufferWithSize(buffer_size)),
105 address(address) { 132 address(address),
133 retried(true) {
106 memcpy(data->data(), buffer, buffer_size); 134 memcpy(data->data(), buffer, buffer_size);
107 } 135 }
108 136
109 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance) 137 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance)
110 : instance_(instance), 138 : instance_(instance),
111 socket_(instance), 139 socket_(instance),
112 state_(STATE_CLOSED), 140 state_(STATE_CLOSED),
113 error_(0), 141 error_(0),
114 min_port_(0), 142 min_port_(0),
115 max_port_(0), 143 max_port_(0),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 ++min_port_; 198 ++min_port_;
171 pp::NetAddress pp_local_address; 199 pp::NetAddress pp_local_address;
172 if (SocketAddressToPpNetAddressWithPort( 200 if (SocketAddressToPpNetAddressWithPort(
173 instance_, local_address_, &pp_local_address, min_port_)) { 201 instance_, local_address_, &pp_local_address, min_port_)) {
174 pp::CompletionCallback callback = 202 pp::CompletionCallback callback =
175 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); 203 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted);
176 int result = socket_.Bind(pp_local_address, callback); 204 int result = socket_.Bind(pp_local_address, callback);
177 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 205 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
178 } 206 }
179 } else { 207 } else {
180 LOG(ERROR) << "Failed to bind UDP socket: " << result; 208 LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString()
209 << ", error: " << result;
181 } 210 }
182 } 211 }
183 212
184 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const { 213 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const {
185 DCHECK_EQ(state_, STATE_BOUND); 214 DCHECK_EQ(state_, STATE_BOUND);
186 return local_address_; 215 return local_address_;
187 } 216 }
188 217
189 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const { 218 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const {
190 // UDP sockets are not connected - this method should never be called. 219 // UDP sockets are not connected - this method should never be called.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 if (result == PP_ERROR_ABORTED) { 303 if (result == PP_ERROR_ABORTED) {
275 // Send is aborted when the socket is being destroyed. 304 // Send is aborted when the socket is being destroyed.
276 // |send_queue_| may be already destroyed, it's not safe to access 305 // |send_queue_| may be already destroyed, it's not safe to access
277 // it here. 306 // it here.
278 return; 307 return;
279 } 308 }
280 309
281 send_pending_ = false; 310 send_pending_ = false;
282 311
283 if (result < 0) { 312 if (result < 0) {
284 LOG(ERROR) << "Send failed on a UDP socket: " << result; 313 bool retry;
314 if (!IsTransientError(result, &retry)) {
315 LOG(ERROR) << "Send failed on a UDP socket: " << result;
316 return;
317 }
285 318
286 // OS (e.g. OSX) may return EHOSTUNREACH when the peer has the 319 // If this is a transient error and we haven't tried resending the packet
287 // same subnet address as the local host but connected to a 320 // yet, then try resending it.
288 // different network. That error must be ingored because the 321 if (retry && !send_queue_.front().retried) {
289 // socket may still be useful for other ICE canidadates (e.g. for 322 send_queue_.front().retried = true;
290 // STUN candidates with a different address). Unfortunately pepper 323 DoSend();
291 // interface currently returns PP_ERROR_FAILED for any error (see 324 return;
292 // crbug.com/136406). It's not possible to distinguish that case 325 }
293 // from other errors and so we have to ingore all of them. This
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
301 // error_ = EINVAL;
302 // return;
303 } 326 }
304 327
305 send_queue_size_ -= send_queue_.front().data->size(); 328 send_queue_size_ -= send_queue_.front().data->size();
306 send_queue_.pop_front(); 329 send_queue_.pop_front();
307 DoSend(); 330 DoSend();
308 } 331 }
309 332
310 void UdpPacketSocket::DoRead() { 333 void UdpPacketSocket::DoRead() {
311 receive_buffer_.resize(kReceiveBufferSize); 334 receive_buffer_.resize(kReceiveBufferSize);
312 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = 335 pp::CompletionCallbackWithOutput<pp::NetAddress> callback =
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 return NULL; 399 return NULL;
377 } 400 }
378 401
379 talk_base::AsyncResolverInterface* 402 talk_base::AsyncResolverInterface*
380 PepperPacketSocketFactory::CreateAsyncResolver() { 403 PepperPacketSocketFactory::CreateAsyncResolver() {
381 NOTREACHED(); 404 NOTREACHED();
382 return NULL; 405 return NULL;
383 } 406 }
384 407
385 } // namespace remoting 408 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698