work on direct connections

This commit is contained in:
Kevin Froman 2019-08-25 03:08:09 -05:00
parent 225f93106d
commit 9fc6e35fe4
10 changed files with 92 additions and 9 deletions

View File

@ -47,10 +47,9 @@ Onionr ships with various application plugins ready for use out of the box:
Currently usable: Currently usable:
* Mail * Mail
* Public anonymous chat * Public anonymous chat/message board
* Simple webpage hosting - Will be greatly extended * Simple webpage hosting - Will be greatly extended
* File sharing (Work in progress) * File sharing (Work in progress)
* Simple Message board
Not yet usable: Not yet usable:

View File

@ -17,11 +17,11 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
import threading import threading # For the client creation thread
from flask import Response from flask import Response # For direct connection management HTTP endpoints
from flask import Blueprint from flask import Blueprint # To make the direct connection management blueprint in the webUI
from flask import g from flask import g # Mainly to access the shared toomanyobjs object
import deadsimplekv import deadsimplekv
import filepaths import filepaths
@ -49,12 +49,16 @@ class DirectConnectionManagement:
def make_new_connection(pubkey): def make_new_connection(pubkey):
communicator = _get_communicator(g) communicator = _get_communicator(g)
resp = "pending" resp = "pending"
if pubkey in communicator.shared_state.get_by_string("ServicePool").bootstrap_pending:
return Response(resp)
if pubkey in communicator.direct_connection_clients: if pubkey in communicator.direct_connection_clients:
resp = communicator.direct_connection_clients[pubkey] resp = communicator.direct_connection_clients[pubkey]
else: else:
"""Spawn a thread that will create the client and eventually add it to the """Spawn a thread that will create the client and eventually add it to the
communicator.active_services communicator.active_services
""" """
threading.Thread(target=onionrservices.OnionrServices().create_client, args=[pubkey, communicator], daemon=True).start() threading.Thread(target=onionrservices.OnionrServices().create_client,
args=[pubkey, communicator], daemon=True).start()
return Response(resp) return Response(resp)

View File

@ -84,6 +84,9 @@ class InvalidAddress(Exception):
class InvalidAPIVersion(Exception): class InvalidAPIVersion(Exception):
pass pass
class Timeout(Exception):
pass
# file exceptions # file exceptions
class DiskAllocationReached(Exception): class DiskAllocationReached(Exception):

View File

@ -31,7 +31,6 @@ class OnionrServices:
self.servers = {} self.servers = {}
self.clients = {} self.clients = {}
self.shutdown = False self.shutdown = False
return
def create_server(self, peer, address, comm_inst): def create_server(self, peer, address, comm_inst):
''' '''
@ -55,7 +54,7 @@ class OnionrServices:
@staticmethod @staticmethod
def create_client(peer, comm_inst=None): def create_client(peer, comm_inst=None):
# Create ephemeral onion service to bootstrap connection # Create ephemeral onion service to bootstrap connection to server
if not comm_inst == None: if not comm_inst == None:
try: try:
return comm_inst.direct_connection_clients[peer] return comm_inst.direct_connection_clients[peer]

View File

@ -25,7 +25,16 @@ from netcontroller import get_open_port
from . import httpheaders from . import httpheaders
from onionrutils import stringvalidators, epoch from onionrutils import stringvalidators, epoch
import config, onionrblocks, filepaths import config, onionrblocks, filepaths
import onionrexceptions
import deadsimplekv as simplekv import deadsimplekv as simplekv
import warden
from . import pool
def __bootstrap_timeout(server: WSGIServer, timeout: int, signal_object):
time.sleep(timeout)
signal_object.timed_out = True
server.stop()
def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300): def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300):
''' '''
Bootstrap client services Bootstrap client services
@ -33,9 +42,17 @@ def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300):
if not stringvalidators.validate_pub_key(peer): if not stringvalidators.validate_pub_key(peer):
raise ValueError('Peer must be valid base32 ed25519 public key') raise ValueError('Peer must be valid base32 ed25519 public key')
connection_pool = None
# here we use a lambda for the timeout thread to set to true
timed_out = lambda: None
timed_out.timed_out = False
bootstrap_port = get_open_port() bootstrap_port = get_open_port()
bootstrap_app = Flask(__name__) bootstrap_app = Flask(__name__)
bootstrap_app.config['MAX_CONTENT_LENGTH'] = 1 * 1024
http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None) http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None)
try: try:
assert comm_inst is not None assert comm_inst is not None
@ -43,6 +60,7 @@ def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300):
pass pass
else: else:
comm_inst.service_greenlets.append(http_server) comm_inst.service_greenlets.append(http_server)
connection_pool = comm_inst.shared_state.get(pool.ServicePool)
bootstrap_address = '' bootstrap_address = ''
shutdown = False shutdown = False
@ -71,12 +89,16 @@ def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300):
return Response("") return Response("")
with Controller.from_port(port=config.get('tor.controlPort')) as controller: with Controller.from_port(port=config.get('tor.controlPort')) as controller:
connection_pool.bootstrap_pending.append(peer)
# Connect to the Tor process for Onionr # Connect to the Tor process for Onionr
controller.authenticate(config.get('tor.controlpassword')) controller.authenticate(config.get('tor.controlpassword'))
# Create the v3 onion service # Create the v3 onion service
response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, key_type = 'NEW', key_content = 'ED25519-V3', await_publication = True) response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, key_type = 'NEW', key_content = 'ED25519-V3', await_publication = True)
onionrblocks.insert(response.service_id, header='con', sign=True, encryptType='asym', onionrblocks.insert(response.service_id, header='con', sign=True, encryptType='asym',
asymPeer=peer, disableForward=True, expire=(epoch.get_epoch() + bootstrap_timeout)) asymPeer=peer, disableForward=True, expire=(epoch.get_epoch() + bootstrap_timeout))
threading.Thread(target=__bootstrap_timeout, args=[http_server, bootstrap_timeout], daemon=True)
# Run the bootstrap server # Run the bootstrap server
try: try:
http_server.serve_forever() http_server.serve_forever()
@ -86,5 +108,10 @@ def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300):
# Add the address to the client pool # Add the address to the client pool
if not comm_inst is None: if not comm_inst is None:
comm_inst.direct_connection_clients[peer] = response.service_id comm_inst.direct_connection_clients[peer] = response.service_id
connection_pool.bootstrap_pending.remove(peer)
if timed_out.timed_out:
raise onionrexceptions.Timeout
# Now that the bootstrap server has received a server, return the address # Now that the bootstrap server has received a server, return the address
return key_store.get(bs_id) return key_store.get(bs_id)

View File

@ -0,0 +1,29 @@
'''
Onionr - Private P2P Communication
Holds active onionrservices clients and servers
'''
'''
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/>.
'''
from onionrutils import epoch
class ServicePool:
def __init__(self):
self.servers = []
self.clients = []
self.bootstrap_pending = []
def add_server(self, service):
self.servers.append((service, epoch.get_epoch()))

View File

@ -0,0 +1,3 @@
from . import client # Client connection warden. Monitors & validates connection security.
from . import server # Server connection warden. Monitors and validates server security
from . import watchdog # Watchdog. Oversees running services for statistic collection and TTL control

View File

@ -0,0 +1,19 @@
'''
Onionr - Private P2P Communication
Bootstrap warden monitors the bootstrap server
'''
'''
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/>.
'''

View File

View File