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.
5 #include "ppapi/proxy/ppb_tcp_socket_proxy.h"
9 #include "base/logging.h"
10 #include "ppapi/proxy/plugin_dispatcher.h"
11 #include "ppapi/proxy/plugin_globals.h"
12 #include "ppapi/proxy/ppapi_messages.h"
13 #include "ppapi/shared_impl/resource.h"
14 #include "ppapi/shared_impl/socket_option_data.h"
15 #include "ppapi/shared_impl/tcp_socket_shared.h"
16 #include "ppapi/thunk/enter.h"
17 #include "ppapi/thunk/ppb_net_address_api.h"
18 #include "ppapi/thunk/ppb_tcp_socket_api.h"
19 #include "ppapi/thunk/thunk.h"
26 typedef thunk::EnterResourceNoLock
<thunk::PPB_NetAddress_API
>
27 EnterNetAddressNoLock
;
29 typedef std::map
<uint32
, TCPSocketShared
*> IDToSocketMap
;
30 IDToSocketMap
* g_id_to_socket
= NULL
;
32 class TCPSocket
: public thunk::PPB_TCPSocket_API
,
34 public TCPSocketShared
{
36 TCPSocket(const HostResource
& resource
, uint32 socket_id
);
39 // Resource overrides.
40 virtual thunk::PPB_TCPSocket_API
* AsPPB_TCPSocket_API() OVERRIDE
;
42 // thunk::PPB_TCPSocket_API implementation.
43 virtual int32_t Connect(PP_Resource addr
,
44 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
45 virtual PP_Resource
GetLocalAddress() OVERRIDE
;
46 virtual PP_Resource
GetRemoteAddress() OVERRIDE
;
47 virtual int32_t Read(char* buffer
,
48 int32_t bytes_to_read
,
49 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
50 virtual int32_t Write(const char* buffer
,
51 int32_t bytes_to_write
,
52 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
53 virtual void Close() OVERRIDE
;
54 virtual int32_t SetOption(PP_TCPSocket_Option name
,
56 scoped_refptr
<TrackedCallback
> callback
) OVERRIDE
;
58 // TCPSocketShared implementation.
59 virtual void SendConnect(const std::string
& host
, uint16_t port
) OVERRIDE
;
60 virtual void SendConnectWithNetAddress(
61 const PP_NetAddress_Private
& addr
) OVERRIDE
;
62 virtual void SendSSLHandshake(
63 const std::string
& server_name
,
65 const std::vector
<std::vector
<char> >& trusted_certs
,
66 const std::vector
<std::vector
<char> >& untrusted_certs
) OVERRIDE
;
67 virtual void SendRead(int32_t bytes_to_read
) OVERRIDE
;
68 virtual void SendWrite(const std::string
& buffer
) OVERRIDE
;
69 virtual void SendDisconnect() OVERRIDE
;
70 virtual void SendSetOption(PP_TCPSocket_Option name
,
71 const SocketOptionData
& value
) OVERRIDE
;
72 virtual Resource
* GetOwnerResource() OVERRIDE
;
75 void SendToBrowser(IPC::Message
* msg
);
77 DISALLOW_COPY_AND_ASSIGN(TCPSocket
);
80 TCPSocket::TCPSocket(const HostResource
& resource
, uint32 socket_id
)
81 : Resource(OBJECT_IS_PROXY
, resource
),
82 TCPSocketShared(OBJECT_IS_PROXY
, socket_id
) {
84 g_id_to_socket
= new IDToSocketMap();
85 DCHECK(g_id_to_socket
->find(socket_id
) == g_id_to_socket
->end());
86 (*g_id_to_socket
)[socket_id
] = this;
89 TCPSocket::~TCPSocket() {
93 thunk::PPB_TCPSocket_API
* TCPSocket::AsPPB_TCPSocket_API() {
97 int32_t TCPSocket::Connect(PP_Resource addr
,
98 scoped_refptr
<TrackedCallback
> callback
) {
99 EnterNetAddressNoLock
enter(addr
, true);
101 return PP_ERROR_BADARGUMENT
;
103 return ConnectWithNetAddressImpl(&enter
.object()->GetNetAddressPrivate(),
107 PP_Resource
TCPSocket::GetLocalAddress() {
108 PP_NetAddress_Private addr_private
;
109 if (!GetLocalAddressImpl(&addr_private
))
112 thunk::EnterResourceCreationNoLock
enter(pp_instance());
115 return enter
.functions()->CreateNetAddressFromNetAddressPrivate(
116 pp_instance(), addr_private
);
119 PP_Resource
TCPSocket::GetRemoteAddress() {
120 PP_NetAddress_Private addr_private
;
121 if (!GetRemoteAddressImpl(&addr_private
))
124 thunk::EnterResourceCreationNoLock
enter(pp_instance());
127 return enter
.functions()->CreateNetAddressFromNetAddressPrivate(
128 pp_instance(), addr_private
);
131 int32_t TCPSocket::Read(char* buffer
,
132 int32_t bytes_to_read
,
133 scoped_refptr
<TrackedCallback
> callback
) {
134 return ReadImpl(buffer
, bytes_to_read
, callback
);
137 int32_t TCPSocket::Write(const char* buffer
,
138 int32_t bytes_to_write
,
139 scoped_refptr
<TrackedCallback
> callback
) {
140 return WriteImpl(buffer
, bytes_to_write
, callback
);
143 void TCPSocket::Close() {
147 int32_t TCPSocket::SetOption(PP_TCPSocket_Option name
,
149 scoped_refptr
<TrackedCallback
> callback
) {
150 return SetOptionImpl(name
, value
, callback
);
153 void TCPSocket::SendConnect(const std::string
& host
, uint16_t port
) {
157 void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private
& addr
) {
158 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
159 API_ID_PPB_TCPSOCKET
, socket_id_
, addr
));
162 void TCPSocket::SendSSLHandshake(
163 const std::string
& server_name
,
164 uint16_t server_port
,
165 const std::vector
<std::vector
<char> >& trusted_certs
,
166 const std::vector
<std::vector
<char> >& untrusted_certs
) {
170 void TCPSocket::SendRead(int32_t bytes_to_read
) {
171 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_
, bytes_to_read
));
174 void TCPSocket::SendWrite(const std::string
& buffer
) {
175 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_
, buffer
));
178 void TCPSocket::SendDisconnect() {
179 // After removed from the mapping, this object won't receive any notifications
181 DCHECK(g_id_to_socket
->find(socket_id_
) != g_id_to_socket
->end());
182 g_id_to_socket
->erase(socket_id_
);
183 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_
));
186 void TCPSocket::SendSetOption(PP_TCPSocket_Option name
,
187 const SocketOptionData
& value
) {
189 new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_
, name
, value
));
192 Resource
* TCPSocket::GetOwnerResource() {
196 void TCPSocket::SendToBrowser(IPC::Message
* msg
) {
197 PluginGlobals::Get()->GetBrowserSender()->Send(msg
);
202 //------------------------------------------------------------------------------
204 PPB_TCPSocket_Proxy::PPB_TCPSocket_Proxy(Dispatcher
* dispatcher
)
205 : InterfaceProxy(dispatcher
) {
208 PPB_TCPSocket_Proxy::~PPB_TCPSocket_Proxy() {
212 PP_Resource
PPB_TCPSocket_Proxy::CreateProxyResource(PP_Instance instance
) {
213 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
217 uint32 socket_id
= 0;
218 PluginGlobals::Get()->GetBrowserSender()->Send(
219 new PpapiHostMsg_PPBTCPSocket_Create(
220 API_ID_PPB_TCPSOCKET
, dispatcher
->plugin_dispatcher_id(),
224 return (new TCPSocket(HostResource::MakeInstanceOnly(instance
),
225 socket_id
))->GetReference();
228 bool PPB_TCPSocket_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
230 IPC_BEGIN_MESSAGE_MAP(PPB_TCPSocket_Proxy
, msg
)
231 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK
,
233 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK
, OnMsgReadACK
)
234 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK
, OnMsgWriteACK
)
235 IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK
,
237 IPC_MESSAGE_UNHANDLED(handled
= false)
238 IPC_END_MESSAGE_MAP()
242 void PPB_TCPSocket_Proxy::OnMsgConnectACK(
243 uint32
/* plugin_dispatcher_id */,
246 const PP_NetAddress_Private
& local_addr
,
247 const PP_NetAddress_Private
& remote_addr
) {
248 if (!g_id_to_socket
) {
252 IDToSocketMap::iterator iter
= g_id_to_socket
->find(socket_id
);
253 if (iter
== g_id_to_socket
->end())
255 iter
->second
->OnConnectCompleted(result
, local_addr
, remote_addr
);
258 void PPB_TCPSocket_Proxy::OnMsgReadACK(uint32
/* plugin_dispatcher_id */,
261 const std::string
& data
) {
262 if (!g_id_to_socket
) {
266 IDToSocketMap::iterator iter
= g_id_to_socket
->find(socket_id
);
267 if (iter
== g_id_to_socket
->end())
269 iter
->second
->OnReadCompleted(result
, data
);
272 void PPB_TCPSocket_Proxy::OnMsgWriteACK(uint32
/* plugin_dispatcher_id */,
275 if (!g_id_to_socket
) {
279 IDToSocketMap::iterator iter
= g_id_to_socket
->find(socket_id
);
280 if (iter
== g_id_to_socket
->end())
282 iter
->second
->OnWriteCompleted(result
);
285 void PPB_TCPSocket_Proxy::OnMsgSetOptionACK(uint32
/* plugin_dispatcher_id */,
288 if (!g_id_to_socket
) {
292 IDToSocketMap::iterator iter
= g_id_to_socket
->find(socket_id
);
293 if (iter
== g_id_to_socket
->end())
295 iter
->second
->OnSetOptionCompleted(result
);