blob: 509ade4ab79af1b9066abb5a0e4957d656fe09bb [file] [log] [blame]
[email protected]0ae97592012-10-22 22:06:051// 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.
[email protected]0ae97592012-10-22 22:06:054
5#include "device/bluetooth/bluetooth_socket_win.h"
6
[email protected]ef2f0022014-04-29 10:24:357#include <objbase.h>
8
[email protected]0fd66b502013-01-29 23:29:509#include <string>
dcheng70c49422016-03-02 23:20:3410#include <utility>
[email protected]0fd66b502013-01-29 23:29:5011
[email protected]0ae97592012-10-22 22:06:0512#include "base/logging.h"
[email protected]246493d2013-02-03 18:24:0313#include "base/memory/ref_counted.h"
[email protected]73131fc12014-04-08 01:02:2714#include "base/sequenced_task_runner.h"
[email protected]85317222014-06-06 11:03:3915#include "base/strings/stringprintf.h"
[email protected]13ac53532013-03-30 00:27:0016#include "base/strings/sys_string_conversions.h"
[email protected]ef2f0022014-04-29 10:24:3517#include "base/strings/utf_string_conversions.h"
[email protected]73131fc12014-04-08 01:02:2718#include "base/threading/thread_restrictions.h"
[email protected]85317222014-06-06 11:03:3919#include "device/bluetooth/bluetooth_device_win.h"
[email protected]246493d2013-02-03 18:24:0320#include "device/bluetooth/bluetooth_init_win.h"
21#include "device/bluetooth/bluetooth_service_record_win.h"
[email protected]2c24d942014-05-02 16:07:3122#include "device/bluetooth/bluetooth_socket_thread.h"
[email protected]0fd66b502013-01-29 23:29:5023#include "net/base/io_buffer.h"
[email protected]73131fc12014-04-08 01:02:2724#include "net/base/ip_endpoint.h"
25#include "net/base/net_errors.h"
[email protected]246493d2013-02-03 18:24:0326#include "net/base/winsock_init.h"
tfarinac5336ca2016-01-11 20:49:3627#include "net/base/winsock_util.h"
[email protected]246493d2013-02-03 18:24:0328
29namespace {
30
[email protected]73131fc12014-04-08 01:02:2731const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported";
32const char kSocketAlreadyConnected[] = "Socket is already connected.";
[email protected]ef2f0022014-04-29 10:24:3533const char kInvalidRfcommPort[] = "Invalid RFCCOMM port.";
34const char kFailedToCreateSocket[] = "Failed to create socket.";
35const char kFailedToBindSocket[] = "Failed to bind socket.";
36const char kFailedToListenOnSocket[] = "Failed to listen on socket.";
37const char kFailedToGetSockNameForSocket[] = "Failed to getsockname.";
[email protected]85317222014-06-06 11:03:3938const char kFailedToAccept[] = "Failed to accept.";
39const char kInvalidUUID[] = "Invalid UUID";
[email protected]ef2f0022014-04-29 10:24:3540const char kWsaSetServiceError[] = "WSASetService error.";
[email protected]73131fc12014-04-08 01:02:2741
[email protected]85317222014-06-06 11:03:3942std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) {
43 if (end_point.address().size() != net::kBluetoothAddressSize)
44 return std::string();
45 // The address is copied from BTH_ADDR field of SOCKADDR_BTH, which is a
46 // 64-bit ULONGLONG that stores Bluetooth address in little-endian. Print in
47 // reverse order to preserve the correct ordering.
martijn98acb9b2016-01-27 07:14:0748 return base::StringPrintf(
49 "%02X:%02X:%02X:%02X:%02X:%02X", end_point.address().bytes()[5],
50 end_point.address().bytes()[4], end_point.address().bytes()[3],
51 end_point.address().bytes()[2], end_point.address().bytes()[1],
52 end_point.address().bytes()[0]);
[email protected]85317222014-06-06 11:03:3953}
54
[email protected]246493d2013-02-03 18:24:0355} // namespace
[email protected]0ae97592012-10-22 22:06:0556
57namespace device {
58
[email protected]ef2f0022014-04-29 10:24:3559struct BluetoothSocketWin::ServiceRegData {
60 ServiceRegData() {
61 ZeroMemory(&address, sizeof(address));
62 ZeroMemory(&address_info, sizeof(address_info));
63 ZeroMemory(&uuid, sizeof(uuid));
64 ZeroMemory(&service, sizeof(service));
65 }
66
67 SOCKADDR_BTH address;
68 CSADDR_INFO address_info;
69 GUID uuid;
70 base::string16 name;
71 WSAQUERYSET service;
72};
73
[email protected]73131fc12014-04-08 01:02:2774// static
[email protected]2c24d942014-05-02 16:07:3175scoped_refptr<BluetoothSocketWin>
76BluetoothSocketWin::CreateBluetoothSocket(
[email protected]73131fc12014-04-08 01:02:2777 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
[email protected]daed8ec2014-07-23 06:18:5478 scoped_refptr<device::BluetoothSocketThread> socket_thread) {
[email protected]73131fc12014-04-08 01:02:2779 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
[email protected]73131fc12014-04-08 01:02:2780
[email protected]ef2f0022014-04-29 10:24:3581 return make_scoped_refptr(
[email protected]daed8ec2014-07-23 06:18:5482 new BluetoothSocketWin(ui_task_runner, socket_thread));
[email protected]73131fc12014-04-08 01:02:2783}
84
85BluetoothSocketWin::BluetoothSocketWin(
86 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
[email protected]daed8ec2014-07-23 06:18:5487 scoped_refptr<BluetoothSocketThread> socket_thread)
88 : BluetoothSocketNet(ui_task_runner, socket_thread),
[email protected]73131fc12014-04-08 01:02:2789 supports_rfcomm_(false),
[email protected]481c3e82014-07-18 01:40:4790 rfcomm_channel_(0xFF),
[email protected]73131fc12014-04-08 01:02:2791 bth_addr_(BTH_ADDR_NULL) {
[email protected]0ae97592012-10-22 22:06:0592}
93
94BluetoothSocketWin::~BluetoothSocketWin() {
95}
96
[email protected]73131fc12014-04-08 01:02:2797void BluetoothSocketWin::Connect(
[email protected]85317222014-06-06 11:03:3998 const BluetoothDeviceWin* device,
99 const BluetoothUUID& uuid,
[email protected]73131fc12014-04-08 01:02:27100 const base::Closure& success_callback,
101 const ErrorCompletionCallback& error_callback) {
[email protected]2c24d942014-05-02 16:07:31102 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
[email protected]85317222014-06-06 11:03:39103 DCHECK(device);
104
105 if (!uuid.IsValid()) {
106 error_callback.Run(kInvalidUUID);
107 return;
108 }
[email protected]ef2f0022014-04-29 10:24:35109
110 const BluetoothServiceRecordWin* service_record_win =
[email protected]85317222014-06-06 11:03:39111 device->GetServiceRecord(uuid);
112 if (!service_record_win) {
113 error_callback.Run(kInvalidUUID);
114 return;
115 }
116
[email protected]44f159f2014-07-20 21:36:24117 device_address_ = service_record_win->device_address();
[email protected]85317222014-06-06 11:03:39118 if (service_record_win->SupportsRfcomm()) {
[email protected]ef2f0022014-04-29 10:24:35119 supports_rfcomm_ = true;
120 rfcomm_channel_ = service_record_win->rfcomm_channel();
[email protected]44f159f2014-07-20 21:36:24121 bth_addr_ = service_record_win->device_bth_addr();
[email protected]ef2f0022014-04-29 10:24:35122 }
123
[email protected]2c24d942014-05-02 16:07:31124 socket_thread()->task_runner()->PostTask(
[email protected]73131fc12014-04-08 01:02:27125 FROM_HERE,
126 base::Bind(
127 &BluetoothSocketWin::DoConnect,
128 this,
129 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback),
130 base::Bind(
131 &BluetoothSocketWin::PostErrorCompletion, this, error_callback)));
132}
133
[email protected]85317222014-06-06 11:03:39134void BluetoothSocketWin::Listen(scoped_refptr<BluetoothAdapter> adapter,
135 const BluetoothUUID& uuid,
[email protected]dbedd5022014-07-03 06:08:20136 const BluetoothAdapter::ServiceOptions& options,
[email protected]85317222014-06-06 11:03:39137 const base::Closure& success_callback,
138 const ErrorCompletionCallback& error_callback) {
139 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
140
141 adapter_ = adapter;
[email protected]dbedd5022014-07-03 06:08:20142 int rfcomm_channel = options.channel ? *options.channel : 0;
[email protected]85317222014-06-06 11:03:39143
[email protected]dbedd5022014-07-03 06:08:20144 // TODO(xiyuan): Use |options.name|.
[email protected]85317222014-06-06 11:03:39145 socket_thread()->task_runner()->PostTask(
146 FROM_HERE,
147 base::Bind(&BluetoothSocketWin::DoListen,
148 this,
149 uuid,
150 rfcomm_channel,
151 success_callback,
152 error_callback));
153}
[email protected]73131fc12014-04-08 01:02:27154
[email protected]2c24d942014-05-02 16:07:31155void BluetoothSocketWin::ResetData() {
[email protected]ef2f0022014-04-29 10:24:35156 if (service_reg_data_) {
157 if (WSASetService(&service_reg_data_->service,RNRSERVICE_DELETE, 0) ==
158 SOCKET_ERROR) {
159 LOG(WARNING) << "Failed to unregister service.";
160 }
161 service_reg_data_.reset();
162 }
[email protected]0ae97592012-10-22 22:06:05163}
164
[email protected]37f0b7f2014-05-12 18:09:51165void BluetoothSocketWin::Accept(
166 const AcceptCompletionCallback& success_callback,
167 const ErrorCompletionCallback& error_callback) {
[email protected]85317222014-06-06 11:03:39168 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
169
170 socket_thread()->task_runner()->PostTask(
171 FROM_HERE,
172 base::Bind(&BluetoothSocketWin::DoAccept,
173 this,
174 success_callback,
175 error_callback));
[email protected]37f0b7f2014-05-12 18:09:51176}
177
[email protected]73131fc12014-04-08 01:02:27178void BluetoothSocketWin::DoConnect(
179 const base::Closure& success_callback,
180 const ErrorCompletionCallback& error_callback) {
[email protected]2c24d942014-05-02 16:07:31181 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
[email protected]73131fc12014-04-08 01:02:27182 base::ThreadRestrictions::AssertIOAllowed();
[email protected]246493d2013-02-03 18:24:03183
[email protected]2c24d942014-05-02 16:07:31184 if (tcp_socket()) {
[email protected]73131fc12014-04-08 01:02:27185 error_callback.Run(kSocketAlreadyConnected);
186 return;
187 }
188
189 if (!supports_rfcomm_) {
190 // TODO(youngki) add support for L2CAP sockets as well.
191 error_callback.Run(kL2CAPNotSupported);
192 return;
193 }
194
[email protected]76caec02014-07-31 12:07:19195 scoped_ptr<net::TCPSocket> scoped_socket(
196 new net::TCPSocket(NULL, net::NetLog::Source()));
[email protected]73131fc12014-04-08 01:02:27197 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_;
204
205 // TODO(rpaquay): Condider making this call non-blocking.
206 int status = connect(socket_fd, reinterpret_cast<SOCKADDR*>(&sa), sizeof(sa));
[email protected]246493d2013-02-03 18:24:03207 DWORD error_code = WSAGetLastError();
[email protected]73131fc12014-04-08 01:02:27208 if (!(status == 0 || error_code == WSAEINPROGRESS)) {
209 LOG(ERROR) << "Failed to connect bluetooth socket "
210 << "(" << device_address_ << "): "
[email protected]69c57392014-04-25 15:16:13211 << logging::SystemErrorCodeToString(error_code);
[email protected]73131fc12014-04-08 01:02:27212 error_callback.Run("Error connecting to socket: " +
[email protected]69c57392014-04-25 15:16:13213 logging::SystemErrorCodeToString(error_code));
[email protected]73131fc12014-04-08 01:02:27214 closesocket(socket_fd);
215 return;
[email protected]246493d2013-02-03 18:24:03216 }
[email protected]73131fc12014-04-08 01:02:27217
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 =
[email protected]76caec02014-07-31 12:07:19221 scoped_socket->AdoptConnectedSocket(socket_fd, net::IPEndPoint());
[email protected]73131fc12014-04-08 01:02:27222 if (net_result != net::OK) {
223 error_callback.Run("Error connecting to socket: " +
[email protected]3030374e32014-08-07 16:12:06224 net::ErrorToString(net_result));
[email protected]73131fc12014-04-08 01:02:27225 closesocket(socket_fd);
226 return;
227 }
228
dcheng70c49422016-03-02 23:20:34229 SetTCPSocket(std::move(scoped_socket));
[email protected]73131fc12014-04-08 01:02:27230 success_callback.Run();
[email protected]dc85cef2014-04-07 19:58:52231}
[email protected]eba06dc2014-04-07 19:21:07232
[email protected]85317222014-06-06 11:03:39233void BluetoothSocketWin::DoListen(
[email protected]ef2f0022014-04-29 10:24:35234 const BluetoothUUID& uuid,
[email protected]ef2f0022014-04-29 10:24:35235 int rfcomm_channel,
236 const base::Closure& success_callback,
[email protected]85317222014-06-06 11:03:39237 const ErrorCompletionCallback& error_callback) {
[email protected]2c24d942014-05-02 16:07:31238 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
[email protected]85317222014-06-06 11:03:39239 DCHECK(!tcp_socket() && !service_reg_data_);
[email protected]ef2f0022014-04-29 10:24:35240
241 // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the
242 // valid RFCOMM port numbers of SOCKADDR_BTH.
243 if (rfcomm_channel < 0 || rfcomm_channel > 30) {
244 LOG(WARNING) << "Failed to start service: "
245 << "Invalid RFCCOMM port " << rfcomm_channel
246 << ", uuid=" << uuid.value();
247 PostErrorCompletion(error_callback, kInvalidRfcommPort);
248 return;
249 }
250
251 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
252 if (socket_fd == INVALID_SOCKET) {
253 LOG(WARNING) << "Failed to start service: create socket, "
254 << "winsock err=" << WSAGetLastError();
255 PostErrorCompletion(error_callback, kFailedToCreateSocket);
256 return;
257 }
258
259 // Note that |socket_fd| belongs to a non-TCP address family (i.e. AF_BTH),
260 // TCPSocket methods that involve address could not be called. So bind()
261 // is called on |socket_fd| directly.
262 scoped_ptr<net::TCPSocket> scoped_socket(
263 new net::TCPSocket(NULL, net::NetLog::Source()));
264 scoped_socket->AdoptListenSocket(socket_fd);
265
266 SOCKADDR_BTH sa;
267 struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa);
268 int sock_addr_len = sizeof(sa);
269 ZeroMemory(&sa, sock_addr_len);
270 sa.addressFamily = AF_BTH;
271 sa.port = rfcomm_channel ? rfcomm_channel : BT_PORT_ANY;
272 if (bind(socket_fd, sock_addr, sock_addr_len) < 0) {
273 LOG(WARNING) << "Failed to start service: create socket, "
274 << "winsock err=" << WSAGetLastError();
275 PostErrorCompletion(error_callback, kFailedToBindSocket);
276 return;
277 }
278
279 const int kListenBacklog = 5;
280 if (scoped_socket->Listen(kListenBacklog) < 0) {
281 LOG(WARNING) << "Failed to start service: Listen"
282 << "winsock err=" << WSAGetLastError();
283 PostErrorCompletion(error_callback, kFailedToListenOnSocket);
284 return;
285 }
286
287 scoped_ptr<ServiceRegData> reg_data(new ServiceRegData);
[email protected]85317222014-06-06 11:03:39288 reg_data->name = base::UTF8ToUTF16(uuid.canonical_value());
[email protected]ef2f0022014-04-29 10:24:35289
290 if (getsockname(socket_fd, sock_addr, &sock_addr_len)) {
291 LOG(WARNING) << "Failed to start service: getsockname, "
292 << "winsock err=" << WSAGetLastError();
293 PostErrorCompletion(error_callback, kFailedToGetSockNameForSocket);
294 return;
295 }
296 reg_data->address = sa;
297
298 reg_data->address_info.LocalAddr.iSockaddrLength = sizeof(sa);
299 reg_data->address_info.LocalAddr.lpSockaddr =
300 reinterpret_cast<struct sockaddr*>(&reg_data->address);
301 reg_data->address_info.iSocketType = SOCK_STREAM;
302 reg_data->address_info.iProtocol = BTHPROTO_RFCOMM;
303
304 base::string16 cannonical_uuid = L"{" + base::ASCIIToUTF16(
305 uuid.canonical_value()) + L"}";
306 if (!SUCCEEDED(CLSIDFromString(cannonical_uuid.c_str(), &reg_data->uuid))) {
307 LOG(WARNING) << "Failed to start service: "
[email protected]85317222014-06-06 11:03:39308 << ", invalid uuid=" << cannonical_uuid;
309 PostErrorCompletion(error_callback, kInvalidUUID);
[email protected]ef2f0022014-04-29 10:24:35310 return;
311 }
312
313 reg_data->service.dwSize = sizeof(WSAQUERYSET);
314 reg_data->service.lpszServiceInstanceName =
315 const_cast<LPWSTR>(reg_data->name.c_str());
316 reg_data->service.lpServiceClassId = &reg_data->uuid;
317 reg_data->service.dwNameSpace = NS_BTH;
318 reg_data->service.dwNumberOfCsAddrs = 1;
319 reg_data->service.lpcsaBuffer = &reg_data->address_info;
320
321 if (WSASetService(&reg_data->service,
322 RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) {
323 LOG(WARNING) << "Failed to register profile: WSASetService"
324 << "winsock err=" << WSAGetLastError();
325 PostErrorCompletion(error_callback, kWsaSetServiceError);
326 return;
327 }
328
dcheng70c49422016-03-02 23:20:34329 SetTCPSocket(std::move(scoped_socket));
330 service_reg_data_ = std::move(reg_data);
[email protected]ef2f0022014-04-29 10:24:35331
332 PostSuccess(success_callback);
333}
334
[email protected]85317222014-06-06 11:03:39335void BluetoothSocketWin::DoAccept(
336 const AcceptCompletionCallback& success_callback,
337 const ErrorCompletionCallback& error_callback) {
[email protected]2c24d942014-05-02 16:07:31338 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
339 int result = tcp_socket()->Accept(
[email protected]ef2f0022014-04-29 10:24:35340 &accept_socket_,
341 &accept_address_,
[email protected]85317222014-06-06 11:03:39342 base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread,
343 this,
344 success_callback,
345 error_callback));
346 if (result != net::OK && result != net::ERR_IO_PENDING) {
[email protected]ef2f0022014-04-29 10:24:35347 LOG(WARNING) << "Failed to accept, net err=" << result;
[email protected]85317222014-06-06 11:03:39348 PostErrorCompletion(error_callback, kFailedToAccept);
349 }
[email protected]ef2f0022014-04-29 10:24:35350}
351
[email protected]85317222014-06-06 11:03:39352void BluetoothSocketWin::OnAcceptOnSocketThread(
353 const AcceptCompletionCallback& success_callback,
354 const ErrorCompletionCallback& error_callback,
355 int accept_result) {
[email protected]2c24d942014-05-02 16:07:31356 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
[email protected]ef2f0022014-04-29 10:24:35357 if (accept_result != net::OK) {
358 LOG(WARNING) << "OnAccept error, net err=" << accept_result;
[email protected]85317222014-06-06 11:03:39359 PostErrorCompletion(error_callback, kFailedToAccept);
[email protected]ef2f0022014-04-29 10:24:35360 return;
361 }
362
[email protected]2c24d942014-05-02 16:07:31363 ui_task_runner()->PostTask(
[email protected]ef2f0022014-04-29 10:24:35364 FROM_HERE,
365 base::Bind(&BluetoothSocketWin::OnAcceptOnUI,
366 this,
367 base::Passed(&accept_socket_),
[email protected]85317222014-06-06 11:03:39368 accept_address_,
369 success_callback,
370 error_callback));
[email protected]ef2f0022014-04-29 10:24:35371}
372
373void BluetoothSocketWin::OnAcceptOnUI(
374 scoped_ptr<net::TCPSocket> accept_socket,
[email protected]85317222014-06-06 11:03:39375 const net::IPEndPoint& peer_address,
376 const AcceptCompletionCallback& success_callback,
377 const ErrorCompletionCallback& error_callback) {
[email protected]2c24d942014-05-02 16:07:31378 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
[email protected]ef2f0022014-04-29 10:24:35379
[email protected]85317222014-06-06 11:03:39380 const std::string peer_device_address =
381 IPEndPointToBluetoothAddress(peer_address);
382 const BluetoothDevice* peer_device = adapter_->GetDevice(peer_device_address);
383 if (!peer_device) {
384 LOG(WARNING) << "OnAccept failed with unknown device, addr="
385 << peer_device_address;
386 error_callback.Run(kFailedToAccept);
387 return;
388 }
389
[email protected]daed8ec2014-07-23 06:18:54390 scoped_refptr<BluetoothSocketWin> peer_socket =
391 CreateBluetoothSocket(ui_task_runner(), socket_thread());
dcheng70c49422016-03-02 23:20:34392 peer_socket->SetTCPSocket(std::move(accept_socket));
[email protected]85317222014-06-06 11:03:39393 success_callback.Run(peer_device, peer_socket);
[email protected]ef2f0022014-04-29 10:24:35394}
395
[email protected]0ae97592012-10-22 22:06:05396} // namespace device