libDwmRDAP-0.1.4
DwmRDAPIpv4Routes.hh
Go to the documentation of this file.
1 //===========================================================================
2 // @(#) $DwmPath: dwm/libDwmRDAP/tags/libDwmRDAP-0.1.4/include/DwmRDAPIpv4Routes.hh 8963 $
3 // @(#) $Id: DwmRDAPIpv4Routes.hh 8963 2017-04-03 04:58:48Z dwm $
4 //===========================================================================
5 // Copyright (c) Daniel W. McRobb 1999-2005, 2016, 2017
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // 1. Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // 2. Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // 3. The names of the authors and copyright holders may not be used to
18 // endorse or promote products derived from this software without
19 // specific prior written permission.
20 //
21 // IN NO EVENT SHALL DANIEL W. MCROBB BE LIABLE TO ANY PARTY FOR
22 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
23 // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE,
24 // EVEN IF DANIEL W. MCROBB HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
25 // DAMAGE.
26 //
27 // THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND
28 // DANIEL W. MCROBB HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
29 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. DANIEL W. MCROBB MAKES NO
30 // REPRESENTATIONS AND EXTENDS NO WARRANTIES OF ANY KIND, EITHER
31 // IMPLIED OR EXPRESS, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,
33 // OR THAT THE USE OF THIS SOFTWARE WILL NOT INFRINGE ANY PATENT,
34 // TRADEMARK OR OTHER RIGHTS.
35 //===========================================================================
36 
37 //---------------------------------------------------------------------------
40 //---------------------------------------------------------------------------
41 
42 #ifndef _DWMRDAPIPV4ROUTES_HH_
43 #define _DWMRDAPIPV4ROUTES_HH_
44 
45 extern "C" {
46  #include <assert.h>
47 }
48 
49 #include <algorithm>
50 #include <unordered_map>
51 #include <shared_mutex>
52 #include <vector>
53 
54 #include "DwmPortability.hh"
55 #include "DwmIO.hh"
56 #include "DwmGZIO.hh"
57 #include "DwmBZ2IO.hh"
58 #include "DwmIpv4Prefix.hh"
59 #include "DwmOperators.hh"
60 #include "DwmReadable.hh"
61 #include "DwmWritable.hh"
62 #include "DwmGZReadable.hh"
63 #include "DwmGZWritable.hh"
64 #include "DwmBZ2Readable.hh"
65 #include "DwmBZ2Writable.hh"
66 
67 namespace Dwm {
68 
69  namespace RDAP {
70 
71  //------------------------------------------------------------------------
81  //------------------------------------------------------------------------
82  template <typename _valueT>
83  class Ipv4Routes
84  : public Readable, public Writable,
85  public GZReadable, public GZWritable,
86  public BZ2Readable, public BZ2Writable
87  {
88  public:
89  typedef std::map<Ipv4Address, _valueT> _RepSubType;
90  typedef typename _RepSubType::const_iterator const_iterator;
91 
92  //----------------------------------------------------------------------
94  //----------------------------------------------------------------------
96  : _maps(33)
97  {
98  }
99 
100  //----------------------------------------------------------------------
102  //----------------------------------------------------------------------
103  void Clear()
104  {
105  std::shared_lock<std::shared_mutex> lock(_mtx);
106  for (uint8_t i = 0; i < 33; ++i)
107  _maps[i].clear();
108  return;
109  }
110 
111  //----------------------------------------------------------------------
113  //----------------------------------------------------------------------
114  bool Empty() const
115  {
116  bool rc = true;
117  std::shared_lock<std::shared_mutex> lock(_mtx);
118  for (uint8_t i = 0; i < 33; ++i) {
119  if (! _maps[i].empty()) {
120  rc = false;
121  break;
122  }
123  }
124  return(rc);
125  }
126 
127  //----------------------------------------------------------------------
130  //----------------------------------------------------------------------
131  bool Add(const Ipv4Prefix & prefix, const _valueT & value)
132  {
133  bool rc = false;
134 
135  std::shared_lock<std::shared_mutex> lock(_mtx);
136  typename _RepSubType::iterator iter =
137  _maps[prefix.MaskLength()].find(prefix.Network());
138  if (iter == _maps[prefix.MaskLength()].end()) {
139  _maps[prefix.MaskLength()][prefix.Network()] = value;
140  rc = true;
141  }
142  return(rc);
143  }
144 
145  //----------------------------------------------------------------------
147  //----------------------------------------------------------------------
148  _valueT & operator [] (const Ipv4Prefix & prefix)
149  {
150  std::shared_lock<std::shared_mutex> lock(_mtx);
151  return(_maps[prefix.MaskLength()][prefix.Network()]);
152  }
153 
154  //----------------------------------------------------------------------
157  //----------------------------------------------------------------------
158  bool Delete(const Ipv4Prefix & prefix)
159  {
160  bool rc = false;
161  std::lock_guard<std::shared_mutex> lock(_mtx);
162  typename _RepSubType::iterator iter =
163  _maps[prefix.MaskLength()].find(prefix.Network());
164  if (iter != _maps[prefix.MaskLength()].end()) {
165  _maps[prefix.MaskLength()].erase(iter);
166  rc = true;
167  }
168  return(rc);
169  }
170 
171  //----------------------------------------------------------------------
175  //----------------------------------------------------------------------
176  bool Find(const Ipv4Prefix & prefix, _valueT & match) const
177  {
178  bool rc = false;
179  std::shared_lock<std::shared_mutex> lock(_mtx);
180  if (! _maps[prefix.MaskLength()].empty()) {
181  typename _RepSubType::const_iterator iter =
182  _maps[prefix.MaskLength()].find(prefix.Network());
183  if (iter != _maps[prefix.MaskLength()].end()) {
184  match = iter->second;
185  rc = true;
186  }
187  }
188  return(rc);
189  }
190 
191  //----------------------------------------------------------------------
195  //----------------------------------------------------------------------
196  bool FindLongest(const Ipv4Address & ipAddr,
197  std::pair<Ipv4Prefix,_valueT> & match) const
198  {
199  bool rc = false;
200 
201  Ipv4Prefix lp(ipAddr, 32);
202 
203  typename _RepSubType::const_iterator iter;
204  for (int8_t i = 32; i >= 0; --i) {
205  std::shared_lock<std::shared_mutex> lock(_mtx);
206  if (_maps[i].empty())
207  continue;
208  lp.MaskLength(i);
209  iter = _maps[i].find(lp.Network());
210  if (iter != _maps[i].end()) {
211  match.first = lp;
212  match.second = iter->second;
213  rc = true;
214  break;
215  }
216  }
217  return(rc);
218  }
219 
220  //----------------------------------------------------------------------
227  //----------------------------------------------------------------------
228  bool
229  FindLongest(const Ipv4Address & ipAddr,
230  std::pair<Ipv4Prefix, const _valueT *> & match) const
231  {
232  bool rc = false;
233  Ipv4Prefix lp(ipAddr, 32);
234  typename _RepSubType::const_iterator iter;
235  for (int8_t i = 32; i >= 0; --i) {
236  std::shared_lock<std::shared_mutex> lock(_mtx);
237  if (_maps[i].empty())
238  continue;
239  lp.MaskLength(i);
240  iter = _maps[i].find(lp.Network());
241  if (iter != _maps[i].end()) {
242  match.first = lp;
243  match.second = &(iter->second);
244  rc = true;
245  break;
246  }
247  }
248  return(rc);
249  }
250 
251  //----------------------------------------------------------------------
255  //----------------------------------------------------------------------
256  bool Find(const Ipv4Address & ipAddr,
257  std::vector<std::pair<Ipv4Prefix,_valueT> > & matches) const
258  {
259  if (! matches.empty())
260  matches.clear();
261 
262  typename _RepSubType::const_iterator iter;
263 
264  for (int8_t i = 32; i >= 0; --i) {
265  std::shared_lock<std::shared_mutex> lock(_mtx);
266  if (_maps[i].empty())
267  continue;
268  Ipv4Prefix prefix(ipAddr, i);
269  iter = _maps[i].find(prefix.Network());
270  if (iter != _maps[i].end()) {
271  std::pair<Ipv4Prefix,_valueT> match(prefix, iter->second);
272  matches.push_back(match);
273  }
274  }
275  return(! matches.empty());
276  }
277 
278  //----------------------------------------------------------------------
282  //----------------------------------------------------------------------
283  bool operator == (const Ipv4Routes<_valueT> & r) const
284  {
285  for (int8_t i = 32; i >= 0; --i) {
286  std::shared_lock<std::shared_mutex> lock(_mtx);
287  if (_maps[i] != r._maps[i])
288  return(false);
289  }
290  return(true);
291  }
292 
293  //----------------------------------------------------------------------
297  //----------------------------------------------------------------------
298  bool operator != (const Ipv4Routes<_valueT> & r) const
299  {
300  return(! (*this == r));
301  }
302 
303  //----------------------------------------------------------------------
305  //----------------------------------------------------------------------
306  uint32_t Size() const
307  {
308  uint32_t rc = 0;
309  for (uint8_t i = 0; i < 33; ++i) {
310  std::shared_lock<std::shared_mutex> lock(_mtx);
311  rc += _maps[i].size();
312  }
313  return(rc);
314  }
315 
316  //----------------------------------------------------------------------
318  //----------------------------------------------------------------------
319  void HashSizes(std::vector<std::pair<uint8_t, uint32_t> > & sizes) const
320  {
321  if (! sizes.empty())
322  sizes.clear();
323  for (uint8_t i = 0; i < 33; ++i) {
324  std::shared_lock<std::shared_mutex> lock(_mtx);
325  if (! _maps[i].empty()) {
326  sizes.push_back(std::pair<uint8_t,uint32_t>(i,_maps[i].size()));
327  }
328  }
329  return;
330  }
331 
332  //----------------------------------------------------------------------
334  //----------------------------------------------------------------------
335  uint32_t StreamedLength() const
336  {
337  std::shared_lock<std::shared_mutex> lock(_mtx);
338  return(IO::StreamedLength(_maps));
339  }
340 
341  //----------------------------------------------------------------------
343  //----------------------------------------------------------------------
344  std::istream & Read(std::istream & is)
345  {
346  std::lock_guard<std::shared_mutex> lock(_mtx);
347  return(IO::Read(is, _maps));
348  }
349 
350  //----------------------------------------------------------------------
352  //----------------------------------------------------------------------
353  std::ostream & Write(std::ostream & os) const
354  {
355  std::shared_lock<std::shared_mutex> lock(_mtx);
356  return(IO::Write(os, _maps));
357  }
358 
359  //----------------------------------------------------------------------
362  //----------------------------------------------------------------------
363  size_t Read(FILE *f)
364  {
365  std::lock_guard<std::shared_mutex> lock(_mtx);
366  return(IO::Read(f, _maps));
367  }
368 
369  //----------------------------------------------------------------------
372  //----------------------------------------------------------------------
373  size_t Write(FILE *f) const
374  {
375  std::shared_lock<std::shared_mutex> lock(_mtx);
376  return(IO::Write(f, _maps));
377  }
378 
379  //----------------------------------------------------------------------
382  //----------------------------------------------------------------------
383  ssize_t Read(int fd)
384  {
385  std::lock_guard<std::shared_mutex> lock(_mtx);
386  return(IO::Read(fd, _maps));
387  }
388 
389  //----------------------------------------------------------------------
392  //----------------------------------------------------------------------
393  ssize_t Write(int fd) const
394  {
395  std::shared_lock<std::shared_mutex> lock(_mtx);
396  return(IO::Write(fd, _maps));
397  }
398 
399  //----------------------------------------------------------------------
402  //----------------------------------------------------------------------
403  int Read(gzFile gzf)
404  {
405  std::lock_guard<std::shared_mutex> lock(_mtx);
406  return(GZIO::Read(gzf, _maps));
407  }
408 
409  //----------------------------------------------------------------------
412  //----------------------------------------------------------------------
413  int Write(gzFile gzf) const
414  {
415  std::shared_lock<std::shared_mutex> lock(_mtx);
416  return(GZIO::Write(gzf, _maps));
417  }
418 
419  //----------------------------------------------------------------------
422  //----------------------------------------------------------------------
423  int BZRead(BZFILE *bzf)
424  {
425  std::lock_guard<std::shared_mutex> lock(_mtx);
426  return(BZ2IO::BZRead(bzf, _maps));
427  }
428 
429  //----------------------------------------------------------------------
432  //----------------------------------------------------------------------
433  int BZWrite(BZFILE *bzf) const
434  {
435  std::shared_lock<std::shared_mutex> lock(_mtx);
436  return(BZ2IO::BZWrite(bzf, _maps));
437  }
438 
439  void SortByKey(std::vector<std::pair<Ipv4Prefix,_valueT>> & target,
440  bool ascending = true) const
441  {
442  if (! target.empty())
443  target.clear();
444  std::shared_lock<std::shared_mutex> lock(_mtx);
445  if (! this->_maps.empty()) {
446  target.resize(this->Size());
447  typename std::vector<_RepSubType>::const_iterator iter =
448  this->_maps.begin();
449  uint32_t pfx = 0;
450  for (uint8_t hashNum = 0; hashNum < 33; ++hashNum) {
451  if (! this->_maps[hashNum].empty()) {
452  typename _RepSubType::const_iterator hiter =
453  this->_maps[hashNum].begin();
454  for ( ; hiter != iter->end(); ++hiter) {
455  target[pfx].first = Ipv4Prefix(hiter->first, hashNum);
456  target[pfx].second = hiter->second;
457  ++pfx;
458  }
459  }
460  }
461  if (! target.empty()) {
462  if (ascending) {
463  std::sort(target.begin(), target.end(), KeyLess());
464  }
465  else {
466  std::sort(target.begin(), target.end(), KeyGreater());
467  }
468  }
469  }
470 
471  return;
472  }
473 
474  //----------------------------------------------------------------------
480  //----------------------------------------------------------------------
481  void SortByValue(std::vector<std::pair<Ipv4Prefix,_valueT> > & target)
482  {
483  if (! target.empty())
484  target.clear();
485  std::shared_lock<std::shared_mutex> lock(_mtx);
486  if (! this->_maps.empty()) {
487  target.resize(this->Size());
488  typename std::vector<_RepSubType>::const_iterator iter =
489  this->_maps.begin();
490  uint32_t pfx = 0;
491  for (uint8_t hashNum = 0; hashNum < 33; ++hashNum) {
492  if (! this->_maps[hashNum].empty()) {
493  typename _RepSubType::const_iterator hiter =
494  this->_maps[hashNum].begin();
495  for ( ; hiter != iter->end(); ++hiter) {
496  target[pfx].first = Ipv4Prefix(hiter->first, hashNum);
497  target[pfx].second = hiter->second;
498  ++pfx;
499  }
500  }
501  }
502  if (! target.empty())
503  std::sort(target.begin(), target.end(), ValueGreater());
504  }
505 
506  return;
507  }
508 
509  //----------------------------------------------------------------------
512  //----------------------------------------------------------------------
513  uint32_t AddressesCovered() const
514  {
515  uint32_t rc = 0;
516  for (int8_t hashNum = 32; hashNum > 0; --hashNum) {
517  typename _RepSubType::const_iterator hiter =
518  _maps[hashNum].begin();
519  for ( ; hiter != _maps[hashNum].end(); ++hiter) {
520  bool foundWider = false;
521  for (int8_t widerHash = hashNum - 1; widerHash > 0; --widerHash) {
522  if (_maps[widerHash].find(Ipv4Prefix(hiter->first,widerHash).Network())
523  != _maps[widerHash].end()) {
524  // found wider match, don't count
525  foundWider = true;
526  break;
527  }
528  }
529  if (! foundWider) {
530  rc += ((uint32_t)1 << (32 - hashNum));
531  }
532  }
533  }
534  return rc;
535  }
536 
537  struct KeyGreater
538  {
539  public:
540  bool operator () (const std::pair<Ipv4Prefix,_valueT> & e1,
541  const std::pair<Ipv4Prefix,_valueT> & e2) const
542  {
543  return(e1.first > e2.first);
544  }
545  };
546 
547  struct KeyLess
548  {
549  public:
550  bool operator () (const std::pair<Ipv4Prefix,_valueT> & e1,
551  const std::pair<Ipv4Prefix,_valueT> & e2) const
552  {
553  return(e1.first < e2.first);
554  }
555  };
556 
557  struct ValueGreater
558  {
559  public:
560  bool operator () (const std::pair<Ipv4Prefix,_valueT> & e1,
561  const std::pair<Ipv4Prefix,_valueT> & e2) const
562  {
563  return(e1.second > e2.second);
564  }
565  };
566 
567 
568  protected:
569  std::vector<_RepSubType> _maps;
570  mutable std::shared_mutex _mtx;
571  };
572 
573  } // namespace RDAP
574 
575 } // namespace Dwm
576 
577 #endif // _DWMRDAPIPV4ROUTES_HH_
bool Add(const Ipv4Prefix &prefix, const _valueT &value)
Adds an entry.
Definition: DwmRDAPIpv4Routes.hh:131
void Clear()
Clears all entries.
Definition: DwmRDAPIpv4Routes.hh:103
_valueT & operator[](const Ipv4Prefix &prefix)
operator [] works like you would expect from an STL map.
Definition: DwmRDAPIpv4Routes.hh:148
int BZRead(BZFILE *bzf)
Reads the routes from a BZFILE pointer.
Definition: DwmRDAPIpv4Routes.hh:423
uint32_t AddressesCovered() const
Returns the number of addresses covered by the contained prefixes, not including 0/0.
Definition: DwmRDAPIpv4Routes.hh:513
int BZWrite(BZFILE *bzf) const
Writes the routes to a BZFILE pointer.
Definition: DwmRDAPIpv4Routes.hh:433
bool operator==(const Ipv4Routes< _valueT > &r) const
operator == It&#39;s unlikely you&#39;d ever need to use this, and it&#39;s expensive.
Definition: DwmRDAPIpv4Routes.hh:283
std::istream & Read(std::istream &is)
Reads the routes from an istream. Returns the istream.
Definition: DwmRDAPIpv4Routes.hh:344
void SortByValue(std::vector< std::pair< Ipv4Prefix, _valueT > > &target)
Sorts the contained pair<Ipv4Prefix,_valueT> values into a vector, in descending order by the value s...
Definition: DwmRDAPIpv4Routes.hh:481
uint32_t Size() const
Returns the number of routes.
Definition: DwmRDAPIpv4Routes.hh:306
std::ostream & Write(std::ostream &os) const
Writes the routes to an ostream. Returns the ostream.
Definition: DwmRDAPIpv4Routes.hh:353
int Write(gzFile gzf) const
Writes the routes to a gzFile.
Definition: DwmRDAPIpv4Routes.hh:413
bool Find(const Ipv4Prefix &prefix, _valueT &match) const
Find the entry for the given prefix.
Definition: DwmRDAPIpv4Routes.hh:176
bool Delete(const Ipv4Prefix &prefix)
Deletes the entry for prefix.
Definition: DwmRDAPIpv4Routes.hh:158
bool Find(const Ipv4Address &ipAddr, std::vector< std::pair< Ipv4Prefix, _valueT > > &matches) const
Finds all matches for ipAddr.
Definition: DwmRDAPIpv4Routes.hh:256
This template class provides an associative container keyed by IPv4 addresses, with longest-match sea...
Definition: DwmRDAPIpv4Routes.hh:83
Definition: DwmCountryCode.hh:53
ssize_t Read(int fd)
Reads the routes from a file descriptor.
Definition: DwmRDAPIpv4Routes.hh:383
int Read(gzFile gzf)
Reads the routes from a gzFile.
Definition: DwmRDAPIpv4Routes.hh:403
size_t Read(FILE *f)
Reades the routes from a FILE pointer.
Definition: DwmRDAPIpv4Routes.hh:363
bool Empty() const
Returns true if there are no entries.
Definition: DwmRDAPIpv4Routes.hh:114
size_t Write(FILE *f) const
Writes the routes to a FILE pointer.
Definition: DwmRDAPIpv4Routes.hh:373
bool FindLongest(const Ipv4Address &ipAddr, std::pair< Ipv4Prefix, _valueT > &match) const
Finds the longest match for ipAddr.
Definition: DwmRDAPIpv4Routes.hh:196
ssize_t Write(int fd) const
Writes the routes to a file descriptor.
Definition: DwmRDAPIpv4Routes.hh:393
bool operator!=(const Ipv4Routes< _valueT > &r) const
operator != It&#39;s unlikely you&#39;d ever need to use this, and it&#39;s expensive.
Definition: DwmRDAPIpv4Routes.hh:298
bool FindLongest(const Ipv4Address &ipAddr, std::pair< Ipv4Prefix, const _valueT *> &match) const
Finds the longest match for ipAddr.
Definition: DwmRDAPIpv4Routes.hh:229