Initial network discovery prototype
This commit is contained in:
parent
829000e387
commit
1ee7b787ed
1 changed files with 96 additions and 0 deletions
96
Shared/Disc0very.py
Normal file
96
Shared/Disc0very.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
from socket import *
|
||||||
|
from random import getrandbits
|
||||||
|
from time import time
|
||||||
|
from time import sleep
|
||||||
|
import Utils
|
||||||
|
import Logging
|
||||||
|
from _thread import start_new_thread
|
||||||
|
|
||||||
|
HEY = "HEY".encode()
|
||||||
|
IDENT_SEED_LENGTH = 64
|
||||||
|
WHAT = "WHAT".encode()
|
||||||
|
|
||||||
|
|
||||||
|
class MissingInterfaceError(TypeError):
|
||||||
|
def __init__(self):
|
||||||
|
super(TypeError, self).__init__("platform requires interface parameter.")
|
||||||
|
|
||||||
|
|
||||||
|
class Disc0very:
|
||||||
|
def __init__(self, port, interface="eth0", max_peers=32):
|
||||||
|
self.port = port
|
||||||
|
self.ident = getrandbits(max_peers * 2)
|
||||||
|
self.sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
|
self.sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||||
|
self.sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
|
self.sock.bind(("", self.port))
|
||||||
|
self.discovering = False
|
||||||
|
self.enlisting = False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def discover(self, time_out=2):
|
||||||
|
if not self.enlisting:
|
||||||
|
self.discovering = True
|
||||||
|
self.sock.setblocking(False)
|
||||||
|
self.sock.sendto(HEY, ('255.255.255.255', self.port))
|
||||||
|
end_time = time() + time_out
|
||||||
|
servers = []
|
||||||
|
while time() < end_time:
|
||||||
|
try:
|
||||||
|
data = self.sock.recv(512)
|
||||||
|
if data != HEY:
|
||||||
|
servers.append(data)
|
||||||
|
except BlockingIOError:
|
||||||
|
sleep(0.2)
|
||||||
|
self.discovering = False
|
||||||
|
if len(servers) == 0:
|
||||||
|
return None
|
||||||
|
elif len(servers) > 1:
|
||||||
|
self.sock.sendto(WHAT, ('255.255.255.255', self.port))
|
||||||
|
else:
|
||||||
|
return servers[0]
|
||||||
|
|
||||||
|
|
||||||
|
def enlist(self, interface, blocking=False):
|
||||||
|
if not self.discovering:
|
||||||
|
if blocking:
|
||||||
|
self.__enlist(interface)
|
||||||
|
else:
|
||||||
|
start_new_thread(self.__enlist, (interface, ))
|
||||||
|
|
||||||
|
|
||||||
|
# Interface should always be provided when using a Wallaby
|
||||||
|
# because wlan0 and wlan1 have an IP address assigned
|
||||||
|
def __enlist(self, interface=None):
|
||||||
|
self.enlisting = True
|
||||||
|
self.sock.setblocking(True)
|
||||||
|
ip_address = Utils.get_ip_address(interface)
|
||||||
|
data = ""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = self.sock.recv(512)
|
||||||
|
except BlockingIOError:
|
||||||
|
sleep(0.1)
|
||||||
|
if data == HEY:
|
||||||
|
self.sock.sendto(ip_address.encode(), ('255.255.255.255', self.port))
|
||||||
|
elif data == WHAT:
|
||||||
|
Logging.error("Apparently more than one server is running. "
|
||||||
|
"Investigating...")
|
||||||
|
# Discover and if other server is found shutdown
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
print("starting")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from time import sleep
|
||||||
|
disc0very = Disc0very(3077)
|
||||||
|
server = disc0very.discover()
|
||||||
|
if not server:
|
||||||
|
print("enlisted")
|
||||||
|
disc0very.enlist(None, blocking=True)
|
||||||
|
else:
|
||||||
|
print(server)
|
Reference in a new issue