work on gui, dbstorage, daemon queue responses

This commit is contained in:
Kevin Froman 2019-01-06 23:50:20 -06:00
parent 84fdb23b1c
commit aeb9a6e775
11 changed files with 95 additions and 30 deletions

View File

@ -109,7 +109,7 @@ class PublicAPI:
data = name
if clientAPI._utils.validateHash(data):
if data not in self.hideBlocks:
if os.path.exists(clientAPI._core.dataDir + 'blocks/' + data + '.dat'):
if data in clientAPI._core.getBlockList():
block = Block(hash=data.encode(), core=clientAPI._core)
resp = base64.b64encode(block.getRaw().encode()).decode()
if len(resp) == 0:
@ -244,6 +244,8 @@ class API:
self.host = setBindIP(self._core.privateApiHostFile)
logger.info('Running api on %s:%s' % (self.host, self.bindPort))
self.httpServer = ''
self.queueResponse = {}
onionrInst.setClientAPIInst(self)
@app.before_request
@ -287,6 +289,19 @@ class API:
abort(403)
return send_from_directory(config.get('www.private.path', 'static-data/www/private/'), path)
@app.route('/queueResponseAdd/<name>', methods=['post'])
def queueResponseAdd(name):
self.queueResponse[name] = request.form['data']
return Response('success')
@app.route('/queueResponse/<name>')
def queueResponse(name):
try:
res = self.queueResponse[name]
except KeyError:
resp = ''
return Response(resp)
@app.route('/ping')
def ping():
return Response("pong!")

View File

@ -472,7 +472,7 @@ class OnionrCommunicatorDaemon:
Process daemon commands from daemonQueue
'''
cmd = self._core.daemonQueue()
response = ''
if cmd is not False:
events.event('daemon_command', onionr = None, data = {'cmd' : cmd})
if cmd[0] == 'shutdown':
@ -486,7 +486,7 @@ class OnionrCommunicatorDaemon:
logger.debug('Status check; looks good.')
open(self._core.dataDir + '.runcheck', 'w+').close()
elif cmd[0] == 'connectedPeers':
self.printOnlinePeers()
response = '\n'.join(list(self.onlinePeers)).strip()
elif cmd[0] == 'pex':
for i in self.timers:
if i.timerFunction.__name__ == 'lookupAdders':
@ -507,6 +507,10 @@ class OnionrCommunicatorDaemon:
else:
logger.info('Recieved daemonQueue command:' + cmd[0])
if cmd[4] != '':
if response != '':
self._core._utils.localCommand('queueResponseAdd', data='/' + cmd[4], post=True, postData=response)
self.decrementThreadCount('daemonCommands')
def uploadBlock(self):

View File

@ -129,7 +129,7 @@ def reload():
with open(get_config_file(), 'r', encoding="utf8") as configfile:
set_config(json.loads(configfile.read()))
except:
logger.warn('Failed to parse configuration file.')
logger.debug('Failed to parse configuration file.')
def get_config():
'''

View File

@ -17,7 +17,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 sqlite3, os, sys, time, math, base64, tarfile, nacl, logger, json, netcontroller, math, config
import sqlite3, os, sys, time, math, base64, tarfile, nacl, logger, json, netcontroller, math, config, uuid
from onionrblockapi import Block
import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues
@ -342,7 +342,7 @@ class Core:
conn = sqlite3.connect(self.queueDB, timeout=10)
c = conn.cursor()
try:
for row in c.execute('SELECT command, data, date, min(ID) FROM commands group by id'):
for row in c.execute('SELECT command, data, date, min(ID), responseID FROM commands group by id'):
retData = row
break
except sqlite3.OperationalError:
@ -357,21 +357,20 @@ class Core:
return retData
def daemonQueueAdd(self, command, data=''):
def daemonQueueAdd(self, command, data='', responseID=''):
'''
Add a command to the daemon queue, used by the communication daemon (communicator.py)
'''
retData = True
# Intended to be used by the web server
date = self._utils.getEpoch()
conn = sqlite3.connect(self.queueDB, timeout=10)
c = conn.cursor()
t = (command, data, date)
t = (command, data, date, responseID)
try:
c.execute('INSERT INTO commands (command, data, date) VALUES(?, ?, ?)', t)
c.execute('INSERT INTO commands (command, data, date, responseID) VALUES(?, ?, ?, ?)', t)
conn.commit()
conn.close()
except sqlite3.OperationalError:
@ -380,6 +379,13 @@ class Core:
events.event('queue_push', data = {'command': command, 'data': data}, onionr = None)
return retData
def daemonQueueGetResponse(self, responseID=''):
'''
Get a response sent by communicator to the API, by requesting to the API
'''
assert len(responseID) > 0
resp = self._utils.localCommand('queueResponse', data='/' + responseID, post=True)
def clearDaemonQueue(self):
'''
Clear the daemon queue (somewhat dangerous)

View File

@ -152,7 +152,6 @@ class DBCreator:
conn = sqlite3.connect(self.core.queueDB, timeout=10)
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE commands
(id integer primary key autoincrement, command text, data text, date text)''')
c.execute('''CREATE TABLE commands (id integer primary key autoincrement, command text, data text, date text, responseID text)''')
conn.commit()
conn.close()

