PPB_TCPSocket: add support for TCP server socket operations.
BUG=262601
TEST=new tests in test_tcp_socket.
Review URL: https://chromiumcodereview.appspot.com/24195004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224383 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 95bbd8b..24beb03 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -62,6 +62,7 @@
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/ppb_device_ref_shared.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/shared_impl/ppp_flash_browser_operations_shared.h"
#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
@@ -74,6 +75,8 @@
#define IPC_MESSAGE_START PpapiMsgStart
+IPC_ENUM_TRAITS_MAX_VALUE(ppapi::TCPSocketVersion,
+ ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE)
IPC_ENUM_TRAITS(PP_AudioSampleRate)
IPC_ENUM_TRAITS(PP_DeviceType_Dev)
IPC_ENUM_TRAITS(PP_DecryptorStreamType)
@@ -99,7 +102,7 @@
IPC_ENUM_TRAITS_MAX_VALUE(PP_TalkPermission,
PP_TALKPERMISSION_NUM_PERMISSIONS - 1)
IPC_ENUM_TRAITS_MAX_VALUE(PP_TCPSocket_Option,
- PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE)
+ PP_TCPSOCKET_OPTION_ADDRESS_REUSE)
IPC_ENUM_TRAITS(PP_TextInput_Type)
IPC_ENUM_TRAITS(PP_TrueTypeFontFamily_Dev)
IPC_ENUM_TRAITS(PP_TrueTypeFontStyle_Dev)
@@ -1450,11 +1453,16 @@
// TCP Socket ------------------------------------------------------------------
// Creates a PPB_TCPSocket resource.
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPSocket_Create)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TCPSocket_Create,
+ ppapi::TCPSocketVersion /* version */)
// Creates a PPB_TCPSocket_Private resource.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPSocket_CreatePrivate)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TCPSocket_Bind,
+ PP_NetAddress_Private /* net_addr */)
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_TCPSocket_BindReply,
+ PP_NetAddress_Private /* local_addr */)
IPC_MESSAGE_CONTROL2(PpapiHostMsg_TCPSocket_Connect,
std::string /* host */,
uint16_t /* port */)
@@ -1477,7 +1485,15 @@
IPC_MESSAGE_CONTROL1(PpapiHostMsg_TCPSocket_Write,
std::string /* data */)
IPC_MESSAGE_CONTROL0(PpapiPluginMsg_TCPSocket_WriteReply)
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPSocket_Disconnect)
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_TCPSocket_Listen,
+ int32_t /* backlog */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_TCPSocket_ListenReply)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPSocket_Accept)
+IPC_MESSAGE_CONTROL3(PpapiPluginMsg_TCPSocket_AcceptReply,
+ int /* pending_host_id*/,
+ PP_NetAddress_Private /* local_addr */,
+ PP_NetAddress_Private /* remote_addr */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_TCPSocket_Close)
IPC_MESSAGE_CONTROL2(PpapiHostMsg_TCPSocket_SetOption,
PP_TCPSocket_Option /* name */,
ppapi::SocketOptionData /* value */)
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 60841022..ea01f6e 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -323,9 +323,17 @@
GetReference();
}
+PP_Resource ResourceCreationProxy::CreateTCPSocket1_0(
+ PP_Instance instance) {
+ return (new TCPSocketResource(GetConnection(), instance,
+ TCP_SOCKET_VERSION_1_0))->GetReference();
+}
+
PP_Resource ResourceCreationProxy::CreateTCPSocket(
PP_Instance instance) {
- return (new TCPSocketResource(GetConnection(), instance))->GetReference();
+ return (new TCPSocketResource(
+ GetConnection(), instance, TCP_SOCKET_VERSION_1_1_OR_ABOVE))->
+ GetReference();
}
PP_Resource ResourceCreationProxy::CreateTCPSocketPrivate(
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 210e23c..509b1557 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -138,6 +138,7 @@
virtual PP_Resource CreatePrinting(PP_Instance) OVERRIDE;
virtual PP_Resource CreateTCPServerSocketPrivate(
PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateTCPSocket1_0(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE;
diff --git a/ppapi/proxy/tcp_socket_private_resource.cc b/ppapi/proxy/tcp_socket_private_resource.cc
index 0698e49..76ed4b9e1 100644
--- a/ppapi/proxy/tcp_socket_private_resource.cc
+++ b/ppapi/proxy/tcp_socket_private_resource.cc
@@ -5,13 +5,14 @@
#include "ppapi/proxy/tcp_socket_private_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
namespace ppapi {
namespace proxy {
TCPSocketPrivateResource::TCPSocketPrivateResource(Connection connection,
PP_Instance instance)
- : TCPSocketResourceBase(connection, instance, true) {
+ : TCPSocketResourceBase(connection, instance, TCP_SOCKET_VERSION_PRIVATE) {
SendCreate(BROWSER, PpapiHostMsg_TCPSocket_CreatePrivate());
}
@@ -21,14 +22,12 @@
int pending_resource_id,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr)
- : TCPSocketResourceBase(connection, instance, true,
- local_addr,
- remote_addr) {
+ : TCPSocketResourceBase(connection, instance, TCP_SOCKET_VERSION_PRIVATE,
+ local_addr, remote_addr) {
AttachToPendingHost(BROWSER, pending_resource_id);
}
TCPSocketPrivateResource::~TCPSocketPrivateResource() {
- DisconnectImpl();
}
thunk::PPB_TCPSocket_Private_API*
@@ -91,7 +90,7 @@
}
void TCPSocketPrivateResource::Disconnect() {
- DisconnectImpl();
+ CloseImpl();
}
int32_t TCPSocketPrivateResource::SetOption(
@@ -109,5 +108,13 @@
}
}
+PP_Resource TCPSocketPrivateResource::CreateAcceptedSocket(
+ int /* pending_host_id */,
+ const PP_NetAddress_Private& /* local_addr */,
+ const PP_NetAddress_Private& /* remote_addr */) {
+ NOTREACHED();
+ return 0;
+}
+
} // namespace proxy
} // namespace ppapi
diff --git a/ppapi/proxy/tcp_socket_private_resource.h b/ppapi/proxy/tcp_socket_private_resource.h
index f79ab9d..9ae9bb2 100644
--- a/ppapi/proxy/tcp_socket_private_resource.h
+++ b/ppapi/proxy/tcp_socket_private_resource.h
@@ -59,6 +59,12 @@
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ // TCPSocketResourceBase implementation.
+ virtual PP_Resource CreateAcceptedSocket(
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) OVERRIDE;
+
private:
DISALLOW_COPY_AND_ASSIGN(TCPSocketPrivateResource);
};
diff --git a/ppapi/proxy/tcp_socket_resource.cc b/ppapi/proxy/tcp_socket_resource.cc
index 085aab3..f8f8f68 100644
--- a/ppapi/proxy/tcp_socket_resource.cc
+++ b/ppapi/proxy/tcp_socket_resource.cc
@@ -4,7 +4,9 @@
#include "ppapi/proxy/tcp_socket_resource.h"
+#include "base/logging.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_net_address_api.h"
@@ -19,19 +21,40 @@
} // namespace
TCPSocketResource::TCPSocketResource(Connection connection,
- PP_Instance instance)
- : TCPSocketResourceBase(connection, instance, false) {
- SendCreate(BROWSER, PpapiHostMsg_TCPSocket_Create());
+ PP_Instance instance,
+ TCPSocketVersion version)
+ : TCPSocketResourceBase(connection, instance, version) {
+ DCHECK_NE(version, TCP_SOCKET_VERSION_PRIVATE);
+ SendCreate(BROWSER, PpapiHostMsg_TCPSocket_Create(version));
+}
+
+TCPSocketResource::TCPSocketResource(Connection connection,
+ PP_Instance instance,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr)
+ : TCPSocketResourceBase(connection, instance,
+ TCP_SOCKET_VERSION_1_1_OR_ABOVE, local_addr,
+ remote_addr) {
+ AttachToPendingHost(BROWSER, pending_host_id);
}
TCPSocketResource::~TCPSocketResource() {
- DisconnectImpl();
}
thunk::PPB_TCPSocket_API* TCPSocketResource::AsPPB_TCPSocket_API() {
return this;
}
+int32_t TCPSocketResource::Bind(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterNetAddressNoLock enter(addr, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ return BindImpl(&enter.object()->GetNetAddressPrivate(), callback);
+}
+
int32_t TCPSocketResource::Connect(PP_Resource addr,
scoped_refptr<TrackedCallback> callback) {
EnterNetAddressNoLock enter(addr, true);
@@ -78,8 +101,18 @@
return WriteImpl(buffer, bytes_to_write, callback);
}
+int32_t TCPSocketResource::Listen(int32_t backlog,
+ scoped_refptr<TrackedCallback> callback) {
+ return ListenImpl(backlog, callback);
+}
+
+int32_t TCPSocketResource::Accept(PP_Resource* accepted_tcp_socket,
+ scoped_refptr<TrackedCallback> callback) {
+ return AcceptImpl(accepted_tcp_socket, callback);
+}
+
void TCPSocketResource::Close() {
- DisconnectImpl();
+ CloseImpl();
}
int32_t TCPSocketResource::SetOption(PP_TCPSocket_Option name,
@@ -88,5 +121,13 @@
return SetOptionImpl(name, value, callback);
}
+PP_Resource TCPSocketResource::CreateAcceptedSocket(
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ return (new TCPSocketResource(connection(), pp_instance(), pending_host_id,
+ local_addr, remote_addr))->GetReference();
+}
+
} // namespace proxy
} // namespace ppapi
diff --git a/ppapi/proxy/tcp_socket_resource.h b/ppapi/proxy/tcp_socket_resource.h
index 05b4fe38..5dbfdd54 100644
--- a/ppapi/proxy/tcp_socket_resource.h
+++ b/ppapi/proxy/tcp_socket_resource.h
@@ -11,18 +11,27 @@
#include "ppapi/thunk/ppb_tcp_socket_api.h"
namespace ppapi {
+
+enum TCPSocketVersion;
+
namespace proxy {
class PPAPI_PROXY_EXPORT TCPSocketResource : public thunk::PPB_TCPSocket_API,
public TCPSocketResourceBase {
public:
- TCPSocketResource(Connection connection, PP_Instance instance);
+ // C-tor used for new sockets created.
+ TCPSocketResource(Connection connection,
+ PP_Instance instance,
+ TCPSocketVersion version);
+
virtual ~TCPSocketResource();
// PluginResource overrides.
virtual thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() OVERRIDE;
// thunk::PPB_TCPSocket_API implementation.
+ virtual int32_t Bind(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
virtual int32_t Connect(PP_Resource addr,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
virtual PP_Resource GetLocalAddress() OVERRIDE;
@@ -33,12 +42,29 @@
virtual int32_t Write(const char* buffer,
int32_t bytes_to_write,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Listen(int32_t backlog,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Accept(PP_Resource* accepted_tcp_socket,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
virtual void Close() OVERRIDE;
virtual int32_t SetOption(PP_TCPSocket_Option name,
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ // TCPSocketResourceBase implementation.
+ virtual PP_Resource CreateAcceptedSocket(
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) OVERRIDE;
+
private:
+ // C-tor used for accepted sockets.
+ TCPSocketResource(Connection connection,
+ PP_Instance instance,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+
DISALLOW_COPY_AND_ASSIGN(TCPSocketResource);
};
diff --git a/ppapi/proxy/tcp_socket_resource_base.cc b/ppapi/proxy/tcp_socket_resource_base.cc
index f02895b..2590c41 100644
--- a/ppapi/proxy/tcp_socket_resource_base.cc
+++ b/ppapi/proxy/tcp_socket_resource_base.cc
@@ -32,12 +32,13 @@
TCPSocketResourceBase::TCPSocketResourceBase(Connection connection,
PP_Instance instance,
- bool private_api)
+ TCPSocketVersion version)
: PluginResource(connection, instance),
- connection_state_(BEFORE_CONNECT),
+ state_(TCPSocketState::INITIAL),
read_buffer_(NULL),
bytes_to_read_(-1),
- private_api_(private_api) {
+ accepted_tcp_socket_(NULL),
+ version_(version) {
local_addr_.size = 0;
memset(local_addr_.data, 0,
arraysize(local_addr_.data) * sizeof(*local_addr_.data));
@@ -49,19 +50,42 @@
TCPSocketResourceBase::TCPSocketResourceBase(
Connection connection,
PP_Instance instance,
- bool private_api,
+ TCPSocketVersion version,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr)
: PluginResource(connection, instance),
- connection_state_(CONNECTED),
+ state_(TCPSocketState::CONNECTED),
read_buffer_(NULL),
bytes_to_read_(-1),
local_addr_(local_addr),
remote_addr_(remote_addr),
- private_api_(private_api) {
+ accepted_tcp_socket_(NULL),
+ version_(version) {
}
TCPSocketResourceBase::~TCPSocketResourceBase() {
+ CloseImpl();
+}
+
+int32_t TCPSocketResourceBase::BindImpl(
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (state_.IsPending(TCPSocketState::BIND))
+ return PP_ERROR_INPROGRESS;
+ if (!state_.IsValidTransition(TCPSocketState::BIND))
+ return PP_ERROR_FAILED;
+
+ bind_callback_ = callback;
+ state_.SetPendingTransition(TCPSocketState::BIND);
+
+ Call<PpapiPluginMsg_TCPSocket_BindReply>(
+ BROWSER,
+ PpapiHostMsg_TCPSocket_Bind(*addr),
+ base::Bind(&TCPSocketResourceBase::OnPluginMsgBindReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
}
int32_t TCPSocketResourceBase::ConnectImpl(
@@ -70,12 +94,13 @@
scoped_refptr<TrackedCallback> callback) {
if (!host)
return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
+ if (state_.IsPending(TCPSocketState::CONNECT))
+ return PP_ERROR_INPROGRESS;
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT))
return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
connect_callback_ = callback;
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
Call<PpapiPluginMsg_TCPSocket_ConnectReply>(
BROWSER,
@@ -90,12 +115,13 @@
scoped_refptr<TrackedCallback> callback) {
if (!addr)
return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
+ if (state_.IsPending(TCPSocketState::CONNECT))
+ return PP_ERROR_INPROGRESS;
+ if (!state_.IsValidTransition(TCPSocketState::CONNECT))
return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
connect_callback_ = callback;
+ state_.SetPendingTransition(TCPSocketState::CONNECT);
Call<PpapiPluginMsg_TCPSocket_ConnectReply>(
BROWSER,
@@ -107,7 +133,7 @@
PP_Bool TCPSocketResourceBase::GetLocalAddressImpl(
PP_NetAddress_Private* local_addr) {
- if (!IsConnected() || !local_addr)
+ if (!state_.IsBound() || !local_addr)
return PP_FALSE;
*local_addr = local_addr_;
return PP_TRUE;
@@ -115,7 +141,7 @@
PP_Bool TCPSocketResourceBase::GetRemoteAddressImpl(
PP_NetAddress_Private* remote_addr) {
- if (!IsConnected() || !remote_addr)
+ if (!state_.IsConnected() || !remote_addr)
return PP_FALSE;
*remote_addr = remote_addr_;
return PP_TRUE;
@@ -128,15 +154,16 @@
if (!server_name)
return PP_ERROR_BADARGUMENT;
- if (connection_state_ != CONNECTED)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(ssl_handshake_callback_) ||
+ if (state_.IsPending(TCPSocketState::SSL_CONNECT) ||
TrackedCallback::IsPending(read_callback_) ||
TrackedCallback::IsPending(write_callback_)) {
return PP_ERROR_INPROGRESS;
}
+ if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT))
+ return PP_ERROR_FAILED;
ssl_handshake_callback_ = callback;
+ state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
Call<PpapiPluginMsg_TCPSocket_SSLHandshakeReply>(
BROWSER,
@@ -193,10 +220,10 @@
if (!buffer || bytes_to_read <= 0)
return PP_ERROR_BADARGUMENT;
- if (!IsConnected())
+ if (!state_.IsConnected())
return PP_ERROR_FAILED;
if (TrackedCallback::IsPending(read_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
+ state_.IsPending(TCPSocketState::SSL_CONNECT))
return PP_ERROR_INPROGRESS;
read_buffer_ = buffer;
bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
@@ -217,10 +244,10 @@
if (!buffer || bytes_to_write <= 0)
return PP_ERROR_BADARGUMENT;
- if (!IsConnected())
+ if (!state_.IsConnected())
return PP_ERROR_FAILED;
if (TrackedCallback::IsPending(write_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
+ state_.IsPending(TCPSocketState::SSL_CONNECT))
return PP_ERROR_INPROGRESS;
if (bytes_to_write > kMaxWriteSize)
@@ -236,33 +263,79 @@
return PP_OK_COMPLETIONPENDING;
}
-void TCPSocketResourceBase::DisconnectImpl() {
- if (connection_state_ == DISCONNECTED)
+int32_t TCPSocketResourceBase::ListenImpl(
+ int32_t backlog,
+ scoped_refptr<TrackedCallback> callback) {
+ if (backlog <= 0)
+ return PP_ERROR_BADARGUMENT;
+ if (state_.IsPending(TCPSocketState::LISTEN))
+ return PP_ERROR_INPROGRESS;
+ if (!state_.IsValidTransition(TCPSocketState::LISTEN))
+ return PP_ERROR_FAILED;
+
+ listen_callback_ = callback;
+ state_.SetPendingTransition(TCPSocketState::LISTEN);
+
+ Call<PpapiPluginMsg_TCPSocket_ListenReply>(
+ BROWSER,
+ PpapiHostMsg_TCPSocket_Listen(backlog),
+ base::Bind(&TCPSocketResourceBase::OnPluginMsgListenReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPSocketResourceBase::AcceptImpl(
+ PP_Resource* accepted_tcp_socket,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!accepted_tcp_socket)
+ return PP_ERROR_BADARGUMENT;
+ if (TrackedCallback::IsPending(accept_callback_))
+ return PP_ERROR_INPROGRESS;
+ if (state_.state() != TCPSocketState::LISTENING)
+ return PP_ERROR_FAILED;
+
+ accept_callback_ = callback;
+ accepted_tcp_socket_ = accepted_tcp_socket;
+
+ Call<PpapiPluginMsg_TCPSocket_AcceptReply>(
+ BROWSER,
+ PpapiHostMsg_TCPSocket_Accept(),
+ base::Bind(&TCPSocketResourceBase::OnPluginMsgAcceptReply,
+ base::Unretained(this)));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TCPSocketResourceBase::CloseImpl() {
+ if (state_.state() == TCPSocketState::CLOSED)
return;
- connection_state_ = DISCONNECTED;
+ state_.DoTransition(TCPSocketState::CLOSE, true);
- Post(BROWSER, PpapiHostMsg_TCPSocket_Disconnect());
+ Post(BROWSER, PpapiHostMsg_TCPSocket_Close());
+ PostAbortIfNecessary(&bind_callback_);
PostAbortIfNecessary(&connect_callback_);
PostAbortIfNecessary(&ssl_handshake_callback_);
PostAbortIfNecessary(&read_callback_);
PostAbortIfNecessary(&write_callback_);
+ PostAbortIfNecessary(&listen_callback_);
+ PostAbortIfNecessary(&accept_callback_);
read_buffer_ = NULL;
bytes_to_read_ = -1;
server_certificate_ = NULL;
+ accepted_tcp_socket_ = NULL;
}
int32_t TCPSocketResourceBase::SetOptionImpl(
PP_TCPSocket_Option name,
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) {
- if (!IsConnected())
- return PP_ERROR_FAILED;
-
SocketOptionData option_data;
switch (name) {
case PP_TCPSOCKET_OPTION_NO_DELAY: {
+ if (!state_.IsConnected())
+ return PP_ERROR_FAILED;
+
if (value.type != PP_VARTYPE_BOOL)
return PP_ERROR_BADARGUMENT;
option_data.SetBool(PP_ToBool(value.value.as_bool));
@@ -270,11 +343,25 @@
}
case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
+ if (!state_.IsConnected())
+ return PP_ERROR_FAILED;
+
if (value.type != PP_VARTYPE_INT32)
return PP_ERROR_BADARGUMENT;
option_data.SetInt32(value.value.as_int);
break;
}
+ case PP_TCPSOCKET_OPTION_ADDRESS_REUSE: {
+ if (version_ != TCP_SOCKET_VERSION_1_1_OR_ABOVE)
+ return PP_ERROR_NOTSUPPORTED;
+ if (state_.state() != TCPSocketState::INITIAL)
+ return PP_ERROR_FAILED;
+
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_ERROR_BADARGUMENT;
+ option_data.SetBool(PP_ToBool(value.value.as_bool));
+ break;
+ }
default: {
NOTREACHED();
return PP_ERROR_BADARGUMENT;
@@ -291,34 +378,52 @@
return PP_OK_COMPLETIONPENDING;
}
-bool TCPSocketResourceBase::IsConnected() const {
- return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
-}
-
void TCPSocketResourceBase::PostAbortIfNecessary(
scoped_refptr<TrackedCallback>* callback) {
if (TrackedCallback::IsPending(*callback))
(*callback)->PostAbort();
}
+void TCPSocketResourceBase::OnPluginMsgBindReply(
+ const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& local_addr) {
+ // It is possible that CloseImpl() has been called. We don't want to update
+ // class members in this case.
+ if (!state_.IsPending(TCPSocketState::BIND))
+ return;
+
+ DCHECK(TrackedCallback::IsPending(bind_callback_));
+ if (params.result() == PP_OK) {
+ local_addr_ = local_addr;
+ state_.CompletePendingTransition(true);
+ } else {
+ state_.CompletePendingTransition(false);
+ }
+ RunCallback(bind_callback_, params.result());
+}
+
void TCPSocketResourceBase::OnPluginMsgConnectReply(
const ResourceMessageReplyParams& params,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr) {
- // It is possible that |connect_callback_| is pending while
- // |connection_state_| is not BEFORE_CONNECT: DisconnectImpl() has been
- // called, but a ConnectCompleted notification came earlier than the task to
- // abort |connect_callback_|. We don't want to update |connection_state_| or
- // other members in that case.
- if (connection_state_ != BEFORE_CONNECT ||
- !TrackedCallback::IsPending(connect_callback_)) {
+ // It is possible that CloseImpl() has been called. We don't want to update
+ // class members in this case.
+ if (!state_.IsPending(TCPSocketState::CONNECT))
return;
- }
+ DCHECK(TrackedCallback::IsPending(connect_callback_));
if (params.result() == PP_OK) {
local_addr_ = local_addr;
remote_addr_ = remote_addr;
- connection_state_ = CONNECTED;
+ state_.CompletePendingTransition(true);
+ } else {
+ if (version_ == TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
+ state_.CompletePendingTransition(false);
+ } else {
+ // In order to maintain backward compatibility, allow to connect the
+ // socket again.
+ state_ = TCPSocketState(TCPSocketState::INITIAL);
+ }
}
RunCallback(connect_callback_, params.result());
}
@@ -326,42 +431,33 @@
void TCPSocketResourceBase::OnPluginMsgSSLHandshakeReply(
const ResourceMessageReplyParams& params,
const PPB_X509Certificate_Fields& certificate_fields) {
- // It is possible that |ssl_handshake_callback_| is pending while
- // |connection_state_| is not CONNECT: DisconnectImpl() has been
- // called, but a SSLHandshakeCompleted notification came earlier than the task
- // to abort |ssl_handshake_callback_|. We don't want to update
- // |connection_state_| or other members in that case.
- if (connection_state_ != CONNECTED ||
- !TrackedCallback::IsPending(ssl_handshake_callback_)) {
+ // It is possible that CloseImpl() has been called. We don't want to
+ // update class members in this case.
+ if (!state_.IsPending(TCPSocketState::SSL_CONNECT))
return;
- }
+ DCHECK(TrackedCallback::IsPending(ssl_handshake_callback_));
if (params.result() == PP_OK) {
- connection_state_ = SSL_CONNECTED;
+ state_.CompletePendingTransition(true);
server_certificate_ = new PPB_X509Certificate_Private_Shared(
OBJECT_IS_PROXY,
pp_instance(),
certificate_fields);
- RunCallback(ssl_handshake_callback_, params.result());
} else {
- // The resource might be released in the callback so we need to hold
- // a reference so we can Disconnect() first.
- AddRef();
- RunCallback(ssl_handshake_callback_, params.result());
- DisconnectImpl();
- Release();
+ state_.CompletePendingTransition(false);
}
+ RunCallback(ssl_handshake_callback_, params.result());
}
void TCPSocketResourceBase::OnPluginMsgReadReply(
const ResourceMessageReplyParams& params,
const std::string& data) {
- // It is possible that |read_callback_| is pending while |read_buffer_| is
- // NULL: DisconnectImpl() has been called, but a ReadCompleted notification
- // came earlier than the task to abort |read_callback_|. We shouldn't access
- // the buffer in that case. The user may have released it.
- if (!TrackedCallback::IsPending(read_callback_) || !read_buffer_)
+ // It is possible that CloseImpl() has been called. We shouldn't access the
+ // buffer in that case. The user may have released it.
+ if (!state_.IsConnected() || !TrackedCallback::IsPending(read_callback_) ||
+ !read_buffer_) {
return;
+ }
const bool succeeded = params.result() == PP_OK;
if (succeeded) {
@@ -372,19 +468,48 @@
read_buffer_ = NULL;
bytes_to_read_ = -1;
- read_callback_->Run(succeeded ?
- static_cast<int32_t>(data.size()) :
- ConvertNetworkAPIErrorForCompatibility(params.result(),
- private_api_));
+ RunCallback(read_callback_,
+ succeeded ? static_cast<int32_t>(data.size()) : params.result());
}
void TCPSocketResourceBase::OnPluginMsgWriteReply(
const ResourceMessageReplyParams& params) {
- if (!TrackedCallback::IsPending(write_callback_))
+ if (!state_.IsConnected() || !TrackedCallback::IsPending(write_callback_))
return;
RunCallback(write_callback_, params.result());
}
+void TCPSocketResourceBase::OnPluginMsgListenReply(
+ const ResourceMessageReplyParams& params) {
+ if (!state_.IsPending(TCPSocketState::LISTEN))
+ return;
+
+ DCHECK(TrackedCallback::IsPending(listen_callback_));
+ state_.CompletePendingTransition(params.result() == PP_OK);
+
+ RunCallback(listen_callback_, params.result());
+}
+
+void TCPSocketResourceBase::OnPluginMsgAcceptReply(
+ const ResourceMessageReplyParams& params,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ // It is possible that CloseImpl() has been called. We shouldn't access the
+ // output parameter in that case. The user may have released it.
+ if (state_.state() != TCPSocketState::LISTENING ||
+ !TrackedCallback::IsPending(accept_callback_) || !accepted_tcp_socket_) {
+ return;
+ }
+
+ if (params.result() == PP_OK) {
+ *accepted_tcp_socket_ = CreateAcceptedSocket(pending_host_id, local_addr,
+ remote_addr);
+ }
+ accepted_tcp_socket_ = NULL;
+ RunCallback(accept_callback_, params.result());
+}
+
void TCPSocketResourceBase::OnPluginMsgSetOptionReply(
const ResourceMessageReplyParams& params) {
if (set_option_callbacks_.empty()) {
@@ -399,8 +524,8 @@
void TCPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback,
int32_t pp_result) {
- callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result,
- private_api_));
+ callback->Run(ConvertNetworkAPIErrorForCompatibility(
+ pp_result, version_ == TCP_SOCKET_VERSION_PRIVATE));
}
} // namespace ppapi
diff --git a/ppapi/proxy/tcp_socket_resource_base.h b/ppapi/proxy/tcp_socket_resource_base.h
index 7e8a481..8835ab97 100644
--- a/ppapi/proxy/tcp_socket_resource_base.h
+++ b/ppapi/proxy/tcp_socket_resource_base.h
@@ -15,6 +15,7 @@
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/ppb_tcp_socket_shared.h"
#include "ppapi/shared_impl/tracked_callback.h"
namespace ppapi {
@@ -27,6 +28,7 @@
class PPAPI_PROXY_EXPORT TCPSocketResourceBase : public PluginResource {
public:
+ // TODO(yzshen): Move these constants to ppb_tcp_socket_shared.
// The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read
// message is allowed to request.
static const int32_t kMaxReadSize;
@@ -46,33 +48,28 @@
static const int32_t kMaxReceiveBufferSize;
protected:
- enum ConnectionState {
- // Before a connection is successfully established (including a connect
- // request is pending or a previous connect request failed).
- BEFORE_CONNECT,
- // A connection has been successfully established (including a request of
- // initiating SSL is pending).
- CONNECTED,
- // An SSL connection has been successfully established.
- SSL_CONNECTED,
- // The connection has been ended.
- DISCONNECTED
- };
-
// C-tor used for new sockets.
TCPSocketResourceBase(Connection connection,
PP_Instance instance,
- bool private_api);
+ TCPSocketVersion version);
// C-tor used for already accepted sockets.
TCPSocketResourceBase(Connection connection,
PP_Instance instance,
- bool private_api,
+ TCPSocketVersion version,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr);
virtual ~TCPSocketResourceBase();
+ // Implemented by subclasses to create resources for accepted sockets.
+ virtual PP_Resource CreateAcceptedSocket(
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) = 0;
+
+ int32_t BindImpl(const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback);
int32_t ConnectImpl(const char* host,
uint16_t port,
scoped_refptr<TrackedCallback> callback);
@@ -92,15 +89,19 @@
int32_t WriteImpl(const char* buffer,
int32_t bytes_to_write,
scoped_refptr<TrackedCallback> callback);
- void DisconnectImpl();
+ int32_t ListenImpl(int32_t backlog, scoped_refptr<TrackedCallback> callback);
+ int32_t AcceptImpl(PP_Resource* accepted_tcp_socket,
+ scoped_refptr<TrackedCallback> callback);
+ void CloseImpl();
int32_t SetOptionImpl(PP_TCPSocket_Option name,
const PP_Var& value,
scoped_refptr<TrackedCallback> callback);
- bool IsConnected() const;
void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
// IPC message handlers.
+ void OnPluginMsgBindReply(const ResourceMessageReplyParams& params,
+ const PP_NetAddress_Private& local_addr);
void OnPluginMsgConnectReply(const ResourceMessageReplyParams& params,
const PP_NetAddress_Private& local_addr,
const PP_NetAddress_Private& remote_addr);
@@ -110,15 +111,23 @@
void OnPluginMsgReadReply(const ResourceMessageReplyParams& params,
const std::string& data);
void OnPluginMsgWriteReply(const ResourceMessageReplyParams& params);
+ void OnPluginMsgListenReply(const ResourceMessageReplyParams& params);
+ void OnPluginMsgAcceptReply(const ResourceMessageReplyParams& params,
+ int pending_host_id,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
void OnPluginMsgSetOptionReply(const ResourceMessageReplyParams& params);
+ scoped_refptr<TrackedCallback> bind_callback_;
scoped_refptr<TrackedCallback> connect_callback_;
scoped_refptr<TrackedCallback> ssl_handshake_callback_;
scoped_refptr<TrackedCallback> read_callback_;
scoped_refptr<TrackedCallback> write_callback_;
+ scoped_refptr<TrackedCallback> listen_callback_;
+ scoped_refptr<TrackedCallback> accept_callback_;
std::queue<scoped_refptr<TrackedCallback> > set_option_callbacks_;
- ConnectionState connection_state_;
+ TCPSocketState state_;
char* read_buffer_;
int32_t bytes_to_read_;
@@ -130,10 +139,12 @@
std::vector<std::vector<char> > trusted_certificates_;
std::vector<std::vector<char> > untrusted_certificates_;
+ PP_Resource* accepted_tcp_socket_;
+
private:
void RunCallback(scoped_refptr<TrackedCallback> callback, int32_t pp_result);
- bool private_api_;
+ TCPSocketVersion version_;
DISALLOW_COPY_AND_ASSIGN(TCPSocketResourceBase);
};