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