Use compact encoding of node contact info in the DHT.
[quix0rs-apt-p2p.git] / apt_dht_Khashmir / util.py
1 ## Copyright 2002-2003 Andrew Loewenstern, All Rights Reserved
2 # see LICENSE.txt for license information
3
4 from twisted.trial import unittest
5
6 def bucket_stats(l):
7     """given a list of khashmir instances, finds min, max, and average number of nodes in tables"""
8     max = avg = 0
9     min = None
10     def count(buckets):
11         c = 0
12         for bucket in buckets:
13             c = c + len(bucket.l)
14         return c
15     for node in l:
16         c = count(node.table.buckets)
17         if min == None:
18             min = c
19         elif c < min:
20             min = c
21         if c > max:
22             max = c
23         avg = avg + c
24     avg = avg / len(l)
25     return {'min':min, 'max':max, 'avg':avg}
26
27 def uncompact(s):
28     """Extract the contact info from a compact node representation.
29     
30     @type s: C{string}
31     @param s: the compact representation
32     @rtype: C{dictionary}
33     @return: the node ID, IP address and port to contact the node on
34     @raise ValueError: if the compact representation doesn't exist
35     """
36     if (len(s) != 26):
37         raise ValueError
38     id = s[:20]
39     host = '.'.join([str(ord(i)) for i in s[20:24]])
40     port = (ord(s[24]) << 8) | ord(s[25])
41     return {'id': id, 'host': host, 'port': port}
42
43 def compact(id, host, port):
44     """Create a compact representation of node contact info.
45     
46     @type id: C{string}
47     @param id: the node ID
48     @type host: C{string}
49     @param host: the IP address of the node
50     @type port: C{int}
51     @param port: the port number to contact the node on
52     @rtype: C{string}
53     @return: the compact representation
54     @raise ValueError: if the compact representation doesn't exist
55     """
56     
57     s = id + ''.join([chr(int(i)) for i in host.split('.')]) + \
58           chr((port & 0xFF00) >> 8) + chr(port & 0xFF)
59     if len(s) != 26:
60         raise ValueError
61     return s
62
63 class TestUtil(unittest.TestCase):
64     """Tests for the utilities."""
65     
66     timeout = 5
67     myid = '\xca\xec\xb8\x0c\x00\xe7\x07\xf8~])\x8f\x9d\xe5_B\xff\x1a\xc4!'
68     host = '165.234.1.34'
69     port = 61234
70
71     def test_compact(self):
72         d = uncompact(compact(self.myid, self.host, self.port))
73         self.failUnlessEqual(d['id'], self.myid)
74         self.failUnlessEqual(d['host'], self.host)
75         self.failUnlessEqual(d['port'], self.port)
76