* lan server including discovery and publishing added (only ping implemented in server)

This commit is contained in:
Kevin Froman 2020-03-16 02:28:41 -05:00
parent 92c4109572
commit 3aec35ef33
9 changed files with 99 additions and 45 deletions

View File

@ -7,7 +7,6 @@ from threading import Thread
if TYPE_CHECKING: if TYPE_CHECKING:
from toomanyobjs import TooMany from toomanyobjs import TooMany
from . import server
from .client import Client from .client import Client
from .discover import learn_services, advertise_service from .discover import learn_services, advertise_service
""" """
@ -31,11 +30,10 @@ class LANManager:
def __init__(self, too_many: "TooMany"): def __init__(self, too_many: "TooMany"):
self.too_many = too_many self.too_many = too_many
self.peers: "exploded IP Address string" = set() self.peers: "exploded IP Address string" = []
def start(self): def start(self):
Thread(target=learn_services, args=[[]], daemon=True).start() Thread(target=learn_services, args=[self.peers], daemon=True).start()
Thread(target=advertise_service, daemon=True).start() Thread(target=advertise_service, daemon=True).start()
#Thread(tra)

View File

@ -70,13 +70,16 @@ def learn_services(lan_service_list: List):
# no return intended, list modified by reference # no return intended, list modified by reference
def advertise_service(): def advertise_service(specific_ips=None):
# regarding socket.IP_MULTICAST_TTL # regarding socket.IP_MULTICAST_TTL
# --------------------------------- # ---------------------------------
# for all packets sent, after three hops on the network the packet will not # for all packets sent, after three hops on the network the packet will not
# be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html) # be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html)
MULTICAST_TTL = 3 MULTICAST_TTL = 3
ips = '-'.join(lan_ips) if specific_ips is None:
ips = '-'.join(lan_ips)
else:
ips = '-'.join(specific_ips)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)

View File

@ -17,3 +17,10 @@ for adapter in get_adapters():
else: else:
lan_ips.append(ip.exploded) lan_ips.append(ip.exploded)
for ip in lan_ips:
if '192.168' in ip:
best_ip = ip
break
else:
best_ip = lan_ips[0]

View File

@ -4,6 +4,14 @@ LAN transport server thread
""" """
from gevent.pywsgi import WSGIServer from gevent.pywsgi import WSGIServer
from flask import Flask from flask import Flask
from flask import Response
from gevent import sleep
from httpapi.fdsafehandler import FDSafeHandler
from netcontroller import get_open_port
import config
from coredb.blockmetadb import get_block_list
from lan.getip import lan_ips, best_ip
""" """
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -24,10 +32,24 @@ class LANServer:
def __init__(self, shared_state): def __init__(self, shared_state):
app = Flask(__name__) app = Flask(__name__)
self.app = app self.app = app
self.host = config.get('lan.bind_ip', '')
self.server = None
if self.host == '':
self.host = best_ip
self.port = None
@app.route("/") @app.route('/blist/<time>')
def get_block_list_for_lan(time):
return Response(get_block_list(dateRec=time).split('\n'))
@app.route("/ping")
def ping(): def ping():
return "pong!" return Response("pong!")
def start_server(self):
self.server = WSGIServer((self.host, get_open_port()),
self.app, log=None,
handler_class=FDSafeHandler)
self.port = self.server.server_port
self.server.serve_forever()
def start_server():
return

View File

