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 <string> 8 9 #include "base/logging.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/strings/sys_string_conversions.h" 12 #include "device/bluetooth/bluetooth_init_win.h" 13 #include "device/bluetooth/bluetooth_service_record_win.h" 14 #include "net/base/io_buffer.h" 15 #include "net/base/winsock_init.h" 16 17 namespace { 18 19 std::string FormatErrorMessage(DWORD error_code) { 20 TCHAR error_msg[1024]; 21 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 22 0, 23 error_code, 24 0, 25 error_msg, 26 1024, 27 NULL); 28 return base::SysWideToUTF8(error_msg); 29 } 30 31 } // namespace 32 33 namespace device { 34 35 BluetoothSocketWin::BluetoothSocketWin(SOCKET fd) : fd_(fd) { 36 } 37 38 BluetoothSocketWin::~BluetoothSocketWin() { 39 closesocket(fd_); 40 } 41 42 // static 43 scoped_refptr<BluetoothSocket> BluetoothSocketWin::CreateBluetoothSocket( 44 const BluetoothServiceRecord& service_record) { 45 BluetoothSocketWin* bluetooth_socket = NULL; 46 if (service_record.SupportsRfcomm()) { 47 net::EnsureWinsockInit(); 48 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 49 SOCKADDR_BTH sa; 50 ZeroMemory(&sa, sizeof(sa)); 51 sa.addressFamily = AF_BTH; 52 sa.port = service_record.rfcomm_channel(); 53 const BluetoothServiceRecordWin* service_record_win = 54 static_cast<const BluetoothServiceRecordWin*>(&service_record); 55 sa.btAddr = service_record_win->bth_addr(); 56 57 int status = connect(socket_fd, 58 reinterpret_cast<SOCKADDR *>(&sa), 59 sizeof(sa)); 60 DWORD error_code = WSAGetLastError(); 61 if (status == 0 || error_code == WSAEINPROGRESS) { 62 bluetooth_socket = 63 new BluetoothSocketWin(socket_fd); 64 } else { 65 LOG(ERROR) << "Failed to connect bluetooth socket " 66 << "(" << service_record.address() << "): " 67 << "(" << error_code << ")" << FormatErrorMessage(error_code); 68 closesocket(socket_fd); 69 } 70 } 71 // TODO(youngki) add support for L2CAP sockets as well. 72 73 return scoped_refptr<BluetoothSocketWin>(bluetooth_socket); 74 } 75 76 bool BluetoothSocketWin::Receive(net::GrowableIOBuffer* buffer) { 77 buffer->SetCapacity(1024); 78 int bytes_read; 79 do { 80 if (buffer->RemainingCapacity() == 0) 81 buffer->SetCapacity(buffer->capacity() * 2); 82 bytes_read = recv(fd_, buffer->data(), buffer->RemainingCapacity(), 0); 83 if (bytes_read > 0) 84 buffer->set_offset(buffer->offset() + bytes_read); 85 } while (bytes_read > 0); 86 87 DWORD error_code = WSAGetLastError(); 88 if (bytes_read < 0 && error_code != WSAEWOULDBLOCK) { 89 error_message_ = FormatErrorMessage(error_code); 90 return false; 91 } 92 return true; 93 } 94 95 bool BluetoothSocketWin::Send(net::DrainableIOBuffer* buffer) { 96 int bytes_written; 97 do { 98 bytes_written = send(fd_, buffer->data(), buffer->BytesRemaining(), 0); 99 if (bytes_written > 0) 100 buffer->DidConsume(bytes_written); 101 } while (buffer->BytesRemaining() > 0 && bytes_written > 0); 102 103 DWORD error_code = WSAGetLastError(); 104 if (bytes_written < 0 && error_code != WSAEWOULDBLOCK) { 105 error_message_ = FormatErrorMessage(error_code); 106 return false; 107 } 108 return true; 109 } 110 111 std::string BluetoothSocketWin::GetLastErrorMessage() const { 112 return error_message_; 113 } 114 115 } // namespace device 116