Commit dc4ef785 by Guillaume Bury

Server listen both ipv4 and ipv6

1 parent 409ebea5
#!/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 functools import wraps
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
from OpenSSL import crypto
import traceback
IPV6_V6ONLY = 26
SOL_IPV6 = 41
class RequestHandler(SimpleXMLRPCRequestHandler):
def _dispatch(self, method, 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):
def __init__(self):
......@@ -20,7 +35,6 @@ class main(object):
parser = argparse.ArgumentParser(
description='Peer discovery http server for vifibnet')
_ = parser.add_argument
_('host', help='Address of the host server')
_('port', type=int, help='Port of the host server')
_('--db', required=True,
help='Path to database file')
......@@ -38,7 +52,8 @@ class main(object):
prefix text primary key not null,
ip text 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 (
token text primary key not null,
email text not null,
......@@ -66,9 +81,19 @@ class main(object):
print "Network prefix : %s/%u" % (self.network, len(self.network))
# Starting server
server = SimpleXMLRPCServer((self.config.host, self.config.port), requestHandler=RequestHandler, allow_none=True)
server.register_instance(self)
server.serve_forever()
server4 = SimpleXMLRPCServer4(('0.0.0.0', self.config.port), requestHandler=RequestHandler, allow_none=True)
server4.register_instance(self)
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):
while True:
......@@ -142,12 +167,13 @@ class main(object):
def getBootstrapPeer(self, handler):
# 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()
def declare(self, handler, address):
ip, port, proto = address
client_address, _ = handler.client_address
client_address, ip, port, proto = address
#client_address, _ = handler.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')
if client_ip.startswith(self.network):
......@@ -169,7 +195,5 @@ class main(object):
print "sending peers"
return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall()
if __name__ == "__main__":
main()
......@@ -48,7 +48,8 @@ def main():
boot_ip, boot_port, boot_proto = s.getBootstrapPeer()
# Generating dh file
subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048'])
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'])
# Store cert and key
with open(os.path.join(config.dir, 'cert.key'), 'w') as f:
......@@ -66,8 +67,10 @@ def main():
ip TEXT NOT NULL,
port INTEGER 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_address ON peers(ip, port, proto)")
self.db.execute("INSERT INTO peers (ip, port, proto) VALUES (?,?,?)", (boot_ip, boot_port, boot_proto))
except sqlite3.OperationalError, e:
if e.args[0] == 'table peers already exists':
......
......@@ -23,17 +23,18 @@ class PeersDB:
try:
self.db.execute("UPDATE peers SET used = 0")
except sqlite3.OperationalError, e:
if e.args[0] != 'no such table: peers':
if e.args[0] == 'no such table: peers':
raise RuntimeError
def populate(self, n):
# TODO: don't reconnect to server each time ?
log.log('Connecting to remote server', 3)
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
port = 1194
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.execute("DELETE FROM peers WHERE ip = ?", (config.external_ip,))
......@@ -78,7 +79,10 @@ def startBabel(**kw):
]
if 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():
global config
......@@ -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))
startNewConnection(config.client_count, write_pipe)
peers_db.populate(10)
# Timed refresh initializing
next_refresh = time.time() + config.refresh_time
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!