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. 4 5 #include "device/bluetooth/bluetooth_socket_win.h" 6 7 #include <objbase.h> 8 9 #include <string> 10 11 #include "base/logging.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/sequenced_task_runner.h" 14 #include "base/strings/stringprintf.h" 15 #include "base/strings/sys_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/threading/thread_restrictions.h" 18 #include "device/bluetooth/bluetooth_device_win.h" 19 #include "device/bluetooth/bluetooth_init_win.h" 20 #include "device/bluetooth/bluetooth_service_record_win.h" 21 #include "device/bluetooth/bluetooth_socket_thread.h" 22 #include "net/base/io_buffer.h" 23 #include "net/base/ip_endpoint.h" 24 #include "net/base/net_errors.h" 25 #include "net/base/winsock_init.h" 26 27 namespace { 28 29 const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; 30 const char kSocketAlreadyConnected[] = "Socket is already connected."; 31 const char kInvalidRfcommPort[] = "Invalid RFCCOMM port."; 32 const char kFailedToCreateSocket[] = "Failed to create socket."; 33 const char kFailedToBindSocket[] = "Failed to bind socket."; 34 const char kFailedToListenOnSocket[] = "Failed to listen on socket."; 35 const char kFailedToGetSockNameForSocket[] = "Failed to getsockname."; 36 const char kFailedToAccept[] = "Failed to accept."; 37 const char kInvalidUUID[] = "Invalid UUID"; 38 const char kWsaSetServiceError[] = "WSASetService error."; 39 40 std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) { 41 if (end_point.address().size() != net::kBluetoothAddressSize) 42 return std::string(); 43 // The address is copied from BTH_ADDR field of SOCKADDR_BTH, which is a 44 // 64-bit ULONGLONG that stores Bluetooth address in little-endian. Print in 45 // reverse order to preserve the correct ordering. 46 return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X", 47 end_point.address()[5], 48 end_point.address()[4], 49 end_point.address()[3], 50 end_point.address()[2], 51 end_point.address()[1], 52 end_point.address()[0]); 53 } 54 55 } // namespace 56 57 namespace device { 58 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 74 // static 75 scoped_refptr<BluetoothSocketWin> 76 BluetoothSocketWin::CreateBluetoothSocket( 77 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 78 scoped_refptr<device::BluetoothSocketThread> socket_thread) { 79 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); 80 81 return make_scoped_refptr( 82 new BluetoothSocketWin(ui_task_runner, socket_thread)); 83 } 84 85 BluetoothSocketWin::BluetoothSocketWin( 86 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 87 scoped_refptr<BluetoothSocketThread> socket_thread) 88 : BluetoothSocketNet(ui_task_runner, socket_thread), 89 supports_rfcomm_(false), 90 rfcomm_channel_(0xFF), 91 bth_addr_(BTH_ADDR_NULL) { 92 } 93 94 BluetoothSocketWin::~BluetoothSocketWin() { 95 } 96 97 void BluetoothSocketWin::Connect( 98 const BluetoothDeviceWin* device, 99 const BluetoothUUID& uuid, 100 const base::Closure& success_callback, 101 const ErrorCompletionCallback& error_callback) { 102 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 103 DCHECK(device); 104 105 if (!uuid.IsValid()) { 106 error_callback.Run(kInvalidUUID); 107 return; 108 } 109 110 const BluetoothServiceRecordWin* service_record_win = 111 device->GetServiceRecord(uuid); 112 if (!service_record_win) { 113 error_callback.Run(kInvalidUUID); 114 return; 115 } 116 117 device_address_ = service_record_win->device_address(); 118 if (service_record_win->SupportsRfcomm()) { 119 supports_rfcomm_ = true; 120 rfcomm_channel_ = service_record_win->rfcomm_channel(); 121 bth_addr_ = service_record_win->device_bth_addr(); 122 } 123 124 socket_thread()->task_runner()->PostTask( 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 134 void BluetoothSocketWin::Listen(scoped_refptr<BluetoothAdapter> adapter, 135 const BluetoothUUID& uuid, 136 const BluetoothAdapter::ServiceOptions& options, 137 const base::Closure& success_callback, 138 const ErrorCompletionCallback& error_callback) { 139 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 140 141 adapter_ = adapter; 142 int rfcomm_channel = options.channel ? *options.channel : 0; 143 144 // TODO(xiyuan): Use |options.name|. 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 } 154 155 void BluetoothSocketWin::ResetData() { 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 } 163 } 164 165 void BluetoothSocketWin::Accept( 166 const AcceptCompletionCallback& success_callback, 167 const ErrorCompletionCallback& error_callback) { 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)); 176 } 177 178 void BluetoothSocketWin::DoConnect( 179 const base::Closure& success_callback, 180 const ErrorCompletionCallback& error_callback) { 181 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 182 base::ThreadRestrictions::AssertIOAllowed(); 183 184 if (tcp_socket()) { 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 195 scoped_ptr<net::TCPSocket> scoped_socket( 196 new net::TCPSocket(NULL, net::NetLog::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_; 204 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 << logging::SystemErrorCodeToString(error_code); 212 error_callback.Run("Error connecting to socket: " + 213 logging::SystemErrorCodeToString(error_code)); 214 closesocket(socket_fd); 215 return; 216 } 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 = 221 scoped_socket->AdoptConnectedSocket(socket_fd, net::IPEndPoint()); 222 if (net_result != net::OK) { 223 error_callback.Run("Error connecting to socket: " + 224 net::ErrorToString(net_result)); 225 closesocket(socket_fd); 226 return; 227 } 228 229 SetTCPSocket(scoped_socket.Pass()); 230 success_callback.Run(); 231 } 232 233 void BluetoothSocketWin::DoListen( 234 const BluetoothUUID& uuid, 235 int rfcomm_channel, 236 const base::Closure& success_callback, 237 const ErrorCompletionCallback& error_callback) { 238 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 239 DCHECK(!tcp_socket() && !service_reg_data_); 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); 288 reg_data->name = base::UTF8ToUTF16(uuid.canonical_value()); 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: " 308 << ", invalid uuid=" << cannonical_uuid; 309 PostErrorCompletion(error_callback, kInvalidUUID); 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 329 SetTCPSocket(scoped_socket.Pass()); 330 service_reg_data_ = reg_data.Pass(); 331 332 PostSuccess(success_callback); 333 } 334 335 void BluetoothSocketWin::DoAccept( 336 const AcceptCompletionCallback& success_callback, 337 const ErrorCompletionCallback& error_callback) { 338 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 339 int result = tcp_socket()->Accept( 340 &accept_socket_, 341 &accept_address_, 342 base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread, 343 this, 344 success_callback, 345 error_callback)); 346 if (result != net::OK && result != net::ERR_IO_PENDING) { 347 LOG(WARNING) << "Failed to accept, net err=" << result; 348 PostErrorCompletion(error_callback, kFailedToAccept); 349 } 350 } 351 352 void BluetoothSocketWin::OnAcceptOnSocketThread( 353 const AcceptCompletionCallback& success_callback, 354 const ErrorCompletionCallback& error_callback, 355 int accept_result) { 356 DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 357 if (accept_result != net::OK) { 358 LOG(WARNING) << "OnAccept error, net err=" << accept_result; 359 PostErrorCompletion(error_callback, kFailedToAccept); 360 return; 361 } 362 363 ui_task_runner()->PostTask( 364 FROM_HERE, 365 base::Bind(&BluetoothSocketWin::OnAcceptOnUI, 366 this, 367 base::Passed(&accept_socket_), 368 accept_address_, 369 success_callback, 370 error_callback)); 371 } 372 373 void BluetoothSocketWin::OnAcceptOnUI( 374 scoped_ptr<net::TCPSocket> accept_socket, 375 const net::IPEndPoint& peer_address, 376 const AcceptCompletionCallback& success_callback, 377 const ErrorCompletionCallback& error_callback) { 378 DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 379 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 390 scoped_refptr<BluetoothSocketWin> peer_socket = 391 CreateBluetoothSocket(ui_task_runner(), socket_thread()); 392 peer_socket->SetTCPSocket(accept_socket.Pass()); 393 success_callback.Run(peer_device, peer_socket); 394 } 395 396 } // namespace device 397