View File

@ -25,7 +25,7 @@ if sys.version_info[0] == 2 or sys.version_info[1] < 5:
print('Error, Onionr requires Python 3.5+')
sys.exit(1)
import os, base64, random, getpass, shutil, subprocess, requests, time, platform, datetime, re, json, getpass, sqlite3
import webbrowser
import webbrowser, uuid
from threading import Thread
import api, core, config, logger, onionrplugins as plugins, onionrevents as events
import onionrutils
@ -394,7 +394,14 @@ class Onionr:
return
def listConn(self):
self.onionrCore.daemonQueueAdd('connectedPeers')
randID = str(uuid.uuid4())
self.onionrCore.daemonQueueAdd('connectedPeers', responseID=randID)
while True:
time.sleep(1)
peers = self.onionrCore.daemonQueueGetResponse(randID)
if peers not in ('', None):
print(peers)
break
def listPeers(self):
logger.info('Peer transport address list:')

View File

@ -240,12 +240,14 @@ class Block:
try:
if self.isValid() is True:
'''
if (not self.getBlockFile() is None) and (recreate is True):
onionrstorage.store(self.core, self.getRaw().encode())
#with open(self.getBlockFile(), 'wb') as blockFile:
# blockFile.write(self.getRaw().encode())
else:
self.hash = self.getCore().insertBlock(self.getContent(), header = self.getType(), sign = sign, meta = self.getMetadata(), expire = self.getExpire())
'''
self.hash = self.getCore().insertBlock(self.getRaw(), header = self.getType(), sign = sign, meta = self.getMetadata(), expire = self.getExpire())
if self.hash != False:
self.update()
@ -751,13 +753,16 @@ class Block:
# no input data? scrap it.
if hash is None:
return False
'''
if type(hash) == Block:
blockfile = hash.getBlockFile()
else:
blockfile = onionrcore.Core().dataDir + 'blocks/%s.dat' % hash
'''
return os.path.exists(blockfile) and os.path.isfile(blockfile)
ret = isinstance(onionrstorage.getData(onionrcore.Core(), hash.getHash()), type(None))
return not ret
def getCache(hash = None):
# give a list of the hashes of the cached blocks

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
import threading, time
from tkinter import *
import core
class OnionrGUI:
@ -11,8 +12,7 @@ class OnionrGUI:
# create a pulldown menu, and add it to the menu bar
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Open", command=None)
filemenu.add_command(label="Save", command=None)
#filemenu.add_command(label="Open", command=None)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=self.root.quit)
menubar.add_cascade(label="File", menu=filemenu)
@ -26,16 +26,13 @@ class OnionrGUI:
self.root.config(menu=menubar)
self.menuFrame = Frame(self.root)
self.mainButton = Button(self.menuFrame, text="Main View")
self.mainButton.grid(row=0, column=0, padx=0, pady=2, sticky=N+W)
self.tabButton1 = Button(self.menuFrame, text="Mail")
self.tabButton1 = Button(self.menuFrame, text="Mail", command=self.openMail)
self.tabButton1.grid(row=0, column=1, padx=0, pady=2, sticky=N+W)
self.tabButton2 = Button(self.menuFrame, text="Message Flow")
self.tabButton2.grid(row=0, column=3, padx=0, pady=2, sticky=N+W)
self.menuFrame.grid(row=0, column=0, padx=2, pady=0, sticky=N+W)
self.idFrame = Frame(self.root)
self.ourIDLabel = Label(self.idFrame, text="ID: ")
@ -48,11 +45,34 @@ class OnionrGUI:
self.syncStatus = Label(self.root, text="Sync Status: 15/100")
self.syncStatus.place(relx=1.0, rely=1.0, anchor=S+E)
self.peerCount = Label(self.root, text="Connected Peers: 3")
self.peerCount = Label(self.root, text="Connected Peers: ")
self.peerCount.place(relx=0.0, rely=1.0, anchor='sw')
self.root.wm_title("Onionr")
threading.Thread(target=self.updateStats)
self.root.mainloop()
return
def updateStats(self):
#self.core._utils.localCommand()
self.peerCount.config(text='Connected Peers: %s' % ())
time.sleep(1)
return
def openMail(self):
MailWindow(self)
class MailWindow:
def __init__(self, mainGUI):
assert isinstance(mainGUI, OnionrGUI)
self.core = mainGUI.core
self.mailRoot = Toplevel()
self.inboxFrame = Frame(self.mailRoot)
self.sentboxFrame = Frame(self.mailRoot)
self.composeFrame = Frame(self.mailRoot)
self.mailRoot.mainloop()
OnionrGUI()

