blob: bfdcf4e313f0aff4e9a23f8ec08d3f9155b5d3e8 [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PAIRING_CHANNEL_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PAIRING_CHANNEL_H_
#include <unordered_map>
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/scoped_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/util.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt::sm {
// Bridge class for the SMP L2CAP channel, which implements SM-specific functionality on top of
// existing L2CAP functionality. Besides this SM-specific functionality, also allows runtime
// modification of L2CAP event callbacks by changing the PairingChannel::Handler pointer.
class PairingChannel {
public:
// Interface for receiving L2CAP channel events.
class Handler {
public:
virtual ~Handler() = default;
virtual void OnRxBFrame(ByteBufferPtr) = 0;
virtual void OnChannelClosed() = 0;
};
// Initializes this PairingChannel with the L2CAP SMP fixed channel that this class wraps and the
// specified timer reset method. For use in production code.
PairingChannel(fbl::RefPtr<l2cap::Channel> chan, fit::closure timer_resetter);
// Initializes this PairingChannel with a no-op timer reset method. Only for use in tests of
// classes which do not depend on the timer reset behavior.
explicit PairingChannel(fbl::RefPtr<l2cap::Channel> chan);
// For setting the new handler, expected to be used when switching phases. PairingChannel is not
// fully initialized until SetChannelHandler has been called with a valid Handler. This two-phase
// initialization exists because concrete Handlers are expected to depend on PairingChannels.
void SetChannelHandler(fxl::WeakPtr<Handler> new_handler);
// Wrapper which encapsulates some of the boilerplate involved in sending an SMP object.
template <typename PayloadType>
void SendMessage(Code message_code, const PayloadType& payload) {
auto kExpectedSize = kCodeToPayloadSize.find(message_code);
ZX_ASSERT(kExpectedSize != kCodeToPayloadSize.end());
ZX_ASSERT(sizeof(PayloadType) == kExpectedSize->second);
auto pdu = util::NewPdu(sizeof(PayloadType));
PacketWriter writer(message_code, pdu.get());
*writer.mutable_payload<PayloadType>() = payload;
chan_->Send(std::move(pdu));
reset_timer_();
}
fxl::WeakPtr<PairingChannel> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
bool SupportsSecureConnections() const {
return chan_->max_rx_sdu_size() >= kLeSecureConnectionsMtu &&
chan_->max_tx_sdu_size() >= kLeSecureConnectionsMtu;
}
void SignalLinkError() { chan_->SignalLinkError(); }
hci::Connection::LinkType link_type() const { return chan_->link_type(); }
~PairingChannel() = default;
private:
// Used to delegate the L2CAP callbacks to the current handler
void OnRxBFrame(ByteBufferPtr ptr);
void OnChannelClosed();
// The L2CAP Channel this class wraps. Uses a ScopedChannel because a PairingChannel is expected
// to own the lifetime of the underlying L2CAP channel.
l2cap::ScopedChannel chan_;
// Per v5.2 Vol. 3 Part H 3.4, "The Security Manager Timer shall be reset when an L2CAP SMP
// command is queued for transmission". This closure signals this reset to occur.
fit::closure reset_timer_;
// L2CAP channel events are delegated to this handler.
fxl::WeakPtr<Handler> handler_;
fxl::WeakPtrFactory<PairingChannel> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(PairingChannel);
};
} // namespace bt::sm
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PAIRING_CHANNEL_H_