@ -37,6 +37,7 @@ from netcontroller.torcontrol.onionservicecreator import create_onion_service
from .quotes import QUOTE from .quotes import QUOTE
from utils.boxprint import bordered from utils.boxprint import bordered
from lan import LANManager from lan import LANManager
from lan.server import LANServer
""" """
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -123,37 +124,37 @@ def daemon():
use_existing_tor = config.get('tor.use_existing_tor', False) use_existing_tor = config.get('tor.use_existing_tor', False)
if not offline_mode: if not offline_mode:
if config.get('transports.tor', True):
if use_existing_tor:
try:
os.mkdir(filepaths.tor_hs_loc)
except FileExistsError:
pass
net.socksPort = config.get('tor.existing_socks_port')
try:
net.myID = create_onion_service(
port=net.apiServerIP + ':' + str(net.hsPort))[0]
except IncorrectPassword:
logger.error('Invalid Tor control password', terminal=True)
localcommand.local_command('shutdown')
cleanup.delete_run_files()
sys.exit(1)
if use_existing_tor: if not net.myID.endswith('.onion'):
try: net.myID += '.onion'
os.mkdir(filepaths.tor_hs_loc) with open(filepaths.tor_hs_address_file, 'w') as tor_file:
except FileExistsError: tor_file.write(net.myID)
pass else:
net.socksPort = config.get('tor.existing_socks_port') logger.info('Tor is starting...', terminal=True)
try: if not net.startTor():
net.myID = create_onion_service( localcommand.local_command('shutdown')
port=net.apiServerIP + ':' + str(net.hsPort))[0] cleanup.delete_run_files()
except IncorrectPassword: sys.exit(1)
logger.error('Invalid Tor control password', terminal=True) if len(net.myID) > 0 and security_level == 0:
localcommand.local_command('shutdown') logger.debug('Started .onion service: %s' %
cleanup.delete_run_files() (logger.colors.underline + net.myID))
sys.exit(1) else:
logger.debug('.onion service disabled')
if not net.myID.endswith('.onion'):
net.myID += '.onion'
with open(filepaths.tor_hs_address_file, 'w') as tor_file:
tor_file.write(net.myID)
else:
logger.info('Tor is starting...', terminal=True)
if not net.startTor():
localcommand.local_command('shutdown')
cleanup.delete_run_files()
sys.exit(1)
if len(net.myID) > 0 and security_level == 0:
logger.debug('Started .onion service: %s' %
(logger.colors.underline + net.myID))
else:
logger.debug('.onion service disabled')
logger.info('Using public key: %s' % logger.info('Using public key: %s' %
(logger.colors.underline + (logger.colors.underline +
@ -163,6 +164,7 @@ def daemon():
events.event('init', threaded=False) events.event('init', threaded=False)
events.event('daemon_start') events.event('daemon_start')
Thread(target=LANServer(shared_state).start_server, daemon=True).start()
LANManager(shared_state).start() LANManager(shared_state).start()
communicator.startCommunicator(shared_state) communicator.startCommunicator(shared_state)

View File

@ -13,6 +13,7 @@ from .webpasstest import webpass_test
from .osver import test_os_ver_endpoint from .osver import test_os_ver_endpoint
from .clearnettor import test_clearnet_tor_request from .clearnettor import test_clearnet_tor_request
from .housekeeping import test_inserted_housekeeping from .housekeeping import test_inserted_housekeeping
from .lanservertest import test_lan_server
""" """
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -36,7 +37,8 @@ RUN_TESTS = [uicheck.check_ui,
webpass_test, webpass_test,
test_os_ver_endpoint, test_os_ver_endpoint,
test_clearnet_tor_request, test_clearnet_tor_request,
test_inserted_housekeeping test_inserted_housekeeping,
test_lan_server
] ]
SUCCESS_FILE = os.path.dirname(os.path.realpath(__file__)) + '/../../tests/runtime-result.txt' SUCCESS_FILE = os.path.dirname(os.path.realpath(__file__)) + '/../../tests/runtime-result.txt'
@ -59,13 +61,19 @@ class OnionrRunTestManager:
try: try:
for i in RUN_TESTS: for i in RUN_TESTS:
last = i last = i
logger.info("[RUNTIME TEST] " + last.__name__ + " started",
terminal=True)
i(self) i(self)
logger.info("[RUNTIME TEST] " + last.__name__ + " passed") logger.info("[RUNTIME TEST] " + last.__name__ + " passed",
terminal=True)
except (ValueError, AttributeError): except (ValueError, AttributeError):
logger.error(last.__name__ + ' failed') logger.error(last.__name__ + ' failed assertions', terminal=True)
except Exception as e:
logger.error(last.__name__ + ' failed with non-asserting exception')
logger.error(str(e))
else: else:
ep = str(epoch.get_epoch()) ep = str(epoch.get_epoch())
logger.info(f'All runtime tests passed at {ep}') logger.info(f'All runtime tests passed at {ep}', terminal=True)
with open(SUCCESS_FILE, 'w') as f: with open(SUCCESS_FILE, 'w') as f:
f.write(ep) f.write(ep)

View File

@ -0,0 +1,14 @@
import requests
from lan.getip import best_ip
def test_lan_server(testmanager):
for i in range(1024, 65536):
try:
if requests.get(f"http://{best_ip}:{i}/ping").text == 'pong!':
break
except requests.exceptions.ConnectionError:
pass
else:
raise ValueError

View File

@ -1 +1 @@
1584165158 1584339902