Commit bef61ec6 authored by Guillaume Bury's avatar Guillaume Bury

Merge branch 'master' of https://git.erp5.org/repos/vifibnet

Conflicts:
	TODO
parents 622530d9 2b839604
Bugs :
When no peer is avalaible, the setup crash without the --no-boot option
G : see below
U : this is still a bug to be solved
G : since the server is now a node it shouldn't ( the server will always
have a peer availabel which is himself )
To be done :
use the server as a bootstrap node
Use an algorithm to choose which connections to keep and/or establish
instead of pure randomness
......@@ -19,13 +14,10 @@ To be done :
Use the server events ( client connection/deconnection ) to do something
useful
In peers DB, remove some peers when they are too many of them -> remove the
dead peers
In peers DB, flag the dead peers so we only choose them if necessary and we can remove them if we have enought peers
Use a timeout for the peersDB
G : removing the dead peers should be enough
U : I was speaking of the server peers DB
G : the timeout is the duration of the certificate delivered ( 1y for now )
Use a timeout for the server peersDB so we can rflag unreachable peers and
remove the peers whose certificate is no longer valid
Specify a lease duration in ForwardViaUPnP
......@@ -71,23 +63,3 @@ To be discussed:
enought DB to ensure we can still choose a peer as if it was choosen
directly from the server. The requiered db size can be calculated from
the number of connections and the refresh time.
U : Remove the --no-boot option since we know when no node is avalaible
G : the no-boot option is only useful when the server knows no peer,
irl it should never happen, no-boot is a debug option
U : Ok, but the server knows when no peers is avalaible, doesn't he ?
G : Well when no peer is available the SQL request ( + next() method ) raise
a StopIteration exception
U : Well, I don't think this is a good thing. When not in debug, a node
cannot now if there is anyone else already connected
G : don't reconnect to server each time we repopulate in peers_db ?
U : From what I've read on the internet, when you create a server object,
you don't connect to the server, You only connect to the server once you
send a request for a methode and then you can automatically use the same
connection for 15sec
G : ok, it justs need testing ( for when some requests for the server will
require to be plugged in the network )
U : Use more than one boostrap node
G : we'll use the server as a bootstrap node
......@@ -17,7 +17,8 @@ def openvpn(hello_interval, *args, **kw):
utils.log(str(args), 5)
return subprocess.Popen(args, **kw)
def server(server_ip, network, max_clients, dh_path, pipe_fd, port, proto, hello_interval, *args, **kw):
def server(server_ip, network, max_clients, dh_path, pipe_fd, port, proto,
hello_interval, *args, **kw):
utils.log('Starting server', 3)
return openvpn(hello_interval,
'--tls-server',
......
......@@ -2,21 +2,63 @@ import os, random, traceback, time
import plib, utils, db
log = None
smooth = 0.3
class Connection:
def __init__(self, ip, write_pipe, hello, port, proto, iface, peer_id,
ovpn_args):
self.process = plib.client(ip, write_pipe, hello,
'--dev', iface, '--proto', proto, '--rport', str(port),
*ovpn_args, stdout=os.open(os.path.join(log,
'vifibnet.client.%s.log' % (peer_id,)),
os.O_WRONLY|os.O_CREAT|os.O_TRUNC) )
self.iface = iface
self._lastTrafic = self._getTrafic()
self._bandwidth = None
# TODO : update the stats
def refresh(self):
# Check that the connection is alive
if self.process.poll() != None:
utils.log('Connection with %s has failed with return code %s'
% (id, self.process.returncode), 3)
return False
trafic = self._getTrafic()
if self._bandwidth == None:
self._bandwidth = trafic - self._lastTrafic
else:
self._bandwidth = (1-smooth)*self._bandwidth + smooth*trafic
self._lastTrafic = trafic
utils.log('New bandwidth calculated on iface %s : %sb' % self._bandwidth, 4)
return True
def _getTrafic(self):
try:
f_rx = open('/sys/class/net/%s/statistics/rx_bytes' % self.iface, 'r')
f_tx = open('/sys/class/net/%s/statistics/tx_bytes' % self.iface, 'r')
return int(f_rx.read()) + int(f_tx.read())
except Exception: # TODO : change this
return 0
class TunnelManager:
def __init__(self, write_pipe, peer_db, openvpn_args, hello_interval, refresh, connection_count, refresh_rate):
def __init__(self, write_pipe, peer_db, openvpn_args, hello_interval,
refresh, connection_count, refresh_rate):
self._write_pipe = write_pipe
self._peer_db = peer_db
self._connection_dict = {}
self._ovpn_args = openvpn_args
self._hello = hello_interval
self._refresh_time = refresh
self.free_interface_set = set(('client1', 'client2', 'client3', 'client4', 'client5',
'client6', 'client7', 'client8', 'client9', 'client10'))
self.free_interface_set = set(('client1', 'client2', 'client3',
'client4', 'client5', 'client6',
'client7', 'client8', 'client9',
'client10', 'client11', 'client12'))
self.next_refresh = time.time()
# TODO : choose this automatically
self._client_count = connection_count/2
self._refresh_count = refresh_rate*self._client_count
......@@ -29,39 +71,41 @@ class TunnelManager:
def _cleanDeads(self):
for id in self._connection_dict.keys():
p, iface = self._connection_dict[id]
if p.poll() != None:
utils.log('Connection with %s has failed with return code %s' % (id, p.returncode), 3)
self.free_interface_set.add(iface)
self._peer_db.unusePeer(id)
del self._connection_dict[id]
if not self._connection_dict[id].refresh():
self._kill(id)
def _removeSomeTunnels(self):
for i in range(0, max(0, len(self._connection_dict) - self._client_count + self._refresh_count)):
for i in range(0, max(0, len(self._connection_dict) -
self._client_count + self._refresh_count)):
peer_id = random.choice(self._connection_dict.keys())
self._kill(peer_id)
def _kill(self, peer_id):
utils.log('Killing the connection with id ' + str(peer_id), 2)
p, iface = self._connection_dict.pop(peer_id)
p.kill()
self.free_interface_set.add(iface)
connection = self._connection_dict.pop(peer_id)
try:
connection.process.kill()
except OSError:
# If the process is already exited
pass
self.free_interface_set.add(connection.iface)
self._peer_db.unusePeer(peer_id)
def _makeNewTunnels(self):
#utils.log('Making %i new tunnels' % (self._client_count - len(self._connection_dict)), 3)
utils.log('Trying to make %i new tunnels' %
(self._client_count - len(self._connection_dict)), 3)
try:
for peer_id, ip, port, proto in self._peer_db.getUnusedPeers(self._client_count - len(self._connection_dict)):
utils.log('Establishing a connection with id %s (%s:%s)' % (peer_id, ip, port), 2)
for peer_id, ip, port, proto in self._peer_db.getUnusedPeers(
self._client_count - len(self._connection_dict)):
utils.log('Establishing a connection with id %s (%s:%s)'
% (peer_id, ip, port), 2)
iface = self.free_interface_set.pop()
self._connection_dict[peer_id] = (
plib.client( ip, self._write_pipe, self._hello,
'--dev', iface, '--proto', proto, '--rport', str(port), *self._ovpn_args,
stdout=os.open(os.path.join(log, 'vifibnet.client.%s.log' % (peer_id,)),
os.O_WRONLY|os.O_CREAT|os.O_TRUNC) ),
iface)
self._connection_dict[peer_id] = Connection(ip,
self._write_pipe, self._hello, port, proto, iface,
peer_id, self._ovpn_args)
self._peer_db.usePeer(peer_id)
except KeyError:
utils.log("Can't establish connection with %s : no available interface" % ip, 2)
utils.log("Can't establish connection with %s"
": no available interface" % ip, 2)
except Exception:
traceback.print_exc()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment