Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d47be04 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "PDL: Serialize nested packets in Python"

parents f12c5c46 21161f5b
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -14,8 +14,6 @@
#   See the License for the specific language governing permissions and
#   limitations under the License.

import os
import sys
import logging
import time

@@ -25,6 +23,10 @@ from cert.gd_base_test_facade_only import GdFacadeOnlyBaseTestClass
from cert.event_callback_stream import EventCallbackStream
from cert.event_asserts import EventAsserts

# Test packet nesting
from bluetooth_packets_python3 import hci_packets
from bluetooth_packets_python3 import l2cap_packets


class BogusProto:

@@ -197,3 +199,34 @@ class CertSelfTest(GdFacadeOnlyBaseTestClass):
    def test_skip_a_test(self):
        asserts.skip("Skipping this test because it's blocked by b/xyz")
        assert False

    def test_nested_packets(self):
        handle = 123
        inside = hci_packets.ReadScanEnableBuilder()
        logging.debug(inside.Serialize())
        logging.debug("building outside")
        outside = hci_packets.AclPacketBuilder(
            handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT, inside)
        logging.debug(outside.Serialize())
        logging.debug("Done!")

    def test_l2cap_config_options(self):
        mtu_opt = l2cap_packets.MtuConfigurationOption()
        mtu_opt.mtu = 123
        fcs_opt = l2cap_packets.FrameCheckSequenceOption()
        fcs_opt.fcs_type = l2cap_packets.FcsType.DEFAULT
        request = l2cap_packets.ConfigurationRequestBuilder(
            0x1d,  # Command ID
            0xc1d,  # Channel ID
            l2cap_packets.Continuation.END,
            [mtu_opt, fcs_opt])
        request.Serialize()
        handle = 123
        wrapped = hci_packets.AclPacketBuilder(
            handle,
            hci_packets.PacketBoundaryFlag.FIRST_NON_AUTOMATICALLY_FLUSHABLE,
            hci_packets.BroadcastFlag.POINT_TO_POINT, request)
        asserts.assert_true(
            len(wrapped.Serialize()) == 16, "Packet serialized incorrectly")
