pepper_packet_socket_factory.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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. 4 5#include "remoting/client/plugin/pepper_packet_socket_factory.h" 6 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_address_resolver.h" 15#include "remoting/client/plugin/pepper_util.h" 16#include "remoting/protocol/socket_util.h" 17#include "third_party/webrtc/base/asyncpacketsocket.h" 18#include "third_party/webrtc/base/nethelpers.h" 19 20namespace remoting { 21 22namespace { 23 24// Size of the buffer to allocate for RecvFrom(). 25const int kReceiveBufferSize = 65536; 26 27// Maximum amount of data in the send buffers. This is necessary to 28// prevent out-of-memory crashes if the caller sends data faster than 29// Pepper's UDP API can handle it. This maximum should never be 30// reached under normal conditions. 31const int kMaxSendBufferSize = 256 * 1024; 32 33int PepperErrorToNetError(int error) { 34 switch (error) { 35 case PP_OK: 36 return net::OK; 37 case PP_OK_COMPLETIONPENDING: 38 return net::ERR_IO_PENDING; 39 case PP_ERROR_ABORTED: 40 return net::ERR_ABORTED; 41 case PP_ERROR_BADARGUMENT: 42 return net::ERR_INVALID_ARGUMENT; 43 case PP_ERROR_FILENOTFOUND: 44 return net::ERR_FILE_NOT_FOUND; 45 case PP_ERROR_TIMEDOUT: 46 return net::ERR_TIMED_OUT; 47 case PP_ERROR_FILETOOBIG: 48 return net::ERR_FILE_TOO_BIG; 49 case PP_ERROR_NOTSUPPORTED: 50 return net::ERR_NOT_IMPLEMENTED; 51 case PP_ERROR_NOMEMORY: 52 return net::ERR_OUT_OF_MEMORY; 53 case PP_ERROR_FILEEXISTS: 54 return net::ERR_FILE_EXISTS; 55 case PP_ERROR_NOSPACE: 56 return net::ERR_FILE_NO_SPACE; 57 case PP_ERROR_CONNECTION_CLOSED: 58 return net::ERR_CONNECTION_CLOSED; 59 case PP_ERROR_CONNECTION_RESET: 60 return net::ERR_CONNECTION_RESET; 61 case PP_ERROR_CONNECTION_REFUSED: 62 return net::ERR_CONNECTION_REFUSED; 63 case PP_ERROR_CONNECTION_ABORTED: 64 return net::ERR_CONNECTION_ABORTED; 65 case PP_ERROR_CONNECTION_FAILED: 66 return net::ERR_CONNECTION_FAILED; 67 case PP_ERROR_NAME_NOT_RESOLVED: 68 return net::ERR_NAME_NOT_RESOLVED; 69 case PP_ERROR_ADDRESS_INVALID: 70 return net::ERR_ADDRESS_INVALID; 71 case PP_ERROR_ADDRESS_UNREACHABLE: 72 return net::ERR_ADDRESS_UNREACHABLE; 73 case PP_ERROR_CONNECTION_TIMEDOUT: 74 return net::ERR_CONNECTION_TIMED_OUT; 75 case PP_ERROR_NOACCESS: 76 return net::ERR_NETWORK_ACCESS_DENIED; 77 case PP_ERROR_MESSAGE_TOO_BIG: 78 return net::ERR_MSG_TOO_BIG; 79 case PP_ERROR_ADDRESS_IN_USE: 80 return net::ERR_ADDRESS_IN_USE; 81 default: 82 return net::ERR_FAILED; 83 } 84} 85 86class UdpPacketSocket : public rtc::AsyncPacketSocket { 87 public: 88 explicit UdpPacketSocket(const pp::InstanceHandle& instance); 89 virtual ~UdpPacketSocket(); 90 91 // |min_port| and |max_port| are set to zero if the port number 92 // should be assigned by the OS. 93 bool Init(const rtc::SocketAddress& local_address, 94 int min_port, 95 int max_port); 96 97 // rtc::AsyncPacketSocket interface. 98 virtual rtc::SocketAddress GetLocalAddress() const OVERRIDE; 99 virtual rtc::SocketAddress GetRemoteAddress() const OVERRIDE; 100 virtual int Send(const void* data, size_t data_size, 101 const rtc::PacketOptions& options) OVERRIDE; 102 virtual int SendTo(const void* data, 103 size_t data_size, 104 const rtc::SocketAddress& address, 105 const rtc::PacketOptions& options) OVERRIDE; 106 virtual int Close() OVERRIDE; 107 virtual State GetState() const OVERRIDE; 108 virtual int GetOption(rtc::Socket::Option opt, int* value) OVERRIDE; 109 virtual int SetOption(rtc::Socket::Option opt, int value) OVERRIDE; 110 virtual int GetError() const OVERRIDE; 111 virtual void SetError(int error) OVERRIDE; 112 113 private: 114 struct PendingPacket { 115 PendingPacket(const void* buffer, 116 int buffer_size, 117 const pp::NetAddress& address); 118 119 scoped_refptr<net::IOBufferWithSize> data; 120 pp::NetAddress address; 121 bool retried; 122 }; 123 124 void OnBindCompleted(int error); 125 126 void DoSend(); 127 void OnSendCompleted(int result); 128 129 void DoRead(); 130 void OnReadCompleted(int result, pp::NetAddress address); 131 void HandleReadResult(int result, pp::NetAddress address); 132 133 pp::InstanceHandle instance_; 134 135 pp::UDPSocket socket_; 136 137 State state_; 138 int error_; 139 140 rtc::SocketAddress local_address_; 141 142 // Used to scan ports when necessary. Both values are set to 0 when 143 // the port number is assigned by OS. 144 uint16_t min_port_; 145 uint16_t max_port_; 146 147 std::vector<char> receive_buffer_; 148 149 bool send_pending_; 150 std::list<PendingPacket> send_queue_; 151 int send_queue_size_; 152 153 pp::CompletionCallbackFactory<UdpPacketSocket> callback_factory_; 154 155 DISALLOW_COPY_AND_ASSIGN(UdpPacketSocket); 156}; 157 158UdpPacketSocket::PendingPacket::PendingPacket( 159 const void* buffer, 160 int buffer_size, 161 const pp::NetAddress& address) 162 : data(new net::IOBufferWithSize(buffer_size)), 163 address(address), 164 retried(true) { 165 memcpy(data->data(), buffer, buffer_size); 166} 167 168UdpPacketSocket::UdpPacketSocket(const pp::InstanceHandle& instance) 169 : instance_(instance), 170 socket_(instance), 171 state_(STATE_CLOSED), 172 error_(0), 173 min_port_(0), 174 max_port_(0), 175 send_pending_(false), 176 send_queue_size_(0), 177 callback_factory_(this) { 178} 179 180UdpPacketSocket::~UdpPacketSocket() { 181 Close(); 182} 183 184bool UdpPacketSocket::Init(const rtc::SocketAddress& local_address, 185 int min_port, 186 int max_port) { 187 if (socket_.is_null()) { 188 return false; 189 } 190 191 local_address_ = local_address; 192 max_port_ = max_port; 193 min_port_ = min_port; 194 195 pp::NetAddress pp_local_address; 196 if (!SocketAddressToPpNetAddressWithPort( 197 instance_, local_address_, &pp_local_address, min_port_)) { 198 return false; 199 } 200 201 pp::CompletionCallback callback = 202 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); 203 int result = socket_.Bind(pp_local_address, callback); 204 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 205 state_ = STATE_BINDING; 206 207 return true; 208} 209 210void UdpPacketSocket::OnBindCompleted(int result) { 211 DCHECK(state_ == STATE_BINDING || state_ == STATE_CLOSED); 212 213 if (result == PP_ERROR_ABORTED) { 214 // Socket is being destroyed while binding. 215 return; 216 } 217 218 if (result == PP_OK) { 219 pp::NetAddress address = socket_.GetBoundAddress(); 220 PpNetAddressToSocketAddress(address, &local_address_); 221 state_ = STATE_BOUND; 222 SignalAddressReady(this, local_address_); 223 DoRead(); 224 return; 225 } 226 227 if (min_port_ < max_port_) { 228 // Try to bind to the next available port. 229 ++min_port_; 230 pp::NetAddress pp_local_address; 231 if (SocketAddressToPpNetAddressWithPort( 232 instance_, local_address_, &pp_local_address, min_port_)) { 233 pp::CompletionCallback callback = 234 callback_factory_.NewCallback(&UdpPacketSocket::OnBindCompleted); 235 int result = socket_.Bind(pp_local_address, callback); 236 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 237 } 238 } else { 239 LOG(ERROR) << "Failed to bind UDP socket to " << local_address_.ToString() 240 << ", error: " << result; 241 } 242} 243 244rtc::SocketAddress UdpPacketSocket::GetLocalAddress() const { 245 DCHECK_EQ(state_, STATE_BOUND); 246 return local_address_; 247} 248 249rtc::SocketAddress UdpPacketSocket::GetRemoteAddress() const { 250 // UDP sockets are not connected - this method should never be called. 251 NOTREACHED(); 252 return rtc::SocketAddress(); 253} 254 255int UdpPacketSocket::Send(const void* data, size_t data_size, 256 const rtc::PacketOptions& options) { 257 // UDP sockets are not connected - this method should never be called. 258 NOTREACHED(); 259 return EWOULDBLOCK; 260} 261 262int UdpPacketSocket::SendTo(const void* data, 263 size_t data_size, 264 const rtc::SocketAddress& address, 265 const rtc::PacketOptions& options) { 266 if (state_ != STATE_BOUND) { 267 // TODO(sergeyu): StunPort may try to send stun request before we 268 // are bound. Fix that problem and change this to DCHECK. 269 return EINVAL; 270 } 271 272 if (error_ != 0) { 273 return error_; 274 } 275 276 pp::NetAddress pp_address; 277 if (!SocketAddressToPpNetAddress(instance_, address, &pp_address)) { 278 return EINVAL; 279 } 280 281 if (send_queue_size_ >= kMaxSendBufferSize) { 282 return EWOULDBLOCK; 283 } 284 285 send_queue_.push_back(PendingPacket(data, data_size, pp_address)); 286 send_queue_size_ += data_size; 287 DoSend(); 288 return data_size; 289} 290 291int UdpPacketSocket::Close() { 292 state_ = STATE_CLOSED; 293 socket_.Close(); 294 return 0; 295} 296 297rtc::AsyncPacketSocket::State UdpPacketSocket::GetState() const { 298 return state_; 299} 300 301int UdpPacketSocket::GetOption(rtc::Socket::Option opt, int* value) { 302 // Options are not supported for Pepper UDP sockets. 303 return -1; 304} 305 306int UdpPacketSocket::SetOption(rtc::Socket::Option opt, int value) { 307 // Options are not supported for Pepper UDP sockets. 308 return -1; 309} 310 311int UdpPacketSocket::GetError() const { 312 return error_; 313} 314 315void UdpPacketSocket::SetError(int error) { 316 error_ = error; 317} 318 319void UdpPacketSocket::DoSend() { 320 if (send_pending_ || send_queue_.empty()) 321 return; 322 323 pp::CompletionCallback callback = 324 callback_factory_.NewCallback(&UdpPacketSocket::OnSendCompleted); 325 int result = socket_.SendTo( 326 send_queue_.front().data->data(), send_queue_.front().data->size(), 327 send_queue_.front().address, 328 callback); 329 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 330 send_pending_ = true; 331} 332 333void UdpPacketSocket::OnSendCompleted(int result) { 334 if (result == PP_ERROR_ABORTED) { 335 // Send is aborted when the socket is being destroyed. 336 // |send_queue_| may be already destroyed, it's not safe to access 337 // it here. 338 return; 339 } 340 341 send_pending_ = false; 342 343 if (result < 0) { 344 int net_error = PepperErrorToNetError(result); 345 SocketErrorAction action = GetSocketErrorAction(net_error); 346 switch (action) { 347 case SOCKET_ERROR_ACTION_FAIL: 348 LOG(ERROR) << "Send failed on a UDP socket: " << result; 349 error_ = EINVAL; 350 return; 351 352 case SOCKET_ERROR_ACTION_RETRY: 353 // Retry resending only once. 354 if (!send_queue_.front().retried) { 355 send_queue_.front().retried = true; 356 DoSend(); 357 return; 358 } 359 break; 360 361 case SOCKET_ERROR_ACTION_IGNORE: 362 break; 363 } 364 } 365 366 send_queue_size_ -= send_queue_.front().data->size(); 367 send_queue_.pop_front(); 368 DoSend(); 369} 370 371void UdpPacketSocket::DoRead() { 372 receive_buffer_.resize(kReceiveBufferSize); 373 pp::CompletionCallbackWithOutput<pp::NetAddress> callback = 374 callback_factory_.NewCallbackWithOutput( 375 &UdpPacketSocket::OnReadCompleted); 376 int result = 377 socket_.RecvFrom(&receive_buffer_[0], receive_buffer_.size(), callback); 378 DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); 379} 380 381void UdpPacketSocket::OnReadCompleted(int result, pp::NetAddress address) { 382 HandleReadResult(result, address); 383 if (result > 0) { 384 DoRead(); 385 } 386} 387 388void UdpPacketSocket::HandleReadResult(int result, pp::NetAddress address) { 389 if (result > 0) { 390 rtc::SocketAddress socket_address; 391 PpNetAddressToSocketAddress(address, &socket_address); 392 SignalReadPacket(this, &receive_buffer_[0], result, socket_address, 393 rtc::CreatePacketTime(0)); 394 } else if (result != PP_ERROR_ABORTED) { 395 LOG(ERROR) << "Received error when reading from UDP socket: " << result; 396 } 397} 398 399} // namespace 400 401PepperPacketSocketFactory::PepperPacketSocketFactory( 402 const pp::InstanceHandle& instance) 403 : pp_instance_(instance) { 404} 405 406PepperPacketSocketFactory::~PepperPacketSocketFactory() { 407} 408 409rtc::AsyncPacketSocket* PepperPacketSocketFactory::CreateUdpSocket( 410 const rtc::SocketAddress& local_address, 411 int min_port, 412 int max_port) { 413 scoped_ptr<UdpPacketSocket> result(new UdpPacketSocket(pp_instance_)); 414 if (!result->Init(local_address, min_port, max_port)) 415 return NULL; 416 return result.release(); 417} 418 419rtc::AsyncPacketSocket* PepperPacketSocketFactory::CreateServerTcpSocket( 420 const rtc::SocketAddress& local_address, 421 int min_port, 422 int max_port, 423 int opts) { 424 // We don't use TCP sockets for remoting connections. 425 NOTREACHED(); 426 return NULL; 427} 428 429rtc::AsyncPacketSocket* PepperPacketSocketFactory::CreateClientTcpSocket( 430 const rtc::SocketAddress& local_address, 431 const rtc::SocketAddress& remote_address, 432 const rtc::ProxyInfo& proxy_info, 433 const std::string& user_agent, 434 int opts) { 435 // We don't use TCP sockets for remoting connections. 436 NOTREACHED(); 437 return NULL; 438} 439 440rtc::AsyncResolverInterface* 441PepperPacketSocketFactory::CreateAsyncResolver() { 442 return new PepperAddressResolver(pp_instance_); 443} 444 445} // namespace remoting 446