* lan server including discovery and publishing added (only ping implemented in server)
This commit is contained in:
		
							parent
							
								
									92c4109572
								
							
						
					
					
						commit
						3aec35ef33
					
				
					 9 changed files with 99 additions and 45 deletions
				
			
		|  | @ -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) |  | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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] | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -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 |  | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								src/runtests/lanservertest.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/runtests/lanservertest.py
									
										
									
									
									
										Normal 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 | ||||||
|  | @ -1 +1 @@ | ||||||
| 1584165158 | 1584339902 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue