OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ppapi/shared_impl/tcp_socket_impl.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "ppapi/c/pp_errors.h" | |
9 | |
10 namespace ppapi { | |
11 | |
12 const int32_t TCPSocketImpl::kMaxReadSize = 1024 * 1024; | |
13 const int32_t TCPSocketImpl::kMaxWriteSize = 1024 * 1024; | |
14 | |
15 TCPSocketImpl::TCPSocketImpl(const HostResource& resource, uint32 socket_id) | |
16 : Resource(resource) { | |
17 Init(socket_id); | |
18 } | |
19 | |
20 TCPSocketImpl::TCPSocketImpl(PP_Instance instance, uint32 socket_id) | |
21 : Resource(instance) { | |
22 Init(socket_id); | |
23 } | |
24 | |
25 TCPSocketImpl::~TCPSocketImpl() { | |
26 Disconnect(); | |
yzshen1
2011/11/28 20:59:16
We cannot call it here -- this calls virtual metho
ygorshenin
2011/11/29 18:30:09
Done.
| |
27 } | |
28 | |
29 void TCPSocketImpl::Init(uint32 socket_id) { | |
yzshen1
2011/11/28 20:59:16
Sort the definitions in the same order as the decl
ygorshenin
2011/11/29 18:30:09
Done.
| |
30 DCHECK(socket_id != 0); | |
31 socket_id_ = socket_id; | |
32 connection_state_ = BEFORE_CONNECT; | |
33 connect_callback_ = PP_BlockUntilComplete(); | |
34 ssl_handshake_callback_ = PP_BlockUntilComplete(); | |
35 read_callback_ = PP_BlockUntilComplete(); | |
36 write_callback_ = PP_BlockUntilComplete(); | |
37 read_buffer_ = NULL; | |
38 bytes_to_read_ = -1; | |
39 | |
40 local_addr_.size = 0; | |
41 memset(local_addr_.data, 0, sizeof(local_addr_.data)); | |
dmichael (off chromium)
2011/11/28 20:38:43
please use arraysize instead of sizeof. This will
yzshen1
2011/11/28 20:59:16
Please add include.
ygorshenin
2011/11/29 18:30:09
Done.
ygorshenin
2011/11/29 18:30:09
Done.
| |
42 remote_addr_.size = 0; | |
43 memset(remote_addr_.data, 0, sizeof(remote_addr_.data)); | |
44 } | |
45 | |
46 thunk::PPB_TCPSocket_Private_API* | |
47 TCPSocketImpl::AsPPB_TCPSocket_Private_API() { | |
48 return this; | |
49 } | |
50 | |
51 int32_t TCPSocketImpl::Connect(const char* host, | |
52 uint16_t port, | |
53 PP_CompletionCallback callback) { | |
54 if (!host) | |
55 return PP_ERROR_BADARGUMENT; | |
56 if (!callback.func) | |
57 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
58 if (connection_state_ != BEFORE_CONNECT) | |
59 return PP_ERROR_FAILED; | |
60 if (connect_callback_.func) | |
61 return PP_ERROR_INPROGRESS; // Can only have one pending request. | |
62 | |
63 connect_callback_ = callback; | |
64 // Send the request, the browser will call us back via ConnectACK. | |
65 SendConnect(host, port); | |
66 return PP_OK_COMPLETIONPENDING; | |
67 } | |
68 | |
69 int32_t TCPSocketImpl::ConnectWithNetAddress( | |
70 const PP_NetAddress_Private* addr, | |
71 PP_CompletionCallback callback) { | |
72 if (!addr) | |
73 return PP_ERROR_BADARGUMENT; | |
74 if (!callback.func) | |
75 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
76 if (connection_state_ != BEFORE_CONNECT) | |
77 return PP_ERROR_FAILED; | |
78 if (connect_callback_.func) | |
79 return PP_ERROR_INPROGRESS; // Can only have one pending request. | |
80 | |
81 connect_callback_ = callback; | |
82 // Send the request, the browser will call us back via ConnectACK. | |
83 SendConnectWithNetAddress(*addr); | |
84 return PP_OK_COMPLETIONPENDING; | |
85 } | |
86 | |
87 PP_Bool TCPSocketImpl::GetLocalAddress(PP_NetAddress_Private* local_addr) { | |
88 if (!IsConnected() || !local_addr) | |
89 return PP_FALSE; | |
90 | |
91 *local_addr = local_addr_; | |
92 return PP_TRUE; | |
93 } | |
94 | |
95 PP_Bool TCPSocketImpl::GetRemoteAddress(PP_NetAddress_Private* remote_addr) { | |
96 if (!IsConnected() || !remote_addr) | |
97 return PP_FALSE; | |
98 | |
99 *remote_addr = remote_addr_; | |
100 return PP_TRUE; | |
101 } | |
102 | |
103 int32_t TCPSocketImpl::SSLHandshake(const char* server_name, | |
104 uint16_t server_port, | |
105 PP_CompletionCallback callback) { | |
106 if (!server_name) | |
107 return PP_ERROR_BADARGUMENT; | |
108 if (!callback.func) | |
109 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
110 | |
111 if (connection_state_ != CONNECTED) | |
112 return PP_ERROR_FAILED; | |
113 if (ssl_handshake_callback_.func || read_callback_.func || | |
114 write_callback_.func) | |
115 return PP_ERROR_INPROGRESS; | |
116 | |
117 ssl_handshake_callback_ = callback; | |
118 | |
119 // Send the request, the browser will call us back via SSLHandshakeACK. | |
120 SendSSLHandshake(server_name, server_port); | |
121 return PP_OK_COMPLETIONPENDING; | |
122 } | |
123 | |
124 int32_t TCPSocketImpl::Read(char* buffer, | |
125 int32_t bytes_to_read, | |
126 PP_CompletionCallback callback) { | |
127 if (!buffer || bytes_to_read <= 0) | |
128 return PP_ERROR_BADARGUMENT; | |
129 if (!callback.func) | |
130 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
131 | |
132 if (!IsConnected()) | |
133 return PP_ERROR_FAILED; | |
134 if (read_callback_.func || ssl_handshake_callback_.func) | |
dmichael (off chromium)
2011/11/28 20:38:43
A plugin will eventually be able to provide a comp
yzshen1
2011/11/28 22:11:14
Dave: with line 129-130, it won't get into this st
dmichael (off chromium)
2011/11/28 22:21:27
There's a lot of work still to be done for blockin
ygorshenin
2011/11/29 18:30:09
Added TODO comment.
| |
135 return PP_ERROR_INPROGRESS; | |
136 | |
137 read_buffer_ = buffer; | |
138 bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize); | |
yzshen1
2011/11/28 20:59:16
Please add include.
ygorshenin
2011/11/29 18:30:09
Done.
| |
139 read_callback_ = callback; | |
140 | |
141 // Send the request, the browser will call us back via ReadACK. | |
142 SendRead(bytes_to_read_); | |
143 return PP_OK_COMPLETIONPENDING; | |
144 } | |
145 | |
146 int32_t TCPSocketImpl::Write(const char* buffer, | |
147 int32_t bytes_to_write, | |
148 PP_CompletionCallback callback) { | |
149 if (!buffer || bytes_to_write <= 0) | |
150 return PP_ERROR_BADARGUMENT; | |
151 if (!callback.func) | |
152 return PP_ERROR_BLOCKS_MAIN_THREAD; | |
153 | |
154 if (!IsConnected()) | |
155 return PP_ERROR_FAILED; | |
156 if (write_callback_.func || ssl_handshake_callback_.func) | |
157 return PP_ERROR_INPROGRESS; | |
158 | |
159 if (bytes_to_write > kMaxWriteSize) | |
160 bytes_to_write = kMaxWriteSize; | |
161 | |
162 write_callback_ = callback; | |
163 | |
164 // Send the request, the browser will call us back via WriteACK. | |
165 SendWrite(std::string(buffer, bytes_to_write)); | |
166 return PP_OK_COMPLETIONPENDING; | |
167 } | |
168 | |
169 void TCPSocketImpl::Disconnect() { | |
170 if (connection_state_ == DISCONNECTED) | |
171 return; | |
172 | |
173 connection_state_ = DISCONNECTED; | |
174 | |
175 SendDisconnect(); | |
176 socket_id_ = 0; | |
177 | |
178 PostAbortAndClearIfNecessary(&connect_callback_); | |
179 PostAbortAndClearIfNecessary(&ssl_handshake_callback_); | |
180 PostAbortAndClearIfNecessary(&read_callback_); | |
181 PostAbortAndClearIfNecessary(&write_callback_); | |
182 read_buffer_ = NULL; | |
183 bytes_to_read_ = -1; | |
184 } | |
185 | |
186 void TCPSocketImpl::OnConnectCompleted( | |
187 bool succeeded, | |
188 const PP_NetAddress_Private& local_addr, | |
189 const PP_NetAddress_Private& remote_addr) { | |
190 if (connection_state_ != BEFORE_CONNECT || !connect_callback_.func) { | |
191 NOTREACHED(); | |
192 return; | |
193 } | |
194 | |
195 if (succeeded) { | |
196 local_addr_ = local_addr; | |
197 remote_addr_ = remote_addr; | |
198 connection_state_ = CONNECTED; | |
199 } | |
200 PP_RunAndClearCompletionCallback(&connect_callback_, | |
201 succeeded ? PP_OK : PP_ERROR_FAILED); | |
202 } | |
203 | |
204 void TCPSocketImpl::OnSSLHandshakeCompleted(bool succeeded) { | |
205 if (connection_state_ != CONNECTED || !ssl_handshake_callback_.func) { | |
206 NOTREACHED(); | |
207 return; | |
208 } | |
209 | |
210 if (succeeded) { | |
211 connection_state_ = SSL_CONNECTED; | |
212 PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_OK); | |
213 } else { | |
214 PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_ERROR_FAILED); | |
215 Disconnect(); | |
216 } | |
217 } | |
218 | |
219 void TCPSocketImpl::OnReadCompleted(bool succeeded, | |
220 const std::string& data) { | |
221 if (!read_callback_.func || !read_buffer_) { | |
222 NOTREACHED(); | |
223 return; | |
224 } | |
225 | |
226 if (succeeded) { | |
227 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); | |
228 if (!data.empty()) | |
229 memcpy(read_buffer_, data.c_str(), data.size()); | |
230 } | |
231 read_buffer_ = NULL; | |
232 bytes_to_read_ = -1; | |
233 | |
234 PP_RunAndClearCompletionCallback( | |
235 &read_callback_, | |
236 succeeded ? static_cast<int32_t>(data.size()) : | |
237 static_cast<int32_t>(PP_ERROR_FAILED)); | |
238 } | |
239 | |
240 void TCPSocketImpl::OnWriteCompleted(bool succeeded, | |
241 int32_t bytes_written) { | |
242 if (!write_callback_.func || (succeeded && bytes_written < 0)) { | |
243 NOTREACHED(); | |
244 return; | |
245 } | |
246 | |
247 PP_RunAndClearCompletionCallback( | |
248 &write_callback_, | |
249 succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED)); | |
250 } | |
251 | |
252 bool TCPSocketImpl::IsConnected() const { | |
253 return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED; | |
254 } | |
255 | |
256 void TCPSocketImpl::PostAbortAndClearIfNecessary( | |
257 PP_CompletionCallback* callback) { | |
258 DCHECK(callback); | |
259 | |
260 if (callback->func) { | |
261 PostAbort(*callback); | |
262 *callback = PP_BlockUntilComplete(); | |
263 } | |
264 } | |
265 | |
266 } // namespace ppapi | |
OLD | NEW |