Browse Source

[2893] Extend the Iface object to hold the socket read buffer.

Marcin Siodelski 10 years ago
parent
commit
3c4c599d3c
3 changed files with 85 additions and 2 deletions
  1. 9 1
      src/lib/dhcp/iface_mgr.cc
  2. 42 1
      src/lib/dhcp/iface_mgr.h
  3. 34 0
      src/lib/dhcp/tests/iface_mgr_unittest.cc

+ 9 - 1
src/lib/dhcp/iface_mgr.cc

@@ -55,7 +55,7 @@ Iface::Iface(const std::string& name, int ifindex)
     :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
      flag_loopback_(false), flag_up_(false), flag_running_(false),
      flag_multicast_(false), flag_broadcast_(false), flags_(0),
-     inactive4_(false), inactive6_(false)
+     inactive4_(false), inactive6_(false), read_buffer_()
 {
     memset(mac_, 0, sizeof(mac_));
 }
@@ -167,6 +167,14 @@ bool Iface::delSocket(const uint16_t sockfd) {
     return (false); // socket not found
 }
 
+uint8_t*
+Iface::getReadBufferPtr() {
+    if (read_buffer_.empty()) {
+        return (NULL);
+    }
+    return (static_cast<uint8_t*>(&read_buffer_[0]));
+}
+
 IfaceMgr::IfaceMgr()
     :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
      control_buf_(new char[control_buf_len_]),

+ 42 - 1
src/lib/dhcp/iface_mgr.h

@@ -22,6 +22,7 @@
 #include <dhcp/pkt6.h>
 #include <dhcp/pkt_filter.h>
 #include <dhcp/pkt_filter6.h>
+#include <dhcp/option.h>
 
 #include <boost/function.hpp>
 #include <boost/noncopyable.hpp>
@@ -120,7 +121,6 @@ struct SocketInfo {
 
 };
 
-
 /// @brief Represents a single network interface
 ///
 /// Iface structure represents network interface with all useful
@@ -330,6 +330,40 @@ public:
         return unicasts_;
     }
 
+    /// @brief Returns the pointer to the buffer used for data reading.
+    ///
+    /// The returned pointer is only valid during the lifetime of the
+    /// object which returns it or until the buffer is resized.
+    /// This function is meant to be used with socket API to gather
+    /// data from the socket. In order to process the read data,
+    /// the @c getReadBuffer function should be used.
+    ///
+    /// @return Pointer to the first element of the read buffer or
+    /// NULL if the buffer is empty.
+    uint8_t* getReadBufferPtr();
+
+    /// @brief Returns reference to the buffer used for data reading.
+    ///
+    /// The returned reference is only valid during the lifetime of the
+    /// object which returns it or until the buffer is resized.
+    ///
+    /// @return Reference to the read buffer.
+    const OptionBuffer& getReadBuffer() const {
+        return (read_buffer_);
+    }
+
+    /// @brief Returns the current size of the socket read buffer.
+    size_t getReadBufferSize() const {
+        return (read_buffer_.size());
+    }
+
+    /// @brief Resizes the socket read buffer.
+    ///
+    /// @param new_size New size of the buffer.
+    void resizeReadBuffer(const size_t new_size) {
+        read_buffer_.resize(new_size);
+    }
+
 protected:
     /// Socket used to send data.
     SocketCollection sockets_;
@@ -388,6 +422,13 @@ public:
     /// Indicates that IPv6 sockets should (true) or should not (false)
     /// be opened on this interface.
     bool inactive6_;
+
+    /// @brief Buffer holding the data read from the socket.
+    ///
+    /// This buffer may be pre-allocated when the socket on the interface
+    /// is being opened. The functions which read the data from the socket
+    /// may use this buffer as a storage for the data being read.
+    OptionBuffer read_buffer_;
 };
 
 /// @brief This type describes the callback function invoked when error occurs

+ 34 - 0
src/lib/dhcp/tests/iface_mgr_unittest.cc

@@ -17,6 +17,7 @@
 #include <asiolink/io_address.h>
 #include <dhcp/dhcp4.h>
 #include <dhcp/iface_mgr.h>
+#include <dhcp/option.h>
 #include <dhcp/pkt6.h>
 #include <dhcp/pkt_filter.h>
 #include <dhcp/tests/iface_mgr_test_config.h>
@@ -56,6 +57,39 @@ const uint16_t PORT2 = 10548;   // V4 socket
 // tolerance to 0.01s.
 const uint32_t TIMEOUT_TOLERANCE = 10000;
 
+/// This test verifies that the socket read buffer can be used to
+/// receive the data and that the data can be read from it.
+TEST(IfaceTest, readBuffer) {
+    // Create fake interface object.
+    Iface iface("em0", 0);
+    // The size of read buffer should initially be 0 and the returned
+    // pointer should be NULL.
+    ASSERT_EQ(0, iface.getReadBufferSize());
+    EXPECT_EQ(NULL, iface.getReadBufferPtr());
+
+    // Let's resize the buffer.
+    iface.resizeReadBuffer(256);
+    // Check that the buffer has expected size.
+    ASSERT_EQ(256, iface.getReadBufferSize());
+    // The returned pointer should now be non-NULL.
+    uint8_t* buf_ptr = iface.getReadBufferPtr();
+    ASSERT_FALSE(buf_ptr == NULL);
+
+    // Use the pointer to set some data.
+    for (int i = 0; i < iface.getReadBufferSize(); ++i) {
+        buf_ptr[i] = i;
+    }
+
+    // Validate the data.
+    const OptionBuffer& buf = iface.getReadBuffer();
+    ASSERT_EQ(256, buf.size());
+    for (int i = 0; i < buf.size(); ++i) {
+        // Use assert so as it fails on the first failure, no need
+        // to continue further checks.
+        ASSERT_EQ(i, buf[i]);
+    }
+}
+
 /// Mock object implementing PktFilter class.  It is used by
 /// IfaceMgrTest::setPacketFilter to verify that IfaceMgr::setPacketFilter
 /// sets this object as a handler for opening sockets. This dummy