OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 "device/bluetooth/bluetooth_socket_net.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/sequenced_task_runner.h" | |
12 #include "base/threading/thread_restrictions.h" | |
13 #include "device/bluetooth/bluetooth_socket.h" | |
14 #include "device/bluetooth/bluetooth_socket_thread.h" | |
15 #include "net/base/io_buffer.h" | |
16 #include "net/base/net_errors.h" | |
17 | |
18 namespace { | |
19 | |
20 const char kSocketNotConnected[] = "Socket is not connected."; | |
21 | |
22 static void DeactivateSocket( | |
23 const scoped_refptr<device::BluetoothSocketThread>& socket_thread) { | |
24 socket_thread->OnSocketDeactivate(); | |
25 } | |
26 | |
27 } // namespace | |
28 | |
29 namespace device { | |
30 | |
31 // static | |
32 scoped_refptr<BluetoothSocketNet> | |
33 BluetoothSocketNet::CreateBluetoothSocket( | |
34 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | |
35 scoped_refptr<BluetoothSocketThread> socket_thread, | |
36 net::NetLog* net_log, | |
37 const net::NetLog::Source& source) { | |
38 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); | |
39 | |
40 return make_scoped_refptr( | |
41 new BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source)); | |
42 } | |
43 | |
44 BluetoothSocketNet::WriteRequest::WriteRequest() | |
45 : buffer_size(0) {} | |
46 | |
47 BluetoothSocketNet::WriteRequest::~WriteRequest() {} | |
48 | |
49 BluetoothSocketNet::BluetoothSocketNet( | |
50 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | |
51 scoped_refptr<BluetoothSocketThread> socket_thread, | |
52 net::NetLog* net_log, | |
53 const net::NetLog::Source& source) | |
54 : ui_task_runner_(ui_task_runner), | |
55 socket_thread_(socket_thread), | |
56 net_log_(net_log), | |
57 source_(source) { | |
58 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); | |
59 socket_thread_->OnSocketActivate(); | |
60 } | |
61 | |
62 BluetoothSocketNet::~BluetoothSocketNet() { | |
63 DCHECK(tcp_socket_.get() == NULL); | |
64 ui_task_runner_->PostTask(FROM_HERE, | |
65 base::Bind(&DeactivateSocket, socket_thread_)); | |
66 } | |
67 | |
68 void BluetoothSocketNet::Close() { | |
69 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
70 socket_thread_->task_runner()->PostTask( | |
71 FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this)); | |
72 } | |
73 | |
74 void BluetoothSocketNet::Disconnect( | |
75 const base::Closure& success_callback) { | |
76 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
77 socket_thread_->task_runner()->PostTask( | |
78 FROM_HERE, | |
79 base::Bind( | |
80 &BluetoothSocketNet::DoDisconnect, | |
81 this, | |
82 base::Bind(&BluetoothSocketNet::PostSuccess, | |
83 this, | |
84 success_callback))); | |
85 } | |
86 | |
87 void BluetoothSocketNet::Receive( | |
88 int buffer_size, | |
89 const ReceiveCompletionCallback& success_callback, | |
90 const ReceiveErrorCompletionCallback& error_callback) { | |
91 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
92 socket_thread_->task_runner()->PostTask( | |
93 FROM_HERE, | |
94 base::Bind( | |
95 &BluetoothSocketNet::DoReceive, | |
96 this, | |
97 buffer_size, | |
98 base::Bind(&BluetoothSocketNet::PostReceiveCompletion, | |
99 this, | |
100 success_callback), | |
101 base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion, | |
102 this, | |
103 error_callback))); | |
104 } | |
105 | |
106 void BluetoothSocketNet::Send( | |
107 scoped_refptr<net::IOBuffer> buffer, | |
108 int buffer_size, | |
109 const SendCompletionCallback& success_callback, | |
110 const ErrorCompletionCallback& error_callback) { | |
111 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
112 socket_thread_->task_runner()->PostTask( | |
113 FROM_HERE, | |
114 base::Bind( | |
115 &BluetoothSocketNet::DoSend, | |
116 this, | |
117 buffer, | |
118 buffer_size, | |
119 base::Bind(&BluetoothSocketNet::PostSendCompletion, | |
120 this, | |
121 success_callback), | |
122 base::Bind(&BluetoothSocketNet::PostErrorCompletion, | |
123 this, | |
124 error_callback))); | |
125 } | |
126 | |
127 void BluetoothSocketNet::ResetData() { | |
armansito
2014/05/01 00:14:25
I would at least log something here, maybe VLOG(1)
keybuk
2014/05/01 00:24:09
NAK, this is just for subclasses - Win happens to
armansito
2014/05/01 00:54:17
sgtm
| |
128 } | |
129 | |
130 void BluetoothSocketNet::ResetTCPSocket() { | |
131 tcp_socket_.reset(new net::TCPSocket(net_log_, source_)); | |
132 } | |
133 | |
134 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) { | |
135 tcp_socket_ = tcp_socket.Pass(); | |
136 } | |
137 | |
138 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) { | |
139 ui_task_runner_->PostTask(FROM_HERE, callback); | |
140 } | |
141 | |
142 void BluetoothSocketNet::PostErrorCompletion( | |
143 const ErrorCompletionCallback& callback, | |
144 const std::string& error) { | |
145 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error)); | |
146 } | |
147 | |
148 void BluetoothSocketNet::DoClose() { | |
149 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
150 base::ThreadRestrictions::AssertIOAllowed(); | |
151 | |
152 if (tcp_socket_) { | |
153 tcp_socket_->Close(); | |
154 tcp_socket_.reset(NULL); | |
155 } | |
156 | |
157 // Note: Closing |tcp_socket_| above released all potential pending | |
158 // Send/Receive operations, so we can no safely release the state associated | |
159 // to those pending operations. | |
160 read_buffer_ = NULL; | |
161 std::queue<linked_ptr<WriteRequest> > empty; | |
162 write_queue_.swap(empty); | |
163 | |
164 ResetData(); | |
165 } | |
166 | |
167 void BluetoothSocketNet::DoDisconnect( | |
168 const base::Closure& success_callback) { | |
169 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
170 base::ThreadRestrictions::AssertIOAllowed(); | |
171 | |
172 DoClose(); | |
173 success_callback.Run(); | |
174 } | |
175 | |
176 void BluetoothSocketNet::DoReceive( | |
177 int buffer_size, | |
178 const ReceiveCompletionCallback& success_callback, | |
179 const ReceiveErrorCompletionCallback& error_callback) { | |
180 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
181 base::ThreadRestrictions::AssertIOAllowed(); | |
182 | |
183 if (!tcp_socket_) { | |
184 error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected); | |
185 return; | |
186 } | |
187 | |
188 // Only one pending read at a time | |
189 if (read_buffer_.get()) { | |
190 error_callback.Run(BluetoothSocket::kIOPending, | |
191 net::ErrorToString(net::ERR_IO_PENDING)); | |
192 return; | |
193 } | |
194 | |
195 scoped_refptr<net::IOBufferWithSize> buffer( | |
196 new net::IOBufferWithSize(buffer_size)); | |
197 int read_result = | |
198 tcp_socket_->Read(buffer.get(), | |
199 buffer->size(), | |
200 base::Bind(&BluetoothSocketNet::OnSocketReadComplete, | |
201 this, | |
202 success_callback, | |
203 error_callback)); | |
204 | |
205 if (read_result > 0) { | |
206 success_callback.Run(read_result, buffer); | |
207 } else if (read_result == net::OK || | |
208 read_result == net::ERR_CONNECTION_CLOSED) { | |
209 error_callback.Run(BluetoothSocket::kDisconnected, | |
210 net::ErrorToString(net::ERR_CONNECTION_CLOSED)); | |
211 } else if (read_result == net::ERR_IO_PENDING) { | |
212 read_buffer_ = buffer; | |
213 } else { | |
214 error_callback.Run(BluetoothSocket::kSystemError, | |
215 net::ErrorToString(read_result)); | |
216 } | |
217 } | |
218 | |
219 void BluetoothSocketNet::OnSocketReadComplete( | |
220 const ReceiveCompletionCallback& success_callback, | |
221 const ReceiveErrorCompletionCallback& error_callback, | |
222 int read_result) { | |
223 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
224 base::ThreadRestrictions::AssertIOAllowed(); | |
225 | |
226 scoped_refptr<net::IOBufferWithSize> buffer; | |
227 buffer.swap(read_buffer_); | |
228 if (read_result > 0) { | |
229 success_callback.Run(read_result, buffer); | |
230 } else if (read_result == net::OK || | |
231 read_result == net::ERR_CONNECTION_CLOSED) { | |
232 error_callback.Run(BluetoothSocket::kDisconnected, | |
233 net::ErrorToString(net::ERR_CONNECTION_CLOSED)); | |
234 } else { | |
235 error_callback.Run(BluetoothSocket::kSystemError, | |
236 net::ErrorToString(read_result)); | |
237 } | |
238 } | |
239 | |
240 void BluetoothSocketNet::DoSend( | |
241 scoped_refptr<net::IOBuffer> buffer, | |
242 int buffer_size, | |
243 const SendCompletionCallback& success_callback, | |
244 const ErrorCompletionCallback& error_callback) { | |
245 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
246 base::ThreadRestrictions::AssertIOAllowed(); | |
247 | |
248 if (!tcp_socket_) { | |
249 error_callback.Run(kSocketNotConnected); | |
250 return; | |
251 } | |
252 | |
253 linked_ptr<WriteRequest> request(new WriteRequest()); | |
254 request->buffer = buffer; | |
255 request->buffer_size = buffer_size; | |
256 request->success_callback = success_callback; | |
257 request->error_callback = error_callback; | |
258 | |
259 write_queue_.push(request); | |
260 if (write_queue_.size() == 1) { | |
261 SendFrontWriteRequest(); | |
262 } | |
263 } | |
264 | |
265 void BluetoothSocketNet::SendFrontWriteRequest() { | |
266 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
267 base::ThreadRestrictions::AssertIOAllowed(); | |
268 | |
269 if (!tcp_socket_) | |
270 return; | |
271 | |
272 if (write_queue_.size() == 0) | |
273 return; | |
274 | |
275 linked_ptr<WriteRequest> request = write_queue_.front(); | |
276 net::CompletionCallback callback = | |
277 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete, | |
278 this, | |
279 request->success_callback, | |
280 request->error_callback); | |
281 int send_result = | |
282 tcp_socket_->Write(request->buffer, request->buffer_size, callback); | |
283 if (send_result != net::ERR_IO_PENDING) { | |
284 callback.Run(send_result); | |
285 } | |
286 } | |
287 | |
288 void BluetoothSocketNet::OnSocketWriteComplete( | |
289 const SendCompletionCallback& success_callback, | |
290 const ErrorCompletionCallback& error_callback, | |
291 int send_result) { | |
292 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
293 base::ThreadRestrictions::AssertIOAllowed(); | |
294 | |
295 write_queue_.pop(); | |
296 | |
297 if (send_result >= net::OK) { | |
298 success_callback.Run(send_result); | |
299 } else { | |
300 error_callback.Run(net::ErrorToString(send_result)); | |
301 } | |
302 | |
303 // Don't call directly to avoid potentail large recursion. | |
304 socket_thread_->task_runner()->PostNonNestableTask( | |
305 FROM_HERE, | |
306 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this)); | |
307 } | |
308 | |
309 void BluetoothSocketNet::PostReceiveCompletion( | |
310 const ReceiveCompletionCallback& callback, | |
311 int io_buffer_size, | |
312 scoped_refptr<net::IOBuffer> io_buffer) { | |
313 ui_task_runner_->PostTask(FROM_HERE, | |
314 base::Bind(callback, io_buffer_size, io_buffer)); | |
315 } | |
316 | |
317 void BluetoothSocketNet::PostReceiveErrorCompletion( | |
318 const ReceiveErrorCompletionCallback& callback, | |
319 ErrorReason reason, | |
320 const std::string& error_message) { | |
321 ui_task_runner_->PostTask(FROM_HERE, | |
322 base::Bind(callback, reason, error_message)); | |
323 } | |
324 | |
325 void BluetoothSocketNet::PostSendCompletion( | |
326 const SendCompletionCallback& callback, | |
327 int bytes_written) { | |
328 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); | |
329 } | |
330 | |
331 } // namespace device | |
OLD | NEW |