From: Marcin Siodelski Date: Thu, 3 Jul 2014 19:50:13 +0000 (+0200) Subject: [2893] Extend the Iface object to hold the socket read buffer. X-Git-Tag: trac3482_base~81^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3c4c599d3c35c2dd81b5ff3ce5e9c7e24aa2371b;p=thirdparty%2Fkea.git [2893] Extend the Iface object to hold the socket read buffer. --- diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc index d2aa286f7d..7d094feaa7 100644 --- a/src/lib/dhcp/iface_mgr.cc +++ b/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(&read_buffer_[0])); +} + IfaceMgr::IfaceMgr() :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))), control_buf_(new char[control_buf_len_]), diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h index b2b86256ce..d79d2c322d 100644 --- a/src/lib/dhcp/iface_mgr.h +++ b/src/lib/dhcp/iface_mgr.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc index 4e6ca6da31..45c6ecf829 100644 --- a/src/lib/dhcp/tests/iface_mgr_unittest.cc +++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -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