OverSim
OverlayKey.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include <omnetpp.h>
25 
26 #include "OverlayKey.h"
27 #include "Comparator.h"
28 
29 #include <BinaryValue.h>
30 #include "SHA1.h"
31 
32 using namespace std;
33 
34 uint32_t OverlayKey::keyLength = MAX_KEYLENGTH;
35 
36 // TODO: replace both commands below with simpler macros without conditionals
37 
38 //#define ROUND_NEXT(n, div) (((n) + (div) - 1) / (div))
39 //uint OverlayKey::aSize = ROUND_NEXT(OverlayKey::keyLength, 8*sizeof(mp_limb_t));
40 
41 uint32_t OverlayKey::aSize = OverlayKey::keyLength / (8*sizeof(mp_limb_t)) +
42  (OverlayKey::keyLength % (8*sizeof(mp_limb_t))
43  != 0 ? 1 : 0);
44 
45 mp_limb_t OverlayKey::GMP_MSB_MASK = (OverlayKey::keyLength % GMP_LIMB_BITS)
46  != 0 ? (((mp_limb_t)1 << (OverlayKey::keyLength % GMP_LIMB_BITS))-1)
47  : (mp_limb_t) - 1;
48 
49 //--------------------------------------------------------------------
50 // constants
51 //--------------------------------------------------------------------
52 
53 // predefined keys
55 const OverlayKey OverlayKey::ZERO((uint32_t)0);
56 const OverlayKey OverlayKey::ONE((uint32_t)1);
57 
58 
59 // hex crap
60 const char* HEX = "0123456789abcdef";
61 
62 //--------------------------------------------------------------------
63 // construction and destruction
64 //--------------------------------------------------------------------
65 
66 // default construction: create a unspecified node key
68 {
69  isUnspec = true;
70 }
71 
72 // create a key out of an normal integer
74 {
75  clear();
76  key[0] = num;
77  trim();
78 }
79 
80 // create a key out of a buffer
81 OverlayKey::OverlayKey(const unsigned char* buf, uint32_t size)
82 {
83  int trimSize, offset;
84  clear();
85  trimSize = (int)min((uint32_t) (aSize * sizeof(mp_limb_t)), size);
86  offset = aSize * sizeof(mp_limb_t) - trimSize;
87  memcpy( ((char*)key) + offset, buf, trimSize);
88  trim();
89 }
90 
91 // create a key out of an string with the given base
92 OverlayKey::OverlayKey(const std::string& str, uint32_t base)
93 {
94  if ((base < 2) || (base > 16)) {
95  throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
96  }
97 
98  string s(str);
99  clear();
100 
101  for (uint32_t i=0; i<s.size(); i++) {
102  if ((s[i] >= '0') && (s[i] <= '9')) {
103  s[i] -= '0';
104  } else if ((s[i] >= 'a') && (s[i] <= 'f')) {
105  s[i] -= ('a' - 10);
106  } else if ((s[i] >= 'A') & (s[i] <= 'F')) {
107  s[i] -= ('A' - 10);
108  } else {
109  throw cRuntimeError("OverlayKey::OverlayKey(): "
110  "Invalid character in string!");
111  }
112  }
113 
114  mpn_set_str ((mp_limb_t*)this->key, (const unsigned char*)s.c_str(),
115  str.size(), base);
116  trim();
117 }
118 
119 // copy constructor
121 {
122  (*this) = rhs;
123 }
124 
125 // default destructur
127 {}
128 
129 //--------------------------------------------------------------------
130 // string representations & node key attributes
131 //--------------------------------------------------------------------
132 
133 void OverlayKey::setKeyLength(uint32_t length)
134 {
135  if ((length < 1) || (length > OverlayKey::keyLength)) {
136  opp_error("OverlayKey::setKeyLength(): length must be <= %i "
137  "and setKeyLength() must not be called twice "
138  "with different length!", MAX_KEYLENGTH);
139  }
140 
141  keyLength = length;
142 
143  aSize = keyLength / (8*sizeof(mp_limb_t)) +
144  (keyLength % (8*sizeof(mp_limb_t))!=0 ? 1 : 0);
145 
146  GMP_MSB_MASK = (keyLength % GMP_LIMB_BITS)
147  != 0 ? (((mp_limb_t)1 << (keyLength % GMP_LIMB_BITS))-1)
148  : (mp_limb_t)-1;
149 }
150 
151 
152 // returns the length in bits
154 {
155  return OverlayKey::keyLength;
156 }
157 
159 {
160  return isUnspec;
161 }
162 
163 std::string OverlayKey::toString(uint32_t base) const
164 {
165  if ((base != 2) && (base != 16)) {
166  throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
167  }
168 
169  if (isUnspec)
170  return std::string("<unspec>");
171  else {
172  char temp[MAX_KEYLENGTH+1];
173 
174  if (base==16) {
175  int k=0;
176  for (int i=(keyLength-1)/4; i>=0; i--, k++)
177  temp[k] = HEX[this->getBitRange
178  (4*i,4)];
179 
180  temp[k] = 0;
181  return std::string((const char*)temp);
182  } else if (base==2) {
183  int k=0;
184  for (int i=keyLength-1; i>=0; i-=1, k++)
185  temp[k] = HEX[this->getBit(i)];
186  temp[k] = 0;
187  return std::string((const char*)temp);
188  } else {
189  throw cRuntimeError("OverlayKey::OverlayKey(): Invalid base!");
190  }
191 
192 // the following native libgmp code doesn't work with leading zeros
193 #if 0
194  mp_size_t last = mpn_get_str((unsigned char*)temp, base,
195  (mp_limb_t*)this->key, aSize);
196  for (int i=0; i<last; i++) {
197  temp[i] = HEX[temp[i]];
198  }
199  temp[last] = 0;
200  return std::string((const char*)temp);
201 #endif
202 
203  }
204 }
205 
206 //--------------------------------------------------------------------
207 // operators
208 //--------------------------------------------------------------------
209 
210 // assignment operator
212 {
213  isUnspec = rhs.isUnspec;
214  memcpy( key, rhs.key, aSize*sizeof(mp_limb_t) );
215  return *this;
216 }
217 
218 // sub one prefix operator
220 {
221  return (*this -= ONE);
222 }
223 
224 // sub one postfix operator
226 {
227  OverlayKey clone = *this;
228  *this -= ONE;
229  return clone;
230 }
231 
232 // add one prefix operator
234 {
235  return (*this += ONE);
236 }
237 
238 // sub one postfix operator
240 {
241  OverlayKey clone = *this;
242  *this += ONE;
243  return clone;
244 }
245 
246 // add assign operator
248 {
249  mpn_add_n((mp_limb_t*)key, (mp_limb_t*)key, (mp_limb_t*)rhs.key, aSize);
250  trim();
251  isUnspec = false;
252  return *this;
253 }
254 
255 // sub assign operator
257 {
258  mpn_sub_n((mp_limb_t*)key, (mp_limb_t*)key, (mp_limb_t*)rhs.key, aSize);
259  trim();
260  isUnspec = false;
261  return *this;
262 }
263 
264 // add operator
266 {
267  OverlayKey result = *this;
268  result += rhs;
269  return result;
270 }
271 
272 // sub operator
274 {
275  OverlayKey result = *this;
276  result -= rhs;
277  return result;
278 }
279 
280 // compare operators
281 bool OverlayKey::operator<(const OverlayKey& compKey) const
282 {
283  return compareTo(compKey) < 0;
284 }
285 bool OverlayKey::operator>(const OverlayKey& compKey) const
286 {
287  return compareTo(compKey) > 0;
288 }
289 bool OverlayKey::operator<=(const OverlayKey& compKey) const
290 {
291  return compareTo(compKey) <=0;
292 }
293 bool OverlayKey::operator>=(const OverlayKey& compKey) const
294 {
295  return compareTo(compKey) >=0;
296 }
297 bool OverlayKey::operator==(const OverlayKey& compKey) const
298 {
299  return compareTo(compKey) ==0;
300 }
301 bool OverlayKey::operator!=(const OverlayKey& compKey) const
302 {
303  return compareTo(compKey) !=0;
304 }
305 
306 // bitwise xor
308 {
309  OverlayKey result = *this;
310  for (uint32_t i=0; i<aSize; i++) {
311  result.key[i] ^= rhs.key[i];
312  }
313 
314  return result;
315 }
316 
317 // bitwise or
319 {
320  OverlayKey result = *this;
321  for (uint32_t i=0; i<aSize; i++) {
322  result.key[i] |= rhs.key[i];
323  }
324 
325  return result;
326 }
327 
328 // bitwise and
330 {
331  OverlayKey result = *this;
332  for (uint32_t i=0; i<aSize; i++) {
333  result.key[i] &= rhs.key[i];
334  }
335 
336  return result;
337 }
338 
339 // complement
341 {
342  OverlayKey result = *this;
343  for (uint32_t i=0; i<aSize; i++) {
344  result.key[i] = ~key[i];
345  }
346  result.trim();
347 
348  return result;
349 }
350 
351 // bitwise shift right
353 {
354  OverlayKey result = ZERO;
355  int i = num/GMP_LIMB_BITS;
356 
357  num %= GMP_LIMB_BITS;
358 
359  if (i>=(int)aSize)
360  return result;
361 
362  for (int j=0; j<(int)aSize-i; j++) {
363  result.key[j] = key[j+i];
364  }
365  mpn_rshift(result.key,result.key,aSize,num);
366  result.isUnspec = false;
367  result.trim();
368 
369  return result;
370 }
371 
372 // bitwise shift left
374 {
375  OverlayKey result = ZERO;
376  int i = num/GMP_LIMB_BITS;
377 
378  num %= GMP_LIMB_BITS;
379 
380  if (i>=(int)aSize)
381  return result;
382 
383  for (int j=0; j<(int)aSize-i; j++) {
384  result.key[j+i] = key[j];
385  }
386  mpn_lshift(result.key,result.key,aSize,num);
387  result.isUnspec = false;
388  result.trim();
389 
390  return result;
391 }
392 
393 // get bit
395 {
396  return OverlayKeyBit(getBit(n), n, this);
397 }
398 
399 OverlayKey& OverlayKey::setBit(uint32_t pos, bool value)
400 {
401  if (pos >= keyLength) {
402  throw cRuntimeError("OverlayKey::setBitAt(): "
403  "pos >= keyLength!");
404  }
405 
406  mp_limb_t digit = 1;
407  digit = digit << (pos % GMP_LIMB_BITS);
408 
409  if (value) {
410  key[pos / GMP_LIMB_BITS] |= digit;
411  } else {
412  //key[pos / GMP_LIMB_BITS] = key[pos / GMP_LIMB_BITS] & ~digit;
413  key[pos / GMP_LIMB_BITS] &= ~digit;
414  }
415 
416  return *this;
417 };
418 
419 //--------------------------------------------------------------------
420 // additional math
421 //--------------------------------------------------------------------
422 
423 // returns a sub integer
424 uint32_t OverlayKey::getBitRange(uint32_t p, uint32_t n) const
425 {
426  int i = p / GMP_LIMB_BITS, // index of starting bit
427  f = p % GMP_LIMB_BITS, // position of starting bit
428  f2 = f + n - GMP_LIMB_BITS; // how many bits to take from next index
429 
430  if ((p + n > OverlayKey::keyLength) || (n > 32)) {
431  throw cRuntimeError("OverlayKey::get: Invalid range");
432  }
433  if (GMP_LIMB_BITS < 32) {
434  throw cRuntimeError("OverlayKey::get: GMP_LIMB_BITS too small!");
435  }
436 
437  return ((key[i] >> f) | // get the bits of key[i]
438  (f2 > 0 ? (key[i+1] << (GMP_LIMB_BITS - f)) : 0)) & // the extra bits from key[i+1]
439  (((uint32_t)(~0)) >> (GMP_LIMB_BITS - n)); // delete unused bits
440 }
441 
442 double OverlayKey::toDouble() const
443 {
444  double result = 0;
445  uint8_t range = 32, length = getLength();
446  for (uint8_t i = 0; i < length; i += 32) {
447  if ((length - i) < 32) range = length - i;
448  result += (getBitRange(i, range) * pow(2.0, i));
449  }
450 
451  return result;
452 }
453 
454 // fill suffix with random bits
456 {
457  OverlayKey newKey = *this;
458  int i = pos/GMP_LIMB_BITS, j = pos%GMP_LIMB_BITS;
459  mp_limb_t m = ((mp_limb_t)1 << j)-1;
460  mp_limb_t rnd;
461 
462  // mpn_random(&rnd,1);
463  omnet_random(&rnd,1);
464  newKey.key[i] &= ~m;
465  newKey.key[i] |= (rnd&m);
466  // mpn_random(newKey.key,i);
467  omnet_random(newKey.key,i);
468  newKey.trim();
469 
470  return newKey;
471 }
472 
473 // fill prefix with random bits
475 {
476  OverlayKey newKey = *this;
477  int i = pos/GMP_LIMB_BITS, j = pos%GMP_LIMB_BITS;
478  mp_limb_t m = ((mp_limb_t)1 << j)-1;
479  mp_limb_t rnd;
480 
481  // mpn_random(&rnd,1);
482  omnet_random(&rnd,1);
483 
484  newKey.key[i] &= m;
485  newKey.key[i] |= (rnd&~m);
486  for (int k=aSize-1; k!=i; k--) {
487  // mpn_random( &newKey.key[k], 1 );
488  omnet_random( &newKey.key[k], 1 );
489  }
490  newKey.trim();
491 
492  return newKey;
493 }
494 
495 // calculate shared prefix length
497  uint32_t bitsPerDigit) const
498 {
499  if (compareTo(compKey) == 0) return keyLength;
500 
501  uint32_t length = 0;
502  int i;
503  uint32_t j;
504  bool msb = true;
505 
506  // count equal limbs first:
507  for (i=aSize-1; i>=0; --i) {
508  if (this->key[i] != compKey.key[i]) {
509  // XOR first differing limb for easy counting of the bits:
510  mp_limb_t d = this->key[i] ^ compKey.key[i];
511  if (msb) d <<= ( GMP_LIMB_BITS - (keyLength % GMP_LIMB_BITS) );
512  for (j = GMP_LIMB_BITS-1; d >>= 1; --j);
513  length += j;
514  break;
515  }
516  length += GMP_LIMB_BITS;
517  msb = false;
518  }
519 
520  return length / bitsPerDigit;
521 }
522 
523 // calculate log of base 2
524 int OverlayKey::log_2() const
525 {
526  int16_t i = aSize-1;
527 
528  while (i>=0 && key[i]==0) {
529  i--;
530  }
531 
532  if (i<0) {
533  return -1;
534  }
535 
536  mp_limb_t j = key[i];
537  i *= GMP_LIMB_BITS;
538  while (j!=0) {
539  j >>= 1;
540  i++;
541  }
542 
543  return i-1;
544 }
545 
546 // returns a simple hash of the key
547 size_t OverlayKey::hash() const
548 {
549  return (size_t)key[0];
550 }
551 
552 // returns true, if this key is element of the interval (keyA, keyB)
554  const OverlayKey& keyB) const
555 {
556  if (isUnspec || keyA.isUnspec || keyB.isUnspec)
557  return false;
558 
559  if (*this == keyA)
560  return false;
561  else if (keyA < keyB)
562  return ((*this > keyA) && (*this < keyB));
563  else
564  return ((*this > keyA) || (*this < keyB));
565 }
566 
567 // returns true, if this key is element of the interval (keyA, keyB]
569  const OverlayKey& keyB) const
570 {
571  if (isUnspec || keyA.isUnspec || keyB.isUnspec)
572  return false;
573 
574  if ((keyA == keyB) && (*this == keyA))
575  return true;
576  else if (keyA <= keyB)
577  return ((*this > keyA) && (*this <= keyB));
578  else
579  return ((*this > keyA) || (*this <= keyB));
580 }
581 
582 // returns true, if this key is element of the interval [keyA, keyB)
584  const OverlayKey& keyB) const
585 {
586  if (isUnspec || keyA.isUnspec || keyB.isUnspec)
587  return false;
588 
589  if ((keyA == keyB) && (*this == keyA))
590  return true;
591  else if (keyA <= keyB)
592  return ((*this >= keyA) && (*this < keyB));
593  else
594  return ((*this >= keyA) || (*this < keyB));
595 }
596 
597 // returns true, if this key is element of the interval [keyA, keyB]
599  const OverlayKey& keyB) const
600 {
601  if (isUnspec || keyA.isUnspec || keyB.isUnspec)
602  return false;
603 
604  if ((keyA == keyB) && (*this == keyA))
605  return true;
606  else if (keyA <= keyB)
607  return ((*this >= keyA) && (*this <= keyB));
608  else
609  return ((*this >= keyA) || (*this <= keyB));
610 }
611 
612 
613 //----------------------------------------------------------------------
614 // statics and globals
615 //----------------------------------------------------------------------
616 
617 // default console output
618 std::ostream& operator<<(std::ostream& os, const OverlayKey& c)
619 {
620  os << c.toString(16);
621  return os;
622 };
623 
624 // returns a key filled with bit 1
626 {
627  OverlayKey newKey;
628 
629  for (uint32_t i=0; i<aSize; i++) {
630  newKey.key[i] = ~0;
631  }
632  newKey.isUnspec = false;
633  newKey.trim();
634 
635  return newKey;
636 }
637 
638 // generate random number
640 {
641  OverlayKey newKey = ZERO;
642 
643  omnet_random(newKey.key,aSize);
644 
645  newKey.trim();
646 
647  return newKey;
648 }
649 
650 // generate sha1 hash
652 {
653  OverlayKey newKey = OverlayKey();
654  uint8_t temp[20];
655  CSHA1 sha1;
656 
657  sha1.Reset();
658  sha1.Update((uint8_t*)(&(*input.begin())), input.size());
659  sha1.Final();
660  sha1.GetHash(temp);
661  mpn_set_str(newKey.key, (const uint8_t*)temp,
662  (int)std::min((uint32_t)(aSize * sizeof(mp_limb_t)), 20U), 256);
663  newKey.isUnspec = false;
664  newKey.trim();
665 
666  return newKey;
667 }
668 
669 // generate a key=2**exponent
670 OverlayKey OverlayKey::pow2( uint32_t exponent )
671 {
672  if (exponent >= keyLength) {
673  throw cRuntimeError("OverlayKey::pow2(): "
674  "exponent >= keyLength!");
675  }
676 
677  OverlayKey newKey = ZERO;
678 
679  newKey.key[exponent/GMP_LIMB_BITS] =
680  (mp_limb_t)1 << (exponent % GMP_LIMB_BITS);
681 
682  return newKey;
683 }
684 
685 // pseudo-regression test
687 {
688  // add test
689  cout << endl << "--- Add test ..." << endl;
690  OverlayKey key = 123456789;
691  cout << " key=" << key << endl;
692  cout << " key += 987654321 = " << (key+=987654321) << endl;
693  cout << " prefix++ : " << (++key) << endl;
694  cout << " postfix++ : " << (key++) << endl;
695  cout << " key=" << key << endl;
696 
697  OverlayKey k1 = 256, k2 = 10, k3 = 3;
698 
699  // compare test
700  cout << endl << "--- Compare test ..." << endl;
701  cout << " 256 < 10 = "<< (k1 < k2) << " k1="<<k1<<endl;
702  cout << " 256 > 10 = "<< (k1 > k2) << " k2="<<k2<<endl;
703 
704  cout << " 10 isBetween(3, 256)=" << k2.isBetween(k3, k1) << endl;
705  cout << " 3 isBetween(10, 256)=" << k3.isBetween(k2, k1) << endl;
706  cout << " 256 isBetween(10, 256)=" << k1.isBetween(k2, k1) << endl;
707  cout << " 256 isBetweenR(10, 256)=" << k1.isBetweenR(k2, k1) << endl;
708  cout << " max isBetween(max-1,0)=" << OverlayKey::getMax().isBetween(
709  OverlayKey::getMax()-1, OverlayKey::ZERO) << endl;
710  cout << " max-1 isBetween(max,1)=" << (OverlayKey::getMax()-1).isBetween(
712  cout << " max-1 isBetweenL(max-1,1)=" << (OverlayKey::getMax()-1).
713  isBetweenL(OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
714  cout << " 1 isBetweenL(max-1,1)=" << (OverlayKey::ONE).isBetweenL(
715  OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
716  cout << " 1 isBetweenR(max-1,1)=" << OverlayKey::ONE.isBetweenR(
717  OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
718  cout << " 1 isBetween(max-1,1)=" << OverlayKey::ONE.isBetween(
719  OverlayKey::getMax()-1, OverlayKey::ONE) << endl;
720  cout << " 1 isBetween(max-1,0)=" << OverlayKey::ONE.isBetween(
721  OverlayKey::getMax()-1, OverlayKey::ZERO) << endl;
722  cout << " 256 sharedPrefixLength(3)=" << k1.sharedPrefixLength(k3)
723  << endl;
724  cout << " 256 sharedPrefixLength(256)=" << k1.sharedPrefixLength(k1)
725  << endl;
726 
727  // wrap around test
728  cout << endl << "--- Warp around test ..." << endl;
729 
730  k1 = OverlayKey::getMax();
731  cout << "k1=max= " << k1.toString(16) << endl;
732  cout << "k1+1 = " << (k1 + 1).toString(16) << endl;
733  cout << "k1+2 = " << (k1 + 2).toString(16) << endl;
734 
735  k1 = OverlayKey::ZERO;
736  cout << "k1=0= " << k1.toString(16) << endl;
737  cout << "k1-1 = " << (k1 - 1).toString(16) << endl;
738  cout << "k1-2 = " << (k1 - 2).toString(16) << endl;
739 
740  cout << "max > ONE=" << (OverlayKey::getMax() > OverlayKey::ONE) << endl;
741  cout << "max < ONE=" << (OverlayKey::getMax() < OverlayKey::ONE) << endl;
742 
743  // distance test
744  cout << endl << "--- Distance test ..." << endl;
745 
746  cout << "KeyRingMetric::distance(1, max)="
748  cout << "KeyCwRingMetric::distance(1, max)="
750  cout << "KeyRingMetric::distance(max, 1)="
752  cout << "KeyCwRingMetric::distance(max, 1)="
754 
755  // suffix and log2 test
756  cout << endl << "--- RandomSuffix and log2 test ..." << endl;
757  k1 = OverlayKey::ZERO;
758  for (uint32_t i=0; i<k1.getLength(); i++) {
759  k2=k1.randomSuffix(i);
760  cout << " " << k2.toString(16) << " log2=" << k2.log_2() << endl;
761  }
762  cout << endl << "--- RandomPrefix and log2 test ..." << endl;
763  k1 = OverlayKey::getMax();
764  for (uint32_t i=0; i<k1.getLength(); i++) {
765  k2=k1.randomPrefix(i);
766  cout << " " << k2.toString(16) << " log2=" << k2.log_2() << endl;
767  }
768 
769  cout << endl << "--- pow2 test..." << endl;
770  for (uint32_t i=0; i<k1.getLength(); i++) {
771  k2=pow2(i);
772  cout << " 2^" << i << " = " << k2.toString(16) << " log2="
773  << k2.log_2() << endl;
774  }
775 
776  cout << endl << "--- Bits test ..." << endl << " ";
777  const char* BITS[] = { "000","001","010","011","100","101","110","111" };
778  k1 = OverlayKey::random();
779  for (int i=k1.getLength()-1; i>=0; i--)
780  cout << k1[i];
781  cout << " = " << endl << " ";
782  for (int i=k1.getLength()-3; i>=0; i-=3)
783  cout << BITS[k1.getBitRange(i,3)];
784  cout << endl;
785 
786  cout << endl << "--- SHA1 test ... (verified with test vectors)" << endl;
787  cout << " Empty string: " << OverlayKey::sha1("").toString(16)
788  << " = da39a3ee5e6b4b0d3255bfef95601890afd80709" << endl;
789  cout << " 'Hello World' string: "
790  << OverlayKey::sha1("Hello World").toString(16)
791  << " = 0a4d55a8d778e5022fab701977c5d840bbc486d0" << endl;
792 }
793 
794 //--------------------------------------------------------------------
795 // private methods (mostly inlines)
796 //--------------------------------------------------------------------
797 
798 // trims a key after each operation
799 inline void OverlayKey::trim()
800 {
801  key[aSize-1] &= GMP_MSB_MASK;
802 }
803 
804 
805 // compares this key to any other
806 int OverlayKey::compareTo( const OverlayKey& compKey ) const
807 {
808  if (compKey.isUnspec || isUnspec)
809  opp_error("OverlayKey::compareTo(): key is unspecified!");
810  return mpn_cmp(key,compKey.key,aSize);
811 }
812 
813 // sets key to zero and clears unspecified bit
814 inline void OverlayKey::clear()
815 {
816  memset( key, 0, aSize * sizeof(mp_limb_t) );
817  isUnspec = false;
818 }
819 
820 // replacement function for mpn_random() using omnet's rng
821 inline void omnet_random(mp_limb_t *r1p, mp_size_t r1n)
822 {
823  // fill in 32 bit chunks
824  uint32_t* chunkPtr = (uint32_t*)r1p;
825 
826  for (uint32_t i=0; i < ((r1n*sizeof(mp_limb_t) + 3) / 4); i++) {
827  chunkPtr[i] = intuniform(0, 0xFFFFFFFF);
828  }
829 }
830 
831 #ifdef __GMP_SHORT_LIMB
832 #define GMP_TYPE unsigned int
833 #else
834 #ifdef _LONG_LONG_LIMB
835 #define GMP_TYPE unsigned long long int
836 #else
837 #define GMP_TYPE unsigned long int
838 #endif
839 #endif
840 
841 void OverlayKey::netPack(cCommBuffer *b)
842 {
843  //doPacking(b,(GMP_TYPE*)this->key, MAX_KEYLENGTH / (8*sizeof(mp_limb_t)) +
844  //(MAX_KEYLENGTH % (8*sizeof(mp_limb_t))!=0 ? 1 : 0));
845  // Pack an OverlayKey as uint32_t array and hope for the best
846  // FIXME: This is probably not exactly portable
847  doPacking(b,(uint32_t*)this->key, MAX_KEYLENGTH / (8*sizeof(uint32_t)) +
848  (MAX_KEYLENGTH % (8*sizeof(uint32_t))!=0 ? 1 : 0));
849  doPacking(b,this->isUnspec);
850 }
851 
852 void OverlayKey::netUnpack(cCommBuffer *b)
853 {
854  //doUnpacking(b,(GMP_TYPE*)this->key, MAX_KEYLENGTH / (8*sizeof(mp_limb_t)) +
855  //(MAX_KEYLENGTH % (8*sizeof(mp_limb_t))!=0 ? 1 : 0));
856  doUnpacking(b,(uint32_t*)this->key, MAX_KEYLENGTH / (8*sizeof(uint32_t)) +
857  (MAX_KEYLENGTH % (8*sizeof(uint32_t))!=0 ? 1 : 0));
858  doUnpacking(b,this->isUnspec);
859 
860 }
861