Browse Source

[2140] ClientId class implemented and tested.

Tomek Mrugalski 12 years ago
parent
commit
01eb4277b9
4 changed files with 141 additions and 13 deletions
  1. 48 0
      src/lib/dhcp/duid.cc
  2. 41 0
      src/lib/dhcp/duid.h
  3. 0 13
      src/lib/dhcp/lease_mgr.h
  4. 52 0
      src/lib/dhcp/tests/duid_unittest.cc

+ 48 - 0
src/lib/dhcp/duid.cc

@@ -14,6 +14,8 @@
 
 #include <vector>
 #include <exceptions/exceptions.h>
+#include <stdint.h>
+#include <util/io_utilities.h>
 #include <dhcp/duid.h>
 
 namespace isc {
@@ -59,5 +61,51 @@ bool DUID::operator != (const DUID& other) const {
     return (this->duid_ != other.duid_);
 }
 
+/// constructor based on vector<uint8_t>
+ClientId::ClientId(const std::vector<uint8_t>& clientid)
+    :DUID(clientid) {
+}
+
+/// constructor based on C-style data
+ClientId::ClientId(const uint8_t *clientid, size_t len)
+    :DUID(clientid, len) {
+}
+
+/// constructor based on IOAddress
+ClientId::ClientId(const isc::asiolink::IOAddress& addr)
+    :DUID(std::vector<uint8_t>(4, 0)) {
+    if (addr.getFamily() != AF_INET) {
+        isc_throw(BadValue, "Client-id supports only IPv4 addresses");
+    }
+    isc::util::writeUint32(addr, &duid_[0]);
+}
+
+/// @brief returns reference to the client-id data
+const std::vector<uint8_t> ClientId::getClientId() const {
+    return duid_;
+}
+
+isc::asiolink::IOAddress ClientId::getAddress() const {
+    if (duid_.size() != sizeof(uint32_t)) {
+        isc_throw(BadValue, "This client-id is not an IPv4 address");
+    }
+
+    return isc::asiolink::IOAddress( isc::util::readUint32(&duid_[0]) );
+}
+
+bool ClientId::isAddress() const {
+    return (duid_.size() == sizeof(uint32_t));
+}
+
+// compares two client-ids
+bool ClientId::operator == (const ClientId& other) const {
+    return (this->duid_ == other.duid_);
+}
+
+// compares two client-ids
+bool ClientId::operator != (const ClientId& other) const {
+    return (this->duid_ != other.duid_);
+}
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace

+ 41 - 0
src/lib/dhcp/duid.h

@@ -15,6 +15,8 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <vector>
+#include <asiolink/io_address.h>
+
 
 namespace isc {
 namespace dhcp {
@@ -65,5 +67,44 @@ class DUID {
     std::vector<uint8_t> duid_;
 };
 
+/// @brief Holds Client identifier or client IPv4 address
+///
+/// This class is intended to be a generic IPv4 client identifier. It can hold
+/// a client-id
+class ClientId : DUID {
+ public:
+
+    /// constructor based on vector<uint8_t>
+    ClientId(const std::vector<uint8_t>& clientid);
+
+    /// constructor based on C-style data
+    ClientId(const uint8_t *clientid, size_t len);
+
+    /// constructor based on IOAddress
+    ///
+    /// @throw BadValue if specified address is not IPv4
+    ClientId(const isc::asiolink::IOAddress& addr);
+
+    /// @brief returns reference to the client-id data
+    ///
+    /// This reference is only valid as long as the object
+    /// that returned it.
+    const std::vector<uint8_t> getClientId() const;
+
+    /// @brief return an IPv4 address represented by this client-id
+    ///
+    /// @throw BadValue if this client-id is not an IPv4 address
+    isc::asiolink::IOAddress getAddress() const;
+
+    /// @brief returns if client-id is an address
+    bool isAddress() const;
+
+    // compares two client-ids
+    bool operator == (const ClientId& other) const;
+
+    // compares two client-ids
+    bool operator != (const ClientId& other) const;
+};
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace

+ 0 - 13
src/lib/dhcp/lease_mgr.h

@@ -24,19 +24,6 @@
 namespace isc {
 namespace dhcp {
 
-/// @brief Holds Client identifier
-class ClientId {
- public:
-    ClientId(const std::vector<uint8_t>& duid);
-    ClientId(const char *duid, size_t len);
-    ClientId(uint32_t id);
-    ClientId(const isc::asiolink::IOAddress& addr);
-    const std::vector<uint8_t> getClientId() const;
-    bool operator == (const ClientId& other);
- protected:
-    std::vector<uint8_t> clientid_;
-};
-
 /// @brief Structure that holds a lease for IPv4 address
 ///
 /// For performance reasons it is a simple structure, not a class. If we chose

+ 52 - 0
src/lib/dhcp/tests/duid_unittest.cc

@@ -19,11 +19,13 @@
 #include <gtest/gtest.h>
 #include <exceptions/exceptions.h>
 #include <boost/scoped_ptr.hpp>
+#include <asiolink/io_address.h>
 #include <dhcp/duid.h>
 
 using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
+using namespace isc::asiolink;
 
 // don't import the entire boost namespace.  It will unexpectedly hide uint8_t
 // for some systems.
@@ -116,6 +118,56 @@ TEST(DuidTest, operators) {
     EXPECT_TRUE(*duid1 != *duid3);
 }
 
+TEST(ClientIdTest, constructor) {
+    IOAddress addr2("192.0.2.1");
+    IOAddress addr3("2001:db8:1::1");
 
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+    vector<uint8_t> data2(data1, data1 + sizeof(data1));
+    uint8_t data3[] = {192, 0 , 2, 1 };
+
+    // checks for C-style construtor (uint8_t * + len)
+    scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+    vector<uint8_t> vecdata = id1->getClientId();
+    EXPECT_EQ(data2, vecdata);
+    EXPECT_FALSE(id1->isAddress());
+    EXPECT_THROW(id1->getAddress(), BadValue);
+
+    // checks for vector-based constructor
+    scoped_ptr<ClientId> id2(new ClientId(data2));
+    vecdata = id2->getClientId();
+    EXPECT_EQ(data2, vecdata);
+    EXPECT_FALSE(id1->isAddress());
+    EXPECT_THROW(id1->getAddress(), BadValue);
+
+    // checks for IOAddress based constructor
+    scoped_ptr<ClientId> id3(new ClientId(addr2));
+    vecdata = id3->getClientId();
+    EXPECT_TRUE(vecdata == vector<uint8_t>(data3, data3 + 4));
+    EXPECT_EQ("192.0.2.1", id3->getAddress().toText());
+
+    // should support v4 address only, v6 is a wrong address here
+    EXPECT_THROW(new ClientId(addr3), BadValue);
+}
+
+TEST(ClientIdTest, operators) {
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+    uint8_t data2[] = {0, 1, 2, 3, 4};
+    uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
+    uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
+
+    scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+    scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
+    scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
+    scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
+
+    EXPECT_TRUE(*id1 == *id4);
+    EXPECT_FALSE(*id1 == *id2);
+    EXPECT_FALSE(*id1 == *id3);
+
+    EXPECT_FALSE(*id1 != *id4);
+    EXPECT_TRUE(*id1 != *id2);
+    EXPECT_TRUE(*id1 != *id3);
+}
 
 } // end of anonymous namespace