changes in upnpigd to be able to refresh the forwarding
[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, proto, 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._proto = proto
18 self._manual = manual
19
20 self._proxy = xmlrpclib.ServerProxy('http://%s:%u'
21 % (server, server_port))
22
23 utils.log('Connectiong to peers database', 4)
24 self._db = sqlite3.connect(os.path.join(db_dir_path, 'peers.db'),
25 isolation_level=None)
26 utils.log('Preparing peers database', 4)
27 try:
28 self._db.execute("UPDATE peers SET used = 0")
29 except sqlite3.OperationalError, e:
30 if e.args[0] == 'no such table: peers':
31 raise RuntimeError
32
33 self.next_refresh = time.time()
34
35 def refresh(self):
36 utils.log('Refreshing the peers DB', 2)
37 try:
38 self._declare()
39 self._populate()
40 self.next_refresh = time.time() + self._refresh_time
41 except socket.error, e:
42 utils.log(str(e), 4)
43 utils.log('Connection to server failed, retrying in 30s', 2)
44 self.next_refresh = time.time() + 30
45
46 def _declare(self):
47 if self._address != None:
48 utils.log('Sending connection info to server', 3)
49 self._proxy.declare((self._internal_ip,
50 utils.address_list(self._address)))
51 else:
52 utils.log("Warning : couldn't send ip, unknown external config", 4)
53
54 def _populate(self):
55 utils.log('Populating the peers DB', 2)
56 new_peer_list = self._proxy.getPeerList(self._db_size,
57 self._internal_ip)
58 self._db.execute("""DELETE FROM peers WHERE used <= 0 ORDER BY used,
59 RANDOM() LIMIT MAX(0, ? + (SELECT COUNT(*)
60 FROM peers WHERE used <= 0))""",
61 (str(len(new_peer_list) - self._db_size),))
62 self._db.executemany("""INSERT OR IGNORE INTO peers (prefix, address)
63 VALUES (?,?)""", new_peer_list)
64 self._db.execute("DELETE FROM peers WHERE prefix = ?", (self._prefix,))
65 utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5)
66
67 def getUnusedPeers(self, peer_count):
68 return self._db.execute("""SELECT prefix, address FROM peers WHERE used
69 <= 0 ORDER BY used DESC,RANDOM() LIMIT ?""",
70 (peer_count,))
71
72 def usePeer(self, prefix):
73 utils.log('Updating peers database : using peer ' + str(prefix), 5)
74 self._db.execute("UPDATE peers SET used = 1 WHERE prefix = ?",
75 (prefix,))
76
77 def unusePeer(self, prefix):
78 utils.log('Updating peers database : unusing peer ' + str(prefix), 5)
79 self._db.execute("UPDATE peers SET used = 0 WHERE prefix = ?",
80 (prefix,))
81
82 def flagPeer(self, prefix):
83 utils.log('Updating peers database : flagging peer ' + str(prefix), 5)
84 self._db.execute("UPDATE peers SET used = -1 WHERE prefix = ?",
85 (prefix,))
86
87 def handle_message(self, msg):
88 script_type, arg = msg.split()
89 if script_type == 'client-connect':
90 utils.log('Incomming connection from %s' % (arg,), 3)
91 elif script_type == 'client-disconnect':
92 utils.log('%s has disconnected' % (arg,), 3)
93 elif script_type == 'route-up':
94 if not self._manual:
95 external_ip, external_port = arg.split(',')
96 new_address = list([external_ip, external_port, proto]
97 for proto in self._proto)
98 if self._address != new_address:
99 self._address = new_address
100 utils.log('Received new external configuration : %s:%s'
101 % (external_ip, external_port), 3)
102 self._declare()
103 else:
104 utils.log('Unknow message recieved from the openvpn pipe : '
105 + msg, 1)