Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
7.3 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Declares
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #ifndef CLIENTSTRIE_H
  11. #define CLIENTSTRIE_H
  12. #pragma once
  13. #include "atlbase.h"
  14. #include "iasradius.h"
  15. #include <iostream>
  16. typedef ULONG32 uint32_t;
  17. // Represents an IPv4 subnet. Note that we can model an individual IP host as a
  18. // subnet with a mask 32-bits wide.
  19. class SubNet
  20. {
  21. public:
  22. SubNet() throw ();
  23. // 'width' is the width in bits of the subnet mask. If 'width' is greater
  24. // than 32, it is treated as if it were exactly 32.
  25. explicit SubNet(uint32_t ipAddress, uint32_t width = 32) throw ();
  26. // Use compiler generated versions.
  27. // ~SubNet() throw ();
  28. // SubNet(const SubNet&);
  29. // SubNet& operator=(const SubNet&);
  30. uint32_t IpAddress() const throw ();
  31. uint32_t SubNetMask() const throw ();
  32. // Returns the first bit after the subnet mask.
  33. uint32_t FirstUniqueBit(uint32_t ipAddress) const throw ();
  34. uint32_t FirstUniqueBit(const SubNet& subnet) const throw ();
  35. // Returns true if the argument is a member of the subnet.
  36. bool HasMember(uint32_t ipAddress) const throw ();
  37. bool HasMember(const SubNet& subnet) const throw ();
  38. // Returns the smallest subnet that contains both 'this' and 'subnet'.
  39. SubNet SmallestContainingSubNet(const SubNet& subnet) const throw ();
  40. private:
  41. uint32_t address;
  42. uint32_t subNetMask;
  43. uint32_t firstUniqueBitMask;
  44. };
  45. class ClientNode;
  46. // This class is an auto_ptr for ClientNode. I had to implement this because
  47. // the std::auto_ptr used in Whistler doesn't comply to the standard. Once we
  48. // have a compliant std::auto_ptr, this class can be replaced with a typedef.
  49. class ClientNodePtr
  50. {
  51. public:
  52. ClientNodePtr(ClientNode* node = 0) throw ();
  53. ~ClientNodePtr() throw ();
  54. ClientNodePtr(ClientNodePtr& original) throw ();
  55. ClientNodePtr& operator=(ClientNodePtr& rhs) throw ();
  56. ClientNode& operator*() const throw ();
  57. ClientNode* operator->() const throw ();
  58. ClientNode* get() const throw ();
  59. void reset(ClientNode* node = 0) throw ();
  60. private:
  61. ClientNode* p;
  62. };
  63. // A node in the binary trie used to store clients.
  64. class ClientNode
  65. {
  66. public:
  67. // Used to express the relationship between two nodes.
  68. enum Relationship
  69. {
  70. child,
  71. parent,
  72. brother,
  73. self
  74. };
  75. const SubNet& Key() const throw ();
  76. IIasClient* Value() const throw ();
  77. // Returns the child node (if any) that contains 'ipAddress' assuming that
  78. // this node contains 'ipAddress'.
  79. const ClientNode* WhichChild(uint32_t ipAddress) const throw ();
  80. // Returns the branch from this node to follow when looking for 'node'.
  81. ClientNodePtr& WhichBranch(const ClientNode& node) throw ();
  82. // Returns the relationship between 'this' and 'node'.
  83. Relationship RelationshipTo(const ClientNode& node) const throw ();
  84. // Sets 'node' as a child of 'this'. This function takes ownership of 'node'
  85. // and silently overwrites any existing child on the branch.
  86. void SetChild(ClientNodePtr& node) throw ();
  87. // Create a new ClientNode.
  88. static ClientNodePtr CreateInstance(
  89. const SubNet& subnet,
  90. IIasClient* client = 0
  91. ) throw ();
  92. // Create new ClientNode that is a parent to both 'this' and 'node'.
  93. ClientNodePtr CreateParent(const ClientNode& node) const;
  94. // Dump a branch of the trie to an ostream. Useful for debugging.
  95. static void Write(
  96. const ClientNodePtr& branch,
  97. std::ostream& output,
  98. size_t startingIndent = 0
  99. );
  100. private:
  101. // The constructor and destructor are private since other classes should
  102. // only use ClientNodePtr.
  103. ClientNode(const SubNet& subnet, IIasClient* client) throw ();
  104. ~ClientNode() throw ();
  105. friend class ClientNodePtr;
  106. SubNet key;
  107. // 'value' is mutable because it can change without affecting the structure
  108. // of the trie.
  109. mutable CComPtr<IIasClient> value;
  110. ClientNodePtr zero;
  111. ClientNodePtr one;
  112. // Not implemented.
  113. ClientNode(const ClientNode&);
  114. ClientNode& operator=(const ClientNode&);
  115. };
  116. // A binary trie storing ClientNodes and supporting efficient longest-prefix
  117. // matching.
  118. class ClientTrie
  119. {
  120. public:
  121. ClientTrie() throw ();
  122. // Use compiler-generated version.
  123. // ~ClientTrie() throw ();
  124. // Clear all entries from the trie.
  125. void Clear() throw ();
  126. // Find the client (if any) with the longest prefix match. The returned
  127. // pointer has not been AddRef'ed.
  128. IIasClient* Find(uint32_t ipAddress) const throw ();
  129. // Insert a new client into the trie.
  130. void Insert(const SubNet& subnet, IIasClient* client);
  131. // Dump the trie to an ostream. Useful for debugging.
  132. void Write(std::ostream& output) const;
  133. private:
  134. void Insert(ClientNodePtr& node, ClientNodePtr& newEntry);
  135. ClientNodePtr root;
  136. // Not implemented
  137. ClientTrie(const ClientTrie&);
  138. ClientTrie& operator=(const ClientTrie&);
  139. };
  140. // Useful debugging functions.
  141. std::ostream& operator<<(std::ostream& output, const SubNet& subnet);
  142. std::ostream& operator<<(std::ostream& output, const ClientTrie& tree);
  143. inline SubNet::SubNet() throw ()
  144. : address(0), subNetMask(0), firstUniqueBitMask(0)
  145. {
  146. }
  147. inline uint32_t SubNet::IpAddress() const throw ()
  148. {
  149. return address;
  150. }
  151. inline uint32_t SubNet::SubNetMask() const throw ()
  152. {
  153. return subNetMask;
  154. }
  155. inline uint32_t SubNet::FirstUniqueBit(uint32_t ipAddress) const throw ()
  156. {
  157. return ipAddress & firstUniqueBitMask;
  158. }
  159. inline uint32_t SubNet::FirstUniqueBit(const SubNet& subnet) const throw ()
  160. {
  161. return FirstUniqueBit(subnet.address);
  162. }
  163. inline bool SubNet::HasMember(uint32_t ipAddress) const throw ()
  164. {
  165. return (ipAddress & subNetMask) == address;
  166. }
  167. inline bool SubNet::HasMember(const SubNet& subnet) const throw ()
  168. {
  169. return HasMember(subnet.address);
  170. }
  171. inline ClientNodePtr::ClientNodePtr(ClientNode* node) throw ()
  172. : p(node)
  173. {
  174. }
  175. inline ClientNodePtr::~ClientNodePtr() throw ()
  176. {
  177. delete p;
  178. }
  179. inline ClientNodePtr::ClientNodePtr(ClientNodePtr& original) throw ()
  180. : p(original.p)
  181. {
  182. original.p = 0;
  183. }
  184. inline ClientNode& ClientNodePtr::operator*() const throw ()
  185. {
  186. return *p;
  187. }
  188. inline ClientNode* ClientNodePtr::operator->() const throw ()
  189. {
  190. return p;
  191. }
  192. inline ClientNode* ClientNodePtr::get() const throw ()
  193. {
  194. return p;
  195. }
  196. inline void ClientNodePtr::reset(ClientNode* node) throw ()
  197. {
  198. if (node != p)
  199. {
  200. delete p;
  201. p = node;
  202. }
  203. }
  204. inline const SubNet& ClientNode::Key() const throw ()
  205. {
  206. return key;
  207. }
  208. inline IIasClient* ClientNode::Value() const throw ()
  209. {
  210. return value;
  211. }
  212. inline const ClientNode* ClientNode::WhichChild(
  213. uint32_t ipAddress
  214. ) const throw ()
  215. {
  216. return (key.FirstUniqueBit(ipAddress) ? one : zero).get();
  217. }
  218. inline ClientNodePtr& ClientNode::WhichBranch(const ClientNode& node) throw ()
  219. {
  220. return key.FirstUniqueBit(node.key) ? one : zero;
  221. }
  222. inline ClientNodePtr ClientNode::CreateParent(const ClientNode& node) const
  223. {
  224. return CreateInstance(key.SmallestContainingSubNet(node.key), 0);
  225. }
  226. inline ClientTrie::ClientTrie() throw ()
  227. {
  228. }
  229. inline void ClientTrie::Clear() throw ()
  230. {
  231. root.reset();
  232. }
  233. #endif // CLIENTSTRIE_H