Commit 3c4c599d authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

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

parent 0b7cf4ce
......@@ -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_]),
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment