Leaked source code of windows server 2003
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.

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