Browse Source

[2325] Pkt6::getOptions() implemented.

Tomek Mrugalski 12 years ago
parent
commit
00eee13bde
3 changed files with 52 additions and 14 deletions
  1. 16 10
      src/lib/dhcp/pkt6.cc
  2. 11 4
      src/lib/dhcp/pkt6.h
  3. 25 0
      src/lib/dhcp/tests/pkt6_unittest.cc

+ 16 - 10
src/lib/dhcp/pkt6.cc

@@ -81,13 +81,6 @@ Pkt6::pack() {
 
 
 bool
 bool
 Pkt6::packUDP() {
 Pkt6::packUDP() {
-
-    // TODO: Once OutputBuffer is used here, some thing like this
-    // will be used. Yikes! That's ugly.
-    // bufferOut_.writeData(ciaddr_.getAddress().to_v6().to_bytes().data(), 16);
-    // It is better to implement a method in IOAddress that extracts
-    // vector<uint8_t>
-
     try {
     try {
         // DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
         // DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
         bufferOut_.writeUint8(msg_type_);
         bufferOut_.writeUint8(msg_type_);
@@ -172,17 +165,30 @@ Pkt6::toText() {
     return tmp.str();
     return tmp.str();
 }
 }
 
 
-boost::shared_ptr<isc::dhcp::Option>
+OptionPtr
 Pkt6::getOption(uint16_t opt_type) {
 Pkt6::getOption(uint16_t opt_type) {
     isc::dhcp::Option::OptionCollection::const_iterator x = options_.find(opt_type);
     isc::dhcp::Option::OptionCollection::const_iterator x = options_.find(opt_type);
     if (x!=options_.end()) {
     if (x!=options_.end()) {
         return (*x).second;
         return (*x).second;
     }
     }
-    return boost::shared_ptr<isc::dhcp::Option>(); // NULL
+    return OptionPtr(); // NULL
+}
+
+isc::dhcp::Option::OptionCollection
+Pkt6::getOptions(uint16_t opt_type) {
+    isc::dhcp::Option::OptionCollection found;
+
+    for (Option::OptionCollection::const_iterator x = options_.begin();
+         x != options_.end(); ++x) {
+        if (x->first == opt_type) {
+            found.insert(make_pair(opt_type, x->second));
+        }
+    }
+    return (found);
 }
 }
 
 
 void
 void
-Pkt6::addOption(boost::shared_ptr<Option> opt) {
+Pkt6::addOption(const OptionPtr& opt) {
     options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
     options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
 }
 }
 
 

+ 11 - 4
src/lib/dhcp/pkt6.h

@@ -147,19 +147,28 @@ public:
     /// Adds an option to this packet.
     /// Adds an option to this packet.
     ///
     ///
     /// @param opt option to be added.
     /// @param opt option to be added.
-    void addOption(OptionPtr opt);
+    void addOption(const OptionPtr& opt);
 
 
     /// @brief Returns the first option of specified type.
     /// @brief Returns the first option of specified type.
     ///
     ///
     /// Returns the first option of specified type. Note that in DHCPv6 several
     /// Returns the first option of specified type. Note that in DHCPv6 several
     /// instances of the same option are allowed (and frequently used).
     /// instances of the same option are allowed (and frequently used).
-    /// See getOptions().
+    /// Also see \ref getOptions().
     ///
     ///
     /// @param type option type we are looking for
     /// @param type option type we are looking for
     ///
     ///
     /// @return pointer to found option (or NULL)
     /// @return pointer to found option (or NULL)
     OptionPtr getOption(uint16_t type);
     OptionPtr getOption(uint16_t type);
 
 
+    /// @brief Returns all instances of specified type.
+    ///
+    /// Returns all instances of options of the specified type. DHCPv6 protocol
+    /// allows (and uses frequently) multiple instances.
+    ///
+    /// @param type option type we are looking for
+    /// @return instance of option collection with requested options
+    isc::dhcp::Option::OptionCollection getOptions(uint16_t type);
+
     /// Attempts to delete first suboption of requested type
     /// Attempts to delete first suboption of requested type
     ///
     ///
     /// @param type Type of option to be deleted.
     /// @param type Type of option to be deleted.
@@ -246,8 +255,6 @@ public:
     /// @return interface name
     /// @return interface name
     void setIface(const std::string& iface ) { iface_ = iface; };
     void setIface(const std::string& iface ) { iface_ = iface; };
 
 
-    /// TODO Need to implement getOptions() as well
-
     /// collection of options present in this message
     /// collection of options present in this message
     ///
     ///
     /// @warning This protected member is accessed by derived
     /// @warning This protected member is accessed by derived

+ 25 - 0
src/lib/dhcp/tests/pkt6_unittest.cc

@@ -170,6 +170,8 @@ TEST_F(Pkt6Test, packUnpack) {
     delete clone;
     delete clone;
 }
 }
 
 
+// This test verifies that options can be added (addOption()), retrieved
+// (getOption(), getOptions()) and deleted (delOption()).
 TEST_F(Pkt6Test, addGetDelOptions) {
 TEST_F(Pkt6Test, addGetDelOptions) {
     Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, random() );
     Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, random() );
 
 
@@ -190,6 +192,25 @@ TEST_F(Pkt6Test, addGetDelOptions) {
     // now there are 2 options of type 2
     // now there are 2 options of type 2
     parent->addOption(opt3);
     parent->addOption(opt3);
 
 
+    Option::OptionCollection options = parent->getOptions(2);
+    EXPECT_EQ(2, options.size()); // there should be 2 instances
+
+    // both options must be of type 2 and there must not be
+    // any other type returned
+    for (Option::OptionCollection::const_iterator x= options.begin();
+         x != options.end(); ++x) {
+        EXPECT_EQ(2, x->second->getType());
+    }
+
+    // Try to get a single option. Normally for singular options
+    // it is better to use getOption(), but getOptions() must work
+    // as well
+    options = parent->getOptions(1);
+    ASSERT_EQ(1, options.size());
+
+    EXPECT_EQ(1, (*options.begin()).second->getType());
+    EXPECT_EQ(opt1, options.begin()->second);
+
     // let's delete one of them
     // let's delete one of them
     EXPECT_EQ(true, parent->delOption(2));
     EXPECT_EQ(true, parent->delOption(2));
 
 
@@ -205,6 +226,10 @@ TEST_F(Pkt6Test, addGetDelOptions) {
     // let's try to delete - should fail
     // let's try to delete - should fail
     EXPECT_TRUE(false ==  parent->delOption(2));
     EXPECT_TRUE(false ==  parent->delOption(2));
 
 
+    // Finally try to get a non-existent option
+    options = parent->getOptions(1234);
+    EXPECT_EQ(0, options.size());
+
     delete parent;
     delete parent;
 }
 }