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) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "device/bluetooth/bluetooth_init_win.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "device/bluetooth/bluetooth_service_record_win.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/winsock_init.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string FormatErrorMessage(DWORD error_code) { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TCHAR error_msg[1024]; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_code, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_msg, 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1024, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::SysWideToUTF8(error_msg); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace device { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BluetoothSocketWin::BluetoothSocketWin(SOCKET fd) : fd_(fd) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BluetoothSocketWin::~BluetoothSocketWin() { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closesocket(fd_); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<BluetoothSocket> BluetoothSocketWin::CreateBluetoothSocket( 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BluetoothServiceRecord& service_record) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BluetoothSocketWin* bluetooth_socket = NULL; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (service_record.SupportsRfcomm()) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::EnsureWinsockInit(); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SOCKADDR_BTH sa; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ZeroMemory(&sa, sizeof(sa)); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sa.addressFamily = AF_BTH; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sa.port = service_record.rfcomm_channel(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BluetoothServiceRecordWin* service_record_win = 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<const BluetoothServiceRecordWin*>(&service_record); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sa.btAddr = service_record_win->bth_addr(); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int status = connect(socket_fd, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<SOCKADDR *>(&sa), 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sizeof(sa)); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD error_code = WSAGetLastError(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status == 0 || error_code == WSAEINPROGRESS) { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bluetooth_socket = 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new BluetoothSocketWin(socket_fd); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to connect bluetooth socket " 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "(" << service_record.address() << "): " 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "(" << error_code << ")" << FormatErrorMessage(error_code); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closesocket(socket_fd); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(youngki) add support for L2CAP sockets as well. 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return scoped_refptr<BluetoothSocketWin>(bluetooth_socket); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothSocketWin::Receive(net::GrowableIOBuffer* buffer) { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->SetCapacity(1024); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_read; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buffer->RemainingCapacity() == 0) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->SetCapacity(buffer->capacity() * 2); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_read = recv(fd_, buffer->data(), buffer->RemainingCapacity(), 0); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_read > 0) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->set_offset(buffer->offset() + bytes_read); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (bytes_read > 0); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD error_code = WSAGetLastError(); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_read < 0 && error_code != WSAEWOULDBLOCK) { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_message_ = FormatErrorMessage(error_code); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BluetoothSocketWin::Send(net::DrainableIOBuffer* buffer) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_written; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_written = send(fd_, buffer->data(), buffer->BytesRemaining(), 0); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_written > 0) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->DidConsume(bytes_written); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (buffer->BytesRemaining() > 0 && bytes_written > 0); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD error_code = WSAGetLastError(); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_written < 0 && error_code != WSAEWOULDBLOCK) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_message_ = FormatErrorMessage(error_code); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string BluetoothSocketWin::GetLastErrorMessage() const { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return error_message_; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace device 116