Commit dc4ef785 authored by Guillaume Bury's avatar Guillaume Bury

Server listen both ipv4 and ipv6

parent 409ebea5
#!/usr/bin/env python #!/usr/bin/env python
import argparse, math, random, smtplib, sqlite3, string, struct, socket, time import argparse, math, random, select, smtplib, sqlite3, string, struct, socket, time
from email.mime.text import MIMEText from email.mime.text import MIMEText
from functools import wraps from functools import wraps
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
from OpenSSL import crypto from OpenSSL import crypto
import traceback import traceback
IPV6_V6ONLY = 26
SOL_IPV6 = 41
class RequestHandler(SimpleXMLRPCRequestHandler): class RequestHandler(SimpleXMLRPCRequestHandler):
def _dispatch(self, method, params): def _dispatch(self, method, params):
return self.server._dispatch(method, (self,) + params) return self.server._dispatch(method, (self,) + params)
class SimpleXMLRPCServer4(SimpleXMLRPCServer):
allow_reuse_address = True
class SimpleXMLRPCServer6(SimpleXMLRPCServer4):
address_family = socket.AF_INET6
def server_bind(self):
self.socket.setsockopt(SOL_IPV6, IPV6_V6ONLY, 1)
SimpleXMLRPCServer4.server_bind(self)
class main(object): class main(object):
def __init__(self): def __init__(self):
...@@ -20,7 +35,6 @@ class main(object): ...@@ -20,7 +35,6 @@ class main(object):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Peer discovery http server for vifibnet') description='Peer discovery http server for vifibnet')
_ = parser.add_argument _ = parser.add_argument
_('host', help='Address of the host server')
_('port', type=int, help='Port of the host server') _('port', type=int, help='Port of the host server')
_('--db', required=True, _('--db', required=True,
help='Path to database file') help='Path to database file')
...@@ -38,7 +52,8 @@ class main(object): ...@@ -38,7 +52,8 @@ class main(object):
prefix text primary key not null, prefix text primary key not null,
ip text not null, ip text not null,
port integer not null, port integer not null,
proto text not null)""") proto text not null,
date integer default (strftime('%s','now')))""")
self.db.execute("""CREATE TABLE IF NOT EXISTS tokens ( self.db.execute("""CREATE TABLE IF NOT EXISTS tokens (
token text primary key not null, token text primary key not null,
email text not null, email text not null,
...@@ -66,9 +81,19 @@ class main(object): ...@@ -66,9 +81,19 @@ class main(object):
print "Network prefix : %s/%u" % (self.network, len(self.network)) print "Network prefix : %s/%u" % (self.network, len(self.network))
# Starting server # Starting server
server = SimpleXMLRPCServer((self.config.host, self.config.port), requestHandler=RequestHandler, allow_none=True) server4 = SimpleXMLRPCServer4(('0.0.0.0', self.config.port), requestHandler=RequestHandler, allow_none=True)
server.register_instance(self) server4.register_instance(self)
server.serve_forever() server6 = SimpleXMLRPCServer6(('::', self.config.port), requestHandler=RequestHandler, allow_none=True)
server6.register_instance(self)
while True:
try:
r, w, e = select.select([server4, server6], [], [])
except (OSError, select.error) as e:
if e.args[0] != errno.EINTR:
raise
else:
for r in r:
r._handle_request_noblock()
def requestToken(self, handler, email): def requestToken(self, handler, email):
while True: while True:
...@@ -142,12 +167,13 @@ class main(object): ...@@ -142,12 +167,13 @@ class main(object):
def getBootstrapPeer(self, handler): def getBootstrapPeer(self, handler):
# TODO: Insert a flag column for bootstrap ready servers in peers # TODO: Insert a flag column for bootstrap ready servers in peers
# ( servers which shouldn't go down or change ip and port as opposed to servers owned by particulars ) # ( servers which shouldn't go down or change ip and port as opposed to servers owned by particulars )
# that way, we also ascertain that the server sent is not the new node....
return self.db.execute("SELECT ip, port proto FROM peers ORDER BY random() LIMIT 1").next() return self.db.execute("SELECT ip, port proto FROM peers ORDER BY random() LIMIT 1").next()
def declare(self, handler, address): def declare(self, handler, address):
ip, port, proto = address client_address, ip, port, proto = address
client_address, _ = handler.client_address #client_address, _ = handler.client_address
client_ip1, client_ip2 = struct.unpack('>QQ', socket.inet_pton(socket.AF_INET6, client_address)) client_ip1, client_ip2 = struct.unpack('>QQ', socket.inet_pton(socket.AF_INET6, client_address))
client_ip = bin(client_ip1)[2:].rjust(64, '0') + bin(client_ip2)[2:].rjust(64, '0') client_ip = bin(client_ip1)[2:].rjust(64, '0') + bin(client_ip2)[2:].rjust(64, '0')
if client_ip.startswith(self.network): if client_ip.startswith(self.network):
...@@ -169,7 +195,5 @@ class main(object): ...@@ -169,7 +195,5 @@ class main(object):
print "sending peers" print "sending peers"
return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall() return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall()
if __name__ == "__main__": if __name__ == "__main__":
main() main()
...@@ -48,6 +48,7 @@ def main(): ...@@ -48,6 +48,7 @@ def main():
boot_ip, boot_port, boot_proto = s.getBootstrapPeer() boot_ip, boot_port, boot_proto = s.getBootstrapPeer()
# Generating dh file # Generating dh file
if not os.access(os.path.join(config.dir, 'dh2048.pem'), os.F_OK):
subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048']) subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048'])
# Store cert and key # Store cert and key
...@@ -66,8 +67,10 @@ def main(): ...@@ -66,8 +67,10 @@ def main():
ip TEXT NOT NULL, ip TEXT NOT NULL,
port INTEGER NOT NULL, port INTEGER NOT NULL,
proto TEXT NOT NULL, proto TEXT NOT NULL,
used INTEGER NOT NULL default 0)""") used INTEGER NOT NULL default 0,
date INTEGER DEFAULT strftime('%s', 'now'))""")
self.db.execute("CREATE INDEX _peers_used ON peers(used)") self.db.execute("CREATE INDEX _peers_used ON peers(used)")
self.db.execute("CREATE INDEX _peers_address ON peers(ip, port, proto)")
self.db.execute("INSERT INTO peers (ip, port, proto) VALUES (?,?,?)", (boot_ip, boot_port, boot_proto)) self.db.execute("INSERT INTO peers (ip, port, proto) VALUES (?,?,?)", (boot_ip, boot_port, boot_proto))
except sqlite3.OperationalError, e: except sqlite3.OperationalError, e:
if e.args[0] == 'table peers already exists': if e.args[0] == 'table peers already exists':
......
...@@ -23,17 +23,18 @@ class PeersDB: ...@@ -23,17 +23,18 @@ class PeersDB:
try: try:
self.db.execute("UPDATE peers SET used = 0") self.db.execute("UPDATE peers SET used = 0")
except sqlite3.OperationalError, e: except sqlite3.OperationalError, e:
if e.args[0] != 'no such table: peers': if e.args[0] == 'no such table: peers':
raise RuntimeError raise RuntimeError
def populate(self, n): def populate(self, n):
# TODO: don't reconnect to server each time ?
log.log('Connecting to remote server', 3) log.log('Connecting to remote server', 3)
self.proxy = xmlrpclib.ServerProxy('http://%s:%u' % (config.server, config.server_port)) self.proxy = xmlrpclib.ServerProxy('http://%s:%u' % (config.server, config.server_port))
log.log('Populating Peers DB', 2) log.log('Updating peers database : populating', 2)
# TODO: determine port and proto # TODO: determine port and proto
port = 1194 port = 1194
proto = 'udp' proto = 'udp'
new_peer_list = self.proxy.getPeerList(n, (config.external_ip, port, proto)) new_peer_list = self.proxy.getPeerList(n, (config.internal_ip, config.external_ip, port, proto))
self.db.executemany("INSERT OR REPLACE INTO peers (ip, port, proto) VALUES (?,?,?)", new_peer_list) self.db.executemany("INSERT OR REPLACE INTO peers (ip, port, proto) VALUES (?,?,?)", new_peer_list)
self.db.execute("DELETE FROM peers WHERE ip = ?", (config.external_ip,)) self.db.execute("DELETE FROM peers WHERE ip = ?", (config.external_ip,))
...@@ -78,7 +79,10 @@ def startBabel(**kw): ...@@ -78,7 +79,10 @@ def startBabel(**kw):
] ]
if config.babel_state: if config.babel_state:
args += '-S', config.babel_state args += '-S', config.babel_state
return subprocess.Popen(args + ['vifibnet'] + list(free_interface_set), **kw) args = args + ['vifibnet'] + list(free_interface_set)
if config.verbose >= 5:
print args
return subprocess.Popen(args, **kw)
def getConfig(): def getConfig():
global config global config
...@@ -230,6 +234,8 @@ def main(): ...@@ -230,6 +234,8 @@ def main():
stdout=os.open(os.path.join(config.log, 'vifibnet.server.log'), os.O_WRONLY | os.O_CREAT | os.O_TRUNC)) stdout=os.open(os.path.join(config.log, 'vifibnet.server.log'), os.O_WRONLY | os.O_CREAT | os.O_TRUNC))
startNewConnection(config.client_count, write_pipe) startNewConnection(config.client_count, write_pipe)
peers_db.populate(10)
# Timed refresh initializing # Timed refresh initializing
next_refresh = time.time() + config.refresh_time next_refresh = time.time() + config.refresh_time
......
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