[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 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. |
[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 4 | |
| 5 | #include "device/bluetooth/bluetooth_socket_win.h" |
| 6 | |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 7 | #include <objbase.h> |
| 8 | |
[email protected] | 0fd66b50 | 2013-01-29 23:29:50 | [diff] [blame] | 9 | #include <string> |
dcheng | 70c4942 | 2016-03-02 23:20:34 | [diff] [blame] | 10 | #include <utility> |
[email protected] | 0fd66b50 | 2013-01-29 23:29:50 | [diff] [blame] | 11 | |
[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 12 | #include "base/logging.h" |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 13 | #include "base/memory/ref_counted.h" |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 14 | #include "base/sequenced_task_runner.h" |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 15 | #include "base/strings/stringprintf.h" |
[email protected] | 13ac5353 | 2013-03-30 00:27:00 | [diff] [blame] | 16 | #include "base/strings/sys_string_conversions.h" |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 17 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 18 | #include "base/threading/thread_restrictions.h" |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 19 | #include "device/bluetooth/bluetooth_device_win.h" |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 20 | #include "device/bluetooth/bluetooth_init_win.h" |
| 21 | #include "device/bluetooth/bluetooth_service_record_win.h" |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 22 | #include "device/bluetooth/bluetooth_socket_thread.h" |
[email protected] | 0fd66b50 | 2013-01-29 23:29:50 | [diff] [blame] | 23 | #include "net/base/io_buffer.h" |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 24 | #include "net/base/ip_endpoint.h" |
| 25 | #include "net/base/net_errors.h" |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 26 | #include "net/base/winsock_init.h" |
tfarina | c5336ca | 2016-01-11 20:49:36 | [diff] [blame] | 27 | #include "net/base/winsock_util.h" |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 28 | |
| 29 | namespace { |
| 30 | |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 31 | const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; |
| 32 | const char kSocketAlreadyConnected[] = "Socket is already connected."; |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 33 | const char kInvalidRfcommPort[] = "Invalid RFCCOMM port."; |
| 34 | const char kFailedToCreateSocket[] = "Failed to create socket."; |
| 35 | const char kFailedToBindSocket[] = "Failed to bind socket."; |
| 36 | const char kFailedToListenOnSocket[] = "Failed to listen on socket."; |
| 37 | const char kFailedToGetSockNameForSocket[] = "Failed to getsockname."; |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 38 | const char kFailedToAccept[] = "Failed to accept."; |
| 39 | const char kInvalidUUID[] = "Invalid UUID"; |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 40 | const char kWsaSetServiceError[] = "WSASetService error."; |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 41 | |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 42 | std::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. |
martijn | 98acb9b | 2016-01-27 07:14:07 | [diff] [blame] | 48 | 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] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 53 | } |
| 54 | |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 55 | } // namespace |
[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 56 | |
| 57 | namespace device { |
| 58 | |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 59 | struct 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] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 74 | // static |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 75 | scoped_refptr<BluetoothSocketWin> |
| 76 | BluetoothSocketWin::CreateBluetoothSocket( |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 77 | scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
[email protected] | daed8ec | 2014-07-23 06:18:54 | [diff] [blame] | 78 | scoped_refptr<device::BluetoothSocketThread> socket_thread) { |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 79 | DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 80 | |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 81 | return make_scoped_refptr( |
[email protected] | daed8ec | 2014-07-23 06:18:54 | [diff] [blame] | 82 | new BluetoothSocketWin(ui_task_runner, socket_thread)); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | BluetoothSocketWin::BluetoothSocketWin( |
| 86 | scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
[email protected] | daed8ec | 2014-07-23 06:18:54 | [diff] [blame] | 87 | scoped_refptr<BluetoothSocketThread> socket_thread) |
| 88 | : BluetoothSocketNet(ui_task_runner, socket_thread), |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 89 | supports_rfcomm_(false), |
[email protected] | 481c3e8 | 2014-07-18 01:40:47 | [diff] [blame] | 90 | rfcomm_channel_(0xFF), |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 91 | bth_addr_(BTH_ADDR_NULL) { |
[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | BluetoothSocketWin::~BluetoothSocketWin() { |
| 95 | } |
| 96 | |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 97 | void BluetoothSocketWin::Connect( |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 98 | const BluetoothDeviceWin* device, |
| 99 | const BluetoothUUID& uuid, |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 100 | const base::Closure& success_callback, |
| 101 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 102 | DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 103 | DCHECK(device); |
| 104 | |
| 105 | if (!uuid.IsValid()) { |
| 106 | error_callback.Run(kInvalidUUID); |
| 107 | return; |
| 108 | } |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 109 | |
| 110 | const BluetoothServiceRecordWin* service_record_win = |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 111 | device->GetServiceRecord(uuid); |
| 112 | if (!service_record_win) { |
| 113 | error_callback.Run(kInvalidUUID); |
| 114 | return; |
| 115 | } |
| 116 | |
[email protected] | 44f159f | 2014-07-20 21:36:24 | [diff] [blame] | 117 | device_address_ = service_record_win->device_address(); |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 118 | if (service_record_win->SupportsRfcomm()) { |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 119 | supports_rfcomm_ = true; |
| 120 | rfcomm_channel_ = service_record_win->rfcomm_channel(); |
[email protected] | 44f159f | 2014-07-20 21:36:24 | [diff] [blame] | 121 | bth_addr_ = service_record_win->device_bth_addr(); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 122 | } |
| 123 | |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 124 | socket_thread()->task_runner()->PostTask( |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 125 | 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] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 134 | void BluetoothSocketWin::Listen(scoped_refptr<BluetoothAdapter> adapter, |
| 135 | const BluetoothUUID& uuid, |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 136 | const BluetoothAdapter::ServiceOptions& options, |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 137 | const base::Closure& success_callback, |
| 138 | const ErrorCompletionCallback& error_callback) { |
| 139 | DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
| 140 | |
| 141 | adapter_ = adapter; |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 142 | int rfcomm_channel = options.channel ? *options.channel : 0; |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 143 | |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 144 | // TODO(xiyuan): Use |options.name|. |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 145 | 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] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 154 | |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 155 | void BluetoothSocketWin::ResetData() { |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 156 | 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] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 163 | } |
| 164 | |
[email protected] | 37f0b7f | 2014-05-12 18:09:51 | [diff] [blame] | 165 | void BluetoothSocketWin::Accept( |
| 166 | const AcceptCompletionCallback& success_callback, |
| 167 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 168 | 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] | 37f0b7f | 2014-05-12 18:09:51 | [diff] [blame] | 176 | } |
| 177 | |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 178 | void BluetoothSocketWin::DoConnect( |
| 179 | const base::Closure& success_callback, |
| 180 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 181 | DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 182 | base::ThreadRestrictions::AssertIOAllowed(); |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 183 | |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 184 | if (tcp_socket()) { |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 185 | 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] | 76caec0 | 2014-07-31 12:07:19 | [diff] [blame] | 195 | scoped_ptr<net::TCPSocket> scoped_socket( |
| 196 | new net::TCPSocket(NULL, net::NetLog::Source())); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 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_; |
| 204 | |
| 205 | // TODO(rpaquay): Condider making this call non-blocking. |
| 206 | int status = connect(socket_fd, reinterpret_cast<SOCKADDR*>(&sa), sizeof(sa)); |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 207 | DWORD error_code = WSAGetLastError(); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 208 | if (!(status == 0 || error_code == WSAEINPROGRESS)) { |
| 209 | LOG(ERROR) << "Failed to connect bluetooth socket " |
| 210 | << "(" << device_address_ << "): " |
[email protected] | 69c5739 | 2014-04-25 15:16:13 | [diff] [blame] | 211 | << logging::SystemErrorCodeToString(error_code); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 212 | error_callback.Run("Error connecting to socket: " + |
[email protected] | 69c5739 | 2014-04-25 15:16:13 | [diff] [blame] | 213 | logging::SystemErrorCodeToString(error_code)); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 214 | closesocket(socket_fd); |
| 215 | return; |
[email protected] | 246493d | 2013-02-03 18:24:03 | [diff] [blame] | 216 | } |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 217 | |
| 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] | 76caec0 | 2014-07-31 12:07:19 | [diff] [blame] | 221 | scoped_socket->AdoptConnectedSocket(socket_fd, net::IPEndPoint()); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 222 | if (net_result != net::OK) { |
| 223 | error_callback.Run("Error connecting to socket: " + |
[email protected] | 3030374e3 | 2014-08-07 16:12:06 | [diff] [blame] | 224 | net::ErrorToString(net_result)); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 225 | closesocket(socket_fd); |
| 226 | return; |
| 227 | } |
| 228 | |
dcheng | 70c4942 | 2016-03-02 23:20:34 | [diff] [blame] | 229 | SetTCPSocket(std::move(scoped_socket)); |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 230 | success_callback.Run(); |
[email protected] | dc85cef | 2014-04-07 19:58:52 | [diff] [blame] | 231 | } |
[email protected] | eba06dc | 2014-04-07 19:21:07 | [diff] [blame] | 232 | |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 233 | void BluetoothSocketWin::DoListen( |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 234 | const BluetoothUUID& uuid, |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 235 | int rfcomm_channel, |
| 236 | const base::Closure& success_callback, |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 237 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 238 | DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 239 | DCHECK(!tcp_socket() && !service_reg_data_); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 240 | |
| 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] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 288 | reg_data->name = base::UTF8ToUTF16(uuid.canonical_value()); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 289 | |
| 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*>(®_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(), ®_data->uuid))) { |
| 307 | LOG(WARNING) << "Failed to start service: " |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 308 | << ", invalid uuid=" << cannonical_uuid; |
| 309 | PostErrorCompletion(error_callback, kInvalidUUID); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 310 | 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 = ®_data->uuid; |
| 317 | reg_data->service.dwNameSpace = NS_BTH; |
| 318 | reg_data->service.dwNumberOfCsAddrs = 1; |
| 319 | reg_data->service.lpcsaBuffer = ®_data->address_info; |
| 320 | |
| 321 | if (WSASetService(®_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 | |
dcheng | 70c4942 | 2016-03-02 23:20:34 | [diff] [blame] | 329 | SetTCPSocket(std::move(scoped_socket)); |
| 330 | service_reg_data_ = std::move(reg_data); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 331 | |
| 332 | PostSuccess(success_callback); |
| 333 | } |
| 334 | |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 335 | void BluetoothSocketWin::DoAccept( |
| 336 | const AcceptCompletionCallback& success_callback, |
| 337 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 338 | DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
| 339 | int result = tcp_socket()->Accept( |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 340 | &accept_socket_, |
| 341 | &accept_address_, |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 342 | base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread, |
| 343 | this, |
| 344 | success_callback, |
| 345 | error_callback)); |
| 346 | if (result != net::OK && result != net::ERR_IO_PENDING) { |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 347 | LOG(WARNING) << "Failed to accept, net err=" << result; |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 348 | PostErrorCompletion(error_callback, kFailedToAccept); |
| 349 | } |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 350 | } |
| 351 | |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 352 | void BluetoothSocketWin::OnAcceptOnSocketThread( |
| 353 | const AcceptCompletionCallback& success_callback, |
| 354 | const ErrorCompletionCallback& error_callback, |
| 355 | int accept_result) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 356 | DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 357 | if (accept_result != net::OK) { |
| 358 | LOG(WARNING) << "OnAccept error, net err=" << accept_result; |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 359 | PostErrorCompletion(error_callback, kFailedToAccept); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 360 | return; |
| 361 | } |
| 362 | |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 363 | ui_task_runner()->PostTask( |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 364 | FROM_HERE, |
| 365 | base::Bind(&BluetoothSocketWin::OnAcceptOnUI, |
| 366 | this, |
| 367 | base::Passed(&accept_socket_), |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 368 | accept_address_, |
| 369 | success_callback, |
| 370 | error_callback)); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 371 | } |
| 372 | |
| 373 | void BluetoothSocketWin::OnAcceptOnUI( |
| 374 | scoped_ptr<net::TCPSocket> accept_socket, |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 375 | const net::IPEndPoint& peer_address, |
| 376 | const AcceptCompletionCallback& success_callback, |
| 377 | const ErrorCompletionCallback& error_callback) { |
[email protected] | 2c24d94 | 2014-05-02 16:07:31 | [diff] [blame] | 378 | DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 379 | |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 380 | 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] | daed8ec | 2014-07-23 06:18:54 | [diff] [blame] | 390 | scoped_refptr<BluetoothSocketWin> peer_socket = |
| 391 | CreateBluetoothSocket(ui_task_runner(), socket_thread()); |
dcheng | 70c4942 | 2016-03-02 23:20:34 | [diff] [blame] | 392 | peer_socket->SetTCPSocket(std::move(accept_socket)); |
[email protected] | 8531722 | 2014-06-06 11:03:39 | [diff] [blame] | 393 | success_callback.Run(peer_device, peer_socket); |
[email protected] | ef2f002 | 2014-04-29 10:24:35 | [diff] [blame] | 394 | } |
| 395 | |
[email protected] | 0ae9759 | 2012-10-22 22:06:05 | [diff] [blame] | 396 | } // namespace device |