15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "device/bluetooth/bluetooth_socket_win.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <objbase.h> 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h" 13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/sequenced_task_runner.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/stringprintf.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/utf_string_conversions.h" 17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/threading/thread_restrictions.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "device/bluetooth/bluetooth_device_win.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "device/bluetooth/bluetooth_init_win.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "device/bluetooth/bluetooth_service_record_win.h" 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_socket_thread.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/ip_endpoint.h" 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/net_errors.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/winsock_init.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; 30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst char kSocketAlreadyConnected[] = "Socket is already connected."; 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kInvalidRfcommPort[] = "Invalid RFCCOMM port."; 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kFailedToCreateSocket[] = "Failed to create socket."; 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kFailedToBindSocket[] = "Failed to bind socket."; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kFailedToListenOnSocket[] = "Failed to listen on socket."; 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kFailedToGetSockNameForSocket[] = "Failed to getsockname."; 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kFailedToAccept[] = "Failed to accept."; 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kInvalidUUID[] = "Invalid UUID"; 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kWsaSetServiceError[] = "WSASetService error."; 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) { 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (end_point.address().size() != net::kBluetoothAddressSize) 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return std::string(); 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The address is copied from BTH_ADDR field of SOCKADDR_BTH, which is a 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // 64-bit ULONGLONG that stores Bluetooth address in little-endian. Print in 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // reverse order to preserve the correct ordering. 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X", 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[5], 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[4], 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[3], 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[2], 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[1], 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) end_point.address()[0]); 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace device { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct BluetoothSocketWin::ServiceRegData { 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ServiceRegData() { 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ZeroMemory(&address, sizeof(address)); 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ZeroMemory(&address_info, sizeof(address_info)); 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ZeroMemory(&uuid, sizeof(uuid)); 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ZeroMemory(&service, sizeof(service)); 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SOCKADDR_BTH address; 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CSADDR_INFO address_info; 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GUID uuid; 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::string16 name; 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WSAQUERYSET service; 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// static 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_refptr<BluetoothSocketWin> 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)BluetoothSocketWin::CreateBluetoothSocket( 77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<device::BluetoothSocketThread> socket_thread) { 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return make_scoped_refptr( 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new BluetoothSocketWin(ui_task_runner, socket_thread)); 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothSocketWin::BluetoothSocketWin( 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<BluetoothSocketThread> socket_thread) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : BluetoothSocketNet(ui_task_runner, socket_thread), 89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch supports_rfcomm_(false), 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rfcomm_channel_(0xFF), 91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bth_addr_(BTH_ADDR_NULL) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BluetoothSocketWin::~BluetoothSocketWin() { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothSocketWin::Connect( 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BluetoothDeviceWin* device, 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BluetoothUUID& uuid, 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Closure& success_callback, 101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const ErrorCompletionCallback& error_callback) { 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(device); 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!uuid.IsValid()) { 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback.Run(kInvalidUUID); 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const BluetoothServiceRecordWin* service_record_win = 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) device->GetServiceRecord(uuid); 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!service_record_win) { 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback.Run(kInvalidUUID); 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) device_address_ = service_record_win->device_address(); 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (service_record_win->SupportsRfcomm()) { 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu supports_rfcomm_ = true; 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu rfcomm_channel_ = service_record_win->rfcomm_channel(); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bth_addr_ = service_record_win->device_bth_addr(); 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) socket_thread()->task_runner()->PostTask( 125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FROM_HERE, 126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind( 127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &BluetoothSocketWin::DoConnect, 128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch this, 129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), 130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::Bind( 131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); 132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BluetoothSocketWin::Listen(scoped_refptr<BluetoothAdapter> adapter, 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BluetoothUUID& uuid, 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const BluetoothAdapter::ServiceOptions& options, 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::Closure& success_callback, 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ErrorCompletionCallback& error_callback) { 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) adapter_ = adapter; 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rfcomm_channel = options.channel ? *options.channel : 0; 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(xiyuan): Use |options.name|. 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) socket_thread()->task_runner()->PostTask( 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BluetoothSocketWin::DoListen, 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this, 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uuid, 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) rfcomm_channel, 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) success_callback, 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback)); 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothSocketWin::ResetData() { 1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (service_reg_data_) { 1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (WSASetService(&service_reg_data_->service,RNRSERVICE_DELETE, 0) == 1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SOCKET_ERROR) { 1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to unregister service."; 1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu service_reg_data_.reset(); 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BluetoothSocketWin::Accept( 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const AcceptCompletionCallback& success_callback, 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const ErrorCompletionCallback& error_callback) { 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) socket_thread()->task_runner()->PostTask( 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BluetoothSocketWin::DoAccept, 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this, 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) success_callback, 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback)); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothSocketWin::DoConnect( 179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Closure& success_callback, 180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const ErrorCompletionCallback& error_callback) { 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::ThreadRestrictions::AssertIOAllowed(); 183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (tcp_socket()) { 185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run(kSocketAlreadyConnected); 186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!supports_rfcomm_) { 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(youngki) add support for L2CAP sockets as well. 191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run(kL2CAPNotSupported); 192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<net::TCPSocket> scoped_socket( 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new net::TCPSocket(NULL, net::NetLog::Source())); 197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch net::EnsureWinsockInit(); 198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SOCKADDR_BTH sa; 200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ZeroMemory(&sa, sizeof(sa)); 201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch sa.addressFamily = AF_BTH; 202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch sa.port = rfcomm_channel_; 203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch sa.btAddr = bth_addr_; 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(rpaquay): Condider making this call non-blocking. 206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int status = connect(socket_fd, reinterpret_cast<SOCKADDR*>(&sa), sizeof(sa)); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD error_code = WSAGetLastError(); 208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!(status == 0 || error_code == WSAEINPROGRESS)) { 209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LOG(ERROR) << "Failed to connect bluetooth socket " 210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << "(" << device_address_ << "): " 2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << logging::SystemErrorCodeToString(error_code); 212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run("Error connecting to socket: " + 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu logging::SystemErrorCodeToString(error_code)); 214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch closesocket(socket_fd); 215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TCPSocket implementation does not actually require one. 220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int net_result = 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_socket->AdoptConnectedSocket(socket_fd, net::IPEndPoint()); 222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (net_result != net::OK) { 223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run("Error connecting to socket: " + 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::ErrorToString(net_result)); 225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch closesocket(socket_fd); 226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetTCPSocket(scoped_socket.Pass()); 230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch success_callback.Run(); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BluetoothSocketWin::DoListen( 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const BluetoothUUID& uuid, 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int rfcomm_channel, 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const base::Closure& success_callback, 23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ErrorCompletionCallback& error_callback) { 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(!tcp_socket() && !service_reg_data_); 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // valid RFCOMM port numbers of SOCKADDR_BTH. 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (rfcomm_channel < 0 || rfcomm_channel > 30) { 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: " 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "Invalid RFCCOMM port " << rfcomm_channel 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << ", uuid=" << uuid.value(); 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kInvalidRfcommPort); 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (socket_fd == INVALID_SOCKET) { 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: create socket, " 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "winsock err=" << WSAGetLastError(); 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kFailedToCreateSocket); 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Note that |socket_fd| belongs to a non-TCP address family (i.e. AF_BTH), 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // TCPSocket methods that involve address could not be called. So bind() 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // is called on |socket_fd| directly. 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<net::TCPSocket> scoped_socket( 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new net::TCPSocket(NULL, net::NetLog::Source())); 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_socket->AdoptListenSocket(socket_fd); 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SOCKADDR_BTH sa; 2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa); 2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int sock_addr_len = sizeof(sa); 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ZeroMemory(&sa, sock_addr_len); 2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sa.addressFamily = AF_BTH; 2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sa.port = rfcomm_channel ? rfcomm_channel : BT_PORT_ANY; 2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (bind(socket_fd, sock_addr, sock_addr_len) < 0) { 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: create socket, " 2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "winsock err=" << WSAGetLastError(); 2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kFailedToBindSocket); 2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int kListenBacklog = 5; 2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (scoped_socket->Listen(kListenBacklog) < 0) { 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: Listen" 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "winsock err=" << WSAGetLastError(); 2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kFailedToListenOnSocket); 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<ServiceRegData> reg_data(new ServiceRegData); 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reg_data->name = base::UTF8ToUTF16(uuid.canonical_value()); 2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (getsockname(socket_fd, sock_addr, &sock_addr_len)) { 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: getsockname, " 2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "winsock err=" << WSAGetLastError(); 2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kFailedToGetSockNameForSocket); 2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->address = sa; 2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->address_info.LocalAddr.iSockaddrLength = sizeof(sa); 2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->address_info.LocalAddr.lpSockaddr = 3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reinterpret_cast<struct sockaddr*>(®_data->address); 3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->address_info.iSocketType = SOCK_STREAM; 3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->address_info.iProtocol = BTHPROTO_RFCOMM; 3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::string16 cannonical_uuid = L"{" + base::ASCIIToUTF16( 3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uuid.canonical_value()) + L"}"; 3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!SUCCEEDED(CLSIDFromString(cannonical_uuid.c_str(), ®_data->uuid))) { 3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to start service: " 30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << ", invalid uuid=" << cannonical_uuid; 30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PostErrorCompletion(error_callback, kInvalidUUID); 3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.dwSize = sizeof(WSAQUERYSET); 3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.lpszServiceInstanceName = 3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const_cast<LPWSTR>(reg_data->name.c_str()); 3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.lpServiceClassId = ®_data->uuid; 3175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.dwNameSpace = NS_BTH; 3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.dwNumberOfCsAddrs = 1; 3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reg_data->service.lpcsaBuffer = ®_data->address_info; 3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (WSASetService(®_data->service, 3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) { 3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to register profile: WSASetService" 3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << "winsock err=" << WSAGetLastError(); 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostErrorCompletion(error_callback, kWsaSetServiceError); 3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) SetTCPSocket(scoped_socket.Pass()); 3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu service_reg_data_ = reg_data.Pass(); 3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PostSuccess(success_callback); 3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BluetoothSocketWin::DoAccept( 33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const AcceptCompletionCallback& success_callback, 33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ErrorCompletionCallback& error_callback) { 338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int result = tcp_socket()->Accept( 3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu &accept_socket_, 3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu &accept_address_, 34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread, 34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this, 34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) success_callback, 34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback)); 34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (result != net::OK && result != net::ERR_IO_PENDING) { 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "Failed to accept, net err=" << result; 34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PostErrorCompletion(error_callback, kFailedToAccept); 34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BluetoothSocketWin::OnAcceptOnSocketThread( 35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const AcceptCompletionCallback& success_callback, 35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ErrorCompletionCallback& error_callback, 35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int accept_result) { 356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread()); 3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (accept_result != net::OK) { 3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LOG(WARNING) << "OnAccept error, net err=" << accept_result; 35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PostErrorCompletion(error_callback, kFailedToAccept); 3605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui_task_runner()->PostTask( 3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu FROM_HERE, 3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::Bind(&BluetoothSocketWin::OnAcceptOnUI, 3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this, 3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::Passed(&accept_socket_), 36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) accept_address_, 36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) success_callback, 37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback)); 3715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid BluetoothSocketWin::OnAcceptOnUI( 3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<net::TCPSocket> accept_socket, 37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const net::IPEndPoint& peer_address, 37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const AcceptCompletionCallback& success_callback, 37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ErrorCompletionCallback& error_callback) { 378010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(ui_task_runner()->RunsTasksOnCurrentThread()); 3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string peer_device_address = 38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IPEndPointToBluetoothAddress(peer_address); 38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const BluetoothDevice* peer_device = adapter_->GetDevice(peer_device_address); 38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!peer_device) { 38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(WARNING) << "OnAccept failed with unknown device, addr=" 38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << peer_device_address; 38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error_callback.Run(kFailedToAccept); 38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<BluetoothSocketWin> peer_socket = 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateBluetoothSocket(ui_task_runner(), socket_thread()); 39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) peer_socket->SetTCPSocket(accept_socket.Pass()); 39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) success_callback.Run(peer_device, peer_socket); 3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace device 397