+1 −2
Original line number Diff line number Diff line
@@ -44,8 +44,7 @@ class PacketField : public Loggable {
  // For most field types, this will be the same as GetSize();
  virtual Size GetStructSize() const;

  // Get the type of the field to be used in the builders constructor and
  // variables.
  // Get the type of the field to be used in the member variables.
  virtual std::string GetDataType() const = 0;

  // Given an iterator {name}_it, extract the type.
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ void VariableLengthStructField::GenGetter(std::ostream& s, Size start_offset, Si
  s << "size_t end_index = size();";
  s << "auto to_bound = begin();";
  int num_leading_bits = GenBounds(s, start_offset, end_offset, GetSize());
  s << "std::unique_ptr<" << type_name_ << "> " << GetName() << "_ptr;";
  s << GetDataType() << " " << GetName() << "_ptr;";
  GenExtractor(s, num_leading_bits, false);
  s << "return " << GetName() << "_ptr;";
  s << "}\n";
+3 −0
Original line number Diff line number Diff line
@@ -266,6 +266,8 @@ bool generate_pybind11_sources_one_file(const Declarations& decls, const std::fi
    out_file << "\n\n";
    out_file << "#include " << gen_relative_header << "\n";
    out_file << "\n\n";
    out_file << "#include \"packet/raw_builder.h\"\n";
    out_file << "\n\n";

    for (const auto& c : decls.type_defs_queue_) {
      if (c.second->GetDefinitionType() == TypeDef::Type::CUSTOM) {
@@ -297,6 +299,7 @@ bool generate_pybind11_sources_one_file(const Declarations& decls, const std::fi
    out_file << "using ::bluetooth::packet::BaseStruct;";
    out_file << "using ::bluetooth::packet::PacketStruct;";
    out_file << "using ::bluetooth::packet::PacketView;";
    out_file << "using ::bluetooth::packet::RawBuilder;";
    out_file << "using ::bluetooth::packet::parser::ChecksumTypeChecker;";
    out_file << "\n\n";

+24 −12
Original line number Diff line number Diff line
@@ -501,7 +501,6 @@ void PacketDef::GenBuilderCreatePybind11(std::ostream& s) const {
  s << ".def(py::init([](";
  auto params = GetParamList();
  std::vector<std::string> constructor_args;
  std::vector<std::string> keep_alive_args;
  int i = 1;
  for (const auto& param : params) {
    i++;
@@ -513,7 +512,6 @@ void PacketDef::GenBuilderCreatePybind11(std::ostream& s) const {
    // Use shared_ptr instead of unique_ptr for the Python interface
    if (param->BuilderParameterMustBeMoved()) {
      param_type = util::StringFindAndReplaceAll(param_type, "unique_ptr", "shared_ptr");
      keep_alive_args.push_back(std::to_string(i));
    }
    ss << param_type << " " << param->GetName();
    constructor_args.push_back(ss.str());
@@ -533,19 +531,37 @@ void PacketDef::GenBuilderCreatePybind11(std::ostream& s) const {
    auto move_only_param_name = param->GetName() + "_move_only";
    s << param_type << " " << move_only_param_name << ";";
    if (param->IsContainerField()) {
      // Assume single layer container
      // Assume single layer container and copy it
      auto struct_type = param->GetElementField()->GetDataType();
      struct_type = util::StringFindAndReplaceAll(struct_type, "std::unique_ptr<", "");
      struct_type = util::StringFindAndReplaceAll(struct_type, ">", "");
      s << "for (size_t i = 0; i < " << param->GetName() << ".size(); i++) {";
      // Serialize each struct
      s << "auto " << param->GetName() + "_bytes = std::make_shared<std::vector<uint8_t>>();";
      s << param->GetName() + "_bytes->reserve(" << param->GetName() << "[i]->size());";
      s << "auto " << param->GetName() + "_reparsed = std::make_unique<" << struct_type << ">();";
      s << "BitInserter " << param->GetName() + "_bi(*" << param->GetName() << "_bytes);";
      s << param->GetName() << "[i]->Serialize(" << param->GetName() << "_bi);";
      // Parse it again
      s << "auto " << param->GetName() << "_view = PacketView<kLittleEndian>(" << param->GetName() << "_bytes);";
      s << "auto result = Parse" << struct_type << "(" << param->GetName() + "_view.begin());";
      // Push it into a new container
      if (param->GetFieldType() == VectorField::kFieldType) {
        s << move_only_param_name << ".emplace_back(" << param->GetName() << "[i].get());";
        s << move_only_param_name << ".push_back(std::move(" << param->GetName() + "_reparsed));";
      } else if (param->GetFieldType() == ArrayField::kFieldType) {
        s << move_only_param_name << "[i].reset(" << param->GetName() << "[i].get());";
        s << move_only_param_name << "[i] = " << param->GetName() << "_reparsed;";
      } else {
        ERROR() << param << " is not supported by Pybind11";
      }
      s << "}";
    } else {
      // Release shared_ptr to unique_ptr and leave the Python copy as nullptr and to be garbage collected by Python
      s << move_only_param_name << ".reset(" << param->GetName() << ".get());";
      // Serialize the parameter and pass the bytes in a RawBuilder
      s << "std::vector<uint8_t> " << param->GetName() + "_bytes;";
      s << param->GetName() + "_bytes.reserve(" << param->GetName() << "->size());";
      s << "BitInserter " << param->GetName() + "_bi(" << param->GetName() << "_bytes);";
      s << param->GetName() << "->Serialize(" << param->GetName() + "_bi);";
      s << move_only_param_name << " = ";
      s << "std::make_unique<RawBuilder>(" << param->GetName() << "_bytes);";
    }
  }
  s << "return " << name_ << "Builder::Create(";
@@ -565,11 +581,7 @@ void PacketDef::GenBuilderCreatePybind11(std::ostream& s) const {
    builder_vars.push_back(ss.str());
  }
  s << util::StringJoin(",", builder_vars) << ");}";
  if (keep_alive_args.empty()) {
  s << "))";
  } else {
    s << "), py::keep_alive<1," << util::StringJoin(",", keep_alive_args) << ">())";
  }
}

void PacketDef::GenBuilderParameterChecker(std::ostream& s) const {
Loading