Revert 264226 "Reduce dependency of TiclInvalidationService on P..."
[chromium-blink-merge.git] / device / bluetooth / bluetooth_socket_win.cc
blob9b1e953fb6ddb709705726698625c3232bccd08a
1 // Copyright (c) 2012 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 "device/bluetooth/bluetooth_socket_win.h"
7 #include <string>
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/sequenced_task_runner.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "device/bluetooth/bluetooth_init_win.h"
15 #include "device/bluetooth/bluetooth_service_record_win.h"
16 #include "device/bluetooth/bluetooth_socket_thread_win.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/winsock_init.h"
22 namespace {
24 const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported";
25 const char kSocketAlreadyConnected[] = "Socket is already connected.";
26 const char kSocketNotConnected[] = "Socket is not connected.";
28 using device::BluetoothSocketWin;
30 std::string FormatErrorMessage(DWORD error_code) {
31 TCHAR error_msg[1024];
32 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
34 error_code,
36 error_msg,
37 1024,
38 NULL);
39 return base::SysWideToUTF8(error_msg);
42 static void DeactivateSocket(
43 const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) {
44 socket_thread->OnSocketDeactivate();
47 } // namespace
49 namespace device {
51 // static
52 scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket(
53 const BluetoothServiceRecord& service_record,
54 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
55 scoped_refptr<BluetoothSocketThreadWin> socket_thread,
56 net::NetLog* net_log,
57 const net::NetLog::Source& source) {
58 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
59 const BluetoothServiceRecordWin* service_record_win =
60 static_cast<const BluetoothServiceRecordWin*>(&service_record);
62 scoped_refptr<BluetoothSocketWin> result(
63 new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source));
64 result->device_address_ = service_record_win->address();
65 if (service_record.SupportsRfcomm()) {
66 result->supports_rfcomm_ = true;
67 result->rfcomm_channel_ = service_record_win->rfcomm_channel();
68 result->bth_addr_ = service_record_win->bth_addr();
71 return result;
74 BluetoothSocketWin::BluetoothSocketWin(
75 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
76 scoped_refptr<BluetoothSocketThreadWin> socket_thread,
77 net::NetLog* net_log,
78 const net::NetLog::Source& source)
79 : ui_task_runner_(ui_task_runner),
80 socket_thread_(socket_thread),
81 net_log_(net_log),
82 source_(source),
83 supports_rfcomm_(false),
84 rfcomm_channel_(-1),
85 bth_addr_(BTH_ADDR_NULL) {
86 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
87 socket_thread->OnSocketActivate();
90 BluetoothSocketWin::~BluetoothSocketWin() {
91 ui_task_runner_->PostTask(FROM_HERE,
92 base::Bind(&DeactivateSocket, socket_thread_));
95 void BluetoothSocketWin::Close() {
96 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
97 socket_thread_->task_runner()->PostTask(
98 FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this));
101 void BluetoothSocketWin::Connect(
102 const base::Closure& success_callback,
103 const ErrorCompletionCallback& error_callback) {
104 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
105 socket_thread_->task_runner()->PostTask(
106 FROM_HERE,
107 base::Bind(
108 &BluetoothSocketWin::DoConnect,
109 this,
110 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback),
111 base::Bind(
112 &BluetoothSocketWin::PostErrorCompletion, this, error_callback)));
115 void BluetoothSocketWin::Disconnect(const base::Closure& success_callback) {
116 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
117 socket_thread_->task_runner()->PostTask(
118 FROM_HERE,
119 base::Bind(
120 &BluetoothSocketWin::DoDisconnect,
121 this,
122 base::Bind(
123 &BluetoothSocketWin::PostSuccess, this, success_callback)));
126 void BluetoothSocketWin::Receive(
127 int count,
128 const ReceiveCompletionCallback& success_callback,
129 const ReceiveErrorCompletionCallback& error_callback) {
130 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
131 socket_thread_->task_runner()->PostTask(
132 FROM_HERE,
133 base::Bind(&BluetoothSocketWin::DoReceive,
134 this,
135 count,
136 base::Bind(&BluetoothSocketWin::PostReceiveCompletion,
137 this,
138 success_callback),
139 base::Bind(&BluetoothSocketWin::PostReceiveErrorCompletion,
140 this,
141 error_callback)));
144 void BluetoothSocketWin::Send(scoped_refptr<net::IOBuffer> buffer,
145 int buffer_size,
146 const SendCompletionCallback& success_callback,
147 const ErrorCompletionCallback& error_callback) {
148 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
149 socket_thread_->task_runner()->PostTask(
150 FROM_HERE,
151 base::Bind(
152 &BluetoothSocketWin::DoSend,
153 this,
154 buffer,
155 buffer_size,
156 base::Bind(
157 &BluetoothSocketWin::PostSendCompletion, this, success_callback),
158 base::Bind(
159 &BluetoothSocketWin::PostErrorCompletion, this, error_callback)));
162 void BluetoothSocketWin::DoClose() {
163 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
164 base::ThreadRestrictions::AssertIOAllowed();
166 if (tcp_socket_) {
167 tcp_socket_->Close();
168 tcp_socket_.reset(NULL);
171 // Note: Closing |tcp_socket_| above released all potential pending
172 // Send/Receive operations, so we can no safely release the state associated
173 // to those pending operations.
174 read_buffer_ = NULL;
175 std::queue<linked_ptr<WriteRequest> > empty;
176 write_queue_.swap(empty);
179 void BluetoothSocketWin::DoConnect(
180 const base::Closure& success_callback,
181 const ErrorCompletionCallback& error_callback) {
182 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
183 base::ThreadRestrictions::AssertIOAllowed();
185 if (tcp_socket_) {
186 error_callback.Run(kSocketAlreadyConnected);
187 return;
190 if (!supports_rfcomm_) {
191 // TODO(youngki) add support for L2CAP sockets as well.
192 error_callback.Run(kL2CAPNotSupported);
193 return;
196 tcp_socket_.reset(new net::TCPSocket(net_log_, source_));
197 net::EnsureWinsockInit();
198 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
199 SOCKADDR_BTH sa;
200 ZeroMemory(&sa, sizeof(sa));
201 sa.addressFamily = AF_BTH;
202 sa.port = rfcomm_channel_;
203 sa.btAddr = bth_addr_;
205 // TODO(rpaquay): Condider making this call non-blocking.
206 int status = connect(socket_fd, reinterpret_cast<SOCKADDR*>(&sa), sizeof(sa));
207 DWORD error_code = WSAGetLastError();
208 if (!(status == 0 || error_code == WSAEINPROGRESS)) {
209 LOG(ERROR) << "Failed to connect bluetooth socket "
210 << "(" << device_address_ << "): "
211 << "(" << error_code << ")" << FormatErrorMessage(error_code);
212 error_callback.Run("Error connecting to socket: " +
213 FormatErrorMessage(error_code));
214 closesocket(socket_fd);
215 return;
218 // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the
219 // TCPSocket implementation does not actually require one.
220 int net_result =
221 tcp_socket_->AdoptConnectedSocket(socket_fd, net::IPEndPoint());
222 if (net_result != net::OK) {
223 error_callback.Run("Error connecting to socket: " +
224 std::string(net::ErrorToString(net_result)));
225 closesocket(socket_fd);
226 return;
229 success_callback.Run();
232 void BluetoothSocketWin::DoDisconnect(const base::Closure& success_callback) {
233 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
234 base::ThreadRestrictions::AssertIOAllowed();
236 DoClose();
237 success_callback.Run();
240 void BluetoothSocketWin::DoReceive(
241 int count,
242 const ReceiveCompletionCallback& success_callback,
243 const ReceiveErrorCompletionCallback& error_callback) {
244 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
245 base::ThreadRestrictions::AssertIOAllowed();
247 if (!tcp_socket_) {
248 error_callback.Run(BluetoothSocketWin::kDisconnected, kSocketNotConnected);
249 return;
252 // Only one pending read at a time
253 if (read_buffer_.get()) {
254 error_callback.Run(BluetoothSocketWin::kIOPending,
255 net::ErrorToString(net::ERR_IO_PENDING));
256 return;
259 scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(count));
260 int read_result =
261 tcp_socket_->Read(buffer.get(),
262 buffer->size(),
263 base::Bind(&BluetoothSocketWin::OnSocketReadComplete,
264 this,
265 success_callback,
266 error_callback));
268 if (read_result > 0) {
269 success_callback.Run(read_result, buffer);
270 } else if (read_result == net::OK ||
271 read_result == net::ERR_CONNECTION_CLOSED) {
272 error_callback.Run(BluetoothSocketWin::kDisconnected,
273 net::ErrorToString(net::ERR_CONNECTION_CLOSED));
274 } else if (read_result == net::ERR_IO_PENDING) {
275 read_buffer_ = buffer;
276 } else {
277 error_callback.Run(BluetoothSocketWin::kSystemError,
278 net::ErrorToString(read_result));
282 void BluetoothSocketWin::OnSocketReadComplete(
283 const ReceiveCompletionCallback& success_callback,
284 const ReceiveErrorCompletionCallback& error_callback,
285 int read_result) {
286 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
287 base::ThreadRestrictions::AssertIOAllowed();
289 scoped_refptr<net::IOBufferWithSize> buffer;
290 buffer.swap(read_buffer_);
291 if (read_result > 0) {
292 success_callback.Run(read_result, buffer);
293 } else if (read_result == net::OK ||
294 read_result == net::ERR_CONNECTION_CLOSED) {
295 error_callback.Run(BluetoothSocketWin::kDisconnected,
296 net::ErrorToString(net::ERR_CONNECTION_CLOSED));
297 } else {
298 error_callback.Run(BluetoothSocketWin::kSystemError,
299 net::ErrorToString(read_result));
303 void BluetoothSocketWin::DoSend(scoped_refptr<net::IOBuffer> buffer,
304 int buffer_size,
305 const SendCompletionCallback& success_callback,
306 const ErrorCompletionCallback& error_callback) {
307 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
308 base::ThreadRestrictions::AssertIOAllowed();
310 if (!tcp_socket_) {
311 error_callback.Run(kSocketNotConnected);
312 return;
315 linked_ptr<WriteRequest> request(new WriteRequest());
316 request->buffer = buffer;
317 request->buffer_size = buffer_size;
318 request->success_callback = success_callback;
319 request->error_callback = error_callback;
321 write_queue_.push(request);
322 if (write_queue_.size() == 1) {
323 SendFrontWriteRequest();
327 void BluetoothSocketWin::SendFrontWriteRequest() {
328 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
329 base::ThreadRestrictions::AssertIOAllowed();
331 if (!tcp_socket_)
332 return;
334 if (write_queue_.size() == 0)
335 return;
337 linked_ptr<WriteRequest> request = write_queue_.front();
338 net::CompletionCallback callback =
339 base::Bind(&BluetoothSocketWin::OnSocketWriteComplete,
340 this,
341 request->success_callback,
342 request->error_callback);
343 int send_result =
344 tcp_socket_->Write(request->buffer, request->buffer_size, callback);
345 if (send_result != net::ERR_IO_PENDING) {
346 callback.Run(send_result);
350 void BluetoothSocketWin::OnSocketWriteComplete(
351 const SendCompletionCallback& success_callback,
352 const ErrorCompletionCallback& error_callback,
353 int send_result) {
354 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
355 base::ThreadRestrictions::AssertIOAllowed();
357 write_queue_.pop();
359 if (send_result >= net::OK) {
360 success_callback.Run(send_result);
361 } else {
362 error_callback.Run(net::ErrorToString(send_result));
365 // Don't call directly to avoid potentail large recursion.
366 socket_thread_->task_runner()->PostNonNestableTask(
367 FROM_HERE, base::Bind(&BluetoothSocketWin::SendFrontWriteRequest, this));
370 void BluetoothSocketWin::PostSuccess(const base::Closure& callback) {
371 ui_task_runner_->PostTask(FROM_HERE, callback);
374 void BluetoothSocketWin::PostErrorCompletion(
375 const ErrorCompletionCallback& callback,
376 const std::string& error) {
377 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error));
380 void BluetoothSocketWin::PostReceiveCompletion(
381 const ReceiveCompletionCallback& callback,
382 int io_buffer_size,
383 scoped_refptr<net::IOBuffer> io_buffer) {
384 ui_task_runner_->PostTask(FROM_HERE,
385 base::Bind(callback, io_buffer_size, io_buffer));
388 void BluetoothSocketWin::PostReceiveErrorCompletion(
389 const ReceiveErrorCompletionCallback& callback,
390 ErrorReason reason,
391 const std::string& error_message) {
392 ui_task_runner_->PostTask(FROM_HERE,
393 base::Bind(callback, reason, error_message));
396 void BluetoothSocketWin::PostSendCompletion(
397 const SendCompletionCallback& callback,
398 int bytes_written) {
399 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
402 } // namespace device