Added note on the python~rc dns bug
[re6stnet.git] / db.py
1 import sqlite3, socket, xmlrpclib, time, os
2 import utils
3
4
5 class PeerManager:
6
7 # internal ip = temp arg/attribute
8 def __init__(self, db_dir_path, server, server_port, refresh_time, address,
9 internal_ip, prefix, manual, pp , db_size):
10 self._refresh_time = refresh_time
11 self._address = address
12 self._internal_ip = internal_ip
13 self._prefix = prefix
14 self._server = server
15 self._server_port = server_port
16 self._db_size = db_size
17 self._pp = pp
18 self._blacklist = [(prefix,)]
19 self._manual = manual
20
21 self._proxy = xmlrpclib.ServerProxy('http://%s:%u'
22 % (server, server_port))
23
24 utils.log('Connectiong to peers database...', 4)
25 self._db = sqlite3.connect(os.path.join(db_dir_path, 'peers.db'),
26 isolation_level=None)
27 utils.log('Database opened', 5)
28 utils.log('Preparing peers database...', 4)
29 try:
30 self._db.execute("UPDATE peers SET used = 0")
31 except sqlite3.OperationalError, e:
32 if e.args[0] == 'no such table: peers':
33 raise RuntimeError
34 utils.log('Database prepared', 5)
35
36 self.next_refresh = time.time()
37
38 def reset_blacklist(self):
39 self._blacklist = [(self._prefix)]
40
41 def blacklist(self, prefix):
42 utils.log('Blacklisting %s' % (prefix,), 4)
43 self._db.execute("DELETE FROM peers WHERE prefix = ?", (prefix,))
44 self._blacklist = list(set(self._blacklist + [(prefix,)]))
45
46 def refresh(self):
47 utils.log('Refreshing the peers DB...', 2)
48 try:
49 self._declare()
50 self._populate()
51 utils.log('DB refreshed', 3)
52 self.next_refresh = time.time() + self._refresh_time
53 except socket.error, e:
54 utils.log(str(e), 4)
55 utils.log('Connection to server failed, retrying in 30s', 2)
56 self.next_refresh = time.time() + 30
57
58 def _declare(self):
59 if self._address != None:
60 utils.log('Sending connection info to server...', 3)
61 self._proxy.declare((self._internal_ip,
62 utils.address_list(self._address)))
63 utils.log('Info sent', 5)
64 else:
65 utils.log("Warning : couldn't send ip, unknown external config", 4)
66
67 def _populate(self):
68 utils.log('Populating the peers DB...', 2)
69 new_peer_list = self._proxy.getPeerList(self._db_size,
70 self._internal_ip)
71 self._db.execute("""DELETE FROM peers WHERE used <= 0 ORDER BY used,
72 RANDOM() LIMIT MAX(0, ? + (SELECT COUNT(*)
73 FROM peers WHERE used <= 0))""",
74 (str(len(new_peer_list) - self._db_size),))
75 self._db.executemany("""INSERT OR IGNORE INTO peers (prefix, address)
76 VALUES (?,?)""", new_peer_list)
77 self._db.executemany("DELETE FROM peers WHERE prefix = ?",
78 self._blacklist)
79 utils.log('DB populated', 3)
80 utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5)
81
82 def getUnusedPeers(self, peer_count):
83 return self._db.execute("""SELECT prefix, address FROM peers WHERE used
84 <= 0 ORDER BY used DESC,RANDOM() LIMIT ?""",
85 (peer_count,))
86
87 def usePeer(self, prefix):
88 utils.log('Updating peers database : using peer ' + str(prefix), 5)
89 self._db.execute("UPDATE peers SET used = 1 WHERE prefix = ?",
90 (prefix,))
91 utils.log('DB updated', 5)
92
93 def unusePeer(self, prefix):
94 utils.log('Updating peers database : unusing peer ' + str(prefix), 5)
95 self._db.execute("UPDATE peers SET used = 0 WHERE prefix = ?",
96 (prefix,))
97 utils.log('DB updated', 5)
98
99 def flagPeer(self, prefix):
100 utils.log('Updating peers database : flagging peer ' + str(prefix), 5)
101 self._db.execute("UPDATE peers SET used = -1 WHERE prefix = ?",
102 (prefix,))
103 utils.log('DB updated', 5)
104
105 def handle_message(self, msg):
106 script_type, arg = msg.split()
107 if script_type == 'client-connect':
108 utils.log('Incomming connection from %s' % (arg,), 3)
109 elif script_type == 'client-disconnect':
110 utils.log('%s has disconnected' % (arg,), 3)
111 elif script_type == 'route-up':
112 if not self._manual:
113 external_ip = arg
114 new_address = list([external_ip, port, proto]
115 for port, proto in self._pp)
116 if self._address != new_address:
117 self._address = new_address
118 utils.log('Received new external ip : %s'
119 % (external_ip,), 3)
120 self._declare()
121 else:
122 utils.log('Unknow message recieved from the openvpn pipe : '
123 + msg, 1)