Chromium Code Reviews| 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 |