work on torgossip
This commit is contained in:
parent
4b36e9d3da
commit
7fba65c459
@ -2,6 +2,7 @@
|
||||
|
||||
This file handles all incoming http requests to the client, using Flask
|
||||
"""
|
||||
import http
|
||||
from typing import Dict
|
||||
import hmac
|
||||
|
||||
@ -77,6 +78,7 @@ class PrivateAPI:
|
||||
"""Start client gevent API web server with flask client app."""
|
||||
waitforsetvar.wait_for_set_var(self, "_too_many")
|
||||
fd_handler = httpapi.fdsafehandler.FDSafeHandler
|
||||
self._too_many.add(httpapi.wrappedfunctions.SubProcVDFGenerator(self._too_many))
|
||||
self.publicAPI = self._too_many.get( # pylint: disable=E1101
|
||||
public.PublicAPI)
|
||||
self.httpServer = WSGIServer((self.host, self.bindPort),
|
||||
|
@ -23,7 +23,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
def store_block(block: 'Kasten', safe_db: 'SafeDB'):
|
||||
def store_block(block: 'Kasten', safe_db: 'SafeDB', own_block=False):
|
||||
# This does not handle validation of blocks
|
||||
# safe_db is initialized by the daemon when starting normally
|
||||
# so any other commands need to initialize it seperately
|
||||
|
@ -1,16 +1,23 @@
|
||||
from base64 import b85encode
|
||||
import os
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
import ujson as json
|
||||
|
||||
import kasten
|
||||
|
||||
from onionrplugins import onionrevents
|
||||
from blockio import store_block
|
||||
from onionrblocks.generators.anonvdf import AnonVDFGenerator
|
||||
|
||||
_DIR = os.path.dirname(os.path.realpath(__file__)) + '/../'
|
||||
|
||||
|
||||
def vdf_block(data, data_type, ttl, **metadata):
|
||||
try:
|
||||
data = data.encode('utf-8')
|
||||
except AttributeError:
|
||||
pass
|
||||
data = b85encode(data)
|
||||
generated = subprocess.Popen(
|
||||
[
|
||||
@ -25,3 +32,14 @@ def vdf_block(data, data_type, ttl, **metadata):
|
||||
generated[:64], generated[64:],
|
||||
AnonVDFGenerator, auto_check_generator=True)
|
||||
|
||||
|
||||
def gen_and_store_vdf_block(shared_state, *args, **kwargs):
|
||||
safe_db = shared_state.get_by_string('SafeDB')
|
||||
k = vdf_block(*args, **kwargs)
|
||||
store_block(
|
||||
k,
|
||||
safe_db,
|
||||
own_block=True
|
||||
)
|
||||
onionrevents.event('blockcreated', data=shared_state, threaded=True)
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
"""
|
||||
Onionr - Private P2P Communication
|
||||
|
||||
This file registers plugin's flask blueprints for the client http server
|
||||
Register plugin's flask blueprints for the client http server
|
||||
"""
|
||||
import onionrplugins
|
||||
import config
|
||||
|
||||
from . import wrappedfunctions
|
||||
"""
|
||||
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
|
||||
@ -17,8 +21,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import onionrplugins
|
||||
import config
|
||||
|
||||
|
||||
def load_plugin_blueprints(flaskapp, blueprint: str = 'flask_blueprint'):
|
||||
"""Iterate enabled plugins and load any http endpoints they have"""
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
view and interact with onionr sites
|
||||
"""
|
||||
import traceback
|
||||
|
||||
from flask import Blueprint, Response, request, abort, g
|
||||
import ujson as json
|
||||
"""
|
||||
@ -33,9 +35,10 @@ def serialized(name: str) -> Response:
|
||||
resp = str(resp)
|
||||
return Response(resp, content_type='application/octet-stream')
|
||||
except Exception as e:
|
||||
return Response(repr(e), content_type='text/plain', status=500)
|
||||
return Response(traceback.format_exc(e), content_type='text/plain', status=500)
|
||||
|
||||
initial = g.too_many.get_by_string(name.split('.')[0])
|
||||
print('initial', initial)
|
||||
for c, i in enumerate(name.split('.')):
|
||||
if i and c != 0:
|
||||
attr = getattr(initial, i)
|
||||
@ -44,11 +47,16 @@ def serialized(name: str) -> Response:
|
||||
try:
|
||||
js = request.get_json(force=True)
|
||||
print('json', js, type(js))
|
||||
if not isinstance(js, dict):
|
||||
data = json.loads(js)
|
||||
args = data['args']
|
||||
del data['args']
|
||||
else:
|
||||
data = js
|
||||
args = js['args']
|
||||
del js['args']
|
||||
except (TypeError, ValueError) as e:
|
||||
print(repr(e))
|
||||
print(traceback.format_exc())
|
||||
data = {}
|
||||
args = []
|
||||
print('data', data)
|
||||
|
11
src/httpapi/wrappedfunctions/__init__.py
Normal file
11
src/httpapi/wrappedfunctions/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
from blockio import subprocgenerate
|
||||
|
||||
|
||||
class SubProcVDFGenerator:
|
||||
def __init__(self, shared_state):
|
||||
self.shared_state = shared_state
|
||||
|
||||
def gen_and_store_vdf_block(self, *args, **kwargs):
|
||||
|
||||
return subprocgenerate.gen_and_store_vdf_block(
|
||||
self.shared_state, *args, **kwargs)
|
@ -19,6 +19,7 @@ from .lanservertest import test_lan_server
|
||||
from .sneakernettest import test_sneakernet_import
|
||||
from .dnsrebindingtest import test_dns_rebinding
|
||||
from .serviceonlinetest import test_service_online
|
||||
from .wrappedfunctionstest import test_vdf_create_and_store
|
||||
"""
|
||||
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
|
||||
@ -46,7 +47,8 @@ RUN_TESTS = [uicheck.check_ui,
|
||||
test_lan_server,
|
||||
test_sneakernet_import,
|
||||
test_dns_rebinding,
|
||||
test_service_online
|
||||
test_service_online,
|
||||
test_vdf_create_and_store
|
||||
]
|
||||
|
||||
SUCCESS_FILE = os.path.dirname(os.path.realpath(__file__)) + '/../../tests/runtime-result.txt'
|
||||
|
29
src/runtests/wrappedfunctionstest.py
Normal file
29
src/runtests/wrappedfunctionstest.py
Normal file
@ -0,0 +1,29 @@
|
||||
from time import sleep
|
||||
from secrets import token_hex
|
||||
|
||||
import blockio
|
||||
import logger
|
||||
from onionrutils.localcommand import local_command
|
||||
from blockio import list_all_blocks
|
||||
|
||||
|
||||
def test_vdf_create_and_store(testmanager):
|
||||
# data, data_type, ttl, **metadata
|
||||
db = testmanager._too_many.get_by_string('SafeDB')
|
||||
bls = list_all_blocks(db)
|
||||
b_data = "test" + token_hex(5)
|
||||
res = local_command(
|
||||
'/serialized/SubProcVDFGenerator.gen_and_store_vdf_block', post=True, post_data={"args": [b_data, "txt", 6000]}, is_json=True)
|
||||
|
||||
print(res)
|
||||
|
||||
while len(list_all_blocks(db)) == len(bls):
|
||||
sleep(1)
|
||||
for i in list_all_blocks(db):
|
||||
i = bytes(i)
|
||||
if blockio.load_block(i, db).get_packed().decode('utf-8') == b_data:
|
||||
break
|
||||
else:
|
||||
logger.error("Block was not generated", terminal=True)
|
||||
raise ValueError
|
||||
|
@ -5,18 +5,12 @@ This default plugin handles "flow" messages
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import deadsimplekv as simplekv
|
||||
from utils import identifyhome, reconstructhash
|
||||
from coredb import blockmetadb
|
||||
import threading
|
||||
import time
|
||||
import locale
|
||||
from oldblocks.onionrblockapi import Block
|
||||
import logger
|
||||
import oldblocks
|
||||
from onionrutils import escapeansi, epoch, bytesconverter
|
||||
|
||||
import locale
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
from blockio.subprocgenerate import gen_and_store_vdf_block
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||
# import after path insert
|
||||
import flowapi # noqa
|
||||
@ -39,138 +33,13 @@ flask_blueprint = flowapi.flask_blueprint
|
||||
security_whitelist = ['circles.circlesstatic', 'circles.circlesindex']
|
||||
|
||||
plugin_name = 'circles'
|
||||
PLUGIN_VERSION = '0.1.0'
|
||||
|
||||
EXPIRE_TIME = 43200
|
||||
|
||||
class OnionrFlow:
|
||||
def __init__(self):
|
||||
self.alreadyOutputed = []
|
||||
self.flowRunning = False
|
||||
self.channel = ""
|
||||
return
|
||||
|
||||
def start(self):
|
||||
logger.warn(
|
||||
"Please note: everything said here is public, " +
|
||||
"even if a random channel name is used.", terminal=True)
|
||||
message = ""
|
||||
self.flowRunning = True
|
||||
try:
|
||||
self.channel = logger.readline(
|
||||
"Enter a channel name or none for default:").strip()
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
self.flowRunning = False
|
||||
newThread = threading.Thread(target=self.showOutput, daemon=True)
|
||||
newThread.start()
|
||||
while self.flowRunning:
|
||||
if self.channel == "":
|
||||
self.channel = "global"
|
||||
try:
|
||||
message = logger.readline(f'\nInsert message into {plugin_name}:').strip().replace(
|
||||
'\n', '\\n').replace('\r', '\\r')
|
||||
except EOFError:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
self.flowRunning = False
|
||||
else:
|
||||
if message == "q":
|
||||
self.flowRunning = False
|
||||
expireTime = epoch.get_epoch() + EXPIRE_TIME
|
||||
if len(message) > 0:
|
||||
logger.info('Inserting message as block...', terminal=True)
|
||||
oldblocks.insert(message, header='brd',
|
||||
expire=expireTime,
|
||||
meta = {
|
||||
'ch': self.channel})
|
||||
|
||||
logger.info(f"{plugin_name} is exiting, goodbye", terminal=True)
|
||||
return
|
||||
|
||||
def showOutput(self):
|
||||
while isinstance(self.channel, type(None)) and self.flowRunning:
|
||||
time.sleep(1)
|
||||
try:
|
||||
while self.flowRunning:
|
||||
for block in blockmetadb.get_blocks_by_type('brd'):
|
||||
if block in self.alreadyOutputed:
|
||||
continue
|
||||
block = Block(block)
|
||||
b_hash = bytesconverter.bytes_to_str(block.getHash())
|
||||
if block.getMetadata('ch') != self.channel:
|
||||
continue
|
||||
if not self.flowRunning:
|
||||
break
|
||||
logger.info('\n------------------------',
|
||||
prompt=False, terminal=True)
|
||||
content = block.getContent()
|
||||
# Escape new lines, remove trailing whitespace, and escape ansi sequences
|
||||
content = escapeansi.escape_ANSI(content.replace(
|
||||
b'\n', b'\\n').replace(b'\r', b'\\r').strip().decode('utf-8'))
|
||||
logger.info(block.getDate().strftime(
|
||||
"%m/%d %H:%M") + ' - ' +
|
||||
logger.colors.reset + content,
|
||||
prompt=False, terminal=True)
|
||||
self.alreadyOutputed.append(b_hash)
|
||||
time.sleep(5)
|
||||
except KeyboardInterrupt:
|
||||
self.flowRunning = False
|
||||
PLUGIN_VERSION = '1.0.0'
|
||||
|
||||
|
||||
def on_circles_cmd(api, data=None):
|
||||
OnionrFlow().start()
|
||||
message = ""
|
||||
while message != "-q":
|
||||
message = input("Enter message")
|
||||
gen_and_store_vdf_block()
|
||||
|
||||
|
||||
def on_circlesend_cmd(api, data=None):
|
||||
err_msg = "Second arg is board name, third is quoted message"
|
||||
try:
|
||||
sys.argv[2]
|
||||
except IndexError:
|
||||
logger.error(err_msg, terminal=True)
|
||||
try:
|
||||
sys.argv[3]
|
||||
except IndexError:
|
||||
logger.error(err_msg, terminal=True)
|
||||
|
||||
bl = oldblocks.insert(sys.argv[3], header='brd',
|
||||
expire=(EXPIRE_TIME + epoch.get_epoch()),
|
||||
meta={'ch': sys.argv[2]})
|
||||
print(bl)
|
||||
|
||||
|
||||
|
||||
def on_softreset(api, data=None):
|
||||
try:
|
||||
os.remove(identifyhome.identify_home() + '/board-index.cache.json')
|
||||
logger.info('Cleared Circles board cache')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
def on_processblocks(api, data=None):
|
||||
metadata = data['block'].bmetadata # Get the block metadata
|
||||
if data['type'] != 'brd':
|
||||
return
|
||||
|
||||
b_hash = reconstructhash.deconstruct_hash(
|
||||
data['block'].hash) # Get the 0-truncated block hash
|
||||
board_cache = simplekv.DeadSimpleKV(identifyhome.identify_home(
|
||||
) + '/board-index.cache.json', flush_on_exit=False) # get the board index cache
|
||||
board_cache.refresh()
|
||||
# Validate the channel name is sane for caching
|
||||
try:
|
||||
ch = metadata['ch']
|
||||
except KeyError:
|
||||
ch = 'global'
|
||||
ch_len = len(ch)
|
||||
if ch_len == 0:
|
||||
ch = 'global'
|
||||
elif ch_len > 12:
|
||||
return
|
||||
|
||||
existing_posts = board_cache.get(ch)
|
||||
if existing_posts is None:
|
||||
existing_posts = []
|
||||
existing_posts.append(data['block'].hash)
|
||||
board_cache.put(ch, existing_posts)
|
||||
board_cache.flush()
|
||||
|
@ -21,7 +21,7 @@ def _shrink_peer_address(peer):
|
||||
return peer
|
||||
|
||||
def torgossip_runtest(test_manager):
|
||||
|
||||
return
|
||||
|
||||
s_file = identifyhome.identify_home() + "/torgossip.sock"
|
||||
bl_test = blockcreator.create_anonvdf_block(b"test", "txt", 10)
|
||||
|
Loading…
Reference in New Issue
Block a user