[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_ |
| 6 | #define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_ |
| 7 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 8 | #import <IOBluetooth/IOBluetooth.h> |
| 9 | #import <IOKit/IOReturn.h> |
avi | 176e269 | 2015-12-22 19:26:52 | [diff] [blame] | 10 | #include <stddef.h> |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 11 | |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 12 | #include <memory> |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 13 | #include <string> |
| 14 | |
Brett Wilson | a62d9c0 | 2017-09-20 20:53:20 | [diff] [blame] | 15 | #include "base/containers/queue.h" |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 16 | #include "base/mac/scoped_nsobject.h" |
avi | 176e269 | 2015-12-22 19:26:52 | [diff] [blame] | 17 | #include "base/macros.h" |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 18 | #include "base/memory/ref_counted.h" |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 19 | #include "base/threading/thread_checker.h" |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 20 | #include "device/bluetooth/bluetooth_adapter.h" |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 21 | #include "device/bluetooth/bluetooth_socket.h" |
Jason Majors | 47659c4 | 2019-07-08 18:23:28 | [diff] [blame] | 22 | #include "device/bluetooth/public/cpp/bluetooth_uuid.h" |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 23 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 24 | @class BluetoothRfcommConnectionListener; |
[email protected] | 286b0de | 2014-06-16 22:07:16 | [diff] [blame] | 25 | @class BluetoothL2capConnectionListener; |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 26 | |
| 27 | namespace net { |
[email protected] | 73131fc1 | 2014-04-08 01:02:27 | [diff] [blame] | 28 | class IOBuffer; |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 29 | class IOBufferWithSize; |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 30 | } |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 31 | |
| 32 | namespace device { |
| 33 | |
[email protected] | 5902a7f | 2014-06-18 13:08:50 | [diff] [blame] | 34 | class BluetoothAdapterMac; |
[email protected] | 8696f57 | 2014-06-12 12:59:20 | [diff] [blame] | 35 | class BluetoothChannelMac; |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 36 | |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 37 | // Implements the BluetoothSocket class for the Mac OS X platform. |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 38 | class BluetoothSocketMac : public BluetoothSocket { |
| 39 | public: |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 40 | static scoped_refptr<BluetoothSocketMac> CreateSocket(); |
[email protected] | 476f29d | 2013-04-24 09:06:51 | [diff] [blame] | 41 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 42 | // Connects this socket to the service on |device| published as UUID |uuid|. |
| 43 | // The underlying protocol and PSM or Channel is obtained through service |
| 44 | // discovery. On a successful connection, the socket properties will be |
| 45 | // updated and |success_callback| called. On failure, |error_callback| will be |
| 46 | // called with a message explaining the cause of failure. |
| 47 | void Connect(IOBluetoothDevice* device, |
| 48 | const BluetoothUUID& uuid, |
| 49 | const base::Closure& success_callback, |
| 50 | const ErrorCompletionCallback& error_callback); |
[email protected] | 649726b9 | 2014-04-28 23:54:19 | [diff] [blame] | 51 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 52 | // Listens for incoming RFCOMM connections using this socket: Publishes an |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 53 | // RFCOMM service on the |adapter| as UUID |uuid| with Channel |
| 54 | // |options.channel|, or an automatically allocated Channel if |
| 55 | // |options.channel| is left null. The service is published with English name |
| 56 | // |options.name| if that is non-null. |success_callback| will be called if |
| 57 | // the service is successfully registered, |error_callback| on failure with a |
| 58 | // message explaining the cause. |
[email protected] | 5902a7f | 2014-06-18 13:08:50 | [diff] [blame] | 59 | void ListenUsingRfcomm(scoped_refptr<BluetoothAdapterMac> adapter, |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 60 | const BluetoothUUID& uuid, |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 61 | const BluetoothAdapter::ServiceOptions& options, |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 62 | const base::Closure& success_callback, |
| 63 | const ErrorCompletionCallback& error_callback); |
| 64 | |
| 65 | // Listens for incoming L2CAP connections using this socket: Publishes an |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 66 | // L2CAP service on the |adapter| as UUID |uuid| with PSM |options.psm|, or an |
| 67 | // automatically allocated PSM if |options.psm| is left null. The service is |
| 68 | // published with English name |options.name| if that is non-null. |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 69 | // |success_callback| will be called if the service is successfully |
| 70 | // registered, |error_callback| on failure with a message explaining the |
| 71 | // cause. |
[email protected] | 5902a7f | 2014-06-18 13:08:50 | [diff] [blame] | 72 | void ListenUsingL2cap(scoped_refptr<BluetoothAdapterMac> adapter, |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 73 | const BluetoothUUID& uuid, |
[email protected] | dbedd502 | 2014-07-03 06:08:20 | [diff] [blame] | 74 | const BluetoothAdapter::ServiceOptions& options, |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 75 | const base::Closure& success_callback, |
| 76 | const ErrorCompletionCallback& error_callback); |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 77 | |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 78 | // BluetoothSocket: |
dcheng | b5aaf40 | 2014-10-22 23:07:52 | [diff] [blame] | 79 | void Close() override; |
| 80 | void Disconnect(const base::Closure& callback) override; |
| 81 | void Receive(int /* buffer_size */, |
| 82 | const ReceiveCompletionCallback& success_callback, |
| 83 | const ReceiveErrorCompletionCallback& error_callback) override; |
| 84 | void Send(scoped_refptr<net::IOBuffer> buffer, |
| 85 | int buffer_size, |
| 86 | const SendCompletionCallback& success_callback, |
| 87 | const ErrorCompletionCallback& error_callback) override; |
| 88 | void Accept(const AcceptCompletionCallback& success_callback, |
| 89 | const ErrorCompletionCallback& error_callback) override; |
[email protected] | 37f0b7f | 2014-05-12 18:09:51 | [diff] [blame] | 90 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 91 | // Callback that is invoked when the OS completes an SDP query. |
| 92 | // |status| is the returned status from the SDP query, |device| is the |
| 93 | // IOBluetoothDevice for which the query was made. The remaining |
| 94 | // parameters are those from |Connect()|. |
| 95 | void OnSDPQueryComplete( |
| 96 | IOReturn status, |
| 97 | IOBluetoothDevice* device, |
| 98 | const base::Closure& success_callback, |
| 99 | const ErrorCompletionCallback& error_callback); |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 100 | |
[email protected] | 286b0de | 2014-06-16 22:07:16 | [diff] [blame] | 101 | // Called by BluetoothRfcommConnectionListener and |
| 102 | // BluetoothL2capConnectionListener. |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 103 | void OnChannelOpened(std::unique_ptr<BluetoothChannelMac> channel); |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 104 | |
[email protected] | 8696f57 | 2014-06-12 12:59:20 | [diff] [blame] | 105 | // Called by |channel_|. |
| 106 | // Note: OnChannelOpenComplete might be called before the |channel_| is set. |
| 107 | void OnChannelOpenComplete(const std::string& device_address, |
| 108 | IOReturn status); |
| 109 | void OnChannelClosed(); |
| 110 | void OnChannelDataReceived(void* data, size_t length); |
| 111 | void OnChannelWriteComplete(void* refcon, IOReturn status); |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 112 | |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 113 | private: |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 114 | struct AcceptRequest { |
| 115 | AcceptRequest(); |
| 116 | ~AcceptRequest(); |
| 117 | |
| 118 | AcceptCompletionCallback success_callback; |
| 119 | ErrorCompletionCallback error_callback; |
| 120 | }; |
| 121 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 122 | struct SendRequest { |
| 123 | SendRequest(); |
| 124 | ~SendRequest(); |
| 125 | int buffer_size; |
| 126 | SendCompletionCallback success_callback; |
| 127 | ErrorCompletionCallback error_callback; |
| 128 | IOReturn status; |
| 129 | int active_async_writes; |
| 130 | bool error_signaled; |
| 131 | }; |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 132 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 133 | struct ReceiveCallbacks { |
| 134 | ReceiveCallbacks(); |
| 135 | ~ReceiveCallbacks(); |
| 136 | ReceiveCompletionCallback success_callback; |
| 137 | ReceiveErrorCompletionCallback error_callback; |
| 138 | }; |
| 139 | |
| 140 | struct ConnectCallbacks { |
| 141 | ConnectCallbacks(); |
| 142 | ~ConnectCallbacks(); |
| 143 | base::Closure success_callback; |
| 144 | ErrorCompletionCallback error_callback; |
| 145 | }; |
| 146 | |
[email protected] | 649726b9 | 2014-04-28 23:54:19 | [diff] [blame] | 147 | BluetoothSocketMac(); |
dcheng | b5aaf40 | 2014-10-22 23:07:52 | [diff] [blame] | 148 | ~BluetoothSocketMac() override; |
[email protected] | 649726b9 | 2014-04-28 23:54:19 | [diff] [blame] | 149 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 150 | // Accepts a single incoming connection. |
| 151 | void AcceptConnectionRequest(); |
| 152 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 153 | void ReleaseChannel(); |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 154 | void ReleaseListener(); |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 155 | |
dcheng | bd780bf | 2016-03-12 04:56:00 | [diff] [blame] | 156 | bool is_connecting() const { return !!connect_callbacks_; } |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 157 | |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 158 | // Used to verify that all methods are called on the same thread. |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 159 | base::ThreadChecker thread_checker_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 160 | |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 161 | // Adapter the socket is registered against. This is only present when the |
| 162 | // socket is listening. |
[email protected] | 5902a7f | 2014-06-18 13:08:50 | [diff] [blame] | 163 | scoped_refptr<BluetoothAdapterMac> adapter_; |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 164 | |
| 165 | // UUID of the profile being connected to, or that the socket is listening on. |
| 166 | device::BluetoothUUID uuid_; |
| 167 | |
[email protected] | 286b0de | 2014-06-16 22:07:16 | [diff] [blame] | 168 | // Simple helpers that register for OS notifications and forward them to |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 169 | // |this| profile. |
| 170 | base::scoped_nsobject<BluetoothRfcommConnectionListener> |
| 171 | rfcomm_connection_listener_; |
[email protected] | 286b0de | 2014-06-16 22:07:16 | [diff] [blame] | 172 | base::scoped_nsobject<BluetoothL2capConnectionListener> |
| 173 | l2cap_connection_listener_; |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 174 | |
shrike | 07aa6dca | 2016-10-25 00:08:24 | [diff] [blame] | 175 | // The service record registered in the system SDP server, used to |
| 176 | // eventually unregister the service. |
| 177 | base::scoped_nsobject<IOBluetoothSDPServiceRecord> service_record_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 178 | |
[email protected] | 8696f57 | 2014-06-12 12:59:20 | [diff] [blame] | 179 | // The channel used to issue commands. |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 180 | std::unique_ptr<BluetoothChannelMac> channel_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 181 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 182 | // Connection callbacks -- when a pending async connection is active. |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 183 | std::unique_ptr<ConnectCallbacks> connect_callbacks_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 184 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 185 | // Packets received while there is no pending "receive" callback. |
Brett Wilson | a62d9c0 | 2017-09-20 20:53:20 | [diff] [blame] | 186 | base::queue<scoped_refptr<net::IOBufferWithSize>> receive_queue_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 187 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 188 | // Receive callbacks -- when a receive call is active. |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 189 | std::unique_ptr<ReceiveCallbacks> receive_callbacks_; |
[email protected] | 99c8c9b9 | 2014-04-17 04:14:30 | [diff] [blame] | 190 | |
[email protected] | 3b01756 | 2014-04-10 17:09:55 | [diff] [blame] | 191 | // Send queue -- one entry per pending send operation. |
Avi Drissman | d3c4eab | 2018-12-05 02:42:09 | [diff] [blame] | 192 | base::queue<std::unique_ptr<SendRequest>> send_queue_; |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 193 | |
| 194 | // The pending request to an Accept() call, or null if there is no pending |
| 195 | // request. |
thakis | 08c9d69b0 | 2016-04-11 04:37:25 | [diff] [blame] | 196 | std::unique_ptr<AcceptRequest> accept_request_; |
[email protected] | 2b38b73 | 2014-06-10 20:56:46 | [diff] [blame] | 197 | |
[email protected] | 8696f57 | 2014-06-12 12:59:20 | [diff] [blame] | 198 | // Queue of incoming connections. |
Avi Drissman | d3c4eab | 2018-12-05 02:42:09 | [diff] [blame] | 199 | base::queue<std::unique_ptr<BluetoothChannelMac>> accept_queue_; |
[email protected] | 6cc9b8d | 2013-03-18 21:07:03 | [diff] [blame] | 200 | |
| 201 | DISALLOW_COPY_AND_ASSIGN(BluetoothSocketMac); |
| 202 | }; |
| 203 | |
| 204 | } // namespace device |
| 205 | |
| 206 | #endif // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_ |