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