local nodes

This commit is contained in:
j 2014-05-24 11:39:45 +02:00
parent d22c08e97c
commit bea8efe6c4

View file

@ -30,17 +30,14 @@ def can_connect(data):
logger.debug('can_connect failed') logger.debug('can_connect failed')
return False return False
class LocalNodes(Thread): class LocalNodesBase(Thread):
_active = True
_nodes = {}
_MODE = 6
_BROADCAST = "ff02::1"
_BROADCAST4 = "239.255.255.250"
_PORT = 9851 _PORT = 9851
TTL = 1 _TTL = 1
def __init__(self, app): def __init__(self, app, nodes):
self._active = True
self._nodes = nodes
self._app = app self._app = app
Thread.__init__(self) Thread.__init__(self)
if not server['localnode_discovery']: if not server['localnode_discovery']:
@ -59,49 +56,15 @@ class LocalNodes(Thread):
packet = json.dumps([sig, USER_ID, message]) packet = json.dumps([sig, USER_ID, message])
return packet return packet
def send(self): def get_socket(self):
if not server['localnode_discovery']: pass
return
if self._MODE == 4:
return self.send4()
packet = self.get_packet()
ttl = struct.pack('@i', self.TTL)
address = self._BROADCAST + get_interface()
addrs = socket.getaddrinfo(address, self._PORT, socket.AF_INET6, socket.SOCK_DGRAM)
addr = addrs[0]
(family, socktype, proto, canonname, sockaddr) = addr
s = socket.socket(family, socktype, proto)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl)
s.sendto(packet + '\0', sockaddr)
s.close()
def send4(self): def send(self):
logger.debug('send4') pass
packet = self.get_packet()
sockaddr = (self._BROADCAST4, self._PORT)
s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt (socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
s.sendto(packet + '\0', sockaddr)
s.close()
logger.debug('sent4')
'''
try:
s.sendto(packet + '\0', sockaddr)
s.close()
except:
logger.debug('send failed %s', )
return
'''
def receive(self): def receive(self):
if self._MODE == 4: s = self.get_socket()
return self.receive4()
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', self._PORT)) s.bind(('', self._PORT))
group_bin = socket.inet_pton(socket.AF_INET6, self._BROADCAST) + '\0'*4
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group_bin)
while self._active: while self._active:
data, addr = s.recvfrom(1024) data, addr = s.recvfrom(1024)
while data[-1] == '\0': while data[-1] == '\0':
@ -110,24 +73,6 @@ class LocalNodes(Thread):
if data: if data:
self.update_node(data) self.update_node(data)
def receive4(self):
logger.debug('receive4')
s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
mreq = struct.pack("=4sl", socket.inet_aton(self._BROADCAST4), socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
s.bind(('', self._PORT))
while self._active:
data, addr = s.recvfrom(1024)
logger.debug('receive4')
while data[-1] == '\0':
data = data[:-1] # Strip trailing \0's
logger.debug('receive4 %s', data)
data = self.verify(data)
if data:
self.update_node(data)
def verify(self, data): def verify(self, data):
try: try:
packet = json.loads(data) packet = json.loads(data)
@ -149,8 +94,7 @@ class LocalNodes(Thread):
if data['id'] != USER_ID: if data['id'] != USER_ID:
if data['id'] not in self._nodes: if data['id'] not in self._nodes:
thread.start_new_thread(self.new_node, (data, )) thread.start_new_thread(self.new_node, (data, ))
#else: elif can_connect(data):
# print 'UPDATE NODE', data
self._nodes[data['id']] = data self._nodes[data['id']] = data
def get(self, user_id): def get(self, user_id):
@ -171,15 +115,88 @@ class LocalNodes(Thread):
state.nodes.queue('add', u.id) state.nodes.queue('add', u.id)
self.send() self.send()
def get_ip(self):
pass
def run(self): def run(self):
self.host = get_public_ipv6() self.host = self.get_ip()
if not self.host:
logger.debug('no ipv6 detected, fall back to local ipv4 sharing')
self.host = get_local_ipv4()
self._MODE = 4
self.send() self.send()
self.receive() self.receive()
def join(self): def join(self):
self._active = False self._active = False
return Thread.join(self) return Thread.join(self)
class LocalNodes4(LocalNodesBase):
_BROADCAST = "239.255.255.250"
_TTL = 1
def send(self):
packet = self.get_packet()
sockaddr = (self._BROADCAST, self._PORT)
s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt (socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, self._TTL)
s.sendto(packet + '\0', sockaddr)
s.close()
def get_socket(self):
s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
mreq = struct.pack("=4sl", socket.inet_aton(self._BROADCAST), socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
return s
def get_ip(self):
return get_local_ipv4()
class LocalNodes6(LocalNodesBase):
_BROADCAST = "ff02::1"
def send(self):
logger.debug('send6')
packet = self.get_packet()
ttl = struct.pack('@i', self._TTL)
address = self._BROADCAST + get_interface()
addrs = socket.getaddrinfo(address, self._PORT, socket.AF_INET6, socket.SOCK_DGRAM)
addr = addrs[0]
(family, socktype, proto, canonname, sockaddr) = addr
s = socket.socket(family, socktype, proto)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl)
s.sendto(packet + '\0', sockaddr)
s.close()
def get_socket(self):
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
group_bin = socket.inet_pton(socket.AF_INET6, self._BROADCAST) + '\0'*4
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group_bin)
return s
def get_ip(self):
return get_public_ipv6()
class LocalNodes(object):
_nodes4 = None
_nodes6 = None
def __init__(self, app):
self._nodes = {}
self._app = app
if not server['localnode_discovery']:
return
self._nodes4 = LocalNodes4(app, self._nodes)
self._nodes6 = LocalNodes6(app, self._nodes)
def get(self, user_id):
if user_id in self._nodes:
if can_connect(self._nodes[user_id]):
return self._nodes[user_id]
def join(self):
if self._nodes4:
self._nodes4.join()
if self._nodes6:
self._nodes6.join()