Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1119)

Side by Side Diff: device/bluetooth/bluetooth_profile_win.cc

Issue 236203018: win: Implement Bluetooth server. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_profile_win.h" 5 #include "device/bluetooth/bluetooth_profile_win.h"
6 6
7 #include <objbase.h>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h"
8 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
9 #include "base/sequenced_task_runner.h" 12 #include "base/sequenced_task_runner.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
10 #include "device/bluetooth/bluetooth_adapter_factory.h" 16 #include "device/bluetooth/bluetooth_adapter_factory.h"
17 #include "device/bluetooth/bluetooth_adapter_win.h"
11 #include "device/bluetooth/bluetooth_device_win.h" 18 #include "device/bluetooth/bluetooth_device_win.h"
12 #include "device/bluetooth/bluetooth_service_record.h" 19 #include "device/bluetooth/bluetooth_service_record.h"
13 #include "device/bluetooth/bluetooth_socket_thread_win.h" 20 #include "device/bluetooth/bluetooth_socket_thread_win.h"
14 #include "device/bluetooth/bluetooth_socket_win.h" 21 #include "device/bluetooth/bluetooth_socket_win.h"
22 #include "net/base/net_errors.h"
23 #include "net/socket/tcp_socket.h"
15 24
16 namespace { 25 namespace {
17 26
18 using device::BluetoothAdapter; 27 using device::BluetoothAdapter;
19 using device::BluetoothDevice; 28 using device::BluetoothDevice;
20 using device::BluetoothProfileWin; 29 using device::BluetoothProfileWin;
21 using device::BluetoothSocket; 30 using device::BluetoothSocket;
22 using device::BluetoothSocketWin; 31 using device::BluetoothSocketWin;
23 32
24 const char kNoConnectionCallback[] = "Connection callback not set"; 33 const char kNoConnectionCallback[] = "Connection callback not set";
(...skipping 30 matching lines...) Expand all
55 socket)); 64 socket));
56 } 65 }
57 66
58 void OnConnectErrorUI(scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 67 void OnConnectErrorUI(scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
59 const BluetoothProfileWin::ErrorCallback& error_callback, 68 const BluetoothProfileWin::ErrorCallback& error_callback,
60 const std::string& error) { 69 const std::string& error) {
61 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); 70 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
62 error_callback.Run(error); 71 error_callback.Run(error);
63 } 72 }
64 73
74 std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) {
75 const size_t kBtAddressSize = 6;
76 if (end_point.address().size() != kBtAddressSize)
77 return std::string();
78 return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
79 end_point.address()[5],
80 end_point.address()[4],
81 end_point.address()[3],
82 end_point.address()[2],
83 end_point.address()[1],
84 end_point.address()[0]);
85 }
86
65 } // namespace 87 } // namespace
66 88
67 namespace device { 89 namespace device {
68 90
69 BluetoothProfileWin::BluetoothProfileWin(const BluetoothUUID& uuid, 91 struct BluetoothProfileWin::ProfileRegData {
70 const std::string& name) 92 ProfileRegData() {
71 : BluetoothProfile(), uuid_(uuid), name_(name) { 93 ZeroMemory(this, sizeof(ProfileRegData));
94 }
95
96 SOCKADDR_BTH address;
97 CSADDR_INFO address_info;
98 GUID uuid;
99 base::string16 name;
100 WSAQUERYSET service;
101 };
102
103 BluetoothProfileWin::BluetoothProfileWin()
104 : BluetoothProfile(), rfcomm_channel_(0), weak_ptr_factory_(this) {
72 } 105 }
73 106
74 BluetoothProfileWin::~BluetoothProfileWin() { 107 BluetoothProfileWin::~BluetoothProfileWin() {
75 } 108 }
76 109
77 void BluetoothProfileWin::Unregister() { 110 void BluetoothProfileWin::Unregister() {
111 if (adapter_) {
112 if (profile_reg_data_) {
113 adapter()->socket_thread()->task_runner()->PostTask(
114 FROM_HERE,
115 base::Bind(&BluetoothProfileWin::UnregisterProfileOnSocketThread,
116 base::Passed(&profile_reg_data_)));
117 }
118 if (profile_socket_)
119 profile_socket_->Close();
120
121 adapter()->socket_thread()->OnSocketDeactivate();
122 }
123
78 delete this; 124 delete this;
79 } 125 }
80 126
81 void BluetoothProfileWin::SetConnectionCallback( 127 void BluetoothProfileWin::SetConnectionCallback(
82 const ConnectionCallback& callback) { 128 const ConnectionCallback& callback) {
83 connection_callback_ = callback; 129 connection_callback_ = callback;
84 } 130 }
85 131
132 void BluetoothProfileWin::Init(const BluetoothUUID& uuid,
133 const BluetoothProfile::Options& options,
134 const ProfileCallback& callback) {
135 uuid_ = uuid;
136 name_ = options.name;
137 rfcomm_channel_ = options.channel;
138
139 BluetoothAdapterFactory::GetAdapter(
140 base::Bind(&BluetoothProfileWin::OnGetAdapter,
141 weak_ptr_factory_.GetWeakPtr(),
142 callback));
143 }
144
86 void BluetoothProfileWin::Connect( 145 void BluetoothProfileWin::Connect(
87 const BluetoothDeviceWin* device, 146 const BluetoothDeviceWin* device,
88 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 147 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
89 scoped_refptr<BluetoothSocketThreadWin> socket_thread, 148 scoped_refptr<BluetoothSocketThreadWin> socket_thread,
90 net::NetLog* net_log, 149 net::NetLog* net_log,
91 const net::NetLog::Source& source, 150 const net::NetLog::Source& source,
92 const base::Closure& success_callback, 151 const base::Closure& success_callback,
93 const ErrorCallback& error_callback) { 152 const ErrorCallback& error_callback) {
94 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); 153 DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
95 if (connection_callback_.is_null()) { 154 if (connection_callback_.is_null()) {
(...skipping 13 matching lines...) Expand all
109 168
110 socket->Connect(base::Bind(&OnConnectSuccessUI, 169 socket->Connect(base::Bind(&OnConnectSuccessUI,
111 ui_task_runner, 170 ui_task_runner,
112 success_callback, 171 success_callback,
113 connection_callback_, 172 connection_callback_,
114 device->GetAddress(), 173 device->GetAddress(),
115 socket), 174 socket),
116 error_callback); 175 error_callback);
117 } 176 }
118 177
178 void BluetoothProfileWin::OnGetAdapter(
179 const ProfileCallback& callback,
180 scoped_refptr<BluetoothAdapter> in_adapter) {
181 DCHECK(!adapter_);
182 DCHECK(!profile_socket_);
183 DCHECK(!profile_reg_data_);
184
185 adapter_ = in_adapter;
186 adapter()->socket_thread()->OnSocketActivate();
187
188 // The followings are owned by register profile reply callback.
189 bool* success = new bool(false);
190 scoped_ptr<net::TCPSocket>* socket = new scoped_ptr<net::TCPSocket>;
191 scoped_ptr<ProfileRegData>* reg_data = new scoped_ptr<ProfileRegData>;
192
193 adapter()->socket_thread()->task_runner()
194 ->PostTaskAndReply(
195 FROM_HERE,
196 base::Bind(&BluetoothProfileWin::RegisterProfileOnSocketThread,
197 uuid_,
198 name_,
199 rfcomm_channel_,
200 success,
201 socket,
202 reg_data),
203 base::Bind(&BluetoothProfileWin::OnRegisterProfileOnUI,
204 weak_ptr_factory_.GetWeakPtr(),
205 base::Owned(success),
206 base::Owned(socket),
207 base::Owned(reg_data),
208 callback));
209 }
210
211 // static
212 void BluetoothProfileWin::RegisterProfileOnSocketThread(
213 const device::BluetoothUUID& uuid,
214 const std::string& name,
215 int rfcomm_channel,
216 bool* out_success,
217 scoped_ptr<net::TCPSocket>* out_socket,
218 scoped_ptr<ProfileRegData>* out_reg_data) {
219 *out_success = false;
220
221 // The valid range is 0-30. 0 means BT_PORT_ANY and 1-30 are the
222 // valid RFCOMM port numbers of SOCKADDR_BTH.
223 if (rfcomm_channel < 0 || rfcomm_channel > 30) {
224 LOG(WARNING) << "Failed to register profile: "
225 << "Invalid RFCCOMM port " << rfcomm_channel
226 << ", uuid=" << uuid.value();
227 return;
228 }
229
230 SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
231 if (socket_fd == INVALID_SOCKET) {
232 LOG(WARNING) << "Failed to register profile: create socket, "
233 << "winsock err=" << WSAGetLastError();
234 return;
235 }
236
237 scoped_ptr<net::TCPSocket> scoped_socket(
238 new net::TCPSocket(NULL, net::NetLog::Source()));
239 scoped_socket->AdoptBoundSocket(socket_fd);
240
241 SOCKADDR_BTH sa;
242 struct sockaddr* sock_addr = reinterpret_cast<struct sockaddr*>(&sa);
243 int sock_addr_len = sizeof(sa);
244 ZeroMemory(&sa, sock_addr_len);
245 sa.addressFamily = AF_BTH;
246 sa.port = rfcomm_channel ? rfcomm_channel : BT_PORT_ANY;
247 if (bind(socket_fd, sock_addr, sock_addr_len) < 0) {
248 LOG(WARNING) << "Failed to register profile: create socket, "
249 << "winsock err=" << WSAGetLastError();
250 return;
251 }
252
253 const int kListenBacklog = 5;
254 if (scoped_socket->Listen(kListenBacklog) < 0) {
255 LOG(WARNING) << "Failed to register profile: Listen"
256 << "winsock err=" << WSAGetLastError();
257 return;
258 }
259
260 scoped_ptr<ProfileRegData> reg_data(new ProfileRegData);
261 reg_data->name = base::UTF8ToUTF16(name);
262
263 if (getsockname(socket_fd, sock_addr, &sock_addr_len)) {
264 LOG(WARNING) << "Failed to register profile: getsockname, "
265 << "winsock err=" << WSAGetLastError();
266 return;
267 }
268 reg_data->address = sa;
269
270 reg_data->address_info.LocalAddr.iSockaddrLength = sizeof(sa);
271 reg_data->address_info.LocalAddr.lpSockaddr =
272 reinterpret_cast<struct sockaddr*>(&reg_data->address);
273 reg_data->address_info.iSocketType = SOCK_STREAM;
274 reg_data->address_info.iProtocol = BTHPROTO_RFCOMM;
275
276 base::string16 cannonical_uuid = L"{" + base::ASCIIToUTF16(
277 uuid.canonical_value()) + L"}";
278 if (!SUCCEEDED(CLSIDFromString(cannonical_uuid.c_str(), &reg_data->uuid))) {
279 LOG(WARNING) << "Failed to register profile: "
280 << ", bad uuid=" << cannonical_uuid;
281 return;
282 }
283
284 reg_data->service.dwSize = sizeof(WSAQUERYSET);
285 reg_data->service.lpszServiceInstanceName =
286 const_cast<LPWSTR>(reg_data->name.c_str());
287 reg_data->service.lpServiceClassId = &reg_data->uuid;
288 reg_data->service.dwNameSpace = NS_BTH;
289 reg_data->service.dwNumberOfCsAddrs = 1;
290 reg_data->service.lpcsaBuffer = &reg_data->address_info;
291
292 if (WSASetService(&reg_data->service,
293 RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) {
294 LOG(WARNING) << "Failed to register profile: WSASetService"
295 << "winsock err=" << WSAGetLastError();
296 return;
297 }
298
299 *out_socket = scoped_socket.Pass();
300 *out_reg_data = reg_data.Pass();
301 *out_success = true;
302 }
303
304 void BluetoothProfileWin::OnRegisterProfileOnUI(
305 bool* success,
306 scoped_ptr<net::TCPSocket>* socket,
307 scoped_ptr<ProfileRegData>* reg_data,
308 const ProfileCallback& callback) {
309 DCHECK(adapter()->ui_task_runner()->RunsTasksOnCurrentThread());
310
311 if (!(*success)) {
312 callback.Run(NULL);
313 delete this;
314 return;
315 }
316
317 DCHECK(*socket);
318 DCHECK(*reg_data);
319
320 profile_socket_ = BluetoothSocketWin::CreateBluetoothSocket(
321 socket->Pass(),
322 adapter()->ui_task_runner(),
323 adapter()->socket_thread(),
324 NULL,
325 net::NetLog::Source());
326 profile_reg_data_ = reg_data->Pass();
327
328 profile_socket_->Accept(base::Bind(&BluetoothProfileWin::OnNewConnection,
329 weak_ptr_factory_.GetWeakPtr()));
330 callback.Run(this);
331 }
332
333 // static
334 void BluetoothProfileWin::UnregisterProfileOnSocketThread(
335 scoped_ptr<BluetoothProfileWin::ProfileRegData> reg_data) {
336 if (WSASetService(&reg_data->service,RNRSERVICE_DELETE, 0) == SOCKET_ERROR)
337 LOG(WARNING) << "Failed to unregister profile";
338 }
339
340 void BluetoothProfileWin::OnNewConnection(
341 scoped_refptr<BluetoothSocketWin> connected,
342 const net::IPEndPoint& peer_address) {
343 DCHECK(adapter()->ui_task_runner()->RunsTasksOnCurrentThread());
344 if (connection_callback_.is_null())
345 return;
346
347 std::string device_address = IPEndPointToBluetoothAddress(peer_address);
348 if (device_address.empty()) {
349 LOG(WARNING) << "Failed to accept connection for profile "
350 << "uuid=" << uuid_.value()
351 << ", unexpected peer device address.";
352 return;
353 }
354
355 BluetoothDevice* device = adapter_->GetDevice(device_address);
356 if (!device) {
357 LOG(WARNING) << "Failed to accept connection for profile"
358 << ",uuid=" << uuid_.value()
359 << ", unknown device=" << device_address;
360 return;
361 }
362
363 connection_callback_.Run(device, connected);
364 }
365
366 BluetoothAdapterWin* BluetoothProfileWin::adapter() const {
367 DCHECK(adapter_);
368 return static_cast<BluetoothAdapterWin*>(adapter_.get());
369 }
370
119 } // namespace device 371 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698