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 data = name
if clientAPI._utils.validateHash(data): if clientAPI._utils.validateHash(data):
if data not in self.hideBlocks: 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) block = Block(hash=data.encode(), core=clientAPI._core)
resp = base64.b64encode(block.getRaw().encode()).decode() resp = base64.b64encode(block.getRaw().encode()).decode()
if len(resp) == 0: if len(resp) == 0:
@ -244,6 +244,8 @@ class API:
self.host = setBindIP(self._core.privateApiHostFile) self.host = setBindIP(self._core.privateApiHostFile)
logger.info('Running api on %s:%s' % (self.host, self.bindPort)) logger.info('Running api on %s:%s' % (self.host, self.bindPort))
self.httpServer = '' self.httpServer = ''
self.queueResponse = {}
onionrInst.setClientAPIInst(self) onionrInst.setClientAPIInst(self)
@app.before_request @app.before_request
@ -287,6 +289,19 @@ class API:
abort(403) abort(403)
return send_from_directory(config.get('www.private.path', 'static-data/www/private/'), path) 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') @app.route('/ping')
def ping(): def ping():
return Response("pong!") return Response("pong!")

View File

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

View File

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

View File

@ -17,7 +17,7 @@
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 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 from onionrblockapi import Block
import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues
@ -342,7 +342,7 @@ class Core:
conn = sqlite3.connect(self.queueDB, timeout=10) conn = sqlite3.connect(self.queueDB, timeout=10)
c = conn.cursor() c = conn.cursor()
try: 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 retData = row
break break
except sqlite3.OperationalError: except sqlite3.OperationalError:
@ -357,21 +357,20 @@ class Core:
return retData 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) Add a command to the daemon queue, used by the communication daemon (communicator.py)
''' '''
retData = True retData = True
# Intended to be used by the web server
date = self._utils.getEpoch() date = self._utils.getEpoch()
conn = sqlite3.connect(self.queueDB, timeout=10) conn = sqlite3.connect(self.queueDB, timeout=10)
c = conn.cursor() c = conn.cursor()
t = (command, data, date) t = (command, data, date, responseID)
try: 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.commit()
conn.close() conn.close()
except sqlite3.OperationalError: except sqlite3.OperationalError:
@ -380,6 +379,13 @@ class Core:
events.event('queue_push', data = {'command': command, 'data': data}, onionr = None) events.event('queue_push', data = {'command': command, 'data': data}, onionr = None)
return retData 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): def clearDaemonQueue(self):
''' '''
Clear the daemon queue (somewhat dangerous) Clear the daemon queue (somewhat dangerous)

View File

@ -152,7 +152,6 @@ class DBCreator:
conn = sqlite3.connect(self.core.queueDB, timeout=10) conn = sqlite3.connect(self.core.queueDB, timeout=10)
c = conn.cursor() c = conn.cursor()
# Create table # Create table
c.execute('''CREATE TABLE commands c.execute('''CREATE TABLE commands (id integer primary key autoincrement, command text, data text, date text, responseID text)''')
(id integer primary key autoincrement, command text, data text, date text)''')
conn.commit() conn.commit()
conn.close() 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+') print('Error, Onionr requires Python 3.5+')
sys.exit(1) sys.exit(1)
import os, base64, random, getpass, shutil, subprocess, requests, time, platform, datetime, re, json, getpass, sqlite3 import os, base64, random, getpass, shutil, subprocess, requests, time, platform, datetime, re, json, getpass, sqlite3
import webbrowser import webbrowser, uuid
from threading import Thread from threading import Thread
import api, core, config, logger, onionrplugins as plugins, onionrevents as events import api, core, config, logger, onionrplugins as plugins, onionrevents as events
import onionrutils import onionrutils
@ -394,7 +394,14 @@ class Onionr:
return return
def listConn(self): 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): def listPeers(self):
logger.info('Peer transport address list:') logger.info('Peer transport address list:')

View File

@ -240,12 +240,14 @@ class Block:
try: try:
if self.isValid() is True: if self.isValid() is True:
'''
if (not self.getBlockFile() is None) and (recreate is True): if (not self.getBlockFile() is None) and (recreate is True):
onionrstorage.store(self.core, self.getRaw().encode()) onionrstorage.store(self.core, self.getRaw().encode())
#with open(self.getBlockFile(), 'wb') as blockFile: #with open(self.getBlockFile(), 'wb') as blockFile:
# blockFile.write(self.getRaw().encode()) # blockFile.write(self.getRaw().encode())
else: 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: if self.hash != False:
self.update() self.update()
@ -751,13 +753,16 @@ class Block:
# no input data? scrap it. # no input data? scrap it.
if hash is None: if hash is None:
return False return False
'''
if type(hash) == Block: if type(hash) == Block:
blockfile = hash.getBlockFile() blockfile = hash.getBlockFile()
else: else:
blockfile = onionrcore.Core().dataDir + 'blocks/%s.dat' % hash 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): def getCache(hash = None):
# give a list of the hashes of the cached blocks # give a list of the hashes of the cached blocks

View File

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

View File

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

View File

@ -151,7 +151,7 @@ class OnionrUtils:
logger.error('Failed to read my address.', error = error) logger.error('Failed to read my address.', error = error)
return None 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. 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 != '': if data != '':
data = '&data=' + urllib.parse.quote_plus(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%s' % (hostname, config.get('client.client.port'), command, data)
try: 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: except Exception as error:
if not silent: if not silent:
logger.error('Failed to make local request (command: %s):%s' % (command, error)) logger.error('Failed to make local request (command: %s):%s' % (command, error))

View File

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