diff --git a/onionr/communicator.py b/onionr/communicator.py index 12fbabbc..37c0cbdb 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -24,7 +24,7 @@ from dependencies import secrets from utils import networkmerger import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block from communicatorutils import onionrdaemontools -import onionrsockets, onionr, onionrproofs +import onionrservices, onionr, onionrproofs from communicatorutils import onionrcommunicatortimers, proxypicker OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers @@ -126,9 +126,9 @@ class OnionrCommunicatorDaemon: #forwardSecrecyTimer.count = (forwardSecrecyTimer.frequency - 990) if config.get('general.socket_servers'): - self.socketServer = threading.Thread(target=onionrsockets.OnionrSocketServer, args=(self._core,)) - self.socketServer.start() - self.socketClient = onionrsockets.OnionrSocketClient(self._core) + self.services = onionrservices.OnionrServices(self._core) + else: + self.services = None # Main daemon loop, mainly for calling timers, don't do any complex operations here to avoid locking try: @@ -565,19 +565,6 @@ class OnionrCommunicatorDaemon: i.count = (i.frequency - 1) elif cmd[0] == 'uploadBlock': self.blocksToUpload.append(cmd[1]) - elif cmd[0] == 'startSocket': - # Create our own socket server - socketInfo = json.loads(cmd[1]) - socketInfo['id'] = uuid.uuid4() - self._core.startSocket = socketInfo - elif cmd[0] == 'addSocket': - # Socket server was created for us - socketInfo = json.loads(cmd[1]) - peer = socketInfo['peer'] - reason = socketInfo['reason'] - threading.Thread(target=self.socketClient.startSocket, args=(peer, reason)).start() - else: - logger.info('Recieved daemonQueue command:' + cmd[0]) if cmd[0] not in ('', None): if response != '': diff --git a/onionr/core.py b/onionr/core.py index 1cbce026..ecbe2d73 100755 --- a/onionr/core.py +++ b/onionr/core.py @@ -353,7 +353,6 @@ class Core: conn = sqlite3.connect(self.queueDB, timeout=30) c = conn.cursor() t = (command, data, date, responseID) - try: c.execute('INSERT INTO commands (command, data, date, responseID) VALUES(?, ?, ?, ?)', t) conn.commit() diff --git a/onionr/onionrservices/__init__.py b/onionr/onionrservices/__init__.py index 68612cf7..5ea0ef3e 100644 --- a/onionr/onionrservices/__init__.py +++ b/onionr/onionrservices/__init__.py @@ -1,17 +1,29 @@ +import time import stem import core -from . import connectionserver, connectionclient, bootstrapservice +from . import connectionserver, bootstrapservice class OnionrServices: def __init__(self, onionr_core): assert isinstance(onionr_core, core.Core) self._core = onionr_core self.servers = {} self.clients = {} + self.shutdown = False return - def create_server(self): - return - + def create_server(self, peer, address): + assert self._core._utils.validateID(address) + BOOTSTRAP_TRIES = 10 + TRY_WAIT = 3 + for x in range(BOOTSTRAP_TRIES): + if self._core._utils.doGetRequest('http://' + address + '/ping') == 'pong!': + connectionserver.ConnectionServer(peer, address, core_inst=self._core) + return True + else: + time.sleep(TRY_WAIT) + else: + return False + def create_client(self, peer): # Create ephemeral onion service to bootstrap connection address = bootstrapservice.bootstrap_client_service(peer) diff --git a/onionr/onionrservices/bootstrapservice.py b/onionr/onionrservices/bootstrapservice.py index 7a2c3823..b0b2fb7d 100644 --- a/onionr/onionrservices/bootstrapservice.py +++ b/onionr/onionrservices/bootstrapservice.py @@ -23,7 +23,7 @@ from flask import Flask import core from netcontroller import getOpenPort -def bootstrap_client_service(peer, core_inst=None): +def bootstrap_client_service(peer, core_inst=None, bootstrap_timeout=120): ''' Bootstrap client services ''' @@ -32,10 +32,10 @@ def bootstrap_client_service(peer, core_inst=None): if not core_inst._utils.validatePubKey(peer): raise ValueError('Peer must be valid base32 ed25519 public key') - - http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None) + bootstrap_port = getOpenPort() - bootstrap_app = flask.Flask(__name__) + bootstrap_app = Flask(__name__) + http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None) bootstrap_address = '' @@ -50,14 +50,14 @@ def bootstrap_client_service(peer, core_inst=None): bootstrap_address = address http_server.stop() - with Controller.from_port() as controller: + with Controller.from_port(port=core_inst.config.get('tor.controlPort')) as controller: # Connect to the Tor process for Onionr - controller.authenticate() + controller.authenticate(core_inst.config.get('tor.controlpassword')) # Create the v3 onion service - response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, await_publication = True, key_type='ED25519-V3') + response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, await_publication = True, key_content = 'ED25519-V3') - core_inst.insertBlock(response.hostname, header='con', sign=True, encryptType='asym', - asymPeer=peer, disableForward=True) + core_inst.insertBlock(response.service_id, header='con', sign=True, encryptType='asym', + asymPeer=peer, disableForward=True, expire=(core_inst._utils.getEpoch() + bootstrap_timeout)) # Run the bootstrap server http_server.serve_forever() diff --git a/onionr/onionrservices/connectionserver.py b/onionr/onionrservices/connectionserver.py index d602d8ce..54ff03c3 100644 --- a/onionr/onionrservices/connectionserver.py +++ b/onionr/onionrservices/connectionserver.py @@ -1,4 +1,27 @@ +import stem, flask +import core class ConnectionServer: - def __init__(self): - return - \ No newline at end of file + def __init__(self, peer, address, core_inst=None): + if core_inst is None: + self.core_inst = core.Core() + else: + self.core_inst = core_inst + + if not core_inst._utils.validatePubKey(peer): + raise ValueError('Peer must be valid base32 ed25519 public key') + + service_app = flask.Flask(__name__) + service_port = getOpenPort() + http_server = WSGIServer(('127.0.0.1', service_port), service_app, log=None) + + @service_app.route('/ping') + def get_ping(): + return "pong!" + + with Controller.from_port(port=core_inst.config.get('tor.controlPort')) as controller: + # Connect to the Tor process for Onionr + controller.authenticate(core_inst.config.get('tor.controlpassword')) + # Create the v3 onion service + response = controller.create_ephemeral_hidden_service({80: service_port}, await_publication = True, key_type='ED25519-V3') + logger.info('hosting on ' + response.service_id) + http_server.serve_forever() \ No newline at end of file diff --git a/onionr/static-data/default-plugins/metadataprocessor/main.py b/onionr/static-data/default-plugins/metadataprocessor/main.py index e7277c7d..54f7dc18 100755 --- a/onionr/static-data/default-plugins/metadataprocessor/main.py +++ b/onionr/static-data/default-plugins/metadataprocessor/main.py @@ -46,6 +46,8 @@ def on_processblocks(api, data=None): myBlock = api.data['block'] blockType = api.data['type'] logger.info('blockType is ' + blockType) + utils = api.get_utils() + core = api.get_core() # Process specific block types @@ -54,26 +56,12 @@ def on_processblocks(api, data=None): if api.data['validSig'] == True: _processForwardKey(api, myBlock) # socket blocks - elif blockType == 'socket': + elif blockType == 'con': if api.data['validSig'] == True and myBlock.decrypted: # we check if it is decrypted as a way of seeing if it was for us - logger.info('Detected socket advertised to us...') - try: - address = myBlock.getMetadata('address') - except KeyError: - raise onionrexceptions.MissingAddress("Missing address for new socket") - try: - port = myBlock.getMetadata('port') - except KeyError: - raise ValueError("Missing port for new socket") - try: - reason = myBlock.getMetadata('reason') - except KeyError: - raise ValueError("Missing socket reason") - - socketInfo = json.dumps({'peer': api.data['signer'], 'address': address, 'port': port, 'create': False, 'reason': reason}) - api.get_core().daemonQueueAdd('addSocket', socketInfo) - else: - logger.warn("socket is not for us or is invalid") + myBlock.bcontent = utils.bytesToStr(myBlock.bcontent) + if utils.validateID('%s.onion' % (myBlock.bcontent,)): + logger.info('Detected socket advertised to us...') + core.keyStore.put('con', (myBlock.content, myBlock.signer)) def on_init(api, data = None):