| 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 |