Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/bluetooth/bluetooth_socket_win.h" | 5 #include "device/bluetooth/bluetooth_socket_win.h" |
| 6 | 6 |
| 7 #include <objbase.h> | |
| 8 | |
| 7 #include <string> | 9 #include <string> |
| 8 | 10 |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" |
| 10 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 11 #include "base/sequenced_task_runner.h" | 13 #include "base/sequenced_task_runner.h" |
| 12 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "base/strings/utf_string_conversions.h" | |
| 13 #include "base/threading/thread_restrictions.h" | 16 #include "base/threading/thread_restrictions.h" |
| 14 #include "device/bluetooth/bluetooth_init_win.h" | 17 #include "device/bluetooth/bluetooth_init_win.h" |
| 15 #include "device/bluetooth/bluetooth_service_record_win.h" | 18 #include "device/bluetooth/bluetooth_service_record_win.h" |
| 16 #include "device/bluetooth/bluetooth_socket_thread_win.h" | 19 #include "device/bluetooth/bluetooth_socket_thread_win.h" |
| 17 #include "net/base/io_buffer.h" | 20 #include "net/base/io_buffer.h" |
| 18 #include "net/base/ip_endpoint.h" | 21 #include "net/base/ip_endpoint.h" |
| 19 #include "net/base/net_errors.h" | 22 #include "net/base/net_errors.h" |
| 20 #include "net/base/winsock_init.h" | 23 #include "net/base/winsock_init.h" |
| 21 | 24 |
| 22 namespace { | 25 namespace { |
| 23 | 26 |
| 24 const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; | 27 const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; |
| 25 const char kSocketAlreadyConnected[] = "Socket is already connected."; | 28 const char kSocketAlreadyConnected[] = "Socket is already connected."; |
| 26 const char kSocketNotConnected[] = "Socket is not connected."; | 29 const char kSocketNotConnected[] = "Socket is not connected."; |
| 30 const char kInvalidRfcommPort[] = "Invalid RFCCOMM port."; | |
| 31 const char kFailedToCreateSocket[] = "Failed to create socket."; | |
| 32 const char kFailedToBindSocket[] = "Failed to bind socket."; | |
| 33 const char kFailedToListenOnSocket[] = "Failed to listen on socket."; | |
| 34 const char kFailedToGetSockNameForSocket[] = "Failed to getsockname."; | |
| 35 const char kBadUuid[] = "Bad uuid."; | |
| 36 const char kWsaSetServiceError[] = "WSASetService error."; | |
| 27 | 37 |
| 28 using device::BluetoothSocketWin; | 38 using device::BluetoothSocketWin; |
| 29 | 39 |
| 30 std::string FormatErrorMessage(DWORD error_code) { | 40 std::string FormatErrorMessage(DWORD error_code) { |
| 31 TCHAR error_msg[1024]; | 41 TCHAR error_msg[1024]; |
| 32 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, | 42 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, |
| 33 0, | 43 0, |
| 34 error_code, | 44 error_code, |
| 35 0, | 45 0, |
| 36 error_msg, | 46 error_msg, |
| 37 1024, | 47 1024, |
| 38 NULL); | 48 NULL); |
| 39 return base::SysWideToUTF8(error_msg); | 49 return base::SysWideToUTF8(error_msg); |
| 40 } | 50 } |
| 41 | 51 |
| 42 static void DeactivateSocket( | 52 static void DeactivateSocket( |
| 43 const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) { | 53 const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) { |
| 44 socket_thread->OnSocketDeactivate(); | 54 socket_thread->OnSocketDeactivate(); |
| 45 } | 55 } |
| 46 | 56 |
| 47 } // namespace | 57 } // namespace |
| 48 | 58 |
| 49 namespace device { | 59 namespace device { |
| 50 | 60 |
| 61 struct BluetoothSocketWin::ServiceRegData { | |
| 62 ServiceRegData() { | |
| 63 ZeroMemory(&address, sizeof(address)); | |
| 64 ZeroMemory(&address_info, sizeof(address_info)); | |
| 65 ZeroMemory(&uuid, sizeof(uuid)); | |
| 66 ZeroMemory(&service, sizeof(service)); | |
| 67 } | |
| 68 | |
| 69 SOCKADDR_BTH address; | |
| 70 CSADDR_INFO address_info; | |
| 71 GUID uuid; | |
| 72 base::string16 name; | |
| 73 WSAQUERYSET service; | |
| 74 }; | |
| 75 | |
| 51 // static | 76 // static |
| 52 scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( | 77 scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( |
| 53 const BluetoothServiceRecord& service_record, | |
| 54 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 78 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| 55 scoped_refptr<BluetoothSocketThreadWin> socket_thread, | 79 scoped_refptr<BluetoothSocketThreadWin> socket_thread, |
| 56 net::NetLog* net_log, | 80 net::NetLog* net_log, |
| 57 const net::NetLog::Source& source) { | 81 const net::NetLog::Source& source) { |
| 58 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); | 82 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); |
| 59 const BluetoothServiceRecordWin* service_record_win = | |
| 60 static_cast<const BluetoothServiceRecordWin*>(&service_record); | |
| 61 | 83 |
| 62 scoped_refptr<BluetoothSocketWin> result( | 84 return make_scoped_refptr( |
| 63 new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source)); | 85 new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source)); |
| 64 result->device_address_ = service_record_win->address(); | |
| 65 if (service_record.SupportsRfcomm()) { | |
| 66 result->supports_rfcomm_ = true; | |
| 67 result->rfcomm_channel_ = service_record_win->rfcomm_channel(); | |
| 68 result->bth_addr_ = service_record_win->bth_addr(); | |
| 69 } | |
| 70 | |
| 71 return result; | |
| 72 } | 86 } |
| 73 | 87 |
| 74 BluetoothSocketWin::BluetoothSocketWin( | 88 BluetoothSocketWin::BluetoothSocketWin( |
| 75 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 89 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| 76 scoped_refptr<BluetoothSocketThreadWin> socket_thread, | 90 scoped_refptr<BluetoothSocketThreadWin> socket_thread, |
| 77 net::NetLog* net_log, | 91 net::NetLog* net_log, |
| 78 const net::NetLog::Source& source) | 92 const net::NetLog::Source& source) |
| 79 : ui_task_runner_(ui_task_runner), | 93 : ui_task_runner_(ui_task_runner), |
| 80 socket_thread_(socket_thread), | 94 socket_thread_(socket_thread), |
| 81 net_log_(net_log), | 95 net_log_(net_log), |
| 82 source_(source), | 96 source_(source), |
| 83 supports_rfcomm_(false), | 97 supports_rfcomm_(false), |
| 84 rfcomm_channel_(-1), | 98 rfcomm_channel_(-1), |
| 85 bth_addr_(BTH_ADDR_NULL) { | 99 bth_addr_(BTH_ADDR_NULL) { |
| 86 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 100 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 87 socket_thread->OnSocketActivate(); | 101 socket_thread->OnSocketActivate(); |
| 88 } | 102 } |
| 89 | 103 |
| 90 BluetoothSocketWin::~BluetoothSocketWin() { | 104 BluetoothSocketWin::~BluetoothSocketWin() { |
| 91 ui_task_runner_->PostTask(FROM_HERE, | 105 ui_task_runner_->PostTask(FROM_HERE, |
| 92 base::Bind(&DeactivateSocket, socket_thread_)); | 106 base::Bind(&DeactivateSocket, socket_thread_)); |
| 93 } | 107 } |
| 94 | 108 |
| 109 void BluetoothSocketWin::StartService( | |
| 110 const BluetoothUUID& uuid, | |
| 111 const std::string& name, | |
| 112 int rfcomm_channel, | |
| 113 const base::Closure& success_callback, | |
| 114 const ErrorCompletionCallback& error_callback, | |
| 115 const OnNewConnectionCallback& new_connection_callback) { | |
| 116 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 117 | |
| 118 socket_thread_->task_runner()->PostTask( | |
| 119 FROM_HERE, | |
| 120 base::Bind(&BluetoothSocketWin::DoStartService, | |
| 121 this, | |
| 122 uuid, | |
| 123 name, | |
| 124 rfcomm_channel, | |
| 125 success_callback, | |
| 126 error_callback, | |
| 127 new_connection_callback)); | |
| 128 } | |
| 129 | |
| 95 void BluetoothSocketWin::Close() { | 130 void BluetoothSocketWin::Close() { |
| 96 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 131 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 97 socket_thread_->task_runner()->PostTask( | 132 socket_thread_->task_runner()->PostTask( |
| 98 FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this)); | 133 FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this)); |
| 99 } | 134 } |
| 100 | 135 |
| 101 void BluetoothSocketWin::Connect( | 136 void BluetoothSocketWin::Connect( |
| 137 const BluetoothServiceRecord& service_record, | |
| 102 const base::Closure& success_callback, | 138 const base::Closure& success_callback, |
| 103 const ErrorCompletionCallback& error_callback) { | 139 const ErrorCompletionCallback& error_callback) { |
| 104 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 140 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 141 | |
| 142 const BluetoothServiceRecordWin* service_record_win = | |
| 143 static_cast<const BluetoothServiceRecordWin*>(&service_record); | |
| 144 device_address_ = service_record_win->address(); | |
| 145 if (service_record.SupportsRfcomm()) { | |
| 146 supports_rfcomm_ = true; | |
| 147 rfcomm_channel_ = service_record_win->rfcomm_channel(); | |
| 148 bth_addr_ = service_record_win->bth_addr(); | |
| 149 } | |
| 150 | |
| 105 socket_thread_->task_runner()->PostTask( | 151 socket_thread_->task_runner()->PostTask( |
| 106 FROM_HERE, | 152 FROM_HERE, |
| 107 base::Bind( | 153 base::Bind( |
| 108 &BluetoothSocketWin::DoConnect, | 154 &BluetoothSocketWin::DoConnect, |
| 109 this, | 155 this, |
| 110 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), | 156 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), |
| 111 base::Bind( | 157 base::Bind( |
| 112 &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); | 158 &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); |
| 113 } | 159 } |
| 114 | 160 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 tcp_socket_->Close(); | 213 tcp_socket_->Close(); |
| 168 tcp_socket_.reset(NULL); | 214 tcp_socket_.reset(NULL); |
| 169 } | 215 } |
| 170 | 216 |
| 171 // Note: Closing |tcp_socket_| above released all potential pending | 217 // Note: Closing |tcp_socket_| above released all potential pending |
| 172 // Send/Receive operations, so we can no safely release the state associated | 218 // Send/Receive operations, so we can no safely release the state associated |
| 173 // to those pending operations. | 219 // to those pending operations. |
| 174 read_buffer_ = NULL; | 220 read_buffer_ = NULL; |
| 175 std::queue<linked_ptr<WriteRequest> > empty; | 221 std::queue<linked_ptr<WriteRequest> > empty; |
| 176 write_queue_.swap(empty); | 222 write_queue_.swap(empty); |
| 223 | |
| 224 if (service_reg_data_) { | |
| 225 if (WSASetService(&service_reg_data_->service,RNRSERVICE_DELETE, 0) == | |
| 226 SOCKET_ERROR) { | |
| 227 LOG(WARNING) << "Failed to unregister service."; | |
| 228 } | |
| 229 service_reg_data_.reset(); | |
| 230 } | |
| 177 } | 231 } |
| 178 | 232 |
| 179 void BluetoothSocketWin::DoConnect( | 233 void BluetoothSocketWin::DoConnect( |
| 180 const base::Closure& success_callback, | 234 const base::Closure& success_callback, |
| 181 const ErrorCompletionCallback& error_callback) { | 235 const ErrorCompletionCallback& error_callback) { |
| 182 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | 236 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); |
| 183 base::ThreadRestrictions::AssertIOAllowed(); | 237 base::ThreadRestrictions::AssertIOAllowed(); |
| 184 | 238 |
| 185 if (tcp_socket_) { | 239 if (tcp_socket_) { |
| 186 error_callback.Run(kSocketAlreadyConnected); | 240 error_callback.Run(kSocketAlreadyConnected); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 ui_task_runner_->PostTask(FROM_HERE, | 446 ui_task_runner_->PostTask(FROM_HERE, |
| 393 base::Bind(callback, reason, error_message)); | 447 base::Bind(callback, reason, error_message)); |
| 394 } | 448 } |
| 395 | 449 |
| 396 void BluetoothSocketWin::PostSendCompletion( | 450 void BluetoothSocketWin::PostSendCompletion( |
| 397 const SendCompletionCallback& callback, | 451 const SendCompletionCallback& callback, |
| 398 int bytes_written) { | 452 int bytes_written) { |
| 399 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); | 453 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); |
| 400 } | 454 } |
| 401 | 455 |
| 456 void BluetoothSocketWin::DoStartService( | |
| 457 const BluetoothUUID& uuid, | |
| 458 const std::string& name, | |
| 459 int rfcomm_channel, | |
| 460 const base::Closure& success_callback, | |
| 461 const ErrorCompletionCallback& error_callback, | |
| 462 const OnNewConnectionCallback& new_connection_callback) { | |
| 463 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
| 464 DCHECK(!tcp_socket_ && | |
| 465 !service_reg_data_ && | |
| 466 on_new_connection_callback_.is_null()); | |
| 467 | |
| 468 // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the | |
| 469 // valid RFCOMM port numbers of SOCKADDR_BTH. | |
| 470 if (rfcomm_channel < 0 || rfcomm_channel > 30) { | |
| 471 LOG(WARNING) << "Failed to start service: " | |
| 472 << "Invalid RFCCOMM port " << rfcomm_channel | |
| 473 << ", uuid=" << uuid.value(); | |
| 474 PostErrorCompletion(error_callback, kInvalidRfcommPort); | |
| 475 return; | |
| 476 } | |
| 477 | |
| 478 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); | |
| 479 if (socket_fd == INVALID_SOCKET) { | |
| 480 LOG(WARNING) << "Failed to start service: create socket, " | |
| 481 << "winsock err=" << WSAGetLastError(); | |
| 482 PostErrorCompletion(error_callback, kFailedToCreateSocket); | |
| 483 return; | |
| 484 } | |
| 485 | |
| 486 scoped_ptr<net::TCPSocket> scoped_socket( | |
| 487 new net::TCPSocket(NULL, net::NetLog::Source())); | |
| 488 scoped_socket->AdoptBoundSocket(socket_fd); | |
|
wtc
2014/04/24 23:09:31
At this point, we haven't called bind() yet, so th
xiyuan
2014/04/25 20:29:29
Renamed the function to AdoptListenSocket per disc
| |
| 489 | |
| 490 SOCKADDR_BTH sa; | |
| 491 struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa); | |
| 492 int sock_addr_len = sizeof(sa); | |
| 493 ZeroMemory(&sa, sock_addr_len); | |
| 494 sa.addressFamily = AF_BTH; | |
| 495 sa.port = rfcomm_channel ? rfcomm_channel : BT_PORT_ANY; | |
| 496 if (bind(socket_fd, sock_addr, sock_addr_len) < 0) { | |
| 497 LOG(WARNING) << "Failed to start service: create socket, " | |
| 498 << "winsock err=" << WSAGetLastError(); | |
| 499 PostErrorCompletion(error_callback, kFailedToBindSocket); | |
| 500 return; | |
| 501 } | |
| 502 | |
| 503 const int kListenBacklog = 5; | |
| 504 if (scoped_socket->Listen(kListenBacklog) < 0) { | |
| 505 LOG(WARNING) << "Failed to start service: Listen" | |
| 506 << "winsock err=" << WSAGetLastError(); | |
| 507 PostErrorCompletion(error_callback, kFailedToListenOnSocket); | |
| 508 return; | |
| 509 } | |
| 510 | |
| 511 scoped_ptr<ServiceRegData> reg_data(new ServiceRegData); | |
| 512 reg_data->name = base::UTF8ToUTF16(name); | |
| 513 | |
| 514 if (getsockname(socket_fd, sock_addr, &sock_addr_len)) { | |
| 515 LOG(WARNING) << "Failed to start service: getsockname, " | |
| 516 << "winsock err=" << WSAGetLastError(); | |
| 517 PostErrorCompletion(error_callback, kFailedToGetSockNameForSocket); | |
| 518 return; | |
| 519 } | |
| 520 reg_data->address = sa; | |
| 521 | |
| 522 reg_data->address_info.LocalAddr.iSockaddrLength = sizeof(sa); | |
| 523 reg_data->address_info.LocalAddr.lpSockaddr = | |
| 524 reinterpret_cast<struct sockaddr*>(®_data->address); | |
| 525 reg_data->address_info.iSocketType = SOCK_STREAM; | |
| 526 reg_data->address_info.iProtocol = BTHPROTO_RFCOMM; | |
| 527 | |
| 528 base::string16 cannonical_uuid = L"{" + base::ASCIIToUTF16( | |
| 529 uuid.canonical_value()) + L"}"; | |
| 530 if (!SUCCEEDED(CLSIDFromString(cannonical_uuid.c_str(), ®_data->uuid))) { | |
| 531 LOG(WARNING) << "Failed to start service: " | |
| 532 << ", bad uuid=" << cannonical_uuid; | |
| 533 PostErrorCompletion(error_callback, kBadUuid); | |
| 534 return; | |
| 535 } | |
| 536 | |
| 537 reg_data->service.dwSize = sizeof(WSAQUERYSET); | |
| 538 reg_data->service.lpszServiceInstanceName = | |
| 539 const_cast<LPWSTR>(reg_data->name.c_str()); | |
| 540 reg_data->service.lpServiceClassId = ®_data->uuid; | |
| 541 reg_data->service.dwNameSpace = NS_BTH; | |
| 542 reg_data->service.dwNumberOfCsAddrs = 1; | |
| 543 reg_data->service.lpcsaBuffer = ®_data->address_info; | |
| 544 | |
| 545 if (WSASetService(®_data->service, | |
| 546 RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) { | |
| 547 LOG(WARNING) << "Failed to register profile: WSASetService" | |
| 548 << "winsock err=" << WSAGetLastError(); | |
| 549 PostErrorCompletion(error_callback, kWsaSetServiceError); | |
| 550 return; | |
| 551 } | |
| 552 | |
| 553 tcp_socket_ = scoped_socket.Pass(); | |
| 554 service_reg_data_ = reg_data.Pass(); | |
| 555 on_new_connection_callback_ = new_connection_callback; | |
| 556 DoAccept(); | |
| 557 | |
| 558 PostSuccess(success_callback); | |
| 559 } | |
| 560 | |
| 561 void BluetoothSocketWin::DoAccept() { | |
| 562 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
| 563 int result = tcp_socket_->Accept( | |
| 564 &accept_socket_, | |
| 565 &accept_address_, | |
| 566 base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread, this)); | |
| 567 if (result != net::OK && result != net::ERR_IO_PENDING) | |
| 568 LOG(WARNING) << "Failed to accept, net err=" << result; | |
| 569 } | |
| 570 | |
| 571 void BluetoothSocketWin::OnAcceptOnSocketThread(int accept_result) { | |
| 572 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | |
| 573 if (accept_result != net::OK) { | |
| 574 LOG(WARNING) << "OnAccept error, net err=" << accept_result; | |
| 575 return; | |
| 576 } | |
| 577 | |
| 578 ui_task_runner_->PostTask( | |
| 579 FROM_HERE, | |
| 580 base::Bind(&BluetoothSocketWin::OnAcceptOnUI, | |
| 581 this, | |
| 582 base::Passed(&accept_socket_), | |
| 583 accept_address_)); | |
| 584 DoAccept(); | |
| 585 } | |
| 586 | |
| 587 void BluetoothSocketWin::OnAcceptOnUI( | |
| 588 scoped_ptr<net::TCPSocket> accept_socket, | |
| 589 const net::IPEndPoint& peer_address) { | |
| 590 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 591 | |
| 592 scoped_refptr<BluetoothSocketWin> peer = CreateBluetoothSocket( | |
| 593 ui_task_runner_, | |
| 594 socket_thread_, | |
| 595 net_log_, | |
| 596 source_); | |
| 597 peer->tcp_socket_ = accept_socket.Pass(); | |
| 598 | |
| 599 on_new_connection_callback_.Run(peer, peer_address); | |
| 600 } | |
| 601 | |
| 402 } // namespace device | 602 } // namespace device |
| OLD | NEW |