Index: remoting/client/plugin/pepper_packet_socket_factory.cc |
diff --git a/remoting/client/plugin/pepper_packet_socket_factory.cc b/remoting/client/plugin/pepper_packet_socket_factory.cc |
index 90d7c61bd94cdb5b345ec0cf456be00776c1d66b..f29ef651f5c0120f85e3ea5198bd3f92d6e81327 100644 |
--- a/remoting/client/plugin/pepper_packet_socket_factory.cc |
+++ b/remoting/client/plugin/pepper_packet_socket_factory.cc |
@@ -26,6 +26,32 @@ const int kReceiveBufferSize = 65536; |
// reached under normal conditions. |
const int kMaxSendBufferSize = 256 * 1024; |
+// Returns true if |error| must be ignored when returned from sendto(). |retry| |
+// is set when sendto() should be called for the same packet again. |
+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.
|
+ // Following error codes are returned when one of the previous datagrams was |
+ // 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
|
+ if (error == PP_ERROR_ADDRESS_UNREACHABLE || |
+ error == PP_ERROR_ADDRESS_INVALID || |
+ error == PP_ERROR_CONNECTION_RESET) { |
+ *retry = true; |
+ return true; |
+ } |
+ |
+ // PP_ERROR_NOACCESS may be returned when the packet is blocked by local |
+ // firewall (see https://code.google.com/p/webrtc/issues/detail?id=1207). The |
+ // error is transient because the firewall may block only some target |
+ // addresses. |
+ // |
+ // PP_ERROR_NOMEMORY indicates that the buffer in the network adapter is full. |
+ if (error == PP_ERROR_NOACCESS || error == PP_ERROR_NOMEMORY) { |
+ *retry = false; |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
class UdpPacketSocket : public talk_base::AsyncPacketSocket { |
public: |
explicit UdpPacketSocket(const pp::InstanceHandle& instance); |
@@ -61,6 +87,7 @@ class UdpPacketSocket : public talk_base::AsyncPacketSocket { |
scoped_refptr<net::IOBufferWithSize> data; |
pp::NetAddress address; |
+ bool retried; |
}; |
void OnBindCompleted(int error); |
@@ -102,7 +129,8 @@ UdpPacketSocket::PendingPacket::PendingPacket( |
int buffer_size, |
const pp::NetAddress& address) |
: data(new net::IOBufferWithSize(buffer_size)), |
- address(address) { |
+ address(address), |
+ retried(true) { |
memcpy(data->data(), buffer, buffer_size); |
} |
@@ -177,7 +205,8 @@ void UdpPacketSocket::OnBindCompleted(int result) { |
DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); |
} |
} else { |
- LOG(ERROR) << "Failed to bind UDP socket: " << result; |
+ LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString() |
+ << ", error: " << result; |
} |
} |
@@ -281,25 +310,19 @@ void UdpPacketSocket::OnSendCompleted(int result) { |
send_pending_ = false; |
if (result < 0) { |
- LOG(ERROR) << "Send failed on a UDP socket: " << result; |
- |
- // OS (e.g. OSX) may return EHOSTUNREACH when the peer has the |
- // same subnet address as the local host but connected to a |
- // different network. That error must be ingored because the |
- // socket may still be useful for other ICE canidadates (e.g. for |
- // STUN candidates with a different address). Unfortunately pepper |
- // interface currently returns PP_ERROR_FAILED for any error (see |
- // crbug.com/136406). It's not possible to distinguish that case |
- // from other errors and so we have to ingore all of them. This |
- // behavior matchers the libjingle's AsyncUDPSocket used by the |
- // host. |
- // |
- // TODO(sergeyu): Once implementation of the Pepper UDP interface |
- // is fixed, uncomment the code below, but ignore |
- // host-unreacheable error. |
- |
- // error_ = EINVAL; |
- // return; |
+ bool retry; |
+ if (!IsTransientError(result, &retry)) { |
+ LOG(ERROR) << "Send failed on a UDP socket: " << result; |
+ return; |
+ } |
+ |
+ // If this is a transient error and we haven't tried resending the packet |
+ // yet, then try resending it. |
+ if (retry && !send_queue_.front().retried) { |
+ send_queue_.front().retried = true; |
+ DoSend(); |
+ return; |
+ } |
} |
send_queue_size_ -= send_queue_.front().data->size(); |