work on lan transport, added service discovery logic
This commit is contained in:
parent
a8290e2ac3
commit
7bb95c3b87
38
src/lan/__init__.py
Normal file
38
src/lan/__init__.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
LAN manager
|
||||||
|
"""
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
from threading import Thread
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from toomanyobjs import TooMany
|
||||||
|
|
||||||
|
from . import server
|
||||||
|
from .client import Client
|
||||||
|
from .discover import learn_services, advertise_service
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class LANManager:
|
||||||
|
"""Initialize and start/top LAN transport threads."""
|
||||||
|
|
||||||
|
def __init__(self, too_many: "TooMany"):
|
||||||
|
self.too_many = too_many
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
Thread(target=learn_services, daemon=True).start()
|
||||||
|
Thread(target=advertise_service, daemon=True).start()
|
||||||
|
|
23
src/lan/client/__init__.py
Normal file
23
src/lan/client/__init__.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
LAN transport client thread
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
def __init__(self):
|
||||||
|
return
|
65
src/lan/discover.py
Normal file
65
src/lan/discover.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
Discover and publish private-network
|
||||||
|
"""
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from .getip import lan_ips
|
||||||
|
from utils.bettersleep import better_sleep
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
MCAST_GRP = '224.13.3.7'
|
||||||
|
MCAST_PORT = 1337
|
||||||
|
IS_ALL_GROUPS = True
|
||||||
|
ANNOUNCE_LOOP_SLEEP = 30
|
||||||
|
|
||||||
|
|
||||||
|
def learn_services():
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
if IS_ALL_GROUPS:
|
||||||
|
# on this port, receives ALL multicast groups
|
||||||
|
sock.bind(('', MCAST_PORT))
|
||||||
|
else:
|
||||||
|
# on this port, listen ONLY to MCAST_GRP
|
||||||
|
sock.bind((MCAST_GRP, MCAST_PORT))
|
||||||
|
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
|
||||||
|
|
||||||
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
rec_data = sock.recv(1024)
|
||||||
|
print('reced_data', rec_data)
|
||||||
|
|
||||||
|
sock.shutdown()
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
|
||||||
|
def advertise_service():
|
||||||
|
# regarding socket.IP_MULTICAST_TTL
|
||||||
|
# ---------------------------------
|
||||||
|
# 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)
|
||||||
|
MULTICAST_TTL = 3
|
||||||
|
ips = '-'.join(lan_ips)
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
|
||||||
|
while True:
|
||||||
|
sock.sendto(f"onionr-{ips}".encode('utf-8'), (MCAST_GRP, MCAST_PORT))
|
||||||
|
better_sleep(ANNOUNCE_LOOP_SLEEP)
|
||||||
|
sock.shutdown()
|
||||||
|
sock.close()
|
19
src/lan/getip.py
Normal file
19
src/lan/getip.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from ipaddress import IPv4Address
|
||||||
|
|
||||||
|
from ifaddr import get_adapters
|
||||||
|
|
||||||
|
lan_ips = []
|
||||||
|
|
||||||
|
for adapter in get_adapters():
|
||||||
|
for ip in adapter.ips:
|
||||||
|
ip = ip.ip
|
||||||
|
try:
|
||||||
|
ip = IPv4Address(ip)
|
||||||
|
if not ip.is_private or ip.is_loopback:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
# Raised if not ipv4 or not link local
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
lan_ips.append(ip.exploded)
|
||||||
|
|
18
src/lan/server/__init__.py
Normal file
18
src/lan/server/__init__.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
LAN transport server thread
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
@ -36,6 +36,7 @@ from utils.bettersleep import better_sleep
|
|||||||
from netcontroller.torcontrol.onionservicecreator import create_onion_service
|
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
|
||||||
"""
|
"""
|
||||||
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
|
||||||
@ -162,6 +163,7 @@ def daemon():
|
|||||||
|
|
||||||
events.event('init', threaded=False)
|
events.event('init', threaded=False)
|
||||||
events.event('daemon_start')
|
events.event('daemon_start')
|
||||||
|
LANManager(shared_state).start()
|
||||||
communicator.startCommunicator(shared_state)
|
communicator.startCommunicator(shared_state)
|
||||||
|
|
||||||
clean_ephemeral_services()
|
clean_ephemeral_services()
|
||||||
|
35
tests/integration-tests/test_lan_discover.py
Normal file
35
tests/integration-tests/test_lan_discover.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from unittest.mock import patch
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(".")
|
||||||
|
sys.path.append("src/")
|
||||||
|
import unittest, uuid
|
||||||
|
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
|
||||||
|
print("Test directory:", TEST_DIR)
|
||||||
|
os.environ["ONIONR_HOME"] = TEST_DIR
|
||||||
|
from utils import createdirs
|
||||||
|
from onionrcommands import parser
|
||||||
|
import onionrsetup as setup
|
||||||
|
from netcontroller.torcontrol import customtorrc
|
||||||
|
from utils import createdirs
|
||||||
|
from onionrsetup import setup_config, setup_default_plugins
|
||||||
|
from coredb import blockmetadb
|
||||||
|
from etc.onionrvalues import BLOCK_EXPORT_FILE_EXT
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
createdirs.create_dirs()
|
||||||
|
setup_config()
|
||||||
|
setup_default_plugins()
|
||||||
|
import config
|
||||||
|
from filepaths import export_location
|
||||||
|
|
||||||
|
class OnionrTests(unittest.TestCase):
|
||||||
|
def test_lan_discover(self):
|
||||||
|
testargs = ['onionr.py', 'start']
|
||||||
|
with patch.object(sys, 'argv', testargs):
|
||||||
|
try:
|
||||||
|
Thread(target=parser.register, daemon=True).start()
|
||||||
|
except SystemExit:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
unittest.main()
|
23
tests/test_get_lan_ips.py
Normal file
23
tests/test_get_lan_ips.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(".")
|
||||||
|
sys.path.append("src/")
|
||||||
|
import uuid
|
||||||
|
import ipaddress
|
||||||
|
TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/'
|
||||||
|
print("Test directory:", TEST_DIR)
|
||||||
|
os.environ["ONIONR_HOME"] = TEST_DIR
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from lan.getip import lan_ips
|
||||||
|
|
||||||
|
class TestGetLanIps(unittest.TestCase):
|
||||||
|
def test_get_lan_ips(self):
|
||||||
|
self.assertGreater(len(lan_ips), 0)
|
||||||
|
for ip in lan_ips:
|
||||||
|
ip = ipaddress.IPv4Address(ip)
|
||||||
|
if not ip.is_private or ip.is_multicast or ip.is_reserved:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
unittest.main()
|
0
tests/test_lan_server_thread.py
Normal file
0
tests/test_lan_server_thread.py
Normal file
Loading…
Reference in New Issue
Block a user