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

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
« no previous file with comments | « remoting/client/plugin/pepper_network_manager.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // 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 to perform if sendto() fails with |error|.
37 ErrorAction GetErrorAction(int error) {
38 switch (error) {
39 // UDP is connectionless, so we may receive ICMP unreachable or reset errors
40 // for previous sends to different addresses.
41 case PP_ERROR_ADDRESS_UNREACHABLE:
42 case PP_ERROR_CONNECTION_RESET:
43 return ERROR_ACTION_RETRY;
44
45 // Target address is invalid. The socket is still usable for different
46 // target addresses and the error can be ignored.
47 case PP_ERROR_ADDRESS_INVALID:
48 return ERROR_ACTION_IGNORE;
49
50 // May be returned when the packet is blocked by local firewall (see
51 // https://code.google.com/p/webrtc/issues/detail?id=1207). The firewall may
52 // still allow us to send to other addresses, so ignore the error for this
53 // particular send.
54 case PP_ERROR_NOACCESS:
55 return ERROR_ACTION_IGNORE;
56
57 // Indicates that the buffer in the network adapter is full, so drop this
58 // packet and assume the socket is still usable.
59 case PP_ERROR_NOMEMORY:
60 return ERROR_ACTION_IGNORE;
61
62 default:
63 return ERROR_ACTION_FAIL;
64 }
65 }
66
29 class UdpPacketSocket : public talk_base::AsyncPacketSocket { 67 class UdpPacketSocket : public talk_base::AsyncPacketSocket {
30 public: 68 public:
31 explicit UdpPacketSocket(const pp::InstanceHandle& instance); 69 explicit UdpPacketSocket(const pp::InstanceHandle& instance);
32 virtual ~UdpPacketSocket(); 70 virtual ~UdpPacketSocket();
33 71
34 // |min_port| and |max_port| are set to zero if the port number 72 // |min_port| and |max_port| are set to zero if the port number
35 // should be assigned by the OS. 73 // should be assigned by the OS.
36 bool Init(const talk_base::SocketAddress& local_address, 74 bool Init(const talk_base::SocketAddress& local_address,
37 int min_port, 75 int min_port,
38 int max_port); 76 int max_port);
(...skipping 15 matching lines...) Expand all
54 virtual void SetError(int error) OVERRIDE; 92 virtual void SetError(int error) OVERRIDE;
55 93
56 private: 94 private:
57 struct PendingPacket { 95 struct PendingPacket {
58 PendingPacket(const void* buffer, 96 PendingPacket(const void* buffer,
59 int buffer_size, 97 int buffer_size,
60 const pp::NetAddress& address); 98 const pp::NetAddress& address);
61 99
62 scoped_refptr<net::IOBufferWithSize> data; 100 scoped_refptr<net::IOBufferWithSize> data;
63 pp::NetAddress address; 101 pp::NetAddress address;
102 bool retried;
64 }; 103 };
65 104
66 void OnBindCompleted(int error); 105 void OnBindCompleted(int error);
67 106
68 void DoSend(); 107 void DoSend();
69 void OnSendCompleted(int result); 108 void OnSendCompleted(int result);
70 109
71 void DoRead(); 110 void DoRead();
72 void OnReadCompleted(int result, pp::NetAddress address); 111 void OnReadCompleted(int result, pp::NetAddress address);
73 void HandleReadResult(int result, pp::NetAddress address); 112 void HandleReadResult(int result, pp::NetAddress address);
(...skipping 21 matching lines...) Expand all
95 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_; 134 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_;
96 135
97 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); 136 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket);
98 }; 137 };
99 138
100 UdpPacketSocket::PendingPacket::PendingPacket( 139 UdpPacketSocket::PendingPacket::PendingPacket(
101 const void* buffer, 140 const void* buffer,
102 int buffer_size, 141 int buffer_size,
103 const pp::NetAddress& address) 142 const pp::NetAddress& address)
104 : data(new net::IOBufferWithSize(buffer_size)), 143 : data(new net::IOBufferWithSize(buffer_size)),
105 address(address) { 144 address(address),
145 retried(true) {
106 memcpy(data->data(), buffer, buffer_size); 146 memcpy(data->data(), buffer, buffer_size);
107 } 147 }
108 148
109 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance) 149 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance)
110 : instance_(instance), 150 : instance_(instance),
111 socket_(instance), 151 socket_(instance),
112 state_(STATE_CLOSED), 152 state_(STATE_CLOSED),
113 error_(0), 153 error_(0),
114 min_port_(0), 154 min_port_(0),
115 max_port_(0), 155 max_port_(0),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 ++min_port_; 210 ++min_port_;
171 pp::NetAddress pp_local_address; 211 pp::NetAddress pp_local_address;
172 if (SocketAddressToPpNetAddressWithPort( 212 if (SocketAddressToPpNetAddressWithPort(
173 instance_, local_address_, &pp_local_address, min_port_)) { 213 instance_, local_address_, &pp_local_address, min_port_)) {
174 pp::CompletionCallback callback = 214 pp::CompletionCallback callback =
175 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); 215 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted);
176 int result = socket_.Bind(pp_local_address, callback); 216 int result = socket_.Bind(pp_local_address, callback);
177 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 217 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
178 } 218 }
179 } else { 219 } else {
180 LOG(ERROR) << "Failed to bind UDP socket: " << result; 220 LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString()
221 << ", error: " << result;
181 } 222 }
182 } 223 }
183 224
184 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const { 225 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const {
185 DCHECK_EQ(state_, STATE_BOUND); 226 DCHECK_EQ(state_, STATE_BOUND);
186 return local_address_; 227 return local_address_;
187 } 228 }
188 229
189 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const { 230 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const {
190 // UDP sockets are not connected - this method should never be called. 231 // 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) { 315 if (result == PP_ERROR_ABORTED) {
275 // Send is aborted when the socket is being destroyed. 316 // Send is aborted when the socket is being destroyed.
276 // |send_queue_| may be already destroyed, it's not safe to access 317 // |send_queue_| may be already destroyed, it's not safe to access
277 // it here. 318 // it here.
278 return; 319 return;
279 } 320 }
280 321
281 send_pending_ = false; 322 send_pending_ = false;
282 323
283 if (result < 0) { 324 if (result < 0) {
284 LOG(ERROR) << "Send failed on a UDP socket: " << result; 325 ErrorAction action = GetErrorAction(result);
326 switch (action) {
327 case ERROR_ACTION_FAIL:
328 LOG(ERROR) << "Send failed on a UDP socket: " << result;
329 error_ = EINVAL;
330 return;
285 331
286 // OS (e.g. OSX) may return EHOSTUNREACH when the peer has the 332 case ERROR_ACTION_RETRY:
287 // same subnet address as the local host but connected to a 333 // Retry resending only once.
288 // different network. That error must be ingored because the 334 if (!send_queue_.front().retried) {
289 // socket may still be useful for other ICE canidadates (e.g. for 335 send_queue_.front().retried = true;
290 // STUN candidates with a different address). Unfortunately pepper 336 DoSend();
291 // interface currently returns PP_ERROR_FAILED for any error (see 337 return;
292 // crbug.com/136406). It's not possible to distinguish that case 338 }
293 // from other errors and so we have to ingore all of them. This 339 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 340
301 // error_ = EINVAL; 341 case ERROR_ACTION_IGNORE:
302 // return; 342 break;
343 }
303 } 344 }
304 345
305 send_queue_size_ -= send_queue_.front().data->size(); 346 send_queue_size_ -= send_queue_.front().data->size();
306 send_queue_.pop_front(); 347 send_queue_.pop_front();
307 DoSend(); 348 DoSend();
308 } 349 }
309 350
310 void UdpPacketSocket::DoRead() { 351 void UdpPacketSocket::DoRead() {
311 receive_buffer_.resize(kReceiveBufferSize); 352 receive_buffer_.resize(kReceiveBufferSize);
312 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = 353 pp::CompletionCallbackWithOutput<pp::NetAddress> callback =
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 return NULL; 417 return NULL;
377 } 418 }
378 419
379 talk_base::AsyncResolverInterface* 420 talk_base::AsyncResolverInterface*
380 PepperPacketSocketFactory::CreateAsyncResolver() { 421 PepperPacketSocketFactory::CreateAsyncResolver() {
381 NOTREACHED(); 422 NOTREACHED();
382 return NULL; 423 return NULL;
383 } 424 }
384 425
385 } // namespace remoting 426 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/plugin/pepper_network_manager.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698