OLD | NEW |
---|---|
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_socket_mac.h" | 5 #include "device/bluetooth/bluetooth_socket_mac.h" |
6 | 6 |
7 #import <IOBluetooth/IOBluetooth.h> | 7 #import <IOBluetooth/IOBluetooth.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 | 210 |
211 socket_->OnChannelOpened(std::unique_ptr<device::BluetoothChannelMac>( | 211 socket_->OnChannelOpened(std::unique_ptr<device::BluetoothChannelMac>( |
212 new device::BluetoothL2capChannelMac(NULL, [l2capChannel retain]))); | 212 new device::BluetoothL2capChannelMac(NULL, [l2capChannel retain]))); |
213 } | 213 } |
214 | 214 |
215 @end | 215 @end |
216 | 216 |
217 namespace device { | 217 namespace device { |
218 namespace { | 218 namespace { |
219 | 219 |
220 // It's safe to use 0 to represent an unregistered service, as implied by the | 220 // It's safe to use 0 to represent invalid channel or PSM port numbers, as both |
221 // documentation at [ http://goo.gl/YRtCkF ]. | 221 // are required to be non-zero for valid services. |
222 const BluetoothSDPServiceRecordHandle kInvalidServiceRecordHandle = 0; | |
223 | |
224 // Likewise, it's safe to use 0 to represent invalid channel or PSM port | |
225 // numbers, as both are required to be non-zero for valid services. | |
226 const BluetoothRFCOMMChannelID kInvalidRfcommChannelId = 0; | 222 const BluetoothRFCOMMChannelID kInvalidRfcommChannelId = 0; |
227 const BluetoothL2CAPPSM kInvalidL2capPsm = 0; | 223 const BluetoothL2CAPPSM kInvalidL2capPsm = 0; |
228 | 224 |
229 const char kInvalidOrUsedChannel[] = "Invalid channel or already in use"; | 225 const char kInvalidOrUsedChannel[] = "Invalid channel or already in use"; |
230 const char kInvalidOrUsedPsm[] = "Invalid PSM or already in use"; | 226 const char kInvalidOrUsedPsm[] = "Invalid PSM or already in use"; |
231 const char kProfileNotFound[] = "Profile not found"; | 227 const char kProfileNotFound[] = "Profile not found"; |
232 const char kSDPQueryFailed[] = "SDP query failed"; | 228 const char kSDPQueryFailed[] = "SDP query failed"; |
233 const char kSocketConnecting[] = "The socket is currently connecting"; | 229 const char kSocketConnecting[] = "The socket is currently connecting"; |
234 const char kSocketAlreadyConnected[] = "The socket is already connected"; | 230 const char kSocketAlreadyConnected[] = "The socket is already connected"; |
235 const char kSocketNotConnected[] = "The socket is not connected"; | 231 const char kSocketNotConnected[] = "The socket is not connected"; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 @"DataElementSize" : @2, // 2 bytes. | 331 @"DataElementSize" : @2, // 2 bytes. |
336 @"DataElementValue" : @(psm), | 332 @"DataElementValue" : @(psm), |
337 }, | 333 }, |
338 ], | 334 ], |
339 ]; | 335 ]; |
340 return BuildServiceDefinition( | 336 return BuildServiceDefinition( |
341 uuid, options.name.get(), l2cap_protocol_definition); | 337 uuid, options.name.get(), l2cap_protocol_definition); |
342 } | 338 } |
343 | 339 |
344 // Registers a Bluetooth service with the specified |service_definition| in the | 340 // Registers a Bluetooth service with the specified |service_definition| in the |
345 // system SDP server. Returns a handle to the registered service on success. If | 341 // system SDP server. Returns the registered service on success. If the service |
346 // the service could not be registered, or if |verify_service_callback| | 342 // could not be registered, or if |verify_service_callback| indicates that the |
347 // indicates that the to-be-registered service is not configured correctly, | 343 // to-be-registered service was not configured correctly, returns nil. |
348 // returns |kInvalidServiceRecordHandle|. | 344 IOBluetoothSDPServiceRecord* RegisterService( |
Ilya Sherman
2016/10/20 01:11:05
In regular C++, I'd ask you to change this to be a
shrike
2016/10/20 19:26:18
The object returned by +publishedServiceRecordWith
Ilya Sherman
2016/10/20 19:37:35
That's fair, but it's hard to tell from the metho
erikchen
2016/10/21 01:18:00
In ObjC, any function/method that doesn't have the
| |
349 BluetoothSDPServiceRecordHandle RegisterService( | |
350 NSDictionary* service_definition, | 345 NSDictionary* service_definition, |
351 const base::Callback<bool(IOBluetoothSDPServiceRecord*)>& | 346 const base::Callback<bool(IOBluetoothSDPServiceRecord*)>& |
352 verify_service_callback) { | 347 verify_service_callback) { |
353 // Attempt to register the service. | 348 // Attempt to register the service. |
354 IOBluetoothSDPServiceRecordRef service_record_ref; | 349 IOBluetoothSDPServiceRecord* service_record = [IOBluetoothSDPServiceRecord |
355 IOReturn result = | 350 publishedServiceRecordWithDictionary:service_definition]; |
Ilya Sherman
2016/10/20 01:11:05
Okay, it looks like this method is only available
shrike
2016/10/20 19:26:18
We only support Chrome running on OS X 10.9 and up
Ilya Sherman
2016/10/20 19:37:35
Oh, wow, I hadn't realized we dropped support for
| |
356 IOBluetoothAddServiceDict((CFDictionaryRef)service_definition, | |
357 &service_record_ref); | |
358 if (result != kIOReturnSuccess) | |
359 return kInvalidServiceRecordHandle; | |
360 // Transfer ownership to a scoped object, to simplify memory management. | |
361 base::ScopedCFTypeRef<IOBluetoothSDPServiceRecordRef> | |
362 scoped_service_record_ref(service_record_ref); | |
363 | |
364 // Extract the service record handle. | |
365 BluetoothSDPServiceRecordHandle service_record_handle; | |
366 IOBluetoothSDPServiceRecord* service_record = | |
367 [IOBluetoothSDPServiceRecord withSDPServiceRecordRef:service_record_ref]; | |
368 result = [service_record getServiceRecordHandle:&service_record_handle]; | |
369 if (result != kIOReturnSuccess) | |
370 return kInvalidServiceRecordHandle; | |
371 | 351 |
372 // Verify that the registered service was configured correctly. If not, | 352 // Verify that the registered service was configured correctly. If not, |
373 // withdraw the service. | 353 // withdraw the service. |
374 if (!verify_service_callback.Run(service_record)) { | 354 if (!service_record || !verify_service_callback.Run(service_record)) { |
375 IOBluetoothRemoveServiceWithRecordHandle(service_record_handle); | 355 [service_record removeServiceRecord]; |
376 return kInvalidServiceRecordHandle; | 356 service_record = nil; |
377 } | 357 } |
378 | 358 |
379 return service_record_handle; | 359 return service_record; |
380 } | 360 } |
381 | 361 |
382 // Returns true iff the |requested_channel_id| was registered in the RFCOMM | 362 // Returns true iff the |requested_channel_id| was registered in the RFCOMM |
383 // |service_record|. If it was, also updates |registered_channel_id| with the | 363 // |service_record|. If it was, also updates |registered_channel_id| with the |
384 // registered value, as the requested id may have been left unspecified. | 364 // registered value, as the requested id may have been left unspecified. |
385 bool VerifyRfcommService(const int* requested_channel_id, | 365 bool VerifyRfcommService(const int* requested_channel_id, |
386 BluetoothRFCOMMChannelID* registered_channel_id, | 366 BluetoothRFCOMMChannelID* registered_channel_id, |
387 IOBluetoothSDPServiceRecord* service_record) { | 367 IOBluetoothSDPServiceRecord* service_record) { |
388 // Test whether the requested channel id was available. | 368 // Test whether the requested channel id was available. |
389 // TODO(isherman): The OS doesn't seem to actually pick a random channel if we | 369 // TODO(isherman): The OS doesn't seem to actually pick a random channel if we |
390 // pass in |kInvalidRfcommChannelId|. | 370 // pass in |kInvalidRfcommChannelId|. |
391 BluetoothRFCOMMChannelID rfcomm_channel_id; | 371 BluetoothRFCOMMChannelID rfcomm_channel_id; |
392 IOReturn result = [service_record getRFCOMMChannelID:&rfcomm_channel_id]; | 372 IOReturn result = [service_record getRFCOMMChannelID:&rfcomm_channel_id]; |
393 if (result != kIOReturnSuccess || | 373 if (result != kIOReturnSuccess || |
394 (requested_channel_id && rfcomm_channel_id != *requested_channel_id)) { | 374 (requested_channel_id && rfcomm_channel_id != *requested_channel_id)) { |
395 return false; | 375 return false; |
396 } | 376 } |
397 | 377 |
398 *registered_channel_id = rfcomm_channel_id; | 378 *registered_channel_id = rfcomm_channel_id; |
399 return true; | 379 return true; |
400 } | 380 } |
401 | 381 |
402 // Registers an RFCOMM service with the specified |uuid|, |options.channel_id|, | 382 // Registers an RFCOMM service with the specified |uuid|, |options.channel_id|, |
403 // and |options.name| in the system SDP server. Automatically allocates a | 383 // and |options.name| in the system SDP server. Automatically allocates a |
404 // channel if |options.channel_id| is null. Does not specify a name if | 384 // channel if |options.channel_id| is null. Does not specify a name if |
405 // |options.name| is null. Returns a handle to the registered service and | 385 // |options.name| is null. Returns a handle to the registered service and |
406 // updates |registered_channel_id| to the actual channel id, or returns | 386 // updates |registered_channel_id| to the actual channel id, or returns nil if |
407 // |kInvalidServiceRecordHandle| if the service could not be registered. | 387 // the service could not be registered. |
408 BluetoothSDPServiceRecordHandle RegisterRfcommService( | 388 IOBluetoothSDPServiceRecord* RegisterRfcommService( |
409 const BluetoothUUID& uuid, | 389 const BluetoothUUID& uuid, |
410 const BluetoothAdapter::ServiceOptions& options, | 390 const BluetoothAdapter::ServiceOptions& options, |
411 BluetoothRFCOMMChannelID* registered_channel_id) { | 391 BluetoothRFCOMMChannelID* registered_channel_id) { |
412 return RegisterService( | 392 return RegisterService( |
413 BuildRfcommServiceDefinition(uuid, options), | 393 BuildRfcommServiceDefinition(uuid, options), |
414 base::Bind( | 394 base::Bind( |
415 &VerifyRfcommService, options.channel.get(), registered_channel_id)); | 395 &VerifyRfcommService, options.channel.get(), registered_channel_id)); |
416 } | 396 } |
417 | 397 |
418 // Returns true iff the |requested_psm| was registered in the L2CAP | 398 // Returns true iff the |requested_psm| was registered in the L2CAP |
(...skipping 13 matching lines...) Expand all Loading... | |
432 } | 412 } |
433 | 413 |
434 *registered_psm = l2cap_psm; | 414 *registered_psm = l2cap_psm; |
435 return true; | 415 return true; |
436 } | 416 } |
437 | 417 |
438 // Registers an L2CAP service with the specified |uuid|, |options.psm|, and | 418 // Registers an L2CAP service with the specified |uuid|, |options.psm|, and |
439 // |options.name| in the system SDP server. Automatically allocates a PSM if | 419 // |options.name| in the system SDP server. Automatically allocates a PSM if |
440 // |options.psm| is null. Does not register a name if |options.name| is null. | 420 // |options.psm| is null. Does not register a name if |options.name| is null. |
441 // Returns a handle to the registered service and updates |registered_psm| to | 421 // Returns a handle to the registered service and updates |registered_psm| to |
442 // the actual PSM, or returns |kInvalidServiceRecordHandle| if the service could | 422 // the actual PSM, or returns nil if the service could not be registered. |
443 // not be registered. | 423 IOBluetoothSDPServiceRecord* RegisterL2capService( |
444 BluetoothSDPServiceRecordHandle RegisterL2capService( | |
445 const BluetoothUUID& uuid, | 424 const BluetoothUUID& uuid, |
446 const BluetoothAdapter::ServiceOptions& options, | 425 const BluetoothAdapter::ServiceOptions& options, |
447 BluetoothL2CAPPSM* registered_psm) { | 426 BluetoothL2CAPPSM* registered_psm) { |
448 return RegisterService( | 427 return RegisterService( |
449 BuildL2capServiceDefinition(uuid, options), | 428 BuildL2capServiceDefinition(uuid, options), |
450 base::Bind(&VerifyL2capService, options.psm.get(), registered_psm)); | 429 base::Bind(&VerifyL2capService, options.psm.get(), registered_psm)); |
451 } | 430 } |
452 | 431 |
453 } // namespace | 432 } // namespace |
454 | 433 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 const BluetoothAdapter::ServiceOptions& options, | 465 const BluetoothAdapter::ServiceOptions& options, |
487 const base::Closure& success_callback, | 466 const base::Closure& success_callback, |
488 const ErrorCompletionCallback& error_callback) { | 467 const ErrorCompletionCallback& error_callback) { |
489 DCHECK(thread_checker_.CalledOnValidThread()); | 468 DCHECK(thread_checker_.CalledOnValidThread()); |
490 | 469 |
491 adapter_ = adapter; | 470 adapter_ = adapter; |
492 uuid_ = uuid; | 471 uuid_ = uuid; |
493 | 472 |
494 DVLOG(1) << uuid_.canonical_value() << ": Registering RFCOMM service."; | 473 DVLOG(1) << uuid_.canonical_value() << ": Registering RFCOMM service."; |
495 BluetoothRFCOMMChannelID registered_channel_id; | 474 BluetoothRFCOMMChannelID registered_channel_id; |
496 service_record_handle_ = | 475 service_record_.reset( |
497 RegisterRfcommService(uuid, options, ®istered_channel_id); | 476 RegisterRfcommService(uuid, options, ®istered_channel_id)); |
498 if (service_record_handle_ == kInvalidServiceRecordHandle) { | 477 if (!service_record_.get()) { |
499 error_callback.Run(kInvalidOrUsedChannel); | 478 error_callback.Run(kInvalidOrUsedChannel); |
500 return; | 479 return; |
501 } | 480 } |
502 | 481 |
503 rfcomm_connection_listener_.reset( | 482 rfcomm_connection_listener_.reset( |
504 [[BluetoothRfcommConnectionListener alloc] | 483 [[BluetoothRfcommConnectionListener alloc] |
505 initWithSocket:this | 484 initWithSocket:this |
506 channelID:registered_channel_id]); | 485 channelID:registered_channel_id]); |
507 | 486 |
508 success_callback.Run(); | 487 success_callback.Run(); |
509 } | 488 } |
510 | 489 |
511 void BluetoothSocketMac::ListenUsingL2cap( | 490 void BluetoothSocketMac::ListenUsingL2cap( |
512 scoped_refptr<BluetoothAdapterMac> adapter, | 491 scoped_refptr<BluetoothAdapterMac> adapter, |
513 const BluetoothUUID& uuid, | 492 const BluetoothUUID& uuid, |
514 const BluetoothAdapter::ServiceOptions& options, | 493 const BluetoothAdapter::ServiceOptions& options, |
515 const base::Closure& success_callback, | 494 const base::Closure& success_callback, |
516 const ErrorCompletionCallback& error_callback) { | 495 const ErrorCompletionCallback& error_callback) { |
517 DCHECK(thread_checker_.CalledOnValidThread()); | 496 DCHECK(thread_checker_.CalledOnValidThread()); |
518 | 497 |
519 adapter_ = adapter; | 498 adapter_ = adapter; |
520 uuid_ = uuid; | 499 uuid_ = uuid; |
521 | 500 |
522 DVLOG(1) << uuid_.canonical_value() << ": Registering L2CAP service."; | 501 DVLOG(1) << uuid_.canonical_value() << ": Registering L2CAP service."; |
523 BluetoothL2CAPPSM registered_psm; | 502 BluetoothL2CAPPSM registered_psm; |
524 service_record_handle_ = RegisterL2capService(uuid, options, ®istered_psm); | 503 service_record_.reset(RegisterL2capService(uuid, options, ®istered_psm)); |
525 if (service_record_handle_ == kInvalidServiceRecordHandle) { | 504 if (!service_record_.get()) { |
526 error_callback.Run(kInvalidOrUsedPsm); | 505 error_callback.Run(kInvalidOrUsedPsm); |
527 return; | 506 return; |
528 } | 507 } |
529 | 508 |
530 l2cap_connection_listener_.reset( | 509 l2cap_connection_listener_.reset( |
531 [[BluetoothL2capConnectionListener alloc] initWithSocket:this | 510 [[BluetoothL2capConnectionListener alloc] initWithSocket:this |
532 psm:registered_psm]); | 511 psm:registered_psm]); |
533 | 512 |
534 success_callback.Run(); | 513 success_callback.Run(); |
535 } | 514 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 } | 636 } |
658 | 637 |
659 temp->success_callback.Run(); | 638 temp->success_callback.Run(); |
660 } | 639 } |
661 | 640 |
662 void BluetoothSocketMac::Close() { | 641 void BluetoothSocketMac::Close() { |
663 DCHECK(thread_checker_.CalledOnValidThread()); | 642 DCHECK(thread_checker_.CalledOnValidThread()); |
664 | 643 |
665 if (channel_) | 644 if (channel_) |
666 ReleaseChannel(); | 645 ReleaseChannel(); |
667 else if (service_record_handle_ != kInvalidServiceRecordHandle) | 646 else if (service_record_.get()) |
668 ReleaseListener(); | 647 ReleaseListener(); |
669 } | 648 } |
670 | 649 |
671 void BluetoothSocketMac::Disconnect(const base::Closure& callback) { | 650 void BluetoothSocketMac::Disconnect(const base::Closure& callback) { |
672 DCHECK(thread_checker_.CalledOnValidThread()); | 651 DCHECK(thread_checker_.CalledOnValidThread()); |
673 | 652 |
674 Close(); | 653 Close(); |
675 callback.Run(); | 654 callback.Run(); |
676 } | 655 } |
677 | 656 |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
902 BluetoothSocketMac::SendRequest::~SendRequest() {} | 881 BluetoothSocketMac::SendRequest::~SendRequest() {} |
903 | 882 |
904 BluetoothSocketMac::ReceiveCallbacks::ReceiveCallbacks() {} | 883 BluetoothSocketMac::ReceiveCallbacks::ReceiveCallbacks() {} |
905 | 884 |
906 BluetoothSocketMac::ReceiveCallbacks::~ReceiveCallbacks() {} | 885 BluetoothSocketMac::ReceiveCallbacks::~ReceiveCallbacks() {} |
907 | 886 |
908 BluetoothSocketMac::ConnectCallbacks::ConnectCallbacks() {} | 887 BluetoothSocketMac::ConnectCallbacks::ConnectCallbacks() {} |
909 | 888 |
910 BluetoothSocketMac::ConnectCallbacks::~ConnectCallbacks() {} | 889 BluetoothSocketMac::ConnectCallbacks::~ConnectCallbacks() {} |
911 | 890 |
912 BluetoothSocketMac::BluetoothSocketMac() | 891 BluetoothSocketMac::BluetoothSocketMac() {} |
913 : service_record_handle_(kInvalidServiceRecordHandle) { | |
914 } | |
915 | 892 |
916 BluetoothSocketMac::~BluetoothSocketMac() { | 893 BluetoothSocketMac::~BluetoothSocketMac() { |
917 DCHECK(thread_checker_.CalledOnValidThread()); | 894 DCHECK(thread_checker_.CalledOnValidThread()); |
918 DCHECK(!channel_); | 895 DCHECK(!channel_); |
919 DCHECK(!rfcomm_connection_listener_); | 896 DCHECK(!rfcomm_connection_listener_); |
920 } | 897 } |
921 | 898 |
922 void BluetoothSocketMac::ReleaseChannel() { | 899 void BluetoothSocketMac::ReleaseChannel() { |
923 DCHECK(thread_checker_.CalledOnValidThread()); | 900 DCHECK(thread_checker_.CalledOnValidThread()); |
924 channel_.reset(); | 901 channel_.reset(); |
925 | 902 |
926 // Closing the channel above prevents the callback delegate from being called | 903 // Closing the channel above prevents the callback delegate from being called |
927 // so it is now safe to release all callback state. | 904 // so it is now safe to release all callback state. |
928 connect_callbacks_.reset(); | 905 connect_callbacks_.reset(); |
929 receive_callbacks_.reset(); | 906 receive_callbacks_.reset(); |
930 empty_queue(receive_queue_); | 907 empty_queue(receive_queue_); |
931 empty_queue(send_queue_); | 908 empty_queue(send_queue_); |
932 } | 909 } |
933 | 910 |
934 void BluetoothSocketMac::ReleaseListener() { | 911 void BluetoothSocketMac::ReleaseListener() { |
935 DCHECK(thread_checker_.CalledOnValidThread()); | 912 DCHECK(thread_checker_.CalledOnValidThread()); |
936 DCHECK_NE(service_record_handle_, kInvalidServiceRecordHandle); | 913 DCHECK(service_record_.get()); |
937 | 914 |
938 IOBluetoothRemoveServiceWithRecordHandle(service_record_handle_); | 915 [service_record_ removeServiceRecord]; |
916 service_record_.reset(); | |
939 rfcomm_connection_listener_.reset(); | 917 rfcomm_connection_listener_.reset(); |
940 l2cap_connection_listener_.reset(); | 918 l2cap_connection_listener_.reset(); |
941 | 919 |
942 // Destroying the listener above prevents the callback delegate from being | 920 // Destroying the listener above prevents the callback delegate from being |
943 // called so it is now safe to release all callback state. | 921 // called so it is now safe to release all callback state. |
944 accept_request_.reset(); | 922 accept_request_.reset(); |
945 empty_queue(accept_queue_); | 923 empty_queue(accept_queue_); |
946 } | 924 } |
947 | 925 |
948 } // namespace device | 926 } // namespace device |
OLD | NEW |