Merge branch 'node-profiling' of gitlab.com:beardog/Onionr into node-profiling
This commit is contained in:
commit
34a970d008
@ -24,7 +24,7 @@ from gevent.wsgi import WSGIServer
|
|||||||
import sys, random, threading, hmac, hashlib, base64, time, math, os, logger, config
|
import sys, random, threading, hmac, hashlib, base64, time, math, os, logger, config
|
||||||
from core import Core
|
from core import Core
|
||||||
from onionrblockapi import Block
|
from onionrblockapi import Block
|
||||||
import onionrutils, onionrcrypto, blockimporter
|
import onionrutils, onionrcrypto, blockimporter, onionrevents as events
|
||||||
|
|
||||||
class API:
|
class API:
|
||||||
'''
|
'''
|
||||||
@ -94,6 +94,7 @@ class API:
|
|||||||
'''
|
'''
|
||||||
Simply define the request as not having yet failed, before every request.
|
Simply define the request as not having yet failed, before every request.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
self.requestFailed = False
|
self.requestFailed = False
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -116,20 +117,63 @@ class API:
|
|||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/client/ui/<path:path>')
|
@app.route('/www/private/<path:path>')
|
||||||
def webUI(path):
|
def www_private(path):
|
||||||
startTime = math.floor(time.time())
|
startTime = math.floor(time.time())
|
||||||
|
|
||||||
if request.args.get('timingToken') is None:
|
if request.args.get('timingToken') is None:
|
||||||
timingToken = ''
|
timingToken = ''
|
||||||
else:
|
else:
|
||||||
timingToken = request.args.get('timingToken')
|
timingToken = request.args.get('timingToken')
|
||||||
|
|
||||||
|
if not config.get("www.private.run", True):
|
||||||
|
abort(403)
|
||||||
|
|
||||||
self.validateHost('private')
|
self.validateHost('private')
|
||||||
|
|
||||||
endTime = math.floor(time.time())
|
endTime = math.floor(time.time())
|
||||||
elapsed = endTime - startTime
|
elapsed = endTime - startTime
|
||||||
|
|
||||||
if not hmac.compare_digest(timingToken, self.timeBypassToken):
|
if not hmac.compare_digest(timingToken, self.timeBypassToken):
|
||||||
if elapsed < self._privateDelayTime:
|
if elapsed < self._privateDelayTime:
|
||||||
time.sleep(self._privateDelayTime - elapsed)
|
time.sleep(self._privateDelayTime - elapsed)
|
||||||
return send_from_directory('static-data/ui/dist/', path)
|
|
||||||
|
return send_from_directory('static-data/www/private/', path)
|
||||||
|
|
||||||
|
@app.route('/www/public/<path:path>')
|
||||||
|
def www_public(path):
|
||||||
|
if not config.get("www.public.run", True):
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
self.validateHost('public')
|
||||||
|
|
||||||
|
return send_from_directory('static-data/www/public/', path)
|
||||||
|
|
||||||
|
@app.route('/ui/<path:path>')
|
||||||
|
def ui_private(path):
|
||||||
|
startTime = math.floor(time.time())
|
||||||
|
|
||||||
|
if request.args.get('timingToken') is None:
|
||||||
|
timingToken = ''
|
||||||
|
else:
|
||||||
|
timingToken = request.args.get('timingToken')
|
||||||
|
|
||||||
|
if not config.get("www.ui.run", True):
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
if config.get("www.ui.private", True):
|
||||||
|
self.validateHost('private')
|
||||||
|
else:
|
||||||
|
self.validateHost('public')
|
||||||
|
|
||||||
|
endTime = math.floor(time.time())
|
||||||
|
elapsed = endTime - startTime
|
||||||
|
|
||||||
|
if not hmac.compare_digest(timingToken, self.timeBypassToken):
|
||||||
|
if elapsed < self._privateDelayTime:
|
||||||
|
time.sleep(self._privateDelayTime - elapsed)
|
||||||
|
|
||||||
|
return send_from_directory('static-data/www/ui/dist/', path)
|
||||||
|
|
||||||
@app.route('/client/')
|
@app.route('/client/')
|
||||||
def private_handler():
|
def private_handler():
|
||||||
@ -150,6 +194,9 @@ class API:
|
|||||||
|
|
||||||
if not self.validateToken(token):
|
if not self.validateToken(token):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
events.event('webapi_private', onionr = None, data = {'action' : action, 'data' : data, 'timingToken' : timingToken, 'token' : token})
|
||||||
|
|
||||||
self.validateHost('private')
|
self.validateHost('private')
|
||||||
if action == 'hello':
|
if action == 'hello':
|
||||||
resp = Response('Hello, World! ' + request.host)
|
resp = Response('Hello, World! ' + request.host)
|
||||||
@ -198,12 +245,12 @@ class API:
|
|||||||
response['hash'] = hash
|
response['hash'] = hash
|
||||||
response['reason'] = 'Successfully wrote block to file'
|
response['reason'] = 'Successfully wrote block to file'
|
||||||
else:
|
else:
|
||||||
response['reason'] = 'Faield to save the block'
|
response['reason'] = 'Failed to save the block'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug('insertBlock api request failed', error = e)
|
logger.debug('insertBlock api request failed', error = e)
|
||||||
|
|
||||||
resp = Response(json.dumps(response))
|
resp = Response(json.dumps(response))
|
||||||
elif action in callbacks['private']:
|
elif action in API.callbacks['private']:
|
||||||
resp = Response(str(getCallback(action, scope = 'private')(request)))
|
resp = Response(str(getCallback(action, scope = 'private')(request)))
|
||||||
else:
|
else:
|
||||||
resp = Response('(O_o) Dude what? (invalid command)')
|
resp = Response('(O_o) Dude what? (invalid command)')
|
||||||
@ -257,6 +304,9 @@ class API:
|
|||||||
data = data
|
data = data
|
||||||
except:
|
except:
|
||||||
data = ''
|
data = ''
|
||||||
|
|
||||||
|
events.event('webapi_public', onionr = None, data = {'action' : action, 'data' : data, 'requestingPeer' : requestingPeer, 'request' : request})
|
||||||
|
|
||||||
if action == 'firstConnect':
|
if action == 'firstConnect':
|
||||||
pass
|
pass
|
||||||
elif action == 'ping':
|
elif action == 'ping':
|
||||||
@ -299,7 +349,7 @@ class API:
|
|||||||
peers = self._core.listPeers(getPow=True)
|
peers = self._core.listPeers(getPow=True)
|
||||||
response = ','.join(peers)
|
response = ','.join(peers)
|
||||||
resp = Response(response)
|
resp = Response(response)
|
||||||
elif action in callbacks['public']:
|
elif action in API.callbacks['public']:
|
||||||
resp = Response(str(getCallback(action, scope = 'public')(request)))
|
resp = Response(str(getCallback(action, scope = 'public')(request)))
|
||||||
else:
|
else:
|
||||||
resp = Response("")
|
resp = Response("")
|
||||||
@ -373,29 +423,29 @@ class API:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def setCallback(action, callback, scope = 'public'):
|
def setCallback(action, callback, scope = 'public'):
|
||||||
if not scope in callbacks:
|
if not scope in API.callbacks:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
callbacks[scope][action] = callback
|
API.callbacks[scope][action] = callback
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def removeCallback(action, scope = 'public'):
|
def removeCallback(action, scope = 'public'):
|
||||||
if (not scope in callbacks) or (not action in callbacks[scope]):
|
if (not scope in API.callbacks) or (not action in API.callbacks[scope]):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
del callbacks[scope][action]
|
del API.callbacks[scope][action]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getCallback(action, scope = 'public'):
|
def getCallback(action, scope = 'public'):
|
||||||
if (not scope in callbacks) or (not action in callbacks[scope]):
|
if (not scope in API.callbacks) or (not action in API.callbacks[scope]):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return callbacks[scope][action]
|
return API.callbacks[scope][action]
|
||||||
|
|
||||||
def getCallbacks(scope = None):
|
def getCallbacks(scope = None):
|
||||||
if (not scope is None) and (scope in callbacks):
|
if (not scope is None) and (scope in API.callbacks):
|
||||||
return callbacks[scope]
|
return API.callbacks[scope]
|
||||||
|
|
||||||
return callbacks
|
return API.callbacks
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
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 sys, os, core, config, json, onionrblockapi as block, requests, time, logger, threading, onionrplugins as plugins, base64, onionr
|
import sys, os, core, config, json, requests, time, logger, threading, base64, onionr
|
||||||
import onionrexceptions, onionrpeers
|
import onionrexceptions, onionrpeers, onionrevents as events, onionrplugins as plugins, onionrblockapi as block
|
||||||
from defusedxml import minidom
|
from defusedxml import minidom
|
||||||
|
|
||||||
class OnionrCommunicatorDaemon:
|
class OnionrCommunicatorDaemon:
|
||||||
@ -363,6 +363,8 @@ class OnionrCommunicatorDaemon:
|
|||||||
cmd = self._core.daemonQueue()
|
cmd = self._core.daemonQueue()
|
||||||
|
|
||||||
if cmd is not False:
|
if cmd is not False:
|
||||||
|
events.event('daemon_command', onionr = None, data = {'cmd' : cmd})
|
||||||
|
|
||||||
if cmd[0] == 'shutdown':
|
if cmd[0] == 'shutdown':
|
||||||
self.shutdown = True
|
self.shutdown = True
|
||||||
elif cmd[0] == 'announceNode':
|
elif cmd[0] == 'announceNode':
|
||||||
@ -381,6 +383,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
threading.Thread(target=self.uploadBlock).start()
|
threading.Thread(target=self.uploadBlock).start()
|
||||||
else:
|
else:
|
||||||
logger.info('Recieved daemonQueue command:' + cmd[0])
|
logger.info('Recieved daemonQueue command:' + cmd[0])
|
||||||
|
|
||||||
self.decrementThreadCount('daemonCommands')
|
self.decrementThreadCount('daemonCommands')
|
||||||
|
|
||||||
def uploadBlock(self):
|
def uploadBlock(self):
|
||||||
@ -427,6 +430,7 @@ class OnionrCommunicatorDaemon:
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
else:
|
else:
|
||||||
# This executes if the api is NOT detected to be running
|
# This executes if the api is NOT detected to be running
|
||||||
|
events.event('daemon_crash', onionr = None, data = {})
|
||||||
logger.error('Daemon detected API crash (or otherwise unable to reach API after long time), stopping...')
|
logger.error('Daemon detected API crash (or otherwise unable to reach API after long time), stopping...')
|
||||||
self.shutdown = True
|
self.shutdown = True
|
||||||
self.decrementThreadCount('detectAPICrash')
|
self.decrementThreadCount('detectAPICrash')
|
||||||
|
@ -100,7 +100,7 @@ DataDirectory data/tordata/
|
|||||||
logger.fatal('Failed to start Tor. Try killing any other Tor processes owned by this user.')
|
logger.fatal('Failed to start Tor. Try killing any other Tor processes owned by this user.')
|
||||||
return False
|
return False
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.fatal("Got keyboard interrupt")
|
logger.fatal("Got keyboard interrupt.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.debug('Finished starting Tor.', timestamp=True)
|
logger.debug('Finished starting Tor.', timestamp=True)
|
||||||
|
@ -40,9 +40,9 @@ except ImportError:
|
|||||||
raise Exception("You need the PySocks module (for use with socks5 proxy to use Tor)")
|
raise Exception("You need the PySocks module (for use with socks5 proxy to use Tor)")
|
||||||
|
|
||||||
ONIONR_TAGLINE = 'Anonymous P2P Platform - GPLv3 - https://Onionr.VoidNet.Tech'
|
ONIONR_TAGLINE = 'Anonymous P2P Platform - GPLv3 - https://Onionr.VoidNet.Tech'
|
||||||
ONIONR_VERSION = '0.1.0' # for debugging and stuff
|
ONIONR_VERSION = '0.1.1' # for debugging and stuff
|
||||||
ONIONR_VERSION_TUPLE = tuple(ONIONR_VERSION.split('.')) # (MAJOR, MINOR, VERSION)
|
ONIONR_VERSION_TUPLE = tuple(ONIONR_VERSION.split('.')) # (MAJOR, MINOR, VERSION)
|
||||||
API_VERSION = '4' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes knows how to communicate without learning too much information about you.
|
API_VERSION = '4' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes know how to communicate without learning too much information about you.
|
||||||
|
|
||||||
class Onionr:
|
class Onionr:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -33,10 +33,10 @@ def __event_caller(event_name, data = {}, onionr = None):
|
|||||||
try:
|
try:
|
||||||
call(plugins.get_plugin(plugin), event_name, data, get_pluginapi(onionr, data))
|
call(plugins.get_plugin(plugin), event_name, data, get_pluginapi(onionr, data))
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
logger.warn('Disabling nonexistant plugin \"' + plugin + '\"...')
|
logger.warn('Disabling nonexistant plugin "%s"...' % plugin)
|
||||||
plugins.disable(plugin, onionr, stop_event = False)
|
plugins.disable(plugin, onionr, stop_event = False)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn('Event \"' + event_name + '\" failed for plugin \"' + plugin + '\".')
|
logger.warn('Event "%s" failed for plugin "%s".' % (event_name, plugin))
|
||||||
logger.debug(str(e))
|
logger.debug(str(e))
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,5 +49,6 @@ class InvalidProof(Exception):
|
|||||||
# network level exceptions
|
# network level exceptions
|
||||||
class MissingPort(Exception):
|
class MissingPort(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class InvalidAddress(Exception):
|
class InvalidAddress(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -2,8 +2,26 @@
|
|||||||
"general" : {
|
"general" : {
|
||||||
"dev_mode": true,
|
"dev_mode": true,
|
||||||
"display_header" : true,
|
"display_header" : true,
|
||||||
"dc_response": true,
|
|
||||||
"dc_execcallbacks" : true
|
"direct_connect" : {
|
||||||
|
"respond" : true,
|
||||||
|
"execute_callbacks" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"www" : {
|
||||||
|
"public" : {
|
||||||
|
"run" : true
|
||||||
|
},
|
||||||
|
|
||||||
|
"private" : {
|
||||||
|
"run" : true
|
||||||
|
},
|
||||||
|
|
||||||
|
"ui" : {
|
||||||
|
"run" : true,
|
||||||
|
"private" : true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"client" : {
|
"client" : {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
Static files for Onionr's web ui, change at your own risk.
|
|
44
onionr/static-data/www/ui/README.md
Normal file
44
onionr/static-data/www/ui/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Onionr UI
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
The default GUI for Onionr
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
To compile the application, simply execute the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 compile.py
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are wanting to compile Onionr UI for another language, execute the following, replacing `[lang]` with the target language (supported languages include `eng` for English, `spa` para español, and `zho`为中国人):
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 compile.py [lang]
|
||||||
|
```
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
### Why "compile" anyway?
|
||||||
|
This web application is compiled for a few reasons:
|
||||||
|
1. To make it easier to update; this way, we do not have to update the header in every file if we want to change something about it.
|
||||||
|
2. To make the application smaller in size; there is less duplicated code when the code like the header and footer can be stored in an individual file rather than every file.
|
||||||
|
3. For multi-language support; with the Python "tags" feature, we can reference strings by variable name, and based on a language file, they can be dynamically inserted into the page on compilation.
|
||||||
|
4. For compile-time customizations.
|
||||||
|
|
||||||
|
### What exactly happens when you compile?
|
||||||
|
Upon compilation, files from the `src/` directory will be copied to `dist/` directory, header and footers will be injected in the proper places, and Python "tags" will be interpreted.
|
||||||
|
|
||||||
|
|
||||||
|
### How do Python "tags" work?
|
||||||
|
There are two types of Python "tags":
|
||||||
|
1. Logic tags (`<$ logic $>`): These tags allow you to perform logic at compile time. Example: `<$ import datetime; lastUpdate = datetime.datetime.now() $>`: This gets the current time while compiling, then stores it in `lastUpdate`.
|
||||||
|
2. Data tags (`<$= data $>`): These tags take whatever the return value of the statement in the tags is, and write it directly to the page. Example: `<$= 'This application was compiled at %s.' % lastUpdate $>`: This will write the message in the string in the tags to the page.
|
||||||
|
|
||||||
|
**Note:** Logic tags take a higher priority and will always be interpreted first.
|
||||||
|
|
||||||
|
### How does the language feature work?
|
||||||
|
When you use a data tag to write a string to the page (e.g. `<$= LANG.HELLO_WORLD $>`), the language feature simply takes dictionary of the language that is currently being used from the language map file (`lang.json`), then searches for the key (being the variable name after the characters `LANG.` in the data tag, like `HELLO_WORLD` from the example before). It then writes that string to the page. Language variables are always prefixed with `LANG.` and should always be uppercase (as they are a constant).
|
||||||
|
|
||||||
|
### I changed a few things in the application and tried to view the updates in my browser, but nothing changed!
|
||||||
|
You most likely forgot to compile. Try running `python3 compile.py` and check again. If you are still having issues, [open up an issue](https://gitlab.com/beardog/Onionr/issues/new?issue[title]=Onionr UI not updating after compiling).
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Loading…
Reference in New Issue
Block a user