blob: 6c46bb0b34b57c7cc4fe13b79bdab1aa67029554 [file] [log] [blame]
// 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>
#include <IOKit/IOReturn.h>
#include "base/mac/scoped_nsobject.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "device/bluetooth/bluetooth_socket.h"
@class BluetoothRFCOMMChannelDelegate;
@class IOBluetoothRFCOMMChannel;
@class IOBluetoothSDPServiceRecord;
namespace net {
class IOBuffer;
class IOBufferWithSize;
} // namespace net
namespace device {
class BluetoothServiceRecord;
// Implements the BluetoothSocket class for the Mac OS X platform.
class BluetoothSocketMac : public BluetoothSocket {
public:
typedef base::Callback<void(scoped_refptr<BluetoothSocket>)>
ConnectSuccessCallback;
// Creates a client socket and connects it to the Bluetooth service |record|.
// Calls |success_callback|, passing in the created socket, on success.
// Calls |error_callback| on failure.
static void Connect(IOBluetoothSDPServiceRecord* record,
const ConnectSuccessCallback& success_callback,
const ErrorCompletionCallback& error_callback);
// Creates a server socket to wrap the |rfcomm_channel|, which should be an
// incoming channel in the process of being opened.
// Calls |success_callback|, passing in the created socket, on success.
// Calls |error_callback| on failure.
static void AcceptConnection(IOBluetoothRFCOMMChannel* rfcomm_channel,
const ConnectSuccessCallback& success_callback,
const ErrorCompletionCallback& error_callback);
// BluetoothSocket:
virtual void Close() OVERRIDE;
virtual void Disconnect(const base::Closure& callback) OVERRIDE;
virtual void Receive(
int /* buffer_size */,
const ReceiveCompletionCallback& success_callback,
const ReceiveErrorCompletionCallback& error_callback) OVERRIDE;
virtual void Send(scoped_refptr<net::IOBuffer> buffer,
int buffer_size,
const SendCompletionCallback& success_callback,
const ErrorCompletionCallback& error_callback) OVERRIDE;
// Called by BluetoothRFCOMMChannelDelegate.
void OnChannelOpened(IOBluetoothRFCOMMChannel* rfcomm_channel,
IOReturn status);
void OnChannelClosed(IOBluetoothRFCOMMChannel* rfcomm_channel);
void OnChannelDataReceived(IOBluetoothRFCOMMChannel* rfcomm_channel,
void* data,
size_t length);
void OnChannelWriteComplete(IOBluetoothRFCOMMChannel* rfcomm_channel,
void* refcon,
IOReturn status);
private:
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();
virtual ~BluetoothSocketMac();
void ReleaseChannel();
// Connects to the peer device corresponding to |record| and calls
// |success_callback| when the connection has been established
// successfully. If an error occurs, calls |error_callback| with a system
// error message.
void ConnectImpl(IOBluetoothSDPServiceRecord* record,
const ConnectSuccessCallback& success_callback,
const ErrorCompletionCallback& error_callback);
// Accepts a connection from a peer device. The connection is represented as
// the |rfcomm_channel|, which should be an incoming channel in the process of
// being opened. Calls |success_callback|, passing in |this|, on success.
// Calls |error_callback| on failure.
void AcceptConnectionImpl(IOBluetoothRFCOMMChannel* rfcomm_channel,
const ConnectSuccessCallback& success_callback,
const ErrorCompletionCallback& error_callback);
bool connecting() const { return connect_callbacks_; }
// Used to verify that all methods are called on the same thread.
base::ThreadChecker thread_checker_;
// The RFCOMM channel delegate.
base::scoped_nsobject<BluetoothRFCOMMChannelDelegate> delegate_;
// The IOBluetooth RFCOMM channel used to issue commands.
base::scoped_nsobject<IOBluetoothRFCOMMChannel> rfcomm_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_;
DISALLOW_COPY_AND_ASSIGN(BluetoothSocketMac);
};
} // namespace device
#endif // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_MAC_H_