packet_storage.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef PACKET_STORAGE_H
  15. #define PACKET_STORAGE_H
  16. #include <boost/noncopyable.hpp>
  17. #include <boost/shared_ptr.hpp>
  18. #include <list>
  19. #include <stdint.h>
  20. namespace isc {
  21. namespace perfdhcp {
  22. /// \brief Represents a list of packets with a sequential and random access to
  23. /// list elements.
  24. ///
  25. /// The main purpose of this class is to support sending Renew and Release
  26. /// messages from perfdhcp. The Renew and Release messages are sent for existing
  27. /// leases only. Therefore, the typical use case for this class is that it holds
  28. /// a list of Rely messages sent by the server in response to Request messages.
  29. /// The Request messages hold addresses and/or IPv6 prefixes acquired so they
  30. /// can be used to identify existing leases. When perfdhcp needs to send Renew
  31. /// or Release message, it will access one of the elements on this list and
  32. /// will create the Renew or Release message based on its content. Once the
  33. /// element (packet) is returned it is also deleted from the list, so as it is
  34. /// not used again. This class provide either sequential access to the packets
  35. /// or random access. The random access algorithm is much slower but at least
  36. /// it allows to simulate more real scenario when the renewing or releasing
  37. /// client is random.
  38. ///
  39. /// \tparam Pkt4 or Pkt6 class, which represents DHCPv4 or DHCPv6 message
  40. /// respectively.
  41. ///
  42. /// \note Although the class is intended to hold Pkt4 and Pkt6 objects, the
  43. /// current implementation is generic enough to holds any object wrapped in the
  44. /// boost::shared_ptr.
  45. template<typename T>
  46. class PacketStorage : public boost::noncopyable {
  47. public:
  48. /// A type which represents the pointer to a packet.
  49. typedef boost::shared_ptr<T> PacketPtr;
  50. private:
  51. /// An internal container actually holding packets.
  52. typedef typename std::list<PacketPtr> PacketContainer;
  53. /// An iterator to the element in the internal container.
  54. typedef typename PacketContainer::iterator PacketContainerIterator;
  55. public:
  56. /// \brief Constructor.
  57. PacketStorage() { }
  58. /// \brief Appends the new packet object to the collection.
  59. ///
  60. /// \param packet A pointer to an object representing a packet.
  61. void append(const PacketPtr& packet) {
  62. storage_.push_back(packet);
  63. if (storage_.size() == 1) {
  64. current_pointer_ = storage_.begin();
  65. }
  66. }
  67. /// \brief Removes all packets from the storage.
  68. void clear() {
  69. storage_.clear();
  70. }
  71. /// \brief Checks if the storage has no packets.
  72. ///
  73. /// \return true if storage is empty, false otherwise.
  74. bool empty() const {
  75. return (storage_.empty());
  76. }
  77. /// \brief Returns next packet from the storage..
  78. ///
  79. /// This function returns packets sequentially (in the same order
  80. /// in which they have been appended). The returned packet is
  81. /// instantly removed from the storage.
  82. ///
  83. /// \return next packet from the storage.
  84. PacketPtr getNext() {
  85. if (storage_.empty()) {
  86. return (PacketPtr());
  87. } else if (current_pointer_ == storage_.end()) {
  88. current_pointer_ = storage_.begin();
  89. }
  90. PacketPtr packet = *current_pointer_;
  91. current_pointer_ = storage_.erase(current_pointer_);
  92. return (packet);
  93. }
  94. /// \brief Returns random packet from the storage.
  95. ///
  96. /// This function picks random packet from the storage and returns
  97. /// it. It is way slower than the @c getNext function because it has to
  98. /// iterate over all existing entries from the beginning of the storage
  99. /// to the random packet's position. Therefore, care should be taken
  100. /// when using this function to access elements when storage is large.
  101. ///
  102. /// \return random packet from the storage.
  103. PacketPtr getRandom() {
  104. if (empty()) {
  105. return (PacketPtr());
  106. }
  107. current_pointer_ = storage_.begin();
  108. if (size() > 1) {
  109. std::advance(current_pointer_, rand() % (size() - 1));
  110. }
  111. PacketPtr packet = *current_pointer_;
  112. current_pointer_ = storage_.erase(current_pointer_);
  113. return (packet);
  114. }
  115. /// \brief Returns number of packets in the storage.
  116. ///
  117. /// \return number of packets in the storage.
  118. uint32_t size() const {
  119. return (storage_.size());
  120. }
  121. private:
  122. std::list<PacketPtr> storage_; ///< Holds all appended packets.
  123. PacketContainerIterator current_pointer_; ///< Holds the iterator to the
  124. ///< next element returned.
  125. };
  126. } // namespace perfdhcp
  127. } // namespace isc
  128. #endif // PACKET_STORAGE_H