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 8 #include <queue> 9 #include <string> 10 11 #import <IOBluetooth/IOBluetooth.h> 12 #import <IOKit/IOReturn.h> 13 14 #include "base/mac/scoped_nsobject.h" 15 #include "base/memory/linked_ptr.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/threading/thread_checker.h" 19 #include "device/bluetooth/bluetooth_adapter.h" 20 #include "device/bluetooth/bluetooth_socket.h" 21 #include "device/bluetooth/bluetooth_uuid.h" 22 23 @class BluetoothRfcommConnectionListener; 24 @class BluetoothL2capConnectionListener; 25 26 namespace net { 27 class IOBuffer; 28 class IOBufferWithSize; 29 } 30 31 namespace device { 32 33 class BluetoothAdapterMac; 34 class BluetoothChannelMac; 35 36 // Implements the BluetoothSocket class for the Mac OS X platform. 37 class BluetoothSocketMac : public BluetoothSocket { 38 public: 39 static scoped_refptr<BluetoothSocketMac> CreateSocket(); 40 41 // Connects this socket to the service on |device| published as UUID |uuid|. 42 // The underlying protocol and PSM or Channel is obtained through service 43 // discovery. On a successful connection, the socket properties will be 44 // updated and |success_callback| called. On failure, |error_callback| will be 45 // called with a message explaining the cause of failure. 46 void Connect(IOBluetoothDevice* device, 47 const BluetoothUUID& uuid, 48 const base::Closure& success_callback, 49 const ErrorCompletionCallback& error_callback); 50 51 // Listens for incoming RFCOMM connections using this socket: Publishes an 52 // RFCOMM service on the |adapter| as UUID |uuid| with Channel 53 // |options.channel|, or an automatically allocated Channel if 54 // |options.channel| is left null. The service is published with English name 55 // |options.name| if that is non-null. |success_callback| will be called if 56 // the service is successfully registered, |error_callback| on failure with a 57 // message explaining the cause. 58 void ListenUsingRfcomm(scoped_refptr<BluetoothAdapterMac> adapter, 59 const BluetoothUUID& uuid, 60 const BluetoothAdapter::ServiceOptions& options, 61 const base::Closure& success_callback, 62 const ErrorCompletionCallback& error_callback); 63 64 // Listens for incoming L2CAP connections using this socket: Publishes an 65 // L2CAP service on the |adapter| as UUID |uuid| with PSM |options.psm|, or an 66 // automatically allocated PSM if |options.psm| is left null. The service is 67 // published with English name |options.name| if that is non-null. 68 // |success_callback| will be called if the service is successfully 69 // registered, |error_callback| on failure with a message explaining the 70 // cause. 71 void ListenUsingL2cap(scoped_refptr<BluetoothAdapterMac> adapter, 72 const BluetoothUUID& uuid, 73 const BluetoothAdapter::ServiceOptions& options, 74 const base::Closure& success_callback, 75 const ErrorCompletionCallback& error_callback); 76 77 // BluetoothSocket: 78 virtual void Close() OVERRIDE; 79 virtual void Disconnect(const base::Closure& callback) OVERRIDE; 80 virtual void Receive( 81 int /* buffer_size */, 82 const ReceiveCompletionCallback& success_callback, 83 const ReceiveErrorCompletionCallback& error_callback) OVERRIDE; 84 virtual void Send(scoped_refptr<net::IOBuffer> buffer, 85 int buffer_size, 86 const SendCompletionCallback& success_callback, 87 const ErrorCompletionCallback& error_callback) OVERRIDE; 88 virtual void Accept(const AcceptCompletionCallback& success_callback, 89 const ErrorCompletionCallback& error_callback) OVERRIDE; 90 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); 100 101 // Called by BluetoothRfcommConnectionListener and 102 // BluetoothL2capConnectionListener. 103 void OnChannelOpened(scoped_ptr<BluetoothChannelMac> channel); 104 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); 112 113 private: 114 struct AcceptRequest { 115 AcceptRequest(); 116 ~AcceptRequest(); 117 118 AcceptCompletionCallback success_callback; 119 ErrorCompletionCallback error_callback; 120 }; 121 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 }; 132 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 147 BluetoothSocketMac(); 148 virtual ~BluetoothSocketMac(); 149 150 // Accepts a single incoming connection. 151 void AcceptConnectionRequest(); 152 153 void ReleaseChannel(); 154 void ReleaseListener(); 155 is_connecting()156 bool is_connecting() const { return connect_callbacks_; } 157 158 // Used to verify that all methods are called on the same thread. 159 base::ThreadChecker thread_checker_; 160 161 // Adapter the socket is registered against. This is only present when the 162 // socket is listening. 163 scoped_refptr<BluetoothAdapterMac> adapter_; 164 165 // UUID of the profile being connected to, or that the socket is listening on. 166 device::BluetoothUUID uuid_; 167 168 // Simple helpers that register for OS notifications and forward them to 169 // |this| profile. 170 base::scoped_nsobject<BluetoothRfcommConnectionListener> 171 rfcomm_connection_listener_; 172 base::scoped_nsobject<BluetoothL2capConnectionListener> 173 l2cap_connection_listener_; 174 175 // A handle to the service record registered in the system SDP server. 176 // Used to eventually unregister the service. 177 BluetoothSDPServiceRecordHandle service_record_handle_; 178 179 // The channel used to issue commands. 180 scoped_ptr<BluetoothChannelMac> channel_; 181 182 // Connection callbacks -- when a pending async connection is active. 183 scoped_ptr<ConnectCallbacks> connect_callbacks_; 184 185 // Packets received while there is no pending "receive" callback. 186 std::queue<scoped_refptr<net::IOBufferWithSize> > receive_queue_; 187 188 // Receive callbacks -- when a receive call is active. 189 scoped_ptr<ReceiveCallbacks> receive_callbacks_; 190 191 // Send queue -- one entry per pending send operation. 192 std::queue<linked_ptr<SendRequest>> send_queue_; 193 194 // The pending request to an Accept() call, or null if there is no pending 195 // request. 196 scoped_ptr<AcceptRequest> accept_request_; 197 198 // Queue of incoming connections. 199 std::queue<linked_ptr<BluetoothChannelMac>> accept_queue_; 200 201 DISALLOW_COPY_AND_ASSIGN(BluetoothSocketMac); 202 }; 203 204 } // namespace device 205 206 #endif // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_ 207