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.

249 lines
5.2 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "radcommon.h"
  11. #include "clientstrie.h"
  12. #include <iomanip>
  13. SubNet::SubNet(uint32_t ipAddress, uint32_t width) throw ()
  14. : address(ipAddress)
  15. {
  16. if (width == 0)
  17. {
  18. subNetMask = 0;
  19. firstUniqueBitMask = 0x80000000;
  20. }
  21. else if (width == 32)
  22. {
  23. subNetMask = 0xffffffff;
  24. firstUniqueBitMask = 0;
  25. }
  26. else
  27. {
  28. subNetMask = 0xffffffff;
  29. subNetMask >>= (32 - width);
  30. subNetMask <<= (32 - width);
  31. firstUniqueBitMask = 0x80000000;
  32. firstUniqueBitMask >>= width;
  33. }
  34. address &= subNetMask;
  35. }
  36. SubNet SubNet::SmallestContainingSubNet(const SubNet& subnet) const throw ()
  37. {
  38. // Find the most significant bit where the addresses differ.
  39. uint32_t width = 0;
  40. for (uint32_t mask = 0x80000000;
  41. (mask != 0) && (subnet.address & mask) == (address & mask);
  42. (mask >>= 1), (++width))
  43. {
  44. }
  45. return SubNet(address, width);
  46. }
  47. ClientNodePtr& ClientNodePtr::operator=(ClientNodePtr& rhs) throw ()
  48. {
  49. if (p != rhs.p)
  50. {
  51. delete p;
  52. p = rhs.p;
  53. rhs.p = 0;
  54. }
  55. return *this;
  56. }
  57. ClientNode::Relationship ClientNode::RelationshipTo(
  58. const ClientNode& node
  59. ) const throw ()
  60. {
  61. if (key.HasMember(node.key))
  62. {
  63. return node.key.HasMember(key) ? self : parent;
  64. }
  65. else if (node.key.HasMember(key))
  66. {
  67. return child;
  68. }
  69. else
  70. {
  71. return brother;
  72. }
  73. }
  74. void ClientNode::SetChild(ClientNodePtr& node) throw ()
  75. {
  76. // assert(node.get() != 0);
  77. WhichBranch(*node) = node;
  78. }
  79. inline ClientNode::ClientNode(
  80. const SubNet& subnet,
  81. IIasClient* client
  82. ) throw ()
  83. : key(subnet), value(client)
  84. {
  85. }
  86. ClientNodePtr ClientNode::CreateInstance(
  87. const SubNet& subnet,
  88. IIasClient* client
  89. ) throw ()
  90. {
  91. return ClientNodePtr(new ClientNode(subnet, client));
  92. }
  93. void ClientNode::Write(
  94. const ClientNodePtr& branch,
  95. std::ostream& output,
  96. size_t startingIndent
  97. )
  98. {
  99. for (size_t i = 0; i < startingIndent; ++i)
  100. {
  101. output.put(' ');
  102. }
  103. if (branch.get() != 0)
  104. {
  105. output << branch->Key()
  106. << ((branch->Value() != 0) ? " <value>\n" : " <null>\n");
  107. Write(branch->zero, output, startingIndent + 2);
  108. Write(branch->one, output, startingIndent + 2);
  109. }
  110. else
  111. {
  112. output << "<null>\n";
  113. }
  114. }
  115. ClientNode::~ClientNode() throw ()
  116. {
  117. }
  118. IIasClient* ClientTrie::Find(uint32_t ipAddress) const throw ()
  119. {
  120. IIasClient* bestMatch = 0;
  121. for (const ClientNode* n = root.get();
  122. n != 0 && n->Key().HasMember(ipAddress);
  123. n = n->WhichChild(ipAddress))
  124. {
  125. if (n->Value() != 0)
  126. {
  127. // As we walk down the tree, we are finding longer and longer matches,
  128. // so the last one we find is the best.
  129. bestMatch = n->Value();
  130. }
  131. }
  132. return bestMatch;
  133. }
  134. void ClientTrie::Insert(const SubNet& subnet, IIasClient* client)
  135. {
  136. Insert(root, ClientNode::CreateInstance(subnet, client));
  137. }
  138. void ClientTrie::Write(std::ostream& output) const
  139. {
  140. ClientNode::Write(root, output);
  141. }
  142. void ClientTrie::Insert(ClientNodePtr& node, ClientNodePtr& newEntry)
  143. {
  144. if (node.get() == 0)
  145. {
  146. // We made it to the end of the branch, so we're a leaf.
  147. node = newEntry;
  148. }
  149. else
  150. {
  151. switch (node->RelationshipTo(*newEntry))
  152. {
  153. case ClientNode::parent:
  154. {
  155. // This is an ancestor of ours, so keep walking.
  156. Insert(node->WhichBranch(*newEntry), newEntry);
  157. break;
  158. }
  159. case ClientNode::child:
  160. {
  161. // This is our child, ...
  162. newEntry->SetChild(node);
  163. // ... so we take its place in the tree.
  164. node = newEntry;
  165. break;
  166. }
  167. case ClientNode::brother:
  168. {
  169. // We found a brother, so our parent is missing.
  170. ClientNodePtr parent(node->CreateParent(*newEntry));
  171. parent->SetChild(node);
  172. parent->SetChild(newEntry);
  173. node = parent;
  174. break;
  175. }
  176. case ClientNode::self:
  177. {
  178. // This is a duplicate entry. We do nothing so that the first entry
  179. // in the UI will take precedence.
  180. break;
  181. }
  182. default:
  183. // assert(false);
  184. break;
  185. }
  186. }
  187. }
  188. std::ostream& operator<<(std::ostream& output, const SubNet& subnet)
  189. {
  190. output << std::hex
  191. << std::setfill('0')
  192. << std::setiosflags(std::ios_base::right)
  193. << std::setw(8)
  194. << subnet.IpAddress()
  195. << ':'
  196. << std::setw(8)
  197. << subnet.SubNetMask();
  198. return output;
  199. }
  200. std::ostream& operator<<(std::ostream& output, const ClientTrie& tree)
  201. {
  202. tree.Write(output);
  203. return output;
  204. }