Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Unified Diff: ppapi/proxy/tcp_socket_resource_base.cc

Issue 24195004: PPB_TCPSocket: add support for TCP server socket operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ppapi/proxy/tcp_socket_resource_base.h ('k') | ppapi/shared_impl/ppb_tcp_socket_shared.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ppapi/proxy/tcp_socket_resource_base.cc
diff --git a/ppapi/proxy/tcp_socket_resource_base.cc b/ppapi/proxy/tcp_socket_resource_base.cc
index f02895b64c05d65db987932df6e31d4dae3560c0..2590c417841fefb6dafb5f9cab1681a15208696a 100644
--- a/ppapi/proxy/tcp_socket_resource_base.cc
+++ b/ppapi/proxy/tcp_socket_resource_base.cc
@@ -32,12 +32,13 @@ const int32_t TCPSocketResourceBase::kMaxReceiveBufferSize =
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,
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 @@ int32_t TCPSocketResourceBase::ConnectImpl(
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 @@ int32_t TCPSocketResourceBase::ConnectWithNetAddressImpl(
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 @@ int32_t TCPSocketResourceBase::ConnectWithNetAddressImpl(
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::GetLocalAddressImpl(
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 @@ int32_t TCPSocketResourceBase::SSLHandshakeImpl(
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 @@ int32_t TCPSocketResourceBase::ReadImpl(
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 @@ int32_t TCPSocketResourceBase::WriteImpl(
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 @@ int32_t TCPSocketResourceBase::WriteImpl(
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 @@ int32_t TCPSocketResourceBase::SetOptionImpl(
}
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 @@ int32_t TCPSocketResourceBase::SetOptionImpl(
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::OnPluginMsgConnectReply(
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 @@ void TCPSocketResourceBase::OnPluginMsgReadReply(
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::OnPluginMsgSetOptionReply(
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
« no previous file with comments | « ppapi/proxy/tcp_socket_resource_base.h ('k') | ppapi/shared_impl/ppb_tcp_socket_shared.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698