more...
This commit is contained in:
parent
2ee2bc178a
commit
10d2f35b7b
20 changed files with 1334 additions and 629 deletions
104
oml/localnodes.py
Normal file
104
oml/localnodes.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
import socket
|
||||
import thread
|
||||
import json
|
||||
import struct
|
||||
from threading import Thread
|
||||
|
||||
from settings import preferences, server, USER_ID
|
||||
from node.utils import get_public_ipv6
|
||||
|
||||
def can_connect(data):
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
s.settimeout(1)
|
||||
s.connect((data['host'], data['port']))
|
||||
s.close()
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
class LocalNodes(Thread):
|
||||
_active = True
|
||||
_nodes = {}
|
||||
|
||||
_BROADCAST = "ff02::1"
|
||||
_PORT = 9851
|
||||
TTL = 2
|
||||
|
||||
def __init__(self, app):
|
||||
self._app = app
|
||||
Thread.__init__(self)
|
||||
self.daemon = True
|
||||
self.start()
|
||||
self.host = get_public_ipv6()
|
||||
self.send()
|
||||
|
||||
def send(self):
|
||||
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
|
||||
ttl = struct.pack('@i', self.TTL)
|
||||
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl)
|
||||
message = json.dumps({
|
||||
'id': USER_ID,
|
||||
'username': preferences.get('username', 'anonymous'),
|
||||
'host': self.host,
|
||||
'port': server['node_port'],
|
||||
})
|
||||
s.sendto(message + '\0', (self._BROADCAST, self._PORT))
|
||||
|
||||
def receive(self):
|
||||
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
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:
|
||||
data, addr = s.recvfrom(1024)
|
||||
while data[-1] == '\0':
|
||||
data = data[:-1] # Strip trailing \0's
|
||||
data = self.validate(data)
|
||||
if data:
|
||||
if data['id'] not in self._nodes:
|
||||
thread.start_new_thread(self.new_node, (data, ))
|
||||
else:
|
||||
print 'UPDATE NODE', data
|
||||
self._nodes[data['id']] = data
|
||||
|
||||
def validate(self, data):
|
||||
try:
|
||||
data = json.loads(data)
|
||||
except:
|
||||
return None
|
||||
for key in ['id', 'username', 'host', 'port']:
|
||||
if key not in data:
|
||||
return None
|
||||
return data
|
||||
|
||||
def get(self, user_id):
|
||||
if user_id in self._nodes:
|
||||
if can_connect(self._nodes[user_id]):
|
||||
return self._nodes[user_id]
|
||||
|
||||
def new_node(self, data):
|
||||
print 'NEW NODE', data
|
||||
if can_connect(data):
|
||||
self._nodes[data['id']] = data
|
||||
with self._app.app_context():
|
||||
import user.models
|
||||
u = user.models.User.get_or_create(data['id'])
|
||||
u.info['username'] = data['username']
|
||||
u.info['local'] = data
|
||||
u.save()
|
||||
self.send()
|
||||
|
||||
def run(self):
|
||||
self.receive()
|
||||
|
||||
def join(self):
|
||||
self._active = False
|
||||
return Thread.join(self)
|
||||
Loading…
Add table
Add a link
Reference in a new issue