Loading system/gd/cert/cert_self_test.py +35 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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: Loading Loading @@ -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") system/gd/packet/parser/fields/packet_field.h +1 −2 Original line number Diff line number Diff line Loading @@ -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. Loading system/gd/packet/parser/fields/variable_length_struct_field.cc +1 −1 Original line number Diff line number Diff line Loading @@ -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"; Loading system/gd/packet/parser/main.cc +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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"; Loading system/gd/packet/parser/packet_def.cc +24 −12 Original line number Diff line number Diff line Loading @@ -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++; Loading @@ -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()); Loading @@ -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("; Loading @@ -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 Loading
system/gd/cert/cert_self_test.py +35 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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: Loading Loading @@ -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")
system/gd/packet/parser/fields/packet_field.h +1 −2 Original line number Diff line number Diff line Loading @@ -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. Loading
system/gd/packet/parser/fields/variable_length_struct_field.cc +1 −1 Original line number Diff line number Diff line Loading @@ -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"; Loading
system/gd/packet/parser/main.cc +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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"; Loading
system/gd/packet/parser/packet_def.cc +24 −12 Original line number Diff line number Diff line Loading @@ -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++; Loading @@ -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()); Loading @@ -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("; Loading @@ -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