Update parsing of dumpsys batterystats
[chromium-blink-merge.git] / remoting / client / plugin / pepper_packet_socket_factory.cc
blob6669266afeab87ffaf1e3ab53529a4f527f87716
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
3 // found in the LICENSE file.
5 #include "remoting/client/plugin/pepper_packet_socket_factory.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "ppapi/cpp/net_address.h"
12 #include "ppapi/cpp/udp_socket.h"
13 #include "ppapi/utility/completion_callback_factory.h"
14 #include "remoting/client/plugin/pepper_util.h"
15 #include "remoting/protocol/socket_util.h"
16 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
18 namespace remoting {
20 namespace {
22 // Size of the buffer to allocate for RecvFrom().
23 const int kReceiveBufferSize = 65536;
25 // 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 // Pepper's UDP API can handle it. This maximum should never be
28 // reached under normal conditions.
29 const int kMaxSendBufferSize = 256 * 1024;
31 int PepperErrorToNetError(int error) {
32 switch (error) {
33 case PP_OK:
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;
69 case PP_ERROR_ADDRESS_UNREACHABLE:
70 return net::ERR_ADDRESS_UNREACHABLE;
71 case PP_ERROR_CONNECTION_TIMEDOUT:
72 return net::ERR_CONNECTION_TIMED_OUT;
73 case PP_ERROR_NOACCESS:
74 return net::ERR_NETWORK_ACCESS_DENIED;
75 case PP_ERROR_MESSAGE_TOO_BIG:
76 return net::ERR_MSG_TOO_BIG;
77 case PP_ERROR_ADDRESS_IN_USE:
78 return net::ERR_ADDRESS_IN_USE;
79 default:
80 return net::ERR_FAILED;
84 class UdpPacketSocket : public talk_base::AsyncPacketSocket {
85 public:
86 explicit UdpPacketSocket(const pp::InstanceHandle& instance);
87 virtual ~UdpPacketSocket();
89 // |min_port| and |max_port| are set to zero if the port number
90 // should be assigned by the OS.
91 bool Init(const talk_base::SocketAddress& local_address,
92 int min_port,
93 int max_port);
95 // talk_base::AsyncPacketSocket interface.
96 virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE;
97 virtual talk_base::SocketAddress GetRemoteAddress() const OVERRIDE;
98 virtual int Send(const void* data, size_t data_size,
99 const talk_base::PacketOptions& options) OVERRIDE;
100 virtual int SendTo(const void* data,
101 size_t data_size,
102 const talk_base::SocketAddress& address,
103 const talk_base::PacketOptions& options) OVERRIDE;
104 virtual int Close() OVERRIDE;
105 virtual State GetState() const OVERRIDE;
106 virtual int GetOption(talk_base::Socket::Option opt, int* value) OVERRIDE;
107 virtual int SetOption(talk_base::Socket::Option opt, int value) OVERRIDE;
108 virtual int GetError() const OVERRIDE;
109 virtual void SetError(int error) OVERRIDE;
111 private:
112 struct PendingPacket {
113 PendingPacket(const void* buffer,
114 int buffer_size,
115 const pp::NetAddress& address);
117 scoped_refptr<net::IOBufferWithSize> data;
118 pp::NetAddress address;
119 bool retried;
122 void OnBindCompleted(int error);
124 void DoSend();
125 void OnSendCompleted(int result);
127 void DoRead();
128 void OnReadCompleted(int result, pp::NetAddress address);
129 void HandleReadResult(int result, pp::NetAddress address);
131 pp::InstanceHandle instance_;
133 pp::UDPSocket socket_;
135 State state_;
136 int error_;
138 talk_base::SocketAddress local_address_;
140 // Used to scan ports when necessary. Both values are set to 0 when
141 // the port number is assigned by OS.
142 uint16_t min_port_;
143 uint16_t max_port_;
145 std::vector<char> receive_buffer_;
147 bool send_pending_;
148 std::list<PendingPacket> send_queue_;
149 int send_queue_size_;
151 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_;
153 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket);
156 UdpPacketSocket::PendingPacket::PendingPacket(
157 const void* buffer,
158 int buffer_size,
159 const pp::NetAddress& address)
160 : data(new net::IOBufferWithSize(buffer_size)),
161 address(address),
162 retried(true) {
163 memcpy(data->data(), buffer, buffer_size);
166 UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance)
167 : instance_(instance),
168 socket_(instance),
169 state_(STATE_CLOSED),
170 error_(0),
171 min_port_(0),
172 max_port_(0),
173 send_pending_(false),
174 send_queue_size_(0),
175 callback_factory_(this) {
178 UdpPacketSocket::~UdpPacketSocket() {
179 Close();
182 bool UdpPacketSocket::Init(const talk_base::SocketAddress& local_address,
183 int min_port,
184 int max_port) {
185 if (socket_.is_null()) {
186 return false;
189 local_address_ = local_address;
190 max_port_ = max_port;
191 min_port_ = min_port;
193 pp::NetAddress pp_local_address;
194 if (!SocketAddressToPpNetAddressWithPort(
195 instance_, local_address_, &pp_local_address, min_port_)) {
196 return false;
199 pp::CompletionCallback callback =
200 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted);
201 int result = socket_.Bind(pp_local_address, callback);
202 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
203 state_ = STATE_BINDING;
205 return true;
208 void UdpPacketSocket::OnBindCompleted(int result) {
209 DCHECK(state_ == STATE_BINDING || state_ == STATE_CLOSED);
211 if (result == PP_ERROR_ABORTED) {
212 // Socket is being destroyed while binding.
213 return;
216 if (result == PP_OK) {
217 pp::NetAddress address = socket_.GetBoundAddress();
218 PpNetAddressToSocketAddress(address, &local_address_);
219 state_ = STATE_BOUND;
220 SignalAddressReady(this, local_address_);
221 DoRead();
222 return;
225 if (min_port_ < max_port_) {
226 // Try to bind to the next available port.
227 ++min_port_;
228 pp::NetAddress pp_local_address;
229 if (SocketAddressToPpNetAddressWithPort(
230 instance_, local_address_, &pp_local_address, min_port_)) {
231 pp::CompletionCallback callback =
232 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted);
233 int result = socket_.Bind(pp_local_address, callback);
234 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
236 } else {
237 LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString()
238 << ", error: " << result;
242 talk_base::SocketAddress UdpPacketSocket::GetLocalAddress() const {
243 DCHECK_EQ(state_, STATE_BOUND);
244 return local_address_;
247 talk_base::SocketAddress UdpPacketSocket::GetRemoteAddress() const {
248 // UDP sockets are not connected - this method should never be called.
249 NOTREACHED();
250 return talk_base::SocketAddress();
253 int UdpPacketSocket::Send(const void* data, size_t data_size,
254 const talk_base::PacketOptions& options) {
255 // UDP sockets are not connected - this method should never be called.
256 NOTREACHED();
257 return EWOULDBLOCK;
260 int UdpPacketSocket::SendTo(const void* data,
261 size_t data_size,
262 const talk_base::SocketAddress& address,
263 const talk_base::PacketOptions& options) {
264 if (state_ != STATE_BOUND) {
265 // TODO(sergeyu): StunPort may try to send stun request before we
266 // are bound. Fix that problem and change this to DCHECK.
267 return EINVAL;
270 if (error_ != 0) {
271 return error_;
274 pp::NetAddress pp_address;
275 if (!SocketAddressToPpNetAddress(instance_, address, &pp_address)) {
276 return EINVAL;
279 if (send_queue_size_ >= kMaxSendBufferSize) {
280 return EWOULDBLOCK;
283 send_queue_.push_back(PendingPacket(data, data_size, pp_address));
284 send_queue_size_ += data_size;
285 DoSend();
286 return data_size;
289 int UdpPacketSocket::Close() {
290 state_ = STATE_CLOSED;
291 socket_.Close();
292 return 0;
295 talk_base::AsyncPacketSocket::State UdpPacketSocket::GetState() const {
296 return state_;
299 int UdpPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) {
300 // Options are not supported for Pepper UDP sockets.
301 return -1;
304 int UdpPacketSocket::SetOption(talk_base::Socket::Option opt, int value) {
305 // Options are not supported for Pepper UDP sockets.
306 return -1;
309 int UdpPacketSocket::GetError() const {
310 return error_;
313 void UdpPacketSocket::SetError(int error) {
314 error_ = error;
317 void UdpPacketSocket::DoSend() {
318 if (send_pending_ || send_queue_.empty())
319 return;
321 pp::CompletionCallback callback =
322 callback_factory_.NewCallback(&UdpPacketSocket::OnSendCompleted);
323 int result = socket_.SendTo(
324 send_queue_.front().data->data(), send_queue_.front().data->size(),
325 send_queue_.front().address,
326 callback);
327 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
328 send_pending_ = true;
331 void UdpPacketSocket::OnSendCompleted(int result) {
332 if (result == PP_ERROR_ABORTED) {
333 // Send is aborted when the socket is being destroyed.
334 // |send_queue_| may be already destroyed, it's not safe to access
335 // it here.
336 return;
339 send_pending_ = false;
341 if (result < 0) {
342 int net_error = PepperErrorToNetError(result);
343 SocketErrorAction action = GetSocketErrorAction(net_error);
344 switch (action) {
345 case SOCKET_ERROR_ACTION_FAIL:
346 LOG(ERROR) << "Send failed on a UDP socket: " << result;
347 error_ = EINVAL;
348 return;
350 case SOCKET_ERROR_ACTION_RETRY:
351 // Retry resending only once.
352 if (!send_queue_.front().retried) {
353 send_queue_.front().retried = true;
354 DoSend();
355 return;
357 break;
359 case SOCKET_ERROR_ACTION_IGNORE:
360 break;
364 send_queue_size_ -= send_queue_.front().data->size();
365 send_queue_.pop_front();
366 DoSend();
369 void UdpPacketSocket::DoRead() {
370 receive_buffer_.resize(kReceiveBufferSize);
371 pp::CompletionCallbackWithOutput<pp::NetAddress> callback =
372 callback_factory_.NewCallbackWithOutput(
373 &UdpPacketSocket::OnReadCompleted);
374 int result =
375 socket_.RecvFrom(&receive_buffer_[0], receive_buffer_.size(), callback);
376 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
379 void UdpPacketSocket::OnReadCompleted(int result, pp::NetAddress address) {
380 HandleReadResult(result, address);
381 if (result > 0) {
382 DoRead();
386 void UdpPacketSocket::HandleReadResult(int result, pp::NetAddress address) {
387 if (result > 0) {
388 talk_base::SocketAddress socket_address;
389 PpNetAddressToSocketAddress(address, &socket_address);
390 SignalReadPacket(this, &receive_buffer_[0], result, socket_address,
391 talk_base::CreatePacketTime(0));
392 } else if (result != PP_ERROR_ABORTED) {
393 LOG(ERROR) << "Received error when reading from UDP socket: " << result;
397 } // namespace
399 PepperPacketSocketFactory::PepperPacketSocketFactory(
400 const pp::InstanceHandle& instance)
401 : pp_instance_(instance) {
404 PepperPacketSocketFactory::~PepperPacketSocketFactory() {
407 talk_base::AsyncPacketSocket* PepperPacketSocketFactory::CreateUdpSocket(
408 const talk_base::SocketAddress& local_address,
409 int min_port,
410 int max_port) {
411 scoped_ptr<UdpPacketSocket> result(new UdpPacketSocket(pp_instance_));
412 if (!result->Init(local_address, min_port, max_port))
413 return NULL;
414 return result.release();
417 talk_base::AsyncPacketSocket* PepperPacketSocketFactory::CreateServerTcpSocket(
418 const talk_base::SocketAddress& local_address,
419 int min_port,
420 int max_port,
421 int opts) {
422 // We don't use TCP sockets for remoting connections.
423 NOTREACHED();
424 return NULL;
427 talk_base::AsyncPacketSocket* PepperPacketSocketFactory::CreateClientTcpSocket(
428 const talk_base::SocketAddress& local_address,
429 const talk_base::SocketAddress& remote_address,
430 const talk_base::ProxyInfo& proxy_info,
431 const std::string& user_agent,
432 int opts) {
433 // We don't use TCP sockets for remoting connections.
434 NOTREACHED();
435 return NULL;
438 talk_base::AsyncResolverInterface*
439 PepperPacketSocketFactory::CreateAsyncResolver() {
440 NOTREACHED();
441 return NULL;
444 } // namespace remoting