diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 91a0e227..f5a31c5d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,7 +27,7 @@ And most importantly, please be patient. Onionr is an open source project done b ## Asking Questions -If you need help with Onionr, you can ask in our +If you need help with Onionr, you can contact the devs (be polite and remember this is a volunteer-driven non-profit project). ## Contributing Code diff --git a/Makefile b/Makefile index 7e235b4f..c3616e3d 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/onionr test: - @./run-linux stop + @./onionr.sh stop @sleep 1 @rm -rf onionr/data-backup @mv onionr/data onionr/data-backup | true > /dev/null 2>&1 @@ -29,15 +29,15 @@ test: soft-reset: @echo "Soft-resetting Onionr..." rm -f onionr/data/blocks/*.dat onionr/data/*.db onionr/data/block-nonces.dat | true > /dev/null 2>&1 - @./run-linux version | grep -v "Failed" --color=always + @./onionr.sh version | grep -v "Failed" --color=always reset: @echo "Hard-resetting Onionr..." rm -rf onionr/data/ | true > /dev/null 2>&1 cd onionr/static-data/www/ui/; rm -rf ./dist; python compile.py - #@./RUN-LINUX.sh version | grep -v "Failed" --color=always + #@./onionr.sh.sh version | grep -v "Failed" --color=always plugins-reset: @echo "Resetting plugins..." rm -rf onionr/data/plugins/ | true > /dev/null 2>&1 - @./run-linux version | grep -v "Failed" --color=always + @./onionr.sh version | grep -v "Failed" --color=always diff --git a/onionr-daemon-linux b/onionr-daemon-linux deleted file mode 100644 index d72ac015..00000000 --- a/onionr-daemon-linux +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/sh -nohup ./run-linux start & disown diff --git a/onionr/api.py b/onionr/api.py index a10a9163..358b64ad 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -17,9 +17,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' +from gevent.pywsgi import WSGIServer +import gevent.monkey +gevent.monkey.patch_socket() import flask, cgi from flask import request, Response, abort, send_from_directory -from gevent.pywsgi import WSGIServer import sys, random, threading, hmac, hashlib, base64, time, math, os, json, socket import core from onionrblockapi import Block @@ -238,6 +240,7 @@ class API: self.debug = debug self._privateDelayTime = 3 self._core = core.Core() + self.startTime = self._core._utils.getEpoch() self._crypto = onionrcrypto.OnionrCrypto(self._core) self._utils = onionrutils.OnionrUtils(self._core) app = flask.Flask(__name__) @@ -301,18 +304,20 @@ class API: @app.route('/queueResponseAdd/', methods=['post']) def queueResponseAdd(name): + print('added',name) self.queueResponse[name] = request.form['data'] return Response('success') @app.route('/queueResponse/') def queueResponse(name): - resp = '' + resp = 'failure' try: resp = self.queueResponse[name] except KeyError: pass else: del self.queueResponse[name] + print(name, resp) return Response(resp) @app.route('/ping') @@ -321,7 +326,7 @@ class API: @app.route('/', endpoint='onionrhome') def hello(): - return Response("Welcome to Onionr") + return send_from_directory('static-data/www/private/', 'index.html') @app.route('/getblocksbytype/') def getBlocksByType(name): @@ -375,6 +380,14 @@ class API: except AttributeError: pass return Response("bye") + + @app.route('/getstats') + def getStats(): + return Response(self._core.serializer.getStats()) + + @app.route('/getuptime') + def showUptime(): + return Response(str(self.getUptime())) self.httpServer = WSGIServer((self.host, bindPort), app, log=None) self.httpServer.serve_forever() @@ -397,3 +410,6 @@ class API: return True except TypeError: return False + + def getUptime(self): + return self._utils.getEpoch() - self.startTime \ No newline at end of file diff --git a/onionr/communicator2.py b/onionr/communicator2.py index 0458aa74..95c84b32 100755 --- a/onionr/communicator2.py +++ b/onionr/communicator2.py @@ -486,7 +486,10 @@ class OnionrCommunicatorDaemon: logger.debug('Status check; looks good.') open(self._core.dataDir + '.runcheck', 'w+').close() elif cmd[0] == 'connectedPeers': + print('yup') response = '\n'.join(list(self.onlinePeers)).strip() + if response == '': + response = 'none' elif cmd[0] == 'pex': for i in self.timers: if i.timerFunction.__name__ == 'lookupAdders': @@ -507,7 +510,7 @@ class OnionrCommunicatorDaemon: else: logger.info('Recieved daemonQueue command:' + cmd[0]) - if cmd[4] != '' and cmd[0] not in ('', None): + if cmd[0] not in ('', None): if response != '': self._core._utils.localCommand('queueResponseAdd/' + cmd[4], post=True, postData={'data': response}) response = '' diff --git a/onionr/core.py b/onionr/core.py index 35e9bb11..987a6940 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -22,7 +22,7 @@ from onionrblockapi import Block import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues import onionrblacklist, onionrchat, onionrusers -import dbcreator, onionrstorage +import dbcreator, onionrstorage, serializeddata if sys.version_info < (3, 6): try: @@ -101,6 +101,7 @@ class Core: # Initialize the crypto object self._crypto = onionrcrypto.OnionrCrypto(self) self._blacklist = onionrblacklist.OnionrBlackList(self) + self.serializer = serializeddata.SerializedData(self) except Exception as error: logger.error('Failed to initialize core Onionr library.', error=error) @@ -386,6 +387,24 @@ class Core: assert len(responseID) > 0 resp = self._utils.localCommand('queueResponse/' + responseID) return resp + + def daemonQueueWaitForResponse(self, responseID='', checkFreqSecs=1): + resp = 'failure' + while resp == 'failure': + resp = self.daemonQueueGetResponse(responseID) + time.sleep(1) + print(resp) + return resp + + def daemonQueueSimple(self, command, data='', checkFreqSecs=1): + ''' + A simplified way to use the daemon queue. Will register a command (with optional data) and wait, return the data + Not always useful, but saves time + LOC in some cases. + This is a blocking function, so be careful. + ''' + responseID = str(uuid.uuid4()) # generate unique response ID + self.daemonQueueAdd(command, data=data, responseID=responseID) + return self.daemonQueueWaitForResponse(responseID, checkFreqSecs) def clearDaemonQueue(self): ''' diff --git a/onionr/onionr.py b/onionr/onionr.py index e4f4b9f1..c213c0f9 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -180,6 +180,9 @@ class Onionr: 'add-site': self.addWebpage, 'addsite': self.addWebpage, + 'openhome': self.openHome, + 'open-home': self.openHome, + 'get-file': self.getFile, 'getfile': self.getFile, @@ -240,7 +243,8 @@ class Onionr: 'introduce': 'Introduce your node to the public Onionr network', 'friend': '[add|remove] [public key/id]', 'add-id': 'Generate a new ID (key pair)', - 'change-id': 'Change active ID' + 'change-id': 'Change active ID', + 'open-home': 'Open your node\'s home/info screen' } # initialize plugins @@ -274,6 +278,14 @@ class Onionr: for detail in details: logger.info('%s%s: \n%s%s\n' % (logger.colors.fg.lightgreen, detail, logger.colors.fg.green, details[detail]), sensitive = True) + def openHome(self): + try: + url = self.onionrUtils.getClientAPIServer() + except FileNotFoundError: + logger.error('Onionr seems to not be running (could not get api host)') + else: + webbrowser.open_new_tab('http://%s/#%s' % (url, config.get('client.webpassword'))) + def addID(self): try: sys.argv[2] @@ -409,8 +421,11 @@ class Onionr: except KeyboardInterrupt: break if not type(peers) is None: - if peers not in ('', None): - print(peers) + if peers not in ('', 'failure', None): + if peers != False: + print(peers) + else: + print('Daemon probably not running. Unable to list connected peers.') break def listPeers(self): diff --git a/onionr/onionrpeers.py b/onionr/onionrpeers.py index e0a509c4..8a88d649 100644 --- a/onionr/onionrpeers.py +++ b/onionr/onionrpeers.py @@ -49,8 +49,8 @@ class PeerProfiles: def getConnectTime(self): try: - self.connectTime = self.coreInst.getAddressInfo(self.address, 'lastConnect') - except KeyError: + self.connectTime = int(self.coreInst.getAddressInfo(self.address, 'lastConnect')) + except (KeyError, ValueError, TypeError) as e: pass def saveScore(self): @@ -83,7 +83,6 @@ def getScoreSortedPeerList(coreInst): # Sort peers by their score, greatest to least, and then last connected time peerList = sorted(peerScores, key=peerScores.get, reverse=True) peerList = sorted(peerTimes, key=peerTimes.get, reverse=True) - print(peerList) return peerList def peerCleanup(coreInst): diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index 883b9756..7207756e 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -150,6 +150,17 @@ class OnionrUtils: except Exception as error: logger.error('Failed to read my address.', error = error) return None + + def getClientAPIServer(self): + retData = '' + try: + with open(self._core.privateApiHostFile, 'r') as host: + hostname = host.read() + except FileNotFoundError: + raise FileNotFoundError + else: + retData += '%s:%s' % (hostname, config.get('client.client.port')) + return retData def localCommand(self, command, data='', silent = True, post=False, postData = {}): ''' @@ -163,8 +174,7 @@ class OnionrUtils: waited = 0 while hostname == '': try: - with open(self._core.privateApiHostFile, 'r') as host: - hostname = host.read() + hostname = self.getClientAPIServer() except FileNotFoundError: time.sleep(1) waited += 1 @@ -172,12 +182,13 @@ class OnionrUtils: return False if data != '': data = '&data=' + urllib.parse.quote_plus(data) - payload = 'http://%s:%s/%s%s' % (hostname, config.get('client.client.port'), command, data) + payload = 'http://%s/%s%s' % (hostname, command, data) + print(payload,config.get('client.webpassword')) try: if post: - retData = requests.post(payload, data=postData, headers={'token': config.get('client.webpassword')}).text + retData = requests.post(payload, data=postData, headers={'token': config.get('client.webpassword')}, timeout=(15, 30)).text else: - retData = requests.get(payload, headers={'token': config.get('client.webpassword')}).text + retData = requests.get(payload, headers={'token': config.get('client.webpassword')}, timeout=(15, 30)).text except Exception as error: if not silent: logger.error('Failed to make local request (command: %s):%s' % (command, error)) diff --git a/onionr/static-data/default-plugins/cliui/main.py b/onionr/static-data/default-plugins/cliui/main.py index 323b9419..c7c88acf 100644 --- a/onionr/static-data/default-plugins/cliui/main.py +++ b/onionr/static-data/default-plugins/cliui/main.py @@ -19,7 +19,7 @@ ''' # Imports some useful libraries -import logger, config, threading, time, uuid, subprocess +import logger, config, threading, time, uuid, subprocess, sys from onionrblockapi import Block plugin_name = 'cliui' diff --git a/onionr/static-data/www/board/index.html b/onionr/static-data/www/board/index.html index df48e912..ffc47159 100644 --- a/onionr/static-data/www/board/index.html +++ b/onionr/static-data/www/board/index.html @@ -2,6 +2,7 @@ + OnionrBoard diff --git a/run-linux b/run-linux deleted file mode 100755 index 286a0f7f..00000000 --- a/run-linux +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cd "$(dirname "$0")" -cd onionr/ -./onionr.py "$@"