View File

@ -67,10 +67,12 @@ def getData(coreInst, bHash):
assert isinstance(coreInst, core.Core)
assert coreInst._utils.validateHash(bHash)
bHash = coreInst._utils.bytesToStr(bHash)
# First check DB for data entry by hash
# if no entry, check disk
# If no entry in either, raise an exception
retData = ''
retData = None
fileLocation = '%s/%s.dat' % (coreInst.blockDataLocation, bHash)
if os.path.exists(fileLocation):
with open(fileLocation, 'rb') as block:

View File

@ -151,7 +151,7 @@ class OnionrUtils:
logger.error('Failed to read my address.', error = error)
return None
def localCommand(self, command, data='', silent = True):
def localCommand(self, command, data='', silent = True, post=False, postData = {}):
'''
Send a command to the local http API server, securely. Intended for local clients, DO NOT USE for remote peers.
'''
@ -173,8 +173,12 @@ class OnionrUtils:
if data != '':
data = '&data=' + urllib.parse.quote_plus(data)
payload = 'http://%s:%s/%s%s' % (hostname, config.get('client.client.port'), command, data)
try:
retData = requests.get(payload, headers={'token': config.get('client.webpassword')}).text
if post:
retData = requests.post(payload, data=postData, headers={'token': config.get('client.webpassword')}).text
else:
retData = requests.get(payload, headers={'token': config.get('client.webpassword')}).text
except Exception as error:
if not silent:
logger.error('Failed to make local request (command: %s):%s' % (command, error))

View File

@ -54,7 +54,7 @@ class OnionrFlow:
self.flowRunning = False
expireTime = self.myCore._utils.getEpoch() + 43200
if len(message) > 0:
self.myCore.insertBlock(message, header='txt', expire=expireTime)
self.myCore.insertBlock(message, header='txt', expire=expireTime, meta={'ch': self.channel})
#insertBL = Block(content = message, type = 'txt', expire=expireTime, core = self.myCore)
#insertBL.setMetadata('ch', self.channel)
#insertBL.save()
@ -67,10 +67,13 @@ class OnionrFlow:
time.sleep(1)
try:
while self.flowRunning:
for block in Block.getBlocks(type = 'txt', core = self.myCore):
for block in self.myCore.getBlocksByType('txt'):
block = Block(block)
if block.getMetadata('ch') != self.channel:
#print('not chan', block.getMetadata('ch'))
continue
if block.getHash() in self.alreadyOutputed:
#print('already')
continue
if not self.flowRunning:
break
@ -80,7 +83,7 @@ class OnionrFlow:
content = self.myCore._utils.escapeAnsi(content.replace('\n', '\\n').replace('\r', '\\r').strip())
logger.info(block.getDate().strftime("%m/%d %H:%M") + ' - ' + logger.colors.reset + content, prompt = False)
self.alreadyOutputed.append(block.getHash())
time.sleep(5)
time.sleep(5)
except KeyboardInterrupt:
self.flowRunning = False