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

Side by Side Diff: ppapi/proxy/ppb_tcp_socket_private_proxy.cc

Issue 8688002: PPB_TCPSocket_Private/PPB_UDPSocket_Private are exposed to Browser (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed codereview issues. Created 9 years 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" 5 #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
6 6
7 #include <algorithm>
8 #include <cstring>
9 #include <map> 7 #include <map>
8 #include <string>
yzshen1 2011/11/29 20:19:33 You have included it in .h file.
ygorshenin 2011/11/30 11:50:54 Done.
10 9
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h" 10 #include "base/message_loop.h"
14 #include "base/task.h" 11 #include "base/task.h"
15 #include "ppapi/c/pp_errors.h" 12 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/proxy/plugin_dispatcher.h" 13 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/plugin_resource_tracker.h" 14 #include "ppapi/proxy/plugin_resource_tracker.h"
18 #include "ppapi/proxy/ppapi_messages.h" 15 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/shared_impl/resource.h" 16 #include "ppapi/shared_impl/resource.h"
20 #include "ppapi/thunk/ppb_tcp_socket_private_api.h" 17 #include "ppapi/shared_impl/tcp_socket_impl.h"
21 #include "ppapi/thunk/thunk.h" 18 #include "ppapi/thunk/thunk.h"
22 19
23 using ppapi::thunk::PPB_TCPSocket_Private_API;
24
25 namespace ppapi { 20 namespace ppapi {
26 namespace proxy { 21 namespace proxy {
27 22
28 const int32_t kTCPSocketMaxReadSize = 1024 * 1024;
29 const int32_t kTCPSocketMaxWriteSize = 1024 * 1024;
30
31 class TCPSocket;
32
33 namespace { 23 namespace {
34 24
35 typedef std::map<uint32, TCPSocket*> IDToSocketMap; 25 typedef std::map<uint32, TCPSocketImpl*> IDToSocketMap;
36 IDToSocketMap* g_id_to_socket = NULL; 26 IDToSocketMap* g_id_to_socket = NULL;
37 27
38 class AbortCallbackTask : public Task { 28 class AbortCallbackTask : public Task {
39 public: 29 public:
40 explicit AbortCallbackTask(PP_CompletionCallback callback) 30 explicit AbortCallbackTask(PP_CompletionCallback callback)
41 : callback_(callback) {} 31 : callback_(callback) {}
42 virtual ~AbortCallbackTask() {} 32 virtual ~AbortCallbackTask() {}
43 virtual void Run() { 33 virtual void Run() {
44 if (callback_.func) 34 if (callback_.func)
45 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED); 35 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
46 } 36 }
47 37
48 private: 38 private:
49 PP_CompletionCallback callback_; 39 PP_CompletionCallback callback_;
50 }; 40 };
51 41
52 } // namespace 42 class TCPSocket : public TCPSocketImpl {
53
54 class TCPSocket : public PPB_TCPSocket_Private_API,
55 public Resource {
56 public: 43 public:
57 TCPSocket(const HostResource& resource, uint32 socket_id); 44 TCPSocket(const HostResource& resource, uint32 socket_id);
58 virtual ~TCPSocket(); 45 virtual ~TCPSocket();
59 46
60 // Resource overrides. 47 virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE;
61 virtual PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() OVERRIDE; 48 virtual void SendConnectWithNetAddress(
62 49 const PP_NetAddress_Private& addr) OVERRIDE;
63 // PPB_TCPSocket_Private_API implementation. 50 virtual void SendSSLHandshake(const std::string& server_name,
64 virtual int32_t Connect(const char* host, 51 uint16_t server_port) OVERRIDE;
65 uint16_t port, 52 virtual void SendRead(int32_t bytes_to_read) OVERRIDE;
66 PP_CompletionCallback callback) OVERRIDE; 53 virtual void SendWrite(const std::string& buffer) OVERRIDE;
67 virtual int32_t ConnectWithNetAddress( 54 virtual void SendDisconnect() OVERRIDE;
68 const PP_NetAddress_Private* addr, 55 virtual void PostAbort(PP_CompletionCallback callback) OVERRIDE;
69 PP_CompletionCallback callback) OVERRIDE;
70 virtual PP_Bool GetLocalAddress(PP_NetAddress_Private* local_addr) OVERRIDE;
71 virtual PP_Bool GetRemoteAddress(PP_NetAddress_Private* remote_addr) OVERRIDE;
72 virtual int32_t SSLHandshake(const char* server_name,
73 uint16_t server_port,
74 PP_CompletionCallback callback) OVERRIDE;
75 virtual int32_t Read(char* buffer,
76 int32_t bytes_to_read,
77 PP_CompletionCallback callback) OVERRIDE;
78 virtual int32_t Write(const char* buffer,
79 int32_t bytes_to_write,
80 PP_CompletionCallback callback) OVERRIDE;
81 virtual void Disconnect() OVERRIDE;
82
83 // Notifications from the proxy.
84 void OnConnectCompleted(bool succeeded,
85 const PP_NetAddress_Private& local_addr,
86 const PP_NetAddress_Private& remote_addr);
87 void OnSSLHandshakeCompleted(bool succeeded);
88 void OnReadCompleted(bool succeeded, const std::string& data);
89 void OnWriteCompleted(bool succeeded, int32_t bytes_written);
90 56
91 private: 57 private:
92 enum ConnectionState { 58 void SendToBrowser(IPC::Message* msg);
93 // Before a connection is successfully established (including a connect
94 // request is pending or a previous connect request failed).
95 BEFORE_CONNECT,
96 // A connection has been successfully established (including a request of
97 // initiating SSL is pending).
98 CONNECTED,
99 // An SSL connection has been successfully established.
100 SSL_CONNECTED,
101 // The connection has been ended.
102 DISCONNECTED
103 };
104
105 bool IsConnected() const;
106
107 PluginDispatcher* GetDispatcher() const {
108 return PluginDispatcher::GetForResource(this);
109 }
110
111 // Backend for both Connect() and ConnectWithNetAddress(). To keep things
112 // generic, the message is passed in (on error, it's deleted).
113 int32_t ConnectWithMessage(IPC::Message* msg,
114 PP_CompletionCallback callback);
115
116 void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback);
117
118 uint32 socket_id_;
119 ConnectionState connection_state_;
120
121 PP_CompletionCallback connect_callback_;
122 PP_CompletionCallback ssl_handshake_callback_;
123 PP_CompletionCallback read_callback_;
124 PP_CompletionCallback write_callback_;
125
126 char* read_buffer_;
127 int32_t bytes_to_read_;
128
129 PP_NetAddress_Private local_addr_;
130 PP_NetAddress_Private remote_addr_;
131 59
132 DISALLOW_COPY_AND_ASSIGN(TCPSocket); 60 DISALLOW_COPY_AND_ASSIGN(TCPSocket);
133 }; 61 };
134 62
135 TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id) 63 TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id)
136 : Resource(resource), 64 : TCPSocketImpl(resource, socket_id) {
137 socket_id_(socket_id),
138 connection_state_(BEFORE_CONNECT),
139 connect_callback_(PP_BlockUntilComplete()),
140 ssl_handshake_callback_(PP_BlockUntilComplete()),
141 read_callback_(PP_BlockUntilComplete()),
142 write_callback_(PP_BlockUntilComplete()),
143 read_buffer_(NULL),
144 bytes_to_read_(-1) {
145 DCHECK(socket_id != 0);
146
147 local_addr_.size = 0;
148 memset(local_addr_.data, 0, sizeof(local_addr_.data));
149 remote_addr_.size = 0;
150 memset(remote_addr_.data, 0, sizeof(remote_addr_.data));
151
152 if (!g_id_to_socket) 65 if (!g_id_to_socket)
153 g_id_to_socket = new IDToSocketMap(); 66 g_id_to_socket = new IDToSocketMap();
154 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); 67 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
155 (*g_id_to_socket)[socket_id] = this; 68 (*g_id_to_socket)[socket_id] = this;
156 } 69 }
157 70
158 TCPSocket::~TCPSocket() { 71 TCPSocket::~TCPSocket() {
159 Disconnect(); 72 Disconnect();
160 } 73 }
161 74
162 PPB_TCPSocket_Private_API* TCPSocket::AsPPB_TCPSocket_Private_API() { 75 void TCPSocket::SendConnect(const std::string& host, uint16_t port) {
163 return this; 76 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Connect(socket_id_, host, port));
164 } 77 }
165 78
166 int32_t TCPSocket::Connect(const char* host, 79 void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) {
167 uint16_t port, 80 SendToBrowser(
168 PP_CompletionCallback callback) { 81 new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(socket_id_, addr));
169 if (!host)
170 return PP_ERROR_BADARGUMENT;
171
172 return ConnectWithMessage(
173 new PpapiHostMsg_PPBTCPSocket_Connect(socket_id_, host, port),
174 callback);
175 } 82 }
176 83
177 int32_t TCPSocket::ConnectWithNetAddress( 84 void TCPSocket::SendSSLHandshake(const std::string& server_name,
178 const PP_NetAddress_Private* addr, 85 uint16_t server_port) {
179 PP_CompletionCallback callback) { 86 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_SSLHandshake(
180 if (!addr) 87 socket_id_, server_name, server_port));
181 return PP_ERROR_BADARGUMENT;
182
183 return ConnectWithMessage(
184 new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
185 socket_id_, *addr),
186 callback);
187 } 88 }
188 89
189 PP_Bool TCPSocket::GetLocalAddress(PP_NetAddress_Private* local_addr) { 90 void TCPSocket::SendRead(int32_t bytes_to_read) {
190 if (!IsConnected() || !local_addr) 91 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read));
191 return PP_FALSE;
192
193 *local_addr = local_addr_;
194 return PP_TRUE;
195 } 92 }
196 93
197 PP_Bool TCPSocket::GetRemoteAddress(PP_NetAddress_Private* remote_addr) { 94 void TCPSocket::SendWrite(const std::string& buffer) {
198 if (!IsConnected() || !remote_addr) 95 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer));
199 return PP_FALSE;
200
201 *remote_addr = remote_addr_;
202 return PP_TRUE;
203 } 96 }
204 97
205 int32_t TCPSocket::SSLHandshake(const char* server_name, 98 void TCPSocket::SendDisconnect() {
206 uint16_t server_port,
207 PP_CompletionCallback callback) {
208 if (!server_name)
209 return PP_ERROR_BADARGUMENT;
210 if (!callback.func)
211 return PP_ERROR_BLOCKS_MAIN_THREAD;
212
213 if (connection_state_ != CONNECTED)
214 return PP_ERROR_FAILED;
215 if (ssl_handshake_callback_.func || read_callback_.func ||
216 write_callback_.func)
217 return PP_ERROR_INPROGRESS;
218
219 ssl_handshake_callback_ = callback;
220
221 // Send the request, the browser will call us back via SSLHandshakeACK.
222 GetDispatcher()->SendToBrowser(
223 new PpapiHostMsg_PPBTCPSocket_SSLHandshake(
224 socket_id_, std::string(server_name), server_port));
225 return PP_OK_COMPLETIONPENDING;
226 }
227
228 int32_t TCPSocket::Read(char* buffer,
229 int32_t bytes_to_read,
230 PP_CompletionCallback callback) {
231 if (!buffer || bytes_to_read <= 0)
232 return PP_ERROR_BADARGUMENT;
233 if (!callback.func)
234 return PP_ERROR_BLOCKS_MAIN_THREAD;
235
236 if (!IsConnected())
237 return PP_ERROR_FAILED;
238 if (read_callback_.func || ssl_handshake_callback_.func)
239 return PP_ERROR_INPROGRESS;
240
241 read_buffer_ = buffer;
242 bytes_to_read_ = std::min(bytes_to_read, kTCPSocketMaxReadSize);
243 read_callback_ = callback;
244
245 // Send the request, the browser will call us back via ReadACK.
246 GetDispatcher()->SendToBrowser(
247 new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read_));
248 return PP_OK_COMPLETIONPENDING;
249 }
250
251 int32_t TCPSocket::Write(const char* buffer,
252 int32_t bytes_to_write,
253 PP_CompletionCallback callback) {
254 if (!buffer || bytes_to_write <= 0)
255 return PP_ERROR_BADARGUMENT;
256 if (!callback.func)
257 return PP_ERROR_BLOCKS_MAIN_THREAD;
258
259 if (!IsConnected())
260 return PP_ERROR_FAILED;
261 if (write_callback_.func || ssl_handshake_callback_.func)
262 return PP_ERROR_INPROGRESS;
263
264 if (bytes_to_write > kTCPSocketMaxWriteSize)
265 bytes_to_write = kTCPSocketMaxWriteSize;
266
267 write_callback_ = callback;
268
269 // Send the request, the browser will call us back via WriteACK.
270 GetDispatcher()->SendToBrowser(
271 new PpapiHostMsg_PPBTCPSocket_Write(
272 socket_id_, std::string(buffer, bytes_to_write)));
273 return PP_OK_COMPLETIONPENDING;
274 }
275
276 void TCPSocket::Disconnect() {
277 if (connection_state_ == DISCONNECTED)
278 return;
279
280 connection_state_ = DISCONNECTED;
281 // After removed from the mapping, this object won't receive any notifications 99 // After removed from the mapping, this object won't receive any notifications
282 // from the proxy. 100 // from the proxy.
283 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); 101 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
284 g_id_to_socket->erase(socket_id_); 102 g_id_to_socket->erase(socket_id_);
285 103 SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
286 GetDispatcher()->SendToBrowser(
287 new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
288 socket_id_ = 0;
289
290 PostAbortAndClearIfNecessary(&connect_callback_);
291 PostAbortAndClearIfNecessary(&ssl_handshake_callback_);
292 PostAbortAndClearIfNecessary(&read_callback_);
293 PostAbortAndClearIfNecessary(&write_callback_);
294 read_buffer_ = NULL;
295 bytes_to_read_ = -1;
296 } 104 }
297 105
298 void TCPSocket::OnConnectCompleted( 106 void TCPSocket::PostAbort(PP_CompletionCallback callback) {
299 bool succeeded, 107 // TODO(ygorshenin): replace AbortCallbackTask with base::Bind
300 const PP_NetAddress_Private& local_addr, 108 MessageLoop::current()->PostTask(FROM_HERE, new AbortCallbackTask(callback));
301 const PP_NetAddress_Private& remote_addr) {
302 if (connection_state_ != BEFORE_CONNECT || !connect_callback_.func) {
303 NOTREACHED();
304 return;
305 }
306
307 if (succeeded) {
308 local_addr_ = local_addr;
309 remote_addr_ = remote_addr;
310 connection_state_ = CONNECTED;
311 }
312 PP_RunAndClearCompletionCallback(&connect_callback_,
313 succeeded ? PP_OK : PP_ERROR_FAILED);
314 } 109 }
315 110
316 void TCPSocket::OnSSLHandshakeCompleted(bool succeeded) { 111 void TCPSocket::SendToBrowser(IPC::Message* msg) {
317 if (connection_state_ != CONNECTED || !ssl_handshake_callback_.func) { 112 PluginDispatcher::GetForResource(this)->SendToBrowser(msg);
318 NOTREACHED();
319 return;
320 }
321
322 if (succeeded) {
323 connection_state_ = SSL_CONNECTED;
324 PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_OK);
325 } else {
326 PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_ERROR_FAILED);
327 Disconnect();
328 }
329 } 113 }
330 114
331 void TCPSocket::OnReadCompleted(bool succeeded, const std::string& data) { 115 } // namespace
332 if (!read_callback_.func || !read_buffer_) {
333 NOTREACHED();
334 return;
335 }
336 116
337 if (succeeded) { 117 //------------------------------------------------------------------------------
338 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
339 if (!data.empty())
340 memcpy(read_buffer_, data.c_str(), data.size());
341 }
342 read_buffer_ = NULL;
343 bytes_to_read_ = -1;
344
345 PP_RunAndClearCompletionCallback(
346 &read_callback_,
347 succeeded ? static_cast<int32_t>(data.size()) :
348 static_cast<int32_t>(PP_ERROR_FAILED));
349 }
350
351 void TCPSocket::OnWriteCompleted(bool succeeded, int32_t bytes_written) {
352 if (!write_callback_.func || (succeeded && bytes_written < 0)) {
353 NOTREACHED();
354 return;
355 }
356
357 PP_RunAndClearCompletionCallback(
358 &write_callback_,
359 succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
360 }
361
362 bool TCPSocket::IsConnected() const {
363 return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
364 }
365
366 int32_t TCPSocket::ConnectWithMessage(IPC::Message* msg,
367 PP_CompletionCallback callback) {
368 scoped_ptr<IPC::Message> msg_deletor(msg);
369 if (!callback.func)
370 return PP_ERROR_BLOCKS_MAIN_THREAD;
371 if (connection_state_ != BEFORE_CONNECT)
372 return PP_ERROR_FAILED;
373 if (connect_callback_.func)
374 return PP_ERROR_INPROGRESS; // Can only have one pending request.
375
376 connect_callback_ = callback;
377 // Send the request, the browser will call us back via ConnectACK.
378 GetDispatcher()->SendToBrowser(msg_deletor.release());
379 return PP_OK_COMPLETIONPENDING;
380 }
381
382 void TCPSocket::PostAbortAndClearIfNecessary(
383 PP_CompletionCallback* callback) {
384 DCHECK(callback);
385
386 if (callback->func) {
387 MessageLoop::current()->PostTask(FROM_HERE,
388 new AbortCallbackTask(*callback));
389 *callback = PP_BlockUntilComplete();
390 }
391 }
392 118
393 PPB_TCPSocket_Private_Proxy::PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher) 119 PPB_TCPSocket_Private_Proxy::PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher)
394 : InterfaceProxy(dispatcher) { 120 : InterfaceProxy(dispatcher) {
395 } 121 }
396 122
397 PPB_TCPSocket_Private_Proxy::~PPB_TCPSocket_Private_Proxy() { 123 PPB_TCPSocket_Private_Proxy::~PPB_TCPSocket_Private_Proxy() {
398 } 124 }
399 125
400 // static 126 // static
401 PP_Resource PPB_TCPSocket_Private_Proxy::CreateProxyResource( 127 PP_Resource PPB_TCPSocket_Private_Proxy::CreateProxyResource(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 return; 209 return;
484 } 210 }
485 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id); 211 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
486 if (iter == g_id_to_socket->end()) 212 if (iter == g_id_to_socket->end())
487 return; 213 return;
488 iter->second->OnWriteCompleted(succeeded, bytes_written); 214 iter->second->OnWriteCompleted(succeeded, bytes_written);
489 } 215 }
490 216
491 } // namespace proxy 217 } // namespace proxy
492 } // namespace ppapi 218 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698