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 static void DeactivateSocket( | 40 static void DeactivateSocket( |
31 const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) { | 41 const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) { |
32 socket_thread->OnSocketDeactivate(); | 42 socket_thread->OnSocketDeactivate(); |
33 } | 43 } |
34 | 44 |
35 } // namespace | 45 } // namespace |
36 | 46 |
37 namespace device { | 47 namespace device { |
38 | 48 |
| 49 struct BluetoothSocketWin::ServiceRegData { |
| 50 ServiceRegData() { |
| 51 ZeroMemory(&address, sizeof(address)); |
| 52 ZeroMemory(&address_info, sizeof(address_info)); |
| 53 ZeroMemory(&uuid, sizeof(uuid)); |
| 54 ZeroMemory(&service, sizeof(service)); |
| 55 } |
| 56 |
| 57 SOCKADDR_BTH address; |
| 58 CSADDR_INFO address_info; |
| 59 GUID uuid; |
| 60 base::string16 name; |
| 61 WSAQUERYSET service; |
| 62 }; |
| 63 |
39 // static | 64 // static |
40 scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( | 65 scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( |
41 const BluetoothServiceRecord& service_record, | |
42 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 66 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
43 scoped_refptr<BluetoothSocketThreadWin> socket_thread, | 67 scoped_refptr<BluetoothSocketThreadWin> socket_thread, |
44 net::NetLog* net_log, | 68 net::NetLog* net_log, |
45 const net::NetLog::Source& source) { | 69 const net::NetLog::Source& source) { |
46 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); | 70 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); |
47 const BluetoothServiceRecordWin* service_record_win = | |
48 static_cast<const BluetoothServiceRecordWin*>(&service_record); | |
49 | 71 |
50 scoped_refptr<BluetoothSocketWin> result( | 72 return make_scoped_refptr( |
51 new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source)); | 73 new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source)); |
52 result->device_address_ = service_record_win->address(); | |
53 if (service_record.SupportsRfcomm()) { | |
54 result->supports_rfcomm_ = true; | |
55 result->rfcomm_channel_ = service_record_win->rfcomm_channel(); | |
56 result->bth_addr_ = service_record_win->bth_addr(); | |
57 } | |
58 | |
59 return result; | |
60 } | 74 } |
61 | 75 |
62 BluetoothSocketWin::BluetoothSocketWin( | 76 BluetoothSocketWin::BluetoothSocketWin( |
63 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | 77 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
64 scoped_refptr<BluetoothSocketThreadWin> socket_thread, | 78 scoped_refptr<BluetoothSocketThreadWin> socket_thread, |
65 net::NetLog* net_log, | 79 net::NetLog* net_log, |
66 const net::NetLog::Source& source) | 80 const net::NetLog::Source& source) |
67 : ui_task_runner_(ui_task_runner), | 81 : ui_task_runner_(ui_task_runner), |
68 socket_thread_(socket_thread), | 82 socket_thread_(socket_thread), |
69 net_log_(net_log), | 83 net_log_(net_log), |
70 source_(source), | 84 source_(source), |
71 supports_rfcomm_(false), | 85 supports_rfcomm_(false), |
72 rfcomm_channel_(-1), | 86 rfcomm_channel_(-1), |
73 bth_addr_(BTH_ADDR_NULL) { | 87 bth_addr_(BTH_ADDR_NULL) { |
74 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 88 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
75 socket_thread->OnSocketActivate(); | 89 socket_thread->OnSocketActivate(); |
76 } | 90 } |
77 | 91 |
78 BluetoothSocketWin::~BluetoothSocketWin() { | 92 BluetoothSocketWin::~BluetoothSocketWin() { |
79 ui_task_runner_->PostTask(FROM_HERE, | 93 ui_task_runner_->PostTask(FROM_HERE, |
80 base::Bind(&DeactivateSocket, socket_thread_)); | 94 base::Bind(&DeactivateSocket, socket_thread_)); |
81 } | 95 } |
82 | 96 |
| 97 void BluetoothSocketWin::StartService( |
| 98 const BluetoothUUID& uuid, |
| 99 const std::string& name, |
| 100 int rfcomm_channel, |
| 101 const base::Closure& success_callback, |
| 102 const ErrorCompletionCallback& error_callback, |
| 103 const OnNewConnectionCallback& new_connection_callback) { |
| 104 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 105 |
| 106 socket_thread_->task_runner()->PostTask( |
| 107 FROM_HERE, |
| 108 base::Bind(&BluetoothSocketWin::DoStartService, |
| 109 this, |
| 110 uuid, |
| 111 name, |
| 112 rfcomm_channel, |
| 113 success_callback, |
| 114 error_callback, |
| 115 new_connection_callback)); |
| 116 } |
| 117 |
83 void BluetoothSocketWin::Close() { | 118 void BluetoothSocketWin::Close() { |
84 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 119 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
85 socket_thread_->task_runner()->PostTask( | 120 socket_thread_->task_runner()->PostTask( |
86 FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this)); | 121 FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this)); |
87 } | 122 } |
88 | 123 |
89 void BluetoothSocketWin::Connect( | 124 void BluetoothSocketWin::Connect( |
| 125 const BluetoothServiceRecord& service_record, |
90 const base::Closure& success_callback, | 126 const base::Closure& success_callback, |
91 const ErrorCompletionCallback& error_callback) { | 127 const ErrorCompletionCallback& error_callback) { |
92 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 128 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 129 |
| 130 const BluetoothServiceRecordWin* service_record_win = |
| 131 static_cast<const BluetoothServiceRecordWin*>(&service_record); |
| 132 device_address_ = service_record_win->address(); |
| 133 if (service_record.SupportsRfcomm()) { |
| 134 supports_rfcomm_ = true; |
| 135 rfcomm_channel_ = service_record_win->rfcomm_channel(); |
| 136 bth_addr_ = service_record_win->bth_addr(); |
| 137 } |
| 138 |
93 socket_thread_->task_runner()->PostTask( | 139 socket_thread_->task_runner()->PostTask( |
94 FROM_HERE, | 140 FROM_HERE, |
95 base::Bind( | 141 base::Bind( |
96 &BluetoothSocketWin::DoConnect, | 142 &BluetoothSocketWin::DoConnect, |
97 this, | 143 this, |
98 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), | 144 base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), |
99 base::Bind( | 145 base::Bind( |
100 &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); | 146 &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); |
101 } | 147 } |
102 | 148 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 tcp_socket_->Close(); | 201 tcp_socket_->Close(); |
156 tcp_socket_.reset(NULL); | 202 tcp_socket_.reset(NULL); |
157 } | 203 } |
158 | 204 |
159 // Note: Closing |tcp_socket_| above released all potential pending | 205 // Note: Closing |tcp_socket_| above released all potential pending |
160 // Send/Receive operations, so we can no safely release the state associated | 206 // Send/Receive operations, so we can no safely release the state associated |
161 // to those pending operations. | 207 // to those pending operations. |
162 read_buffer_ = NULL; | 208 read_buffer_ = NULL; |
163 std::queue<linked_ptr<WriteRequest> > empty; | 209 std::queue<linked_ptr<WriteRequest> > empty; |
164 write_queue_.swap(empty); | 210 write_queue_.swap(empty); |
| 211 |
| 212 if (service_reg_data_) { |
| 213 if (WSASetService(&service_reg_data_->service,RNRSERVICE_DELETE, 0) == |
| 214 SOCKET_ERROR) { |
| 215 LOG(WARNING) << "Failed to unregister service."; |
| 216 } |
| 217 service_reg_data_.reset(); |
| 218 } |
165 } | 219 } |
166 | 220 |
167 void BluetoothSocketWin::DoConnect( | 221 void BluetoothSocketWin::DoConnect( |
168 const base::Closure& success_callback, | 222 const base::Closure& success_callback, |
169 const ErrorCompletionCallback& error_callback) { | 223 const ErrorCompletionCallback& error_callback) { |
170 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); | 224 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); |
171 base::ThreadRestrictions::AssertIOAllowed(); | 225 base::ThreadRestrictions::AssertIOAllowed(); |
172 | 226 |
173 if (tcp_socket_) { | 227 if (tcp_socket_) { |
174 error_callback.Run(kSocketAlreadyConnected); | 228 error_callback.Run(kSocketAlreadyConnected); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 ui_task_runner_->PostTask(FROM_HERE, | 435 ui_task_runner_->PostTask(FROM_HERE, |
382 base::Bind(callback, reason, error_message)); | 436 base::Bind(callback, reason, error_message)); |
383 } | 437 } |
384 | 438 |
385 void BluetoothSocketWin::PostSendCompletion( | 439 void BluetoothSocketWin::PostSendCompletion( |
386 const SendCompletionCallback& callback, | 440 const SendCompletionCallback& callback, |
387 int bytes_written) { | 441 int bytes_written) { |
388 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); | 442 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); |
389 } | 443 } |
390 | 444 |
| 445 void BluetoothSocketWin::DoStartService( |
| 446 const BluetoothUUID& uuid, |
| 447 const std::string& name, |
| 448 int rfcomm_channel, |
| 449 const base::Closure& success_callback, |
| 450 const ErrorCompletionCallback& error_callback, |
| 451 const OnNewConnectionCallback& new_connection_callback) { |
| 452 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); |
| 453 DCHECK(!tcp_socket_ && |
| 454 !service_reg_data_ && |
| 455 on_new_connection_callback_.is_null()); |
| 456 |
| 457 // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the |
| 458 // valid RFCOMM port numbers of SOCKADDR_BTH. |
| 459 if (rfcomm_channel < 0 || rfcomm_channel > 30) { |
| 460 LOG(WARNING) << "Failed to start service: " |
| 461 << "Invalid RFCCOMM port " << rfcomm_channel |
| 462 << ", uuid=" << uuid.value(); |
| 463 PostErrorCompletion(error_callback, kInvalidRfcommPort); |
| 464 return; |
| 465 } |
| 466 |
| 467 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); |
| 468 if (socket_fd == INVALID_SOCKET) { |
| 469 LOG(WARNING) << "Failed to start service: create socket, " |
| 470 << "winsock err=" << WSAGetLastError(); |
| 471 PostErrorCompletion(error_callback, kFailedToCreateSocket); |
| 472 return; |
| 473 } |
| 474 |
| 475 // Note that |socket_fd| belongs to a non-TCP address family (i.e. AF_BTH), |
| 476 // TCPSocket methods that involve address could not be called. So bind() |
| 477 // is called on |socket_fd| directly. |
| 478 scoped_ptr<net::TCPSocket> scoped_socket( |
| 479 new net::TCPSocket(NULL, net::NetLog::Source())); |
| 480 scoped_socket->AdoptListenSocket(socket_fd); |
| 481 |
| 482 SOCKADDR_BTH sa; |
| 483 struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa); |
| 484 int sock_addr_len = sizeof(sa); |
| 485 ZeroMemory(&sa, sock_addr_len); |
| 486 sa.addressFamily = AF_BTH; |
| 487 sa.port = rfcomm_channel ? rfcomm_channel : BT_PORT_ANY; |
| 488 if (bind(socket_fd, sock_addr, sock_addr_len) < 0) { |
| 489 LOG(WARNING) << "Failed to start service: create socket, " |
| 490 << "winsock err=" << WSAGetLastError(); |
| 491 PostErrorCompletion(error_callback, kFailedToBindSocket); |
| 492 return; |
| 493 } |
| 494 |
| 495 const int kListenBacklog = 5; |
| 496 if (scoped_socket->Listen(kListenBacklog) < 0) { |
| 497 LOG(WARNING) << "Failed to start service: Listen" |
| 498 << "winsock err=" << WSAGetLastError(); |
| 499 PostErrorCompletion(error_callback, kFailedToListenOnSocket); |
| 500 return; |
| 501 } |
| 502 |
| 503 scoped_ptr<ServiceRegData> reg_data(new ServiceRegData); |
| 504 reg_data->name = base::UTF8ToUTF16(name); |
| 505 |
| 506 if (getsockname(socket_fd, sock_addr, &sock_addr_len)) { |
| 507 LOG(WARNING) << "Failed to start service: getsockname, " |
| 508 << "winsock err=" << WSAGetLastError(); |
| 509 PostErrorCompletion(error_callback, kFailedToGetSockNameForSocket); |
| 510 return; |
| 511 } |
| 512 reg_data->address = sa; |
| 513 |
| 514 reg_data->address_info.LocalAddr.iSockaddrLength = sizeof(sa); |
| 515 reg_data->address_info.LocalAddr.lpSockaddr = |
| 516 reinterpret_cast<struct sockaddr*>(®_data->address); |
| 517 reg_data->address_info.iSocketType = SOCK_STREAM; |
| 518 reg_data->address_info.iProtocol = BTHPROTO_RFCOMM; |
| 519 |
| 520 base::string16 cannonical_uuid = L"{" + base::ASCIIToUTF16( |
| 521 uuid.canonical_value()) + L"}"; |
| 522 if (!SUCCEEDED(CLSIDFromString(cannonical_uuid.c_str(), ®_data->uuid))) { |
| 523 LOG(WARNING) << "Failed to start service: " |
| 524 << ", bad uuid=" << cannonical_uuid; |
| 525 PostErrorCompletion(error_callback, kBadUuid); |
| 526 return; |
| 527 } |
| 528 |
| 529 reg_data->service.dwSize = sizeof(WSAQUERYSET); |
| 530 reg_data->service.lpszServiceInstanceName = |
| 531 const_cast<LPWSTR>(reg_data->name.c_str()); |
| 532 reg_data->service.lpServiceClassId = ®_data->uuid; |
| 533 reg_data->service.dwNameSpace = NS_BTH; |
| 534 reg_data->service.dwNumberOfCsAddrs = 1; |
| 535 reg_data->service.lpcsaBuffer = ®_data->address_info; |
| 536 |
| 537 if (WSASetService(®_data->service, |
| 538 RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) { |
| 539 LOG(WARNING) << "Failed to register profile: WSASetService" |
| 540 << "winsock err=" << WSAGetLastError(); |
| 541 PostErrorCompletion(error_callback, kWsaSetServiceError); |
| 542 return; |
| 543 } |
| 544 |
| 545 tcp_socket_ = scoped_socket.Pass(); |
| 546 service_reg_data_ = reg_data.Pass(); |
| 547 on_new_connection_callback_ = new_connection_callback; |
| 548 DoAccept(); |
| 549 |
| 550 PostSuccess(success_callback); |
| 551 } |
| 552 |
| 553 void BluetoothSocketWin::DoAccept() { |
| 554 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); |
| 555 int result = tcp_socket_->Accept( |
| 556 &accept_socket_, |
| 557 &accept_address_, |
| 558 base::Bind(&BluetoothSocketWin::OnAcceptOnSocketThread, this)); |
| 559 if (result != net::OK && result != net::ERR_IO_PENDING) |
| 560 LOG(WARNING) << "Failed to accept, net err=" << result; |
| 561 } |
| 562 |
| 563 void BluetoothSocketWin::OnAcceptOnSocketThread(int accept_result) { |
| 564 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); |
| 565 if (accept_result != net::OK) { |
| 566 LOG(WARNING) << "OnAccept error, net err=" << accept_result; |
| 567 return; |
| 568 } |
| 569 |
| 570 ui_task_runner_->PostTask( |
| 571 FROM_HERE, |
| 572 base::Bind(&BluetoothSocketWin::OnAcceptOnUI, |
| 573 this, |
| 574 base::Passed(&accept_socket_), |
| 575 accept_address_)); |
| 576 DoAccept(); |
| 577 } |
| 578 |
| 579 void BluetoothSocketWin::OnAcceptOnUI( |
| 580 scoped_ptr<net::TCPSocket> accept_socket, |
| 581 const net::IPEndPoint& peer_address) { |
| 582 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 583 |
| 584 scoped_refptr<BluetoothSocketWin> peer = CreateBluetoothSocket( |
| 585 ui_task_runner_, |
| 586 socket_thread_, |
| 587 net_log_, |
| 588 source_); |
| 589 peer->tcp_socket_ = accept_socket.Pass(); |
| 590 |
| 591 on_new_connection_callback_.Run(peer, peer_address); |
| 592 } |
| 593 |
391 } // namespace device | 594 } // namespace device |
OLD | NEW |