Chromium Code Reviews| Index: content/browser/renderer_host/pepper_tcp_server_socket.cc |
| diff --git a/content/browser/renderer_host/pepper_tcp_server_socket.cc b/content/browser/renderer_host/pepper_tcp_server_socket.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6ab17a35e893c29082e53cf95bf1d7ff02b68c97 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/pepper_tcp_server_socket.cc |
| @@ -0,0 +1,142 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/pepper_tcp_server_socket.h" |
| + |
| +#include <cstddef> |
| + |
| +#include "base/logging.h" |
| +#include "content/browser/renderer_host/pepper_message_filter.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "net/base/ip_endpoint.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/socket/tcp_client_socket.h" |
| +#include "net/socket/tcp_server_socket.h" |
| +#include "ppapi/proxy/ppapi_messages.h" |
| +#include "ppapi/shared_impl/private/net_address_private_impl.h" |
| + |
| +using content::BrowserThread; |
| +using ppapi::NetAddressPrivateImpl; |
| + |
| +PepperTCPServerSocket::PepperTCPServerSocket( |
| + PepperMessageFilter* manager, |
| + int32 routing_id, |
| + uint32 plugin_dispatcher_id, |
| + uint32 socket_id) |
| + : manager_(manager), |
| + routing_id_(routing_id), |
| + plugin_dispatcher_id_(plugin_dispatcher_id), |
| + socket_id_(socket_id), |
| + state_(BEFORE_LISTENING) { |
| + DCHECK(manager); |
| +} |
| + |
| +PepperTCPServerSocket::~PepperTCPServerSocket() { |
| +} |
| + |
| +void PepperTCPServerSocket::Listen(const PP_NetAddress_Private& addr, |
| + int32 backlog) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + net::IPEndPoint ip_end_point; |
| + if (state_ != BEFORE_LISTENING || |
| + !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &ip_end_point)) { |
| + SendListenACKError(); |
| + return; |
| + } |
| + |
| + state_ = LISTEN_IN_PROGRESS; |
| + |
| + socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source())); |
| + int result = socket_->Listen(ip_end_point, backlog); |
| + if (result != net::ERR_IO_PENDING) |
| + OnListenCompleted(result); |
| +} |
| + |
| +void PepperTCPServerSocket::Accept() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + if (state_ != LISTENING) { |
| + SendAcceptACKError(); |
| + return; |
| + } |
| + |
| + state_ = ACCEPT_IN_PROGRESS; |
| + |
| + int result = socket_->Accept( |
| + &socket_buffer_, |
| + base::Bind(&PepperTCPServerSocket::OnAcceptCompleted, |
| + base::Unretained(this))); |
| + if (result != net::ERR_IO_PENDING) |
| + OnAcceptCompleted(result); |
| +} |
| + |
| +void PepperTCPServerSocket::SendListenACKError() { |
| + manager_->Send(new PpapiMsg_PPBTCPServerSocket_ListenACK( |
| + routing_id_, plugin_dispatcher_id_, socket_id_, false)); |
| +} |
| + |
| +void PepperTCPServerSocket::SendAcceptACKError() { |
| + manager_->Send(new PpapiMsg_PPBTCPServerSocket_AcceptACK( |
| + routing_id_, |
| + plugin_dispatcher_id_, |
| + socket_id_, |
| + 0, |
| + NetAddressPrivateImpl::kInvalidNetAddress, |
| + NetAddressPrivateImpl::kInvalidNetAddress)); |
| +} |
| + |
| +void PepperTCPServerSocket::OnListenCompleted(int result) { |
| + DCHECK(state_ == LISTEN_IN_PROGRESS && socket_.get()); |
| + |
| + if (result != net::OK) { |
| + SendListenACKError(); |
| + state_ = BEFORE_LISTENING; |
| + } else { |
| + manager_->Send(new PpapiMsg_PPBTCPServerSocket_ListenACK( |
| + routing_id_, plugin_dispatcher_id_, socket_id_, true)); |
| + state_ = LISTENING; |
| + } |
| +} |
| + |
| +void PepperTCPServerSocket::OnAcceptCompleted(int result) { |
| + DCHECK(state_ == ACCEPT_IN_PROGRESS && socket_buffer_.get()); |
| + |
| + if (result != net::OK) { |
| + SendAcceptACKError(); |
| + } else { |
| + net::StreamSocket* socket = socket_buffer_.release(); |
|
yzshen1
2012/02/10 22:40:15
I would suggest to transfer socket_buffer_ to a te
ygorshenin1
2012/02/13 14:59:46
Done.
|
| + |
| + net::IPEndPoint ip_end_point; |
| + net::AddressList address_list; |
| + PP_NetAddress_Private local_addr = |
| + NetAddressPrivateImpl::kInvalidNetAddress; |
| + PP_NetAddress_Private remote_addr = |
| + NetAddressPrivateImpl::kInvalidNetAddress; |
| + |
| + if (socket->GetLocalAddress(&ip_end_point) != net::OK || |
| + !NetAddressPrivateImpl::IPEndPointToNetAddress(ip_end_point, |
| + &local_addr) || |
| + socket->GetPeerAddress(&address_list) != net::OK || |
| + !NetAddressPrivateImpl::AddressListToNetAddress(address_list, |
| + &remote_addr)) { |
| + SendAcceptACKError(); |
|
yzshen1
2012/02/10 22:40:15
If you SendAcceptACKError(), you don't need to pro
ygorshenin1
2012/02/13 14:59:46
Done.
|
| + } |
| + uint32 accepted_socket_id = |
| + manager_->AddAcceptedTCPSocket(routing_id_, |
| + plugin_dispatcher_id_, |
| + socket); |
| + if (accepted_socket_id != 0) { |
|
yzshen1
2012/02/10 22:40:15
Please note that you still need to send an error r
ygorshenin1
2012/02/13 14:59:46
Done.
|
| + manager_->Send(new PpapiMsg_PPBTCPServerSocket_AcceptACK( |
| + routing_id_, |
| + plugin_dispatcher_id_, |
| + socket_id_, |
| + accepted_socket_id, |
| + local_addr, |
| + remote_addr)); |
| + } |
| + } |
| + |
| + state_ = LISTENING; |
| +} |