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 |