Big TODO update
[re6stnet.git] / tunnel.py
1 import os, random, traceback, time
2 import plib, utils, db
3
4 log = None
5
6 class TunnelManager:
7
8 def __init__(self, write_pipe, peer_db, openvpn_args, hello_interval, refresh, connection_count, refresh_rate):
9 self._write_pipe = write_pipe
10 self._peer_db = peer_db
11 self._connection_dict = {}
12 self._ovpn_args = openvpn_args
13 self._hello = hello_interval
14 self._refresh_time = refresh
15 self.free_interface_set = set(('client1', 'client2', 'client3', 'client4', 'client5',
16 'client6', 'client7', 'client8', 'client9', 'client10'))
17 self.next_refresh = time.time()
18
19 # TODO : choose this automatically
20 self._client_count = connection_count/2
21 self._refresh_count = refresh_rate*self._client_count
22
23 def refresh(self):
24 utils.log('Refreshing the tunnels', 2)
25 self._cleanDeads()
26 self._removeSomeTunnels()
27 self._makeNewTunnels()
28 self.next_refresh = time.time() + self._refresh_time
29
30 def _cleanDeads(self):
31 for id in self._connection_dict.keys():
32 p, iface = self._connection_dict[id]
33 if p.poll() != None:
34 utils.log('Connection with %s has failed with return code %s' % (id, p.returncode), 3)
35 self.free_interface_set.add(iface)
36 self._peer_db.unusePeer(id)
37 del self._connection_dict[id]
38
39 def _removeSomeTunnels(self):
40 for i in range(0, max(0, len(self._connection_dict) - self._client_count + self._refresh_count)):
41 peer_id = random.choice(self._connection_dict.keys())
42 self._kill(peer_id)
43
44 def _kill(self, peer_id):
45 utils.log('Killing the connection with id ' + str(peer_id), 2)
46 p, iface = self._connection_dict.pop(peer_id)
47 p.kill()
48 self.free_interface_set.add(iface)
49 self._peer_db.unusePeer(peer_id)
50
51 def _makeNewTunnels(self):
52 #utils.log('Making %i new tunnels' % (self._client_count - len(self._connection_dict)), 3)
53 try:
54 for peer_id, ip, port, proto in self._peer_db.getUnusedPeers(self._client_count - len(self._connection_dict)):
55 utils.log('Establishing a connection with id %s (%s:%s)' % (peer_id, ip, port), 2)
56 iface = self.free_interface_set.pop()
57 self._connection_dict[peer_id] = (
58 plib.client( ip, self._write_pipe, self._hello,
59 '--dev', iface, '--proto', proto, '--rport', str(port), *self._ovpn_args,
60 stdout=os.open(os.path.join(log, 'vifibnet.client.%s.log' % (peer_id,)),
61 os.O_WRONLY|os.O_CREAT|os.O_TRUNC) ),
62 iface)
63 self._peer_db.usePeer(peer_id)
64 except KeyError:
65 utils.log("Can't establish connection with %s : no available interface" % ip, 2)
66 except Exception:
67 traceback.print_exc()