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 "net/base/net_errors.h" | |
10 #include "ppapi/cpp/net_address.h" | 11 #include "ppapi/cpp/net_address.h" |
11 #include "ppapi/cpp/udp_socket.h" | 12 #include "ppapi/cpp/udp_socket.h" |
12 #include "ppapi/utility/completion_callback_factory.h" | 13 #include "ppapi/utility/completion_callback_factory.h" |
13 #include "remoting/client/plugin/pepper_util.h" | 14 #include "remoting/client/plugin/pepper_util.h" |
15 #include "remoting/jingle_glue/socket_util.h" | |
14 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" | 16 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" |
15 | 17 |
16 namespace remoting { | 18 namespace remoting { |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 // Size of the buffer to allocate for RecvFrom(). | 22 // Size of the buffer to allocate for RecvFrom(). |
21 const int kReceiveBufferSize = 65536; | 23 const int kReceiveBufferSize = 65536; |
22 | 24 |
23 // Maximum amount of data in the send buffers. This is necessary to | 25 // 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 | 26 // 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 | 27 // Pepper's UDP API can handle it. This maximum should never be |
26 // reached under normal conditions. | 28 // reached under normal conditions. |
27 const int kMaxSendBufferSize = 256 * 1024; | 29 const int kMaxSendBufferSize = 256 * 1024; |
28 | 30 |
29 // Enum for different actions that can be taken after sendto() returns an error. | 31 int PepperErrorToNetError(int error) { |
Wez
2014/06/17 22:39:21
nit: Could this go into e.g. pepper_util.h?
Sergey Ulanov
2014/06/17 22:45:01
I don't think it's necessary because it's specific
| |
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) { | 32 switch (error) { |
39 // UDP is connectionless, so we may receive ICMP unreachable or reset errors | 33 case PP_OK: |
40 // for previous sends to different addresses. | 34 return net::OK; |
35 case PP_OK_COMPLETIONPENDING: | |
36 return net::ERR_IO_PENDING; | |
37 case PP_ERROR_ABORTED: | |
38 return net::ERR_ABORTED; | |
39 case PP_ERROR_BADARGUMENT: | |
40 return net::ERR_INVALID_ARGUMENT; | |
41 case PP_ERROR_FILENOTFOUND: | |
42 return net::ERR_FILE_NOT_FOUND; | |
43 case PP_ERROR_TIMEDOUT: | |
44 return net::ERR_TIMED_OUT; | |
45 case PP_ERROR_FILETOOBIG: | |
46 return net::ERR_FILE_TOO_BIG; | |
47 case PP_ERROR_NOTSUPPORTED: | |
48 return net::ERR_NOT_IMPLEMENTED; | |
49 case PP_ERROR_NOMEMORY: | |
50 return net::ERR_OUT_OF_MEMORY; | |
51 case PP_ERROR_FILEEXISTS: | |
52 return net::ERR_FILE_EXISTS; | |
53 case PP_ERROR_NOSPACE: | |
54 return net::ERR_FILE_NO_SPACE; | |
55 case PP_ERROR_CONNECTION_CLOSED: | |
56 return net::ERR_CONNECTION_CLOSED; | |
57 case PP_ERROR_CONNECTION_RESET: | |
58 return net::ERR_CONNECTION_RESET; | |
59 case PP_ERROR_CONNECTION_REFUSED: | |
60 return net::ERR_CONNECTION_REFUSED; | |
61 case PP_ERROR_CONNECTION_ABORTED: | |
62 return net::ERR_CONNECTION_ABORTED; | |
63 case PP_ERROR_CONNECTION_FAILED: | |
64 return net::ERR_CONNECTION_FAILED; | |
65 case PP_ERROR_NAME_NOT_RESOLVED: | |
66 return net::ERR_NAME_NOT_RESOLVED; | |
67 case PP_ERROR_ADDRESS_INVALID: | |
68 return net::ERR_ADDRESS_INVALID; | |
41 case PP_ERROR_ADDRESS_UNREACHABLE: | 69 case PP_ERROR_ADDRESS_UNREACHABLE: |
42 case PP_ERROR_CONNECTION_RESET: | 70 return net::ERR_ADDRESS_UNREACHABLE; |
43 return ERROR_ACTION_RETRY; | 71 case PP_ERROR_CONNECTION_TIMEDOUT: |
44 | 72 return net::ERR_CONNECTION_TIMED_OUT; |
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: | 73 case PP_ERROR_NOACCESS: |
55 return ERROR_ACTION_IGNORE; | 74 return net::ERR_NETWORK_ACCESS_DENIED; |
56 | 75 case PP_ERROR_MESSAGE_TOO_BIG: |
57 // Indicates that the buffer in the network adapter is full, so drop this | 76 return net::ERR_MSG_TOO_BIG; |
58 // packet and assume the socket is still usable. | 77 case PP_ERROR_ADDRESS_IN_USE: |
59 case PP_ERROR_NOMEMORY: | 78 return net::ERR_ADDRESS_IN_USE; |
60 return ERROR_ACTION_IGNORE; | |
61 | |
62 default: | 79 default: |
63 return ERROR_ACTION_FAIL; | 80 return net::ERR_FAILED; |
64 } | 81 } |
65 } | 82 } |
66 | 83 |
67 class UdpPacketSocket : public talk_base::AsyncPacketSocket { | 84 class UdpPacketSocket : public talk_base::AsyncPacketSocket { |
68 public: | 85 public: |
69 explicit UdpPacketSocket(const pp::InstanceHandle& instance); | 86 explicit UdpPacketSocket(const pp::InstanceHandle& instance); |
70 virtual ~UdpPacketSocket(); | 87 virtual ~UdpPacketSocket(); |
71 | 88 |
72 // |min_port| and |max_port| are set to zero if the port number | 89 // |min_port| and |max_port| are set to zero if the port number |
73 // should be assigned by the OS. | 90 // should be assigned by the OS. |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 if (result == PP_ERROR_ABORTED) { | 332 if (result == PP_ERROR_ABORTED) { |
316 // Send is aborted when the socket is being destroyed. | 333 // Send is aborted when the socket is being destroyed. |
317 // |send_queue_| may be already destroyed, it's not safe to access | 334 // |send_queue_| may be already destroyed, it's not safe to access |
318 // it here. | 335 // it here. |
319 return; | 336 return; |
320 } | 337 } |
321 | 338 |
322 send_pending_ = false; | 339 send_pending_ = false; |
323 | 340 |
324 if (result < 0) { | 341 if (result < 0) { |
325 ErrorAction action = GetErrorAction(result); | 342 int net_error = PepperErrorToNetError(result); |
343 SocketErrorAction action = GetSocketErrorAction(net_error); | |
326 switch (action) { | 344 switch (action) { |
327 case ERROR_ACTION_FAIL: | 345 case SOCKET_ERROR_ACTION_FAIL: |
328 LOG(ERROR) << "Send failed on a UDP socket: " << result; | 346 LOG(ERROR) << "Send failed on a UDP socket: " << result; |
329 error_ = EINVAL; | 347 error_ = EINVAL; |
330 return; | 348 return; |
331 | 349 |
332 case ERROR_ACTION_RETRY: | 350 case SOCKET_ERROR_ACTION_RETRY: |
333 // Retry resending only once. | 351 // Retry resending only once. |
334 if (!send_queue_.front().retried) { | 352 if (!send_queue_.front().retried) { |
335 send_queue_.front().retried = true; | 353 send_queue_.front().retried = true; |
336 DoSend(); | 354 DoSend(); |
337 return; | 355 return; |
338 } | 356 } |
339 break; | 357 break; |
340 | 358 |
341 case ERROR_ACTION_IGNORE: | 359 case SOCKET_ERROR_ACTION_IGNORE: |
342 break; | 360 break; |
343 } | 361 } |
344 } | 362 } |
345 | 363 |
346 send_queue_size_ -= send_queue_.front().data->size(); | 364 send_queue_size_ -= send_queue_.front().data->size(); |
347 send_queue_.pop_front(); | 365 send_queue_.pop_front(); |
348 DoSend(); | 366 DoSend(); |
349 } | 367 } |
350 | 368 |
351 void UdpPacketSocket::DoRead() { | 369 void UdpPacketSocket::DoRead() { |
352 receive_buffer_.resize(kReceiveBufferSize); | 370 receive_buffer_.resize(kReceiveBufferSize); |
353 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = | 371 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = |
354 callback_factory_.NewCallbackWithOutput( | 372 callback_factory_.NewCallbackWithOutput( |
355 &UdpPacketSocket::OnReadCompleted); | 373 &UdpPacketSocket::OnReadCompleted); |
356 int result = | 374 int result = |
357 socket_.RecvFrom(&receive_buffer_[0], receive_buffer_.size(), callback); | 375 socket_.RecvFrom(&receive_buffer_[0], receive_buffer_.size(), callback); |
358 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); | 376 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); |
359 } | 377 } |
360 | 378 |
361 void UdpPacketSocket::OnReadCompleted(int result, pp::NetAddress address) { | 379 void UdpPacketSocket::OnReadCompleted(int result, pp::NetAddress address) { |
362 HandleReadResult(result, address); | 380 HandleReadResult(result, address); |
363 if (result > 0) { | 381 if (result > 0) { |
364 DoRead(); | 382 DoRead(); |
365 } | 383 } |
366 } | 384 } |
367 | 385 |
368 void UdpPacketSocket::HandleReadResult(int result, pp::NetAddress address) { | 386 void UdpPacketSocket::HandleReadResult(int result, pp::NetAddress address) { |
369 if (result > 0) { | 387 if (result > 0) { |
370 talk_base::SocketAddress socket_address; | 388 talk_base::SocketAddress socket_address; |
371 PpNetAddressToSocketAddress(address, &socket_address); | 389 PpNetAddressToSocketAddress(address, &socket_address); |
372 SignalReadPacket(this, &receive_buffer_[0], result, socket_address, | 390 SignalReadPacket(this, &receive_buffer_[0], result, socket_address, |
373 talk_base::CreatePacketTime(0)); | 391 talk_base::CreatePacketTime(0)); |
374 } else if (result != PP_ERROR_ABORTED) { | 392 } else if (result != PP_ERROR_ABORTED) { |
375 LOG(ERROR) << "Received error when reading from UDP socket: " << result; | 393 LOG(ERROR) << "Received error when reading from UDP socket: " << result; |
376 } | 394 } |
377 } | 395 } |
378 | 396 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 return NULL; | 435 return NULL; |
418 } | 436 } |
419 | 437 |
420 talk_base::AsyncResolverInterface* | 438 talk_base::AsyncResolverInterface* |
421 PepperPacketSocketFactory::CreateAsyncResolver() { | 439 PepperPacketSocketFactory::CreateAsyncResolver() { |
422 NOTREACHED(); | 440 NOTREACHED(); |
423 return NULL; | 441 return NULL; |
424 } | 442 } |
425 | 443 |
426 } // namespace remoting | 444 } // namespace remoting |
OLD | NEW |