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/jingle_glue/chromium_socket_factory.h" | 5 #include "remoting/jingle_glue/chromium_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 "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "jingle/glue/utils.h" | 10 #include "jingle/glue/utils.h" |
11 #include "net/base/io_buffer.h" | 11 #include "net/base/io_buffer.h" |
12 #include "net/base/ip_endpoint.h" | 12 #include "net/base/ip_endpoint.h" |
13 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
14 #include "net/udp/udp_server_socket.h" | 14 #include "net/udp/udp_server_socket.h" |
| 15 #include "remoting/jingle_glue/socket_util.h" |
15 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" | 16 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" |
16 #include "third_party/libjingle/source/talk/base/nethelpers.h" | 17 #include "third_party/libjingle/source/talk/base/nethelpers.h" |
17 | 18 |
18 namespace remoting { | 19 namespace remoting { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 // Size of the buffer to allocate for RecvFrom(). | 23 // Size of the buffer to allocate for RecvFrom(). |
23 const int kReceiveBufferSize = 65536; | 24 const int kReceiveBufferSize = 65536; |
24 | 25 |
25 // Maximum amount of data in the send buffers. This is necessary to | 26 // Maximum amount of data in the send buffers. This is necessary to |
26 // prevent out-of-memory crashes if the caller sends data faster than | 27 // prevent out-of-memory crashes if the caller sends data faster than |
27 // Pepper's UDP API can handle it. This maximum should never be | 28 // Pepper's UDP API can handle it. This maximum should never be |
28 // reached under normal conditions. | 29 // reached under normal conditions. |
29 const int kMaxSendBufferSize = 256 * 1024; | 30 const int kMaxSendBufferSize = 256 * 1024; |
30 | 31 |
31 // Defines set of transient errors. These errors are ignored when we get them | |
32 // from sendto() calls. | |
33 bool IsTransientError(int error) { | |
34 return error == net::ERR_ADDRESS_UNREACHABLE || | |
35 error == net::ERR_ADDRESS_INVALID; | |
36 } | |
37 | |
38 class UdpPacketSocket : public talk_base::AsyncPacketSocket { | 32 class UdpPacketSocket : public talk_base::AsyncPacketSocket { |
39 public: | 33 public: |
40 UdpPacketSocket(); | 34 UdpPacketSocket(); |
41 virtual ~UdpPacketSocket(); | 35 virtual ~UdpPacketSocket(); |
42 | 36 |
43 bool Init(const talk_base::SocketAddress& local_address, | 37 bool Init(const talk_base::SocketAddress& local_address, |
44 int min_port, int max_port); | 38 int min_port, int max_port); |
45 | 39 |
46 // talk_base::AsyncPacketSocket interface. | 40 // talk_base::AsyncPacketSocket interface. |
47 virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE; | 41 virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE; |
(...skipping 11 matching lines...) Expand all Loading... |
59 virtual void SetError(int error) OVERRIDE; | 53 virtual void SetError(int error) OVERRIDE; |
60 | 54 |
61 private: | 55 private: |
62 struct PendingPacket { | 56 struct PendingPacket { |
63 PendingPacket(const void* buffer, | 57 PendingPacket(const void* buffer, |
64 int buffer_size, | 58 int buffer_size, |
65 const net::IPEndPoint& address); | 59 const net::IPEndPoint& address); |
66 | 60 |
67 scoped_refptr<net::IOBufferWithSize> data; | 61 scoped_refptr<net::IOBufferWithSize> data; |
68 net::IPEndPoint address; | 62 net::IPEndPoint address; |
| 63 bool retried; |
69 }; | 64 }; |
70 | 65 |
71 void OnBindCompleted(int error); | 66 void OnBindCompleted(int error); |
72 | 67 |
73 void DoSend(); | 68 void DoSend(); |
74 void OnSendCompleted(int result); | 69 void OnSendCompleted(int result); |
75 | 70 |
76 void DoRead(); | 71 void DoRead(); |
77 void OnReadCompleted(int result); | 72 void OnReadCompleted(int result); |
78 void HandleReadResult(int result); | 73 void HandleReadResult(int result); |
(...skipping 14 matching lines...) Expand all Loading... |
93 int send_queue_size_; | 88 int send_queue_size_; |
94 | 89 |
95 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); | 90 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); |
96 }; | 91 }; |
97 | 92 |
98 UdpPacketSocket::PendingPacket::PendingPacket( | 93 UdpPacketSocket::PendingPacket::PendingPacket( |
99 const void* buffer, | 94 const void* buffer, |
100 int buffer_size, | 95 int buffer_size, |
101 const net::IPEndPoint& address) | 96 const net::IPEndPoint& address) |
102 : data(new net::IOBufferWithSize(buffer_size)), | 97 : data(new net::IOBufferWithSize(buffer_size)), |
103 address(address) { | 98 address(address), |
| 99 retried(false) { |
104 memcpy(data->data(), buffer, buffer_size); | 100 memcpy(data->data(), buffer, buffer_size); |
105 } | 101 } |
106 | 102 |
107 UdpPacketSocket::UdpPacketSocket() | 103 UdpPacketSocket::UdpPacketSocket() |
108 : state_(STATE_CLOSED), | 104 : state_(STATE_CLOSED), |
109 error_(0), | 105 error_(0), |
110 send_pending_(false), | 106 send_pending_(false), |
111 send_queue_size_(0) { | 107 send_queue_size_(0) { |
112 } | 108 } |
113 | 109 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 send_pending_ = true; | 274 send_pending_ = true; |
279 } else { | 275 } else { |
280 OnSendCompleted(result); | 276 OnSendCompleted(result); |
281 } | 277 } |
282 } | 278 } |
283 | 279 |
284 void UdpPacketSocket::OnSendCompleted(int result) { | 280 void UdpPacketSocket::OnSendCompleted(int result) { |
285 send_pending_ = false; | 281 send_pending_ = false; |
286 | 282 |
287 if (result < 0) { | 283 if (result < 0) { |
288 if (!IsTransientError(result)) { | 284 SocketErrorAction action = GetSocketErrorAction(result); |
289 LOG(ERROR) << "Send failed on a UDP socket: " << result; | 285 switch (action) { |
290 error_ = EINVAL; | 286 case SOCKET_ERROR_ACTION_FAIL: |
291 return; | 287 LOG(ERROR) << "Send failed on a UDP socket: " << result; |
| 288 error_ = EINVAL; |
| 289 return; |
| 290 |
| 291 case SOCKET_ERROR_ACTION_RETRY: |
| 292 // Retry resending only once. |
| 293 if (!send_queue_.front().retried) { |
| 294 send_queue_.front().retried = true; |
| 295 DoSend(); |
| 296 return; |
| 297 } |
| 298 break; |
| 299 |
| 300 case SOCKET_ERROR_ACTION_IGNORE: |
| 301 break; |
292 } | 302 } |
293 } | 303 } |
294 | 304 |
295 // Don't need to worry about partial sends because this is a datagram | 305 // Don't need to worry about partial sends because this is a datagram |
296 // socket. | 306 // socket. |
297 send_queue_size_ -= send_queue_.front().data->size(); | 307 send_queue_size_ -= send_queue_.front().data->size(); |
298 send_queue_.pop_front(); | 308 send_queue_.pop_front(); |
299 DoSend(); | 309 DoSend(); |
300 } | 310 } |
301 | 311 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 NOTREACHED(); | 386 NOTREACHED(); |
377 return NULL; | 387 return NULL; |
378 } | 388 } |
379 | 389 |
380 talk_base::AsyncResolverInterface* | 390 talk_base::AsyncResolverInterface* |
381 ChromiumPacketSocketFactory::CreateAsyncResolver() { | 391 ChromiumPacketSocketFactory::CreateAsyncResolver() { |
382 return new talk_base::AsyncResolver(); | 392 return new talk_base::AsyncResolver(); |
383 } | 393 } |
384 | 394 |
385 } // namespace remoting | 395 } // namespace remoting |
OLD | NEW |