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

Commit 58fc322e authored by Myles Watson's avatar Myles Watson Committed by Zach Johnson
Browse files

packet: Add Packet classes and tests

Test: atest bluetooth_test_gd
Change-Id: I8e124d5123cff3354f5c451b3806904a2d60b38d
parent d2b1bfa0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -80,6 +80,10 @@ cc_library {
            ]
        }
    },
    srcs: [
        ":BluetoothCommonSources",
        ":BluetoothPacketSources",
    ]
}

cc_test {
@@ -97,6 +101,10 @@ cc_test {
            ]
        }
    },
    srcs: [
        ":BluetoothCommonTestSources",
        ":BluetoothPacketTestSources",
    ],
    static_libs : [
        "libbluetooth_gd",
    ],
+15 −0
Original line number Diff line number Diff line
filegroup {
    name: "BluetoothCommonSources",
    srcs: [
        "address.cc",
        "class_of_device.cc",
    ]
}

filegroup {
    name: "BluetoothCommonTestSources",
    srcs: [
        "address_unittest.cc",
        "class_of_device_unittest.cc",
    ]
}
+92 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include "address.h"

#include <stdint.h>
#include <algorithm>
#include <sstream>
#include <vector>

namespace bluetooth {
namespace common {

static_assert(sizeof(Address) == 6, "Address must be 6 bytes long!");

const Address Address::kAny{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
const Address Address::kEmpty{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};

Address::Address(const uint8_t (&addr)[6]) {
  std::copy(addr, addr + kLength, address);
};

std::string Address::ToString() const {
  char buffer[] = "00:00:00:00:00:00";
  std::snprintf(&buffer[0], sizeof(buffer),
      "%02x:%02x:%02x:%02x:%02x:%02x", address[5], address[4], address[3], address[2], address[1], address[0]);
  std::string str(buffer);
  return str;
}

bool Address::FromString(const std::string& from, Address& to) {
  Address new_addr;
  if (from.length() != 17) {
    return false;
  }

  std::istringstream stream(from);
  std::string token;
  int index = 0;
  while (getline(stream, token, ':')) {
    if (index >= 6) {
      return false;
    }

    if (token.length() != 2) {
      return false;
    }

    char* temp = nullptr;
    new_addr.address[5 - index] = strtol(token.c_str(), &temp, 16);
    if (*temp != '\0') {
      return false;
    }

    index++;
  }

  if (index != 6) {
    return false;
  }

  to = new_addr;
  return true;
}

size_t Address::FromOctets(const uint8_t* from) {
  std::copy(from, from + kLength, address);
  return kLength;
};

bool Address::IsValidAddress(const std::string& address) {
  Address tmp;
  return Address::FromString(address, tmp);
}

}  // namespace common
}  // namespace bluetooth
+81 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#pragma once

#include <string>

namespace bluetooth {
namespace common {

class Address final {
 public:
  static constexpr unsigned int kLength = 6;

  uint8_t address[kLength];

  Address() = default;
  Address(const uint8_t (&addr)[6]);

  bool operator<(const Address& rhs) const {
    return (std::memcmp(address, rhs.address, sizeof(address)) < 0);
  }
  bool operator==(const Address& rhs) const {
    return (std::memcmp(address, rhs.address, sizeof(address)) == 0);
  }
  bool operator>(const Address& rhs) const {
    return (rhs < *this);
  }
  bool operator<=(const Address& rhs) const {
    return !(*this > rhs);
  }
  bool operator>=(const Address& rhs) const {
    return !(*this < rhs);
  }
  bool operator!=(const Address& rhs) const {
    return !(*this == rhs);
  }

  bool IsEmpty() const {
    return *this == kEmpty;
  }

  std::string ToString() const;

  // Converts |string| to Address and places it in |to|. If |from| does
  // not represent a Bluetooth address, |to| is not modified and this function
  // returns false. Otherwise, it returns true.
  static bool FromString(const std::string& from, Address& to);

  // Copies |from| raw Bluetooth address octets to the local object.
  // Returns the number of copied octets - should be always Address::kLength
  size_t FromOctets(const uint8_t* from);

  static bool IsValidAddress(const std::string& address);

  static const Address kEmpty;  // 00:00:00:00:00:00
  static const Address kAny;    // FF:FF:FF:FF:FF:FF
};

inline std::ostream& operator<<(std::ostream& os, const Address& a) {
  os << a.ToString();
  return os;
}

}  // namespace common
}  // namespace bluetooth
+199 −0
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include <gtest/gtest.h>

#include "common/address.h"

using bluetooth::common::Address;

static const char* test_addr = "bc:9a:78:56:34:12";
static const char* test_addr2 = "21:43:65:87:a9:cb";

TEST(AddressUnittest, test_constructor_array) {
  Address bdaddr({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});

  ASSERT_EQ(0x12, bdaddr.address[0]);
  ASSERT_EQ(0x34, bdaddr.address[1]);
  ASSERT_EQ(0x56, bdaddr.address[2]);
  ASSERT_EQ(0x78, bdaddr.address[3]);
  ASSERT_EQ(0x9A, bdaddr.address[4]);
  ASSERT_EQ(0xBC, bdaddr.address[5]);

  std::string ret = bdaddr.ToString();

  ASSERT_STREQ(test_addr, ret.c_str());
}

TEST(AddressUnittest, test_is_empty) {
  Address empty;
  Address::FromString("00:00:00:00:00:00", empty);
  ASSERT_TRUE(empty.IsEmpty());

  Address not_empty;
  Address::FromString("00:00:00:00:00:01", not_empty);
  ASSERT_FALSE(not_empty.IsEmpty());
}

TEST(AddressUnittest, test_to_from_str) {
  Address bdaddr;
  Address::FromString(test_addr, bdaddr);

  ASSERT_EQ(0x12, bdaddr.address[0]);
  ASSERT_EQ(0x34, bdaddr.address[1]);
  ASSERT_EQ(0x56, bdaddr.address[2]);
  ASSERT_EQ(0x78, bdaddr.address[3]);
  ASSERT_EQ(0x9A, bdaddr.address[4]);
  ASSERT_EQ(0xBC, bdaddr.address[5]);

  std::string ret = bdaddr.ToString();

  ASSERT_STREQ(test_addr, ret.c_str());
}

TEST(AddressUnittest, test_from_octets) {
  static const uint8_t test_addr_array[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};

  Address bdaddr;
  size_t expected_result = Address::kLength;
  ASSERT_EQ(expected_result, bdaddr.FromOctets(test_addr_array));

  ASSERT_EQ(0x12, bdaddr.address[0]);
  ASSERT_EQ(0x34, bdaddr.address[1]);
  ASSERT_EQ(0x56, bdaddr.address[2]);
  ASSERT_EQ(0x78, bdaddr.address[3]);
  ASSERT_EQ(0x9A, bdaddr.address[4]);
  ASSERT_EQ(0xBC, bdaddr.address[5]);

  std::string ret = bdaddr.ToString();

  ASSERT_STREQ(test_addr, ret.c_str());
}

TEST(AddressTest, test_equals) {
  Address bdaddr1;
  Address bdaddr2;
  Address bdaddr3;
  Address::FromString(test_addr, bdaddr1);
  Address::FromString(test_addr, bdaddr2);
  EXPECT_TRUE(bdaddr1 == bdaddr2);
  EXPECT_FALSE(bdaddr1 != bdaddr2);
  EXPECT_TRUE(bdaddr1 == bdaddr1);
  EXPECT_FALSE(bdaddr1 != bdaddr1);

  Address::FromString(test_addr2, bdaddr3);
  EXPECT_FALSE(bdaddr2 == bdaddr3);
  EXPECT_TRUE(bdaddr2 != bdaddr3);
}

TEST(AddressTest, test_less_than) {
  Address bdaddr1;
  Address bdaddr2;
  Address bdaddr3;
  Address::FromString(test_addr, bdaddr1);
  Address::FromString(test_addr, bdaddr2);
  EXPECT_FALSE(bdaddr1 < bdaddr2);
  EXPECT_FALSE(bdaddr1 < bdaddr1);

  Address::FromString(test_addr2, bdaddr3);
  EXPECT_TRUE(bdaddr2 < bdaddr3);
  EXPECT_FALSE(bdaddr3 < bdaddr2);
}

TEST(AddressTest, test_more_than) {
  Address bdaddr1;
  Address bdaddr2;
  Address bdaddr3;
  Address::FromString(test_addr, bdaddr1);
  Address::FromString(test_addr, bdaddr2);
  EXPECT_FALSE(bdaddr1 > bdaddr2);
  EXPECT_FALSE(bdaddr1 > bdaddr1);

  Address::FromString(test_addr2, bdaddr3);
  EXPECT_FALSE(bdaddr2 > bdaddr3);
  EXPECT_TRUE(bdaddr3 > bdaddr2);
}

TEST(AddressTest, test_less_than_or_equal) {
  Address bdaddr1;
  Address bdaddr2;
  Address bdaddr3;
  Address::FromString(test_addr, bdaddr1);
  Address::FromString(test_addr, bdaddr2);
  EXPECT_TRUE(bdaddr1 <= bdaddr2);
  EXPECT_TRUE(bdaddr1 <= bdaddr1);

  Address::FromString(test_addr2, bdaddr3);
  EXPECT_TRUE(bdaddr2 <= bdaddr3);
  EXPECT_FALSE(bdaddr3 <= bdaddr2);
}

TEST(AddressTest, test_more_than_or_equal) {
  Address bdaddr1;
  Address bdaddr2;
  Address bdaddr3;
  Address::FromString(test_addr, bdaddr1);
  Address::FromString(test_addr, bdaddr2);
  EXPECT_TRUE(bdaddr1 >= bdaddr2);
  EXPECT_TRUE(bdaddr1 >= bdaddr1);

  Address::FromString(test_addr2, bdaddr3);
  EXPECT_FALSE(bdaddr2 >= bdaddr3);
  EXPECT_TRUE(bdaddr3 >= bdaddr2);
}

TEST(AddressTest, test_copy) {
  Address bdaddr1;
  Address bdaddr2;
  Address::FromString(test_addr, bdaddr1);
  bdaddr2 = bdaddr1;

  EXPECT_TRUE(bdaddr1 == bdaddr2);
}

TEST(AddressTest, IsValidAddress) {
  EXPECT_FALSE(Address::IsValidAddress(""));
  EXPECT_FALSE(Address::IsValidAddress("000000000000"));
  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:0000"));
  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0"));
  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0;"));
  EXPECT_TRUE(Address::IsValidAddress("00:00:00:00:00:00"));
  EXPECT_TRUE(Address::IsValidAddress("AB:cd:00:00:00:00"));
  EXPECT_FALSE(Address::IsValidAddress("aB:cD:eF:Gh:iJ:Kl"));
}

TEST(AddressTest, BdAddrFromString) {
  Address addr;
  memset(&addr, 0, sizeof(addr));

  EXPECT_TRUE(Address::FromString("00:00:00:00:00:00", addr));
  const Address result0 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
  EXPECT_EQ(0, memcmp(&addr, &result0, sizeof(addr)));

  EXPECT_TRUE(Address::FromString("ab:01:4C:d5:21:9f", addr));
  const Address result1 = {{0x9f, 0x21, 0xd5, 0x4c, 0x01, 0xab}};
  EXPECT_EQ(0, memcmp(&addr, &result1, sizeof(addr)));
}

TEST(AddressTest, BdAddrFromStringToStringEquivalent) {
  std::string address = "c1:c2:c3:d1:d2:d3";
  Address addr;

  EXPECT_TRUE(Address::FromString(address, addr));
  EXPECT_EQ(addr.ToString(), address);
}
Loading