blob: 5b460576645c7c88efe11b885ce4062c66a28fa3 [file] [log] [blame]
// Copyright 2017 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_WLAN_LIB_MLME_CPP_INCLUDE_WLAN_MLME_SERVICE_H_
#define SRC_CONNECTIVITY_WLAN_LIB_MLME_CPP_INCLUDE_WLAN_MLME_SERVICE_H_
#include <fuchsia/wlan/mlme/cpp/fidl.h>
#include <lib/fidl/cpp/decoder.h>
#include <lib/fidl/cpp/message.h>
#include <wlan/common/buffer_reader.h>
#include <wlan/common/energy.h>
#include <wlan/common/macaddr.h>
#include <wlan/common/span.h>
#include <wlan/mlme/device_interface.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/packet.h>
#include <zircon/fidl.h>
namespace wlan {
template <typename T>
zx_status_t SerializeServiceMsg(fidl::Encoder* enc, T* msg,
zx_txid_t txid = 0) {
// Encode our message of type T. The encoder will take care of extending the
// buffer to accommodate out-of-line data (e.g., vectors, strings, and
// nullable data).
enc->Alloc(fidl::CodingTraits<T>::encoded_size);
msg->Encode(enc, sizeof(fidl_message_header_t));
// The coding tables for fidl structs do not include offsets for the message
// header, so we must run validation starting after this header.
auto encoded = enc->GetMessage();
ZX_ASSERT(encoded.has_header());
encoded.set_txid(txid);
auto msg_body = encoded.payload();
const char* err_msg = nullptr;
zx_status_t status =
fidl_validate(T::FidlType, msg_body.data(), msg_body.size(), 0, &err_msg);
if (status != ZX_OK) {
errorf("could not validate encoded message: %s\n", err_msg);
}
return status;
}
template <typename T>
static zx_status_t SendServiceMsg(DeviceInterface* device, T* message,
uint32_t ordinal, zx_txid_t txid = 0) {
fidl::Encoder enc(ordinal);
zx_status_t status = SerializeServiceMsg(&enc, message, txid);
if (status != ZX_OK) {
errorf("could not serialize FIDL message %d: %d\n", ordinal, status);
return status;
}
return device->SendService(enc.GetMessage().bytes());
}
template <typename M>
class MlmeMsg;
class BaseMlmeMsg {
public:
virtual ~BaseMlmeMsg() = default;
template <typename M>
const MlmeMsg<M>* As() const {
return get_type_id() == MlmeMsg<M>::type_id()
? static_cast<const MlmeMsg<M>*>(this)
: nullptr;
}
zx_txid_t txid() const { return txid_; }
uint32_t ordinal() const { return ordinal_; }
protected:
BaseMlmeMsg(uint32_t ordinal, zx_txid_t txid)
: ordinal_(ordinal), txid_(txid) {}
BaseMlmeMsg(BaseMlmeMsg&&) = default;
virtual const void* get_type_id() const = 0;
uint32_t ordinal_ = 0;
zx_txid_t txid_ = 0;
private:
BaseMlmeMsg(BaseMlmeMsg const&) = delete;
BaseMlmeMsg& operator=(BaseMlmeMsg const&) = delete;
};
template <typename M>
class MlmeMsg : public BaseMlmeMsg {
public:
static const uint8_t kTypeId = 0;
MlmeMsg(M&& msg, uint32_t ordinal, zx_txid_t txid = 0)
: BaseMlmeMsg(ordinal, txid), msg_(std::move(msg)) {}
MlmeMsg(MlmeMsg&&) = default;
~MlmeMsg() override = default;
static constexpr uint32_t kNoOrdinal =
0; // Not applicable or does not matter
static std::optional<MlmeMsg<M>> Decode(Span<uint8_t> span,
uint32_t ordinal = kNoOrdinal) {
BufferReader reader(span);
auto h = reader.Read<fidl_message_header_t>();
if (h == nullptr) {
errorf("MLME message too short\n");
return {};
}
if (ordinal != kNoOrdinal && ordinal != h->ordinal) {
// Generated code uses hexadecimal to represent ordinal
warnf("Mismatched ordinal: expected: 0x%0x, actual: 0x%0x\n", ordinal,
h->ordinal);
return {};
}
// Extract the message contents and decode in-place (i.e., fixup all the
// out-of-line pointers to be offsets into the span).
auto payload = span.subspan(reader.ReadBytes());
const char* err_msg = nullptr;
auto status = fidl_decode(M::FidlType, payload.data(), payload.size(),
nullptr, 0, &err_msg);
if (status != ZX_OK) {
errorf("could not decode received message: %s\n", err_msg);
return {};
}
// Construct a fidl Message and decode it into M.
fidl::Message msg(
fidl::BytePart(payload.data(), payload.size(), payload.size()),
fidl::HandlePart());
fidl::Decoder decoder(std::move(msg));
return {{fidl::DecodeAs<M>(&decoder, 0), h->ordinal, h->txid}};
}
const M* body() const { return &msg_; }
static const void* type_id() { return &MlmeMsg<M>::kTypeId; }
const void* get_type_id() const override { return type_id(); }
private:
M msg_;
};
template <typename T>
const uint8_t MlmeMsg<T>::kTypeId;
namespace service {
// Returns the peer MAC address for messages which carry one, none otherwise.
std::optional<common::MacAddr> GetPeerAddr(const BaseMlmeMsg& msg);
zx_status_t SendJoinConfirm(DeviceInterface* device,
::fuchsia::wlan::mlme::JoinResultCodes result_code);
zx_status_t SendAuthConfirm(
DeviceInterface* device, const common::MacAddr& peer_sta,
::fuchsia::wlan::mlme::AuthenticateResultCodes code);
zx_status_t SendAuthIndication(
DeviceInterface* device, const common::MacAddr& peer_sta,
::fuchsia::wlan::mlme::AuthenticationTypes auth_type);
zx_status_t SendDeauthConfirm(DeviceInterface* device,
const common::MacAddr& peer_sta);
zx_status_t SendDeauthIndication(DeviceInterface* device,
const common::MacAddr& peer_sta,
::fuchsia::wlan::mlme::ReasonCode code);
zx_status_t SendAssocConfirm(DeviceInterface* device,
::fuchsia::wlan::mlme::AssociateResultCodes code,
uint16_t aid = 0);
zx_status_t SendAssocIndication(DeviceInterface* device,
const common::MacAddr& peer_sta,
uint16_t listen_interval,
Span<const uint8_t> ssid,
std::optional<Span<const uint8_t>> rsn_body);
zx_status_t SendDisassociateIndication(DeviceInterface* device,
const common::MacAddr& peer_sta,
uint16_t code);
zx_status_t SendSignalReportIndication(DeviceInterface* device,
common::dBm rssi_dbm);
zx_status_t SendEapolConfirm(
DeviceInterface* device,
::fuchsia::wlan::mlme::EapolResultCodes result_code);
zx_status_t SendEapolIndication(DeviceInterface* device, const EapolHdr& eapol,
const common::MacAddr& src,
const common::MacAddr& dst);
zx_status_t SendStartConfirm(DeviceInterface* device,
::fuchsia::wlan::mlme::StartResultCodes code);
zx_status_t SendStopConfirm(DeviceInterface* device,
::fuchsia::wlan::mlme::StopResultCodes code);
zx_status_t SendMeshPathTable(DeviceInterface* device,
::fuchsia::wlan::mesh::MeshPathTable& table,
uint32_t ordinal, zx_txid_t txid);
} // namespace service
} // namespace wlan
#endif // SRC_CONNECTIVITY_WLAN_LIB_MLME_CPP_INCLUDE_WLAN_MLME_SERVICE_H_