1// Copyright 2013 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 "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h" 6 7#include <cstring> 8 9#include "base/bind.h" 10#include "base/logging.h" 11#include "build/build_config.h" 12#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 13#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h" 14#include "content/browser/renderer_host/pepper/pepper_socket_utils.h" 15#include "content/public/browser/browser_context.h" 16#include "content/public/browser/browser_thread.h" 17#include "content/public/browser/render_process_host.h" 18#include "content/public/browser/resource_context.h" 19#include "content/public/common/socket_permission_request.h" 20#include "net/base/address_family.h" 21#include "net/base/host_port_pair.h" 22#include "net/base/io_buffer.h" 23#include "net/base/net_errors.h" 24#include "net/dns/single_request_host_resolver.h" 25#include "net/socket/client_socket_factory.h" 26#include "net/socket/client_socket_handle.h" 27#include "net/socket/ssl_client_socket.h" 28#include "net/socket/tcp_client_socket.h" 29#include "ppapi/host/dispatch_host_message.h" 30#include "ppapi/host/error_conversion.h" 31#include "ppapi/host/ppapi_host.h" 32#include "ppapi/host/resource_host.h" 33#include "ppapi/proxy/ppapi_messages.h" 34#include "ppapi/proxy/tcp_socket_resource_base.h" 35#include "ppapi/shared_impl/private/net_address_private_impl.h" 36 37using ppapi::NetAddressPrivateImpl; 38using ppapi::host::NetErrorToPepperError; 39using ppapi::proxy::TCPSocketResourceBase; 40using ppapi::TCPSocketState; 41using ppapi::TCPSocketVersion; 42 43namespace { 44 45size_t g_num_instances = 0; 46 47} // namespace 48 49namespace content { 50 51PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter( 52 ContentBrowserPepperHostFactory* factory, 53 BrowserPpapiHostImpl* host, 54 PP_Instance instance, 55 TCPSocketVersion version) 56 : version_(version), 57 external_plugin_(host->external_plugin()), 58 render_process_id_(0), 59 render_view_id_(0), 60 ppapi_host_(host->GetPpapiHost()), 61 factory_(factory), 62 instance_(instance), 63 state_(TCPSocketState::INITIAL), 64 end_of_file_reached_(false), 65 bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress), 66 address_index_(0), 67 socket_(new net::TCPSocket(NULL, net::NetLog::Source())), 68 ssl_context_helper_(host->ssl_context_helper()), 69 pending_accept_(false) { 70 DCHECK(host); 71 ++g_num_instances; 72 if (!host->GetRenderViewIDsForInstance(instance, 73 &render_process_id_, 74 &render_view_id_)) { 75 NOTREACHED(); 76 } 77} 78 79PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter( 80 BrowserPpapiHostImpl* host, 81 PP_Instance instance, 82 TCPSocketVersion version, 83 scoped_ptr<net::TCPSocket> socket) 84 : version_(version), 85 external_plugin_(host->external_plugin()), 86 render_process_id_(0), 87 render_view_id_(0), 88 ppapi_host_(host->GetPpapiHost()), 89 factory_(NULL), 90 instance_(instance), 91 state_(TCPSocketState::CONNECTED), 92 end_of_file_reached_(false), 93 bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress), 94 address_index_(0), 95 socket_(socket.Pass()), 96 ssl_context_helper_(host->ssl_context_helper()), 97 pending_accept_(false) { 98 DCHECK(host); 99 DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0); 100 101 ++g_num_instances; 102 if (!host->GetRenderViewIDsForInstance(instance, 103 &render_process_id_, 104 &render_view_id_)) { 105 NOTREACHED(); 106 } 107} 108 109PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() { 110 if (socket_) 111 socket_->Close(); 112 if (ssl_socket_) 113 ssl_socket_->Disconnect(); 114 --g_num_instances; 115} 116 117// static 118size_t PepperTCPSocketMessageFilter::GetNumInstances() { 119 return g_num_instances; 120} 121 122scoped_refptr<base::TaskRunner> 123PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage( 124 const IPC::Message& message) { 125 switch (message.type()) { 126 case PpapiHostMsg_TCPSocket_Bind::ID: 127 case PpapiHostMsg_TCPSocket_Connect::ID: 128 case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID: 129 case PpapiHostMsg_TCPSocket_Listen::ID: 130 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 131 case PpapiHostMsg_TCPSocket_SSLHandshake::ID: 132 case PpapiHostMsg_TCPSocket_Read::ID: 133 case PpapiHostMsg_TCPSocket_Write::ID: 134 case PpapiHostMsg_TCPSocket_Accept::ID: 135 case PpapiHostMsg_TCPSocket_Close::ID: 136 case PpapiHostMsg_TCPSocket_SetOption::ID: 137 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 138 } 139 return NULL; 140} 141 142int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived( 143 const IPC::Message& msg, 144 ppapi::host::HostMessageContext* context) { 145 IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg) 146 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 147 PpapiHostMsg_TCPSocket_Bind, OnMsgBind) 148 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 149 PpapiHostMsg_TCPSocket_Connect, OnMsgConnect) 150 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 151 PpapiHostMsg_TCPSocket_ConnectWithNetAddress, 152 OnMsgConnectWithNetAddress) 153 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 154 PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake) 155 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 156 PpapiHostMsg_TCPSocket_Read, OnMsgRead) 157 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 158 PpapiHostMsg_TCPSocket_Write, OnMsgWrite) 159 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 160 PpapiHostMsg_TCPSocket_Listen, OnMsgListen) 161 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 162 PpapiHostMsg_TCPSocket_Accept, OnMsgAccept) 163 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 164 PpapiHostMsg_TCPSocket_Close, OnMsgClose) 165 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 166 PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption) 167 IPC_END_MESSAGE_MAP() 168 return PP_ERROR_FAILED; 169} 170 171int32_t PepperTCPSocketMessageFilter::OnMsgBind( 172 const ppapi::host::HostMessageContext* context, 173 const PP_NetAddress_Private& net_addr) { 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 175 176 // This is only supported by PPB_TCPSocket v1.1 or above. 177 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) { 178 NOTREACHED(); 179 return PP_ERROR_NOACCESS; 180 } 181 182 if (!pepper_socket_utils::CanUseSocketAPIs( 183 external_plugin_, false /* private_api */, NULL, render_process_id_, 184 render_view_id_)) { 185 return PP_ERROR_NOACCESS; 186 } 187 188 bind_input_addr_ = net_addr; 189 190 BrowserThread::PostTask( 191 BrowserThread::IO, FROM_HERE, 192 base::Bind(&PepperTCPSocketMessageFilter::DoBind, this, 193 context->MakeReplyMessageContext(), net_addr)); 194 return PP_OK_COMPLETIONPENDING; 195} 196 197int32_t PepperTCPSocketMessageFilter::OnMsgConnect( 198 const ppapi::host::HostMessageContext* context, 199 const std::string& host, 200 uint16_t port) { 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 202 203 // This is only supported by PPB_TCPSocket_Private. 204 if (!IsPrivateAPI()) { 205 NOTREACHED(); 206 return PP_ERROR_NOACCESS; 207 } 208 209 SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT, 210 host, 211 port); 212 if (!pepper_socket_utils::CanUseSocketAPIs( 213 external_plugin_, true /* private_api */, &request, 214 render_process_id_, render_view_id_)) { 215 return PP_ERROR_NOACCESS; 216 } 217 218 RenderProcessHost* render_process_host = 219 RenderProcessHost::FromID(render_process_id_); 220 if (!render_process_host) 221 return PP_ERROR_FAILED; 222 BrowserContext* browser_context = render_process_host->GetBrowserContext(); 223 if (!browser_context || !browser_context->GetResourceContext()) 224 return PP_ERROR_FAILED; 225 226 BrowserThread::PostTask( 227 BrowserThread::IO, FROM_HERE, 228 base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this, 229 context->MakeReplyMessageContext(), 230 host, port, browser_context->GetResourceContext())); 231 return PP_OK_COMPLETIONPENDING; 232} 233 234int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress( 235 const ppapi::host::HostMessageContext* context, 236 const PP_NetAddress_Private& net_addr) { 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 238 239 content::SocketPermissionRequest request = 240 pepper_socket_utils::CreateSocketPermissionRequest( 241 content::SocketPermissionRequest::TCP_CONNECT, net_addr); 242 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(), 243 &request, render_process_id_, 244 render_view_id_)) { 245 return PP_ERROR_NOACCESS; 246 } 247 248 BrowserThread::PostTask( 249 BrowserThread::IO, FROM_HERE, 250 base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this, 251 context->MakeReplyMessageContext(), net_addr)); 252 return PP_OK_COMPLETIONPENDING; 253} 254 255int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake( 256 const ppapi::host::HostMessageContext* context, 257 const std::string& server_name, 258 uint16_t server_port, 259 const std::vector<std::vector<char> >& trusted_certs, 260 const std::vector<std::vector<char> >& untrusted_certs) { 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 262 263 // Allow to do SSL handshake only if currently the socket has been connected 264 // and there isn't pending read or write. 265 if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) || 266 read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) { 267 return PP_ERROR_FAILED; 268 } 269 270 // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting. 271 net::IPEndPoint peer_address; 272 if (socket_->GetPeerAddress(&peer_address) != net::OK) 273 return PP_ERROR_FAILED; 274 275 scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle()); 276 handle->SetSocket(make_scoped_ptr<net::StreamSocket>( 277 new net::TCPClientSocket(socket_.Pass(), peer_address))); 278 net::ClientSocketFactory* factory = 279 net::ClientSocketFactory::GetDefaultFactory(); 280 net::HostPortPair host_port_pair(server_name, server_port); 281 net::SSLClientSocketContext ssl_context; 282 ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier(); 283 ssl_context.transport_security_state = 284 ssl_context_helper_->GetTransportSecurityState(); 285 ssl_socket_ = factory->CreateSSLClientSocket( 286 handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(), 287 ssl_context); 288 if (!ssl_socket_) { 289 LOG(WARNING) << "Failed to create an SSL client socket."; 290 state_.CompletePendingTransition(false); 291 return PP_ERROR_FAILED; 292 } 293 294 state_.SetPendingTransition(TCPSocketState::SSL_CONNECT); 295 296 const ppapi::host::ReplyMessageContext reply_context( 297 context->MakeReplyMessageContext()); 298 int net_result = ssl_socket_->Connect( 299 base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted, 300 base::Unretained(this), reply_context)); 301 if (net_result != net::ERR_IO_PENDING) 302 OnSSLHandshakeCompleted(reply_context, net_result); 303 return PP_OK_COMPLETIONPENDING; 304} 305 306int32_t PepperTCPSocketMessageFilter::OnMsgRead( 307 const ppapi::host::HostMessageContext* context, 308 int32_t bytes_to_read) { 309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 310 if (!state_.IsConnected() || end_of_file_reached_) 311 return PP_ERROR_FAILED; 312 if (read_buffer_.get()) 313 return PP_ERROR_INPROGRESS; 314 if (bytes_to_read <= 0 || 315 bytes_to_read > TCPSocketResourceBase::kMaxReadSize) { 316 return PP_ERROR_BADARGUMENT; 317 } 318 319 ppapi::host::ReplyMessageContext reply_context( 320 context->MakeReplyMessageContext()); 321 read_buffer_ = new net::IOBuffer(bytes_to_read); 322 323 int net_result = net::ERR_FAILED; 324 if (socket_) { 325 DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED); 326 net_result = socket_->Read( 327 read_buffer_.get(), 328 bytes_to_read, 329 base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted, 330 base::Unretained(this), reply_context)); 331 } else if (ssl_socket_) { 332 DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED); 333 net_result = ssl_socket_->Read( 334 read_buffer_.get(), 335 bytes_to_read, 336 base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted, 337 base::Unretained(this), reply_context)); 338 } 339 if (net_result != net::ERR_IO_PENDING) 340 OnReadCompleted(reply_context, net_result); 341 return PP_OK_COMPLETIONPENDING; 342} 343 344int32_t PepperTCPSocketMessageFilter::OnMsgWrite( 345 const ppapi::host::HostMessageContext* context, 346 const std::string& data) { 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 348 349 if (!state_.IsConnected()) 350 return PP_ERROR_FAILED; 351 if (write_buffer_base_.get() || write_buffer_.get()) 352 return PP_ERROR_INPROGRESS; 353 354 size_t data_size = data.size(); 355 if (data_size == 0 || 356 data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) { 357 return PP_ERROR_BADARGUMENT; 358 } 359 360 write_buffer_base_ = new net::IOBuffer(data_size); 361 memcpy(write_buffer_base_->data(), data.data(), data_size); 362 write_buffer_ = 363 new net::DrainableIOBuffer(write_buffer_base_.get(), data_size); 364 DoWrite(context->MakeReplyMessageContext()); 365 return PP_OK_COMPLETIONPENDING; 366} 367 368int32_t PepperTCPSocketMessageFilter::OnMsgListen( 369 const ppapi::host::HostMessageContext* context, 370 int32_t backlog) { 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 372 373 // This is only supported by PPB_TCPSocket v1.1 or above. 374 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) { 375 NOTREACHED(); 376 return PP_ERROR_NOACCESS; 377 } 378 379 content::SocketPermissionRequest request = 380 pepper_socket_utils::CreateSocketPermissionRequest( 381 content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_); 382 if (!pepper_socket_utils::CanUseSocketAPIs( 383 external_plugin_, false /* private_api */, &request, 384 render_process_id_, render_view_id_)) { 385 return PP_ERROR_NOACCESS; 386 } 387 388 BrowserThread::PostTask( 389 BrowserThread::IO, FROM_HERE, 390 base::Bind(&PepperTCPSocketMessageFilter::DoListen, this, 391 context->MakeReplyMessageContext(), backlog)); 392 return PP_OK_COMPLETIONPENDING; 393} 394 395int32_t PepperTCPSocketMessageFilter::OnMsgAccept( 396 const ppapi::host::HostMessageContext* context) { 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 398 399 if (pending_accept_) 400 return PP_ERROR_INPROGRESS; 401 if (state_.state() != TCPSocketState::LISTENING) 402 return PP_ERROR_FAILED; 403 404 pending_accept_ = true; 405 ppapi::host::ReplyMessageContext reply_context( 406 context->MakeReplyMessageContext()); 407 int net_result = socket_->Accept( 408 &accepted_socket_, 409 &accepted_address_, 410 base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted, 411 base::Unretained(this), reply_context)); 412 if (net_result != net::ERR_IO_PENDING) 413 OnAcceptCompleted(reply_context, net_result); 414 return PP_OK_COMPLETIONPENDING; 415} 416 417int32_t PepperTCPSocketMessageFilter::OnMsgClose( 418 const ppapi::host::HostMessageContext* context) { 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 420 if (state_.state() == TCPSocketState::CLOSED) 421 return PP_OK; 422 423 state_.DoTransition(TCPSocketState::CLOSE, true); 424 // Make sure we get no further callbacks from |socket_| or |ssl_socket_|. 425 if (socket_) { 426 socket_->Close(); 427 } else if (ssl_socket_) { 428 ssl_socket_->Disconnect(); 429 } 430 return PP_OK; 431} 432 433int32_t PepperTCPSocketMessageFilter::OnMsgSetOption( 434 const ppapi::host::HostMessageContext* context, 435 PP_TCPSocket_Option name, 436 const ppapi::SocketOptionData& value) { 437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 438 439 switch (name) { 440 case PP_TCPSOCKET_OPTION_NO_DELAY: { 441 if (state_.state() != TCPSocketState::CONNECTED) 442 return PP_ERROR_FAILED; 443 444 bool boolean_value = false; 445 if (!value.GetBool(&boolean_value)) 446 return PP_ERROR_BADARGUMENT; 447 return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED; 448 } 449 case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE: 450 case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: { 451 if (state_.state() != TCPSocketState::CONNECTED) 452 return PP_ERROR_FAILED; 453 454 int32_t integer_value = 0; 455 if (!value.GetInt32(&integer_value) || integer_value <= 0) 456 return PP_ERROR_BADARGUMENT; 457 458 bool result = false; 459 if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) { 460 if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize) 461 return PP_ERROR_BADARGUMENT; 462 result = socket_->SetSendBufferSize(integer_value); 463 } else { 464 if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize) 465 return PP_ERROR_BADARGUMENT; 466 result = socket_->SetReceiveBufferSize(integer_value); 467 } 468 return result ? PP_OK : PP_ERROR_FAILED; 469 } 470 default: { 471 NOTREACHED(); 472 return PP_ERROR_BADARGUMENT; 473 } 474 } 475} 476 477void PepperTCPSocketMessageFilter::DoBind( 478 const ppapi::host::ReplyMessageContext& context, 479 const PP_NetAddress_Private& net_addr) { 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 481 482 if (state_.IsPending(TCPSocketState::BIND)) { 483 SendBindError(context, PP_ERROR_INPROGRESS); 484 return; 485 } 486 if (!state_.IsValidTransition(TCPSocketState::BIND)) { 487 SendBindError(context, PP_ERROR_FAILED); 488 return; 489 } 490 491 int pp_result = PP_OK; 492 do { 493 net::IPAddressNumber address; 494 int port; 495 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address, 496 &port)) { 497 pp_result = PP_ERROR_ADDRESS_INVALID; 498 break; 499 } 500 net::IPEndPoint bind_addr(address, port); 501 502 DCHECK(!socket_->IsValid()); 503 pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily())); 504 if (pp_result != PP_OK) 505 break; 506 507 pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer()); 508 if (pp_result != PP_OK) 509 break; 510 511 pp_result = NetErrorToPepperError(socket_->Bind(bind_addr)); 512 if (pp_result != PP_OK) 513 break; 514 515 net::IPEndPoint ip_end_point_local; 516 pp_result = NetErrorToPepperError( 517 socket_->GetLocalAddress(&ip_end_point_local)); 518 if (pp_result != PP_OK) 519 break; 520 521 PP_NetAddress_Private local_addr = 522 NetAddressPrivateImpl::kInvalidNetAddress; 523 if (!NetAddressPrivateImpl::IPEndPointToNetAddress( 524 ip_end_point_local.address(), 525 ip_end_point_local.port(), 526 &local_addr)) { 527 pp_result = PP_ERROR_ADDRESS_INVALID; 528 break; 529 } 530 531 SendBindReply(context, PP_OK, local_addr); 532 state_.DoTransition(TCPSocketState::BIND, true); 533 return; 534 } while (false); 535 if (socket_->IsValid()) 536 socket_->Close(); 537 SendBindError(context, pp_result); 538 state_.DoTransition(TCPSocketState::BIND, false); 539} 540 541void PepperTCPSocketMessageFilter::DoConnect( 542 const ppapi::host::ReplyMessageContext& context, 543 const std::string& host, 544 uint16_t port, 545 ResourceContext* resource_context) { 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 547 548 if (!state_.IsValidTransition(TCPSocketState::CONNECT)) { 549 SendConnectError(context, PP_ERROR_FAILED); 550 return; 551 } 552 553 state_.SetPendingTransition(TCPSocketState::CONNECT); 554 address_index_ = 0; 555 address_list_.clear(); 556 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); 557 resolver_.reset(new net::SingleRequestHostResolver( 558 resource_context->GetHostResolver())); 559 int net_result = resolver_->Resolve( 560 request_info, 561 net::DEFAULT_PRIORITY, 562 &address_list_, 563 base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted, 564 base::Unretained(this), context), 565 net::BoundNetLog()); 566 if (net_result != net::ERR_IO_PENDING) 567 OnResolveCompleted(context, net_result); 568} 569 570void PepperTCPSocketMessageFilter::DoConnectWithNetAddress( 571 const ppapi::host::ReplyMessageContext& context, 572 const PP_NetAddress_Private& net_addr) { 573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 574 575 if (!state_.IsValidTransition(TCPSocketState::CONNECT)) { 576 SendConnectError(context, PP_ERROR_FAILED); 577 return; 578 } 579 580 state_.SetPendingTransition(TCPSocketState::CONNECT); 581 582 net::IPAddressNumber address; 583 int port; 584 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address, 585 &port)) { 586 state_.CompletePendingTransition(false); 587 SendConnectError(context, PP_ERROR_ADDRESS_INVALID); 588 return; 589 } 590 591 // Copy the single IPEndPoint to address_list_. 592 address_index_ = 0; 593 address_list_.clear(); 594 address_list_.push_back(net::IPEndPoint(address, port)); 595 StartConnect(context); 596} 597 598void PepperTCPSocketMessageFilter::DoWrite( 599 const ppapi::host::ReplyMessageContext& context) { 600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 601 DCHECK(write_buffer_base_.get()); 602 DCHECK(write_buffer_.get()); 603 DCHECK_GT(write_buffer_->BytesRemaining(), 0); 604 DCHECK(state_.IsConnected()); 605 606 int net_result = net::ERR_FAILED; 607 if (socket_) { 608 DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED); 609 net_result = socket_->Write( 610 write_buffer_.get(), 611 write_buffer_->BytesRemaining(), 612 base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted, 613 base::Unretained(this), context)); 614 } else if (ssl_socket_) { 615 DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED); 616 net_result = ssl_socket_->Write( 617 write_buffer_.get(), 618 write_buffer_->BytesRemaining(), 619 base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted, 620 base::Unretained(this), context)); 621 } 622 if (net_result != net::ERR_IO_PENDING) 623 OnWriteCompleted(context, net_result); 624} 625 626void PepperTCPSocketMessageFilter::DoListen( 627 const ppapi::host::ReplyMessageContext& context, 628 int32_t backlog) { 629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 630 631 if (state_.IsPending(TCPSocketState::LISTEN)) { 632 SendListenReply(context, PP_ERROR_INPROGRESS); 633 return; 634 } 635 if (!state_.IsValidTransition(TCPSocketState::LISTEN)) { 636 SendListenReply(context, PP_ERROR_FAILED); 637 return; 638 } 639 640 int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog)); 641 SendListenReply(context, pp_result); 642 state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK); 643} 644 645void PepperTCPSocketMessageFilter::OnResolveCompleted( 646 const ppapi::host::ReplyMessageContext& context, 647 int net_result) { 648 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 649 650 if (!state_.IsPending(TCPSocketState::CONNECT)) { 651 DCHECK(state_.state() == TCPSocketState::CLOSED); 652 SendConnectError(context, PP_ERROR_FAILED); 653 return; 654 } 655 656 if (net_result != net::OK) { 657 SendConnectError(context, NetErrorToPepperError(net_result)); 658 state_.CompletePendingTransition(false); 659 return; 660 } 661 662 StartConnect(context); 663} 664 665void PepperTCPSocketMessageFilter::StartConnect( 666 const ppapi::host::ReplyMessageContext& context) { 667 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 668 DCHECK(state_.IsPending(TCPSocketState::CONNECT)); 669 DCHECK_LT(address_index_, address_list_.size()); 670 671 int net_result = net::OK; 672 if (!socket_->IsValid()) 673 net_result = socket_->Open(address_list_[address_index_].GetFamily()); 674 675 if (net_result == net::OK) { 676 net_result = socket_->Connect( 677 address_list_[address_index_], 678 base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted, 679 base::Unretained(this), context)); 680 } 681 if (net_result != net::ERR_IO_PENDING) 682 OnConnectCompleted(context, net_result); 683} 684 685void PepperTCPSocketMessageFilter::OnConnectCompleted( 686 const ppapi::host::ReplyMessageContext& context, 687 int net_result) { 688 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 689 690 if (!state_.IsPending(TCPSocketState::CONNECT)) { 691 DCHECK(state_.state() == TCPSocketState::CLOSED); 692 SendConnectError(context, PP_ERROR_FAILED); 693 return; 694 } 695 696 int32_t pp_result = NetErrorToPepperError(net_result); 697 do { 698 if (pp_result != PP_OK) 699 break; 700 701 net::IPEndPoint ip_end_point_local; 702 net::IPEndPoint ip_end_point_remote; 703 pp_result = NetErrorToPepperError( 704 socket_->GetLocalAddress(&ip_end_point_local)); 705 if (pp_result != PP_OK) 706 break; 707 pp_result = NetErrorToPepperError( 708 socket_->GetPeerAddress(&ip_end_point_remote)); 709 if (pp_result != PP_OK) 710 break; 711 712 PP_NetAddress_Private local_addr = 713 NetAddressPrivateImpl::kInvalidNetAddress; 714 PP_NetAddress_Private remote_addr = 715 NetAddressPrivateImpl::kInvalidNetAddress; 716 if (!NetAddressPrivateImpl::IPEndPointToNetAddress( 717 ip_end_point_local.address(), 718 ip_end_point_local.port(), 719 &local_addr) || 720 !NetAddressPrivateImpl::IPEndPointToNetAddress( 721 ip_end_point_remote.address(), 722 ip_end_point_remote.port(), 723 &remote_addr)) { 724 pp_result = PP_ERROR_ADDRESS_INVALID; 725 break; 726 } 727 728 socket_->SetDefaultOptionsForClient(); 729 SendConnectReply(context, PP_OK, local_addr, remote_addr); 730 state_.CompletePendingTransition(true); 731 return; 732 } while (false); 733 734 if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) { 735 DCHECK_EQ(1u, address_list_.size()); 736 737 SendConnectError(context, pp_result); 738 state_.CompletePendingTransition(false); 739 } else { 740 // We have to recreate |socket_| because it doesn't allow a second connect 741 // attempt. We won't lose any state such as bound address or set options, 742 // because in the private or v1.0 API, connect must be the first operation. 743 socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source())); 744 745 if (address_index_ + 1 < address_list_.size()) { 746 DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE); 747 address_index_++; 748 StartConnect(context); 749 } else { 750 SendConnectError(context, pp_result); 751 // In order to maintain backward compatibility, allow further attempts to 752 // connect the socket. 753 state_ = TCPSocketState(TCPSocketState::INITIAL); 754 } 755 } 756} 757 758void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted( 759 const ppapi::host::ReplyMessageContext& context, 760 int net_result) { 761 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 762 763 if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) { 764 DCHECK(state_.state() == TCPSocketState::CLOSED); 765 SendSSLHandshakeReply(context, PP_ERROR_FAILED); 766 return; 767 } 768 769 SendSSLHandshakeReply(context, NetErrorToPepperError(net_result)); 770 state_.CompletePendingTransition(net_result == net::OK); 771} 772 773void PepperTCPSocketMessageFilter::OnReadCompleted( 774 const ppapi::host::ReplyMessageContext& context, 775 int net_result) { 776 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 777 DCHECK(read_buffer_.get()); 778 779 if (net_result > 0) { 780 SendReadReply(context, 781 PP_OK, 782 std::string(read_buffer_->data(), net_result)); 783 } else if (net_result == 0) { 784 end_of_file_reached_ = true; 785 SendReadReply(context, PP_OK, std::string()); 786 } else { 787 SendReadError(context, NetErrorToPepperError(net_result)); 788 } 789 read_buffer_ = NULL; 790} 791 792void PepperTCPSocketMessageFilter::OnWriteCompleted( 793 const ppapi::host::ReplyMessageContext& context, 794 int net_result) { 795 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 796 DCHECK(write_buffer_base_.get()); 797 DCHECK(write_buffer_.get()); 798 799 // Note: For partial writes of 0 bytes, don't continue writing to avoid a 800 // likely infinite loop. 801 if (net_result > 0) { 802 write_buffer_->DidConsume(net_result); 803 if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) { 804 DoWrite(context); 805 return; 806 } 807 } 808 809 if (net_result >= 0) 810 SendWriteReply(context, write_buffer_->BytesConsumed()); 811 else 812 SendWriteReply(context, NetErrorToPepperError(net_result)); 813 814 write_buffer_ = NULL; 815 write_buffer_base_ = NULL; 816} 817 818void PepperTCPSocketMessageFilter::OnAcceptCompleted( 819 const ppapi::host::ReplyMessageContext& context, 820 int net_result) { 821 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 822 DCHECK(pending_accept_); 823 824 pending_accept_ = false; 825 826 if (net_result != net::OK) { 827 SendAcceptError(context, NetErrorToPepperError(net_result)); 828 return; 829 } 830 831 DCHECK(accepted_socket_.get()); 832 833 net::IPEndPoint ip_end_point_local; 834 PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress; 835 PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress; 836 837 int32_t pp_result = 838 NetErrorToPepperError(accepted_socket_->GetLocalAddress( 839 &ip_end_point_local)); 840 if (pp_result != PP_OK) { 841 SendAcceptError(context, pp_result); 842 return; 843 } 844 if (!NetAddressPrivateImpl::IPEndPointToNetAddress( 845 ip_end_point_local.address(), 846 ip_end_point_local.port(), 847 &local_addr) || 848 !NetAddressPrivateImpl::IPEndPointToNetAddress( 849 accepted_address_.address(), 850 accepted_address_.port(), 851 &remote_addr)) { 852 SendAcceptError(context, PP_ERROR_ADDRESS_INVALID); 853 return; 854 } 855 856 // |factory_| is guaranteed to be non-NULL here. Only those instances created 857 // in CONNECTED state have a NULL |factory_|, while getting here requires 858 // LISTENING state. 859 scoped_ptr<ppapi::host::ResourceHost> host = 860 factory_->CreateAcceptedTCPSocket( 861 instance_, version_, accepted_socket_.Pass()); 862 if (!host) { 863 SendAcceptError(context, PP_ERROR_NOSPACE); 864 return; 865 } 866 int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass()); 867 if (pending_host_id) 868 SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr); 869 else 870 SendAcceptError(context, PP_ERROR_NOSPACE); 871} 872 873void PepperTCPSocketMessageFilter::SendBindReply( 874 const ppapi::host::ReplyMessageContext& context, 875 int32_t pp_result, 876 const PP_NetAddress_Private& local_addr) { 877 ppapi::host::ReplyMessageContext reply_context(context); 878 reply_context.params.set_result(pp_result); 879 SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr)); 880} 881 882void PepperTCPSocketMessageFilter::SendBindError( 883 const ppapi::host::ReplyMessageContext& context, 884 int32_t pp_error) { 885 SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress); 886} 887 888void PepperTCPSocketMessageFilter::SendConnectReply( 889 const ppapi::host::ReplyMessageContext& context, 890 int32_t pp_result, 891 const PP_NetAddress_Private& local_addr, 892 const PP_NetAddress_Private& remote_addr) { 893 ppapi::host::ReplyMessageContext reply_context(context); 894 reply_context.params.set_result(pp_result); 895 SendReply(reply_context, 896 PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr)); 897} 898 899void PepperTCPSocketMessageFilter::SendConnectError( 900 const ppapi::host::ReplyMessageContext& context, 901 int32_t pp_error) { 902 SendConnectReply(context, 903 pp_error, 904 NetAddressPrivateImpl::kInvalidNetAddress, 905 NetAddressPrivateImpl::kInvalidNetAddress); 906} 907 908void PepperTCPSocketMessageFilter::SendSSLHandshakeReply( 909 const ppapi::host::ReplyMessageContext& context, 910 int32_t pp_result) { 911 ppapi::host::ReplyMessageContext reply_context(context); 912 reply_context.params.set_result(pp_result); 913 ppapi::PPB_X509Certificate_Fields certificate_fields; 914 if (pp_result == PP_OK) { 915 // Our socket is guaranteed to be an SSL socket if we get here. 916 net::SSLInfo ssl_info; 917 ssl_socket_->GetSSLInfo(&ssl_info); 918 if (ssl_info.cert.get()) { 919 pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(), 920 &certificate_fields); 921 } 922 } 923 SendReply(reply_context, 924 PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields)); 925} 926 927void PepperTCPSocketMessageFilter::SendReadReply( 928 const ppapi::host::ReplyMessageContext& context, 929 int32_t pp_result, 930 const std::string& data) { 931 ppapi::host::ReplyMessageContext reply_context(context); 932 reply_context.params.set_result(pp_result); 933 SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data)); 934} 935 936void PepperTCPSocketMessageFilter::SendReadError( 937 const ppapi::host::ReplyMessageContext& context, 938 int32_t pp_error) { 939 SendReadReply(context, pp_error, std::string()); 940} 941 942void PepperTCPSocketMessageFilter::SendWriteReply( 943 const ppapi::host::ReplyMessageContext& context, 944 int32_t pp_result) { 945 ppapi::host::ReplyMessageContext reply_context(context); 946 reply_context.params.set_result(pp_result); 947 SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply()); 948} 949 950void PepperTCPSocketMessageFilter::SendListenReply( 951 const ppapi::host::ReplyMessageContext& context, 952 int32_t pp_result) { 953 ppapi::host::ReplyMessageContext reply_context(context); 954 reply_context.params.set_result(pp_result); 955 SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply()); 956} 957 958void PepperTCPSocketMessageFilter::SendAcceptReply( 959 const ppapi::host::ReplyMessageContext& context, 960 int32_t pp_result, 961 int pending_host_id, 962 const PP_NetAddress_Private& local_addr, 963 const PP_NetAddress_Private& remote_addr) { 964 ppapi::host::ReplyMessageContext reply_context(context); 965 reply_context.params.set_result(pp_result); 966 SendReply(reply_context, 967 PpapiPluginMsg_TCPSocket_AcceptReply( 968 pending_host_id, local_addr, remote_addr)); 969} 970 971void PepperTCPSocketMessageFilter::SendAcceptError( 972 const ppapi::host::ReplyMessageContext& context, 973 int32_t pp_error) { 974 SendAcceptReply(context, pp_error, 0, 975 NetAddressPrivateImpl::kInvalidNetAddress, 976 NetAddressPrivateImpl::kInvalidNetAddress); 977} 978 979} // namespace content 980