summaryrefslogtreecommitdiffstats
path: root/device/bluetooth/bluetooth_socket_mac.h
blob: 7f94dd74ea0bcdf635e6eb06764f788a40cf3811 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_

#include <queue>
#include <string>

#import <IOBluetooth/IOBluetooth.h>
#import <IOKit/IOReturn.h>
#include <stddef.h>

#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/bluetooth_uuid.h"

@class BluetoothRfcommConnectionListener;
@class BluetoothL2capConnectionListener;

namespace net {
class IOBuffer;
class IOBufferWithSize;
}

namespace device {

class BluetoothAdapterMac;
class BluetoothChannelMac;

// Implements the BluetoothSocket class for the Mac OS X platform.
class BluetoothSocketMac : public BluetoothSocket {
 public:
  static scoped_refptr<BluetoothSocketMac> CreateSocket();

  // Connects this socket to the service on |device| published as UUID |uuid|.
  // The underlying protocol and PSM or Channel is obtained through service
  // discovery. On a successful connection, the socket properties will be
  // updated and |success_callback| called. On failure, |error_callback| will be
  // called with a message explaining the cause of failure.
  void Connect(IOBluetoothDevice* device,
               const BluetoothUUID& uuid,
               const base::Closure& success_callback,
               const ErrorCompletionCallback& error_callback);

  // Listens for incoming RFCOMM connections using this socket: Publishes an
  // RFCOMM service on the |adapter| as UUID |uuid| with Channel
  // |options.channel|, or an automatically allocated Channel if
  // |options.channel| is left null. The service is published with English name
  // |options.name| if that is non-null. |success_callback| will be called if
  // the service is successfully registered, |error_callback| on failure with a
  // message explaining the cause.
  void ListenUsingRfcomm(scoped_refptr<BluetoothAdapterMac> adapter,
                         const BluetoothUUID& uuid,
                         const BluetoothAdapter::ServiceOptions& options,
                         const base::Closure& success_callback,
                         const ErrorCompletionCallback& error_callback);

  // Listens for incoming L2CAP connections using this socket: Publishes an
  // L2CAP service on the |adapter| as UUID |uuid| with PSM |options.psm|, or an
  // automatically allocated PSM if |options.psm| is left null. The service is
  // published with English name |options.name| if that is non-null.
  // |success_callback| will be called if the service is successfully
  // registered, |error_callback| on failure with a message explaining the
  // cause.
  void ListenUsingL2cap(scoped_refptr<BluetoothAdapterMac> adapter,
                        const BluetoothUUID& uuid,
                        const BluetoothAdapter::ServiceOptions& options,
                        const base::Closure& success_callback,
                        const ErrorCompletionCallback& error_callback);

  // BluetoothSocket:
  void Close() override;
  void Disconnect(const base::Closure& callback) override;
  void Receive(int /* buffer_size */,
               const ReceiveCompletionCallback& success_callback,
               const ReceiveErrorCompletionCallback& error_callback) override;
  void Send(scoped_refptr<net::IOBuffer> buffer,
            int buffer_size,
            const SendCompletionCallback& success_callback,
            const ErrorCompletionCallback& error_callback) override;
  void Accept(const AcceptCompletionCallback& success_callback,
              const ErrorCompletionCallback& error_callback) override;

  // Callback that is invoked when the OS completes an SDP query.
  // |status| is the returned status from the SDP query, |device| is the
  // IOBluetoothDevice for which the query was made. The remaining
  // parameters are those from |Connect()|.
  void OnSDPQueryComplete(
      IOReturn status,
      IOBluetoothDevice* device,
      const base::Closure& success_callback,
      const ErrorCompletionCallback& error_callback);

  // Called by BluetoothRfcommConnectionListener and
  // BluetoothL2capConnectionListener.
  void OnChannelOpened(scoped_ptr<BluetoothChannelMac> channel);

  // Called by |channel_|.
  // Note: OnChannelOpenComplete might be called before the |channel_| is set.
  void OnChannelOpenComplete(const std::string& device_address,
                             IOReturn status);
  void OnChannelClosed();
  void OnChannelDataReceived(void* data, size_t length);
  void OnChannelWriteComplete(void* refcon, IOReturn status);

 private:
  struct AcceptRequest {
    AcceptRequest();
    ~AcceptRequest();

    AcceptCompletionCallback success_callback;
    ErrorCompletionCallback error_callback;
  };

  struct SendRequest {
    SendRequest();
    ~SendRequest();
    int buffer_size;
    SendCompletionCallback success_callback;
    ErrorCompletionCallback error_callback;
    IOReturn status;
    int active_async_writes;
    bool error_signaled;
  };

  struct ReceiveCallbacks {
    ReceiveCallbacks();
    ~ReceiveCallbacks();
    ReceiveCompletionCallback success_callback;
    ReceiveErrorCompletionCallback error_callback;
  };

  struct ConnectCallbacks {
    ConnectCallbacks();
    ~ConnectCallbacks();
    base::Closure success_callback;
    ErrorCompletionCallback error_callback;
  };

  BluetoothSocketMac();
  ~BluetoothSocketMac() override;

  // Accepts a single incoming connection.
  void AcceptConnectionRequest();

  void ReleaseChannel();
  void ReleaseListener();

  bool is_connecting() const { return !!connect_callbacks_; }

  // Used to verify that all methods are called on the same thread.
  base::ThreadChecker thread_checker_;

  // Adapter the socket is registered against. This is only present when the
  // socket is listening.
  scoped_refptr<BluetoothAdapterMac> adapter_;

  // UUID of the profile being connected to, or that the socket is listening on.
  device::BluetoothUUID uuid_;

  // Simple helpers that register for OS notifications and forward them to
  // |this| profile.
  base::scoped_nsobject<BluetoothRfcommConnectionListener>
      rfcomm_connection_listener_;
  base::scoped_nsobject<BluetoothL2capConnectionListener>
      l2cap_connection_listener_;

  // A handle to the service record registered in the system SDP server.
  // Used to eventually unregister the service.
  BluetoothSDPServiceRecordHandle service_record_handle_;

  // The channel used to issue commands.
  scoped_ptr<BluetoothChannelMac> channel_;

  // Connection callbacks -- when a pending async connection is active.
  scoped_ptr<ConnectCallbacks> connect_callbacks_;

  // Packets received while there is no pending "receive" callback.
  std::queue<scoped_refptr<net::IOBufferWithSize> > receive_queue_;

  // Receive callbacks -- when a receive call is active.
  scoped_ptr<ReceiveCallbacks> receive_callbacks_;

  // Send queue -- one entry per pending send operation.
  std::queue<linked_ptr<SendRequest>> send_queue_;

  // The pending request to an Accept() call, or null if there is no pending
  // request.
  scoped_ptr<AcceptRequest> accept_request_;

  // Queue of incoming connections.
  std::queue<linked_ptr<BluetoothChannelMac>> accept_queue_;

  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketMac);
};

}  // namespace device

#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_