Browse Source

[2312] Added functions to read data of different types from buffer.

Marcin Siodelski 12 years ago
parent
commit
f3da5ed9ef
2 changed files with 121 additions and 21 deletions
  1. 64 20
      src/lib/dhcp/option_data_types.cc
  2. 57 1
      src/lib/dhcp/option_data_types.h

+ 64 - 20
src/lib/dhcp/option_data_types.cc

@@ -19,6 +19,52 @@ namespace isc {
 namespace dhcp {
 namespace dhcp {
 
 
 void
 void
+OptionDataTypeUtil::readAddress(const std::vector<uint8_t>& buf,
+                            const short family,
+                            asiolink::IOAddress& address) {
+    using namespace isc::asiolink;
+    if (family == AF_INET) {
+        if (buf.size() < V4ADDRESS_LEN) {
+            isc_throw(BadDataTypeCast, "unavle to read data from the buffer as"
+                      << " IPv4 address. Invalid buffer size: " << buf.size());
+        }
+        address = IOAddress::from_bytes(AF_INET, &buf[0]);
+    } else if (buf.size() == V6ADDRESS_LEN) {
+        if (buf.size() < V6ADDRESS_LEN) {
+            isc_throw(BadDataTypeCast, "unavle to read data from the buffer as"
+                      << " IPv6 address. Invalid buffer size: " << buf.size());
+        }
+        address = IOAddress::from_bytes(AF_INET6, &buf[0]);
+    } else {
+        isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
+                  "IP address. Invalid family: " << family);
+    }
+}
+
+void
+OptionDataTypeUtil::writeAddress(const asiolink::IOAddress& address,
+                                 std::vector<uint8_t>& buf) {
+    if (address.getAddress().is_v4()) {
+        asio::ip::address_v4::bytes_type addr_bytes =
+            address.getAddress().to_v4().to_bytes();
+        // Increase the buffer size by the size of IPv4 address.
+        buf.resize(buf.size() + addr_bytes.size());
+        std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
+                           buf.end());
+    } else if (address.getAddress().is_v6()) {
+        asio::ip::address_v6::bytes_type addr_bytes =
+            address.getAddress().to_v6().to_bytes();
+        // Incresase the buffer size by the size of IPv6 address.
+        buf.resize(buf.size() + addr_bytes.size());
+        std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
+                           buf.end());
+    } else {
+        isc_throw(BadDataTypeCast, "the address " << address.toText()
+                  << " is neither valid IPv4 not IPv6 address.");
+    }
+}
+
+void
 OptionDataTypeUtil::writeBinary(const std::string& hex_str,
 OptionDataTypeUtil::writeBinary(const std::string& hex_str,
                                 std::vector<uint8_t>& buf) {
                                 std::vector<uint8_t>& buf) {
     // Binary value means that the value is encoded as a string
     // Binary value means that the value is encoded as a string
@@ -36,6 +82,21 @@ OptionDataTypeUtil::writeBinary(const std::string& hex_str,
     buf.insert(buf.end(), binary.begin(), binary.end());
     buf.insert(buf.end(), binary.begin(), binary.end());
 }
 }
 
 
+bool
+OptionDataTypeUtil::readBool(const std::vector<uint8_t>& buf) {
+    if (buf.size() < 1) {
+        isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
+                  << " value. Invalid buffer size " << buf.size());
+    }
+    if (buf[0] == 1) {
+        return (true);
+    } else if (buf[0] == 0) {
+        return (false);
+    }
+    isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
+              << " value. Inavlid value " << static_cast<int>(buf[0]));
+}
+
 void
 void
 OptionDataTypeUtil::writeBool(const bool value,
 OptionDataTypeUtil::writeBool(const bool value,
                               std::vector<uint8_t>& buf) {
                               std::vector<uint8_t>& buf) {
@@ -47,26 +108,9 @@ OptionDataTypeUtil::writeBool(const bool value,
 }
 }
 
 
 void
 void
-OptionDataTypeUtil::writeAddress(const asiolink::IOAddress& address,
-                                 std::vector<uint8_t>& buf) {
-    if (address.getAddress().is_v4()) {
-        asio::ip::address_v4::bytes_type addr_bytes =
-            address.getAddress().to_v4().to_bytes();
-        // Increase the buffer size by the size of IPv4 address.
-        buf.resize(buf.size() + addr_bytes.size());
-        std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
-                           buf.end());
-    } else if (address.getAddress().is_v6()) {
-        asio::ip::address_v6::bytes_type addr_bytes =
-            address.getAddress().to_v6().to_bytes();
-        // Incresase the buffer size by the size of IPv6 address.
-        buf.resize(buf.size() + addr_bytes.size());
-        std::copy_backward(addr_bytes.begin(), addr_bytes.end(),
-                           buf.end());
-    } else {
-        isc_throw(BadDataTypeCast, "the address " << address.toText()
-                  << " is neither valid IPv4 not IPv6 address.");
-    }
+OptionDataTypeUtil::readString(const std::vector<uint8_t>& buf,
+                               std::string& value) {
+    value.insert(value.end(), buf.begin(), buf.end());
 }
 }
 
 
 void
 void

+ 57 - 1
src/lib/dhcp/option_data_types.h

@@ -177,6 +177,16 @@ struct OptionDataTypeTraits<std::string> {
 /// @brief Utility class to write/read data to/from a buffer.
 /// @brief Utility class to write/read data to/from a buffer.
 class OptionDataTypeUtil {
 class OptionDataTypeUtil {
 public:
 public:
+
+    /// @brief Read IPv4 or IPv6 addres from a buffer.
+    ///
+    /// @param buf input buffer.
+    /// @param family address family: AF_INET or AF_INET6.
+    /// @param [out] address being read.
+    static void readAddress(const std::vector<uint8_t>& buf,
+                            const short family,
+                            asiolink::IOAddress& address);
+
     /// @brief Write IPv4 or IPv6 address into a buffer.
     /// @brief Write IPv4 or IPv6 address into a buffer.
     ///
     ///
     /// @param address IPv4 or IPv6 address.
     /// @param address IPv4 or IPv6 address.
@@ -190,7 +200,13 @@ public:
     /// with hexadecimal digits (without 0x prefix).
     /// with hexadecimal digits (without 0x prefix).
     /// @param [out] output buffer.
     /// @param [out] output buffer.
     static void writeBinary(const std::string& hex_str,
     static void writeBinary(const std::string& hex_str,
-                                    std::vector<uint8_t>& buf);
+                            std::vector<uint8_t>& buf);
+
+    /// @brief Read boolean value from a buffer.
+    ///
+    /// @param buf input buffer.
+    /// @return boolean value read from a buffer.
+    static bool readBool(const std::vector<uint8_t>& buf);
 
 
     /// @brief Write boolean value into a buffer.
     /// @brief Write boolean value into a buffer.
     ///
     ///
@@ -201,6 +217,39 @@ public:
     /// @param [out] buf output buffer.
     /// @param [out] buf output buffer.
     static void writeBool(const bool value, std::vector<uint8_t>& buf);
     static void writeBool(const bool value, std::vector<uint8_t>& buf);
 
 
+    /// @brief Read integer value from a buffer.
+    ///
+    /// @param buf input buffer.
+    /// @tparam integer type of the returned value.
+    /// @return integer value being read.
+    template<typename T>
+    T readInt(const std::vector<uint8_t>& buf) {
+        if (!OptionDataTypeTraits<T>::integer_type) {
+            isc_throw(isc::dhcp::InvalidDataType, "specified data type to be returned"
+                      " by readInteger is not supported integer type");
+        }
+
+        assert(buf.size() == OptionDataTypeTraits<T>::len);
+        T value;
+        switch (OptionDataTypeTraits<T>::len) {
+        case 1:
+            value = *(buf.begin());
+            break;
+        case 2:
+            value = isc::util::readUint16(&(*buf.begin()));
+            break;
+        case 4:
+            value = isc::util::readUint32(&(*buf.begin()));
+            break;
+        default:
+            // This should not happen because we made checks on data types
+            // but it does not hurt to keep throw statement here.
+            isc_throw(isc::dhcp::InvalidDataType,
+                      "invalid size of the data type to be read as integer.");
+        }
+        return (value);
+    }
+
     /// @brief Write integer or unsiged integer value into a buffer.
     /// @brief Write integer or unsiged integer value into a buffer.
     ///
     ///
     /// @param value an integer value to be written into a buffer.
     /// @param value an integer value to be written into a buffer.
@@ -232,6 +281,13 @@ public:
         }
         }
     }
     }
 
 
+    /// @brief Read string value from a buffer.
+    ///
+    /// @param buf input buffer.
+    /// @param [out] value string value being read.
+    void readString(const std::vector<uint8_t>& buf,
+                    std::string& value);
+
     /// @brief Write utf8-encoded string into a buffer.
     /// @brief Write utf8-encoded string into a buffer.
     ///
     ///
     /// @param value string value to be written into a buffer.
     /// @param value string value to be written into a buffer.