You can flag peers ( in vifibnet ) so that they are chosen last when looking for...
[re6stnet.git] / db.py
1 import sqlite3, socket, xmlrpclib, time, os
2 import utils
3
4 class PeerManager:
5
6 # internal ip = temp arg/attribute
7 def __init__(self, db_dir_path, server, server_port, refresh_time, address,
8 internal_ip, prefix, manual, proto, db_size):
9 self._refresh_time = refresh_time
10 self._address = address
11 self._internal_ip = internal_ip
12 self._prefix = prefix
13 self._server = server
14 self._server_port = server_port
15 self._db_size = db_size
16 self._proto = proto
17 self._manual = manual
18
19 self._proxy = xmlrpclib.ServerProxy('http://%s:%u' % (server, server_port))
20
21 utils.log('Connectiong to peers database', 4)
22 self._db = sqlite3.connect(os.path.join(db_dir_path, 'peers.db'),
23 isolation_level=None)
24 utils.log('Preparing peers database', 4)
25 try:
26 self._db.execute("UPDATE peers SET used = 0")
27 except sqlite3.OperationalError, e:
28 if e.args[0] == 'no such table: peers':
29 raise RuntimeError
30
31 self.next_refresh = time.time()
32
33 def refresh(self):
34 utils.log('Refreshing the peers DB', 2)
35 try:
36 self._declare()
37 self._populate()
38 self.next_refresh = time.time() + self._refresh_time
39 except socket.error, e:
40 utils.log(str(e), 4)
41 utils.log('Connection to server failed, retrying in 30s', 2)
42 self.next_refresh = time.time() + 30
43
44 def _declare(self):
45 if self._address != None:
46 utils.log('Sending connection info to server', 3)
47 self._proxy.declare((self._internal_ip, utils.address_list(self._address)))
48 else:
49 utils.log("Warning : couldn't advertise to server, external config not known", 4)
50
51 def _populate(self):
52 utils.log('Populating the peers DB', 2)
53 new_peer_list = self._proxy.getPeerList(self._db_size, self._internal_ip)
54 self._db.executemany("INSERT OR IGNORE INTO peers (prefix, address) VALUES (?,?)", new_peer_list)
55 self._db.execute("DELETE FROM peers WHERE prefix = ?", (self._prefix,))
56 utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5)
57
58 def getUnusedPeers(self, peer_count):
59 return self._db.execute("""SELECT prefix, address FROM peers WHERE used <= 0
60 ORDER BY used DESC,RANDOM() LIMIT ?""", (peer_count,))
61
62 def usePeer(self, prefix):
63 utils.log('Updating peers database : using peer ' + str(prefix), 5)
64 self._db.execute("UPDATE peers SET used = 1 WHERE prefix = ?", (prefix,))
65
66 def unusePeer(self, prefix):
67 utils.log('Updating peers database : unusing peer ' + str(prefix), 5)
68 self._db.execute("UPDATE peers SET used = 0 WHERE prefix = ?", (prefix,))
69
70 def flagPeer(self, prefix):
71 utils.log('Updating peers database : flagging peer ' + str(prefix), 5)
72 self._db.execute("UPDATE peers SET used = -1 WHERE prefix = ?", (prefix,))
73
74 def handle_message(self, msg):
75 script_type, arg = msg.split()
76 if script_type == 'client-connect':
77 utils.log('Incomming connection from %s' % (arg,), 3)
78 elif script_type == 'client-disconnect':
79 utils.log('%s has disconnected' % (arg,), 3)
80 elif script_type == 'route-up':
81 if not self._manual:
82 external_ip, external_port = arg.split(',')
83 new_address = list([external_ip, external_port, proto]
84 for proto in self._proto)
85 if self._address != new_address:
86 self._address = new_address
87 utils.log('Received new external configuration : %s:%s' % (external_ip, external_port), 3)
88 self._declare()
89 else:
90 utils.log('Unknow message recieved from the openvpn pipe : ' + msg, 1)