diff --git a/onionr/api.py b/onionr/api.py
index 903a35c1..a1f260ca 100755
--- a/onionr/api.py
+++ b/onionr/api.py
@@ -136,7 +136,7 @@ class API:
if action == 'hello':
resp = Response('Hello, World! ' + request.host)
elif action == 'shutdown':
- request.environ.get('werkzeug.server.shutdown')()
+ # request.environ.get('werkzeug.server.shutdown')()
resp = Response('Goodbye')
elif action == 'ping':
resp = Response('pong')
@@ -163,7 +163,7 @@ class API:
time.sleep(self._privateDelayTime - elapsed)
return resp
-
+
@app.route('/')
def banner():
self.mimeType = 'text/html'
diff --git a/onionr/communicator.py b/onionr/communicator.py
index 13f95341..a5476507 100755
--- a/onionr/communicator.py
+++ b/onionr/communicator.py
@@ -111,7 +111,12 @@ class OnionrCommunicate:
if announceAttemptCount >= announceAttempts:
logger.warn('Unable to announce to ' + command[1])
break
+ elif command[0] == 'runCheck':
+ logger.info('Status check; looks good.')
+ open('data/.runcheck', 'w+').close()
+
apiRunningCheckCount += 1
+
# check if local API is up
if apiRunningCheckCount > apiRunningCheckRate:
if self._core._utils.localCommand('ping') != 'pong':
@@ -127,6 +132,7 @@ class OnionrCommunicate:
apiRunningCheckCount = 0
time.sleep(1)
+
self._netController.killTor()
return
@@ -352,7 +358,7 @@ class OnionrCommunicate:
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
-
+
if len(self._core.hsAdder.strip()) == 0:
raise Exception("Could not perform self address check in performGet due to not knowing our address")
if selfCheck:
diff --git a/onionr/core.py b/onionr/core.py
index 7b94924a..912e7efd 100644
--- a/onionr/core.py
+++ b/onionr/core.py
@@ -155,7 +155,7 @@ class Core:
return True
else:
return False
-
+
def removeBlock(self, block):
'''
remove a block from this node
@@ -590,7 +590,7 @@ class Core:
conn.commit()
conn.close()
return
-
+
def updateBlockInfo(self, hash, key, data):
'''
sets info associated with a block
@@ -611,12 +611,15 @@ class Core:
'''
Inserts a block into the network
'''
+
try:
data.decode()
except AttributeError:
data = data.encode()
+
retData = ''
metadata = {'type': header}
+
if sign:
signature = self._crypto.edSign(data, self._crypto.privKey, encodeResult=True)
ourID = self._crypto.pubKeyHashID()
@@ -627,8 +630,10 @@ class Core:
pass
metadata['id'] = ourID
metadata['sig'] = signature
+
metadata = json.dumps(metadata)
metadata = metadata.encode()
+
if len(data) == 0:
logger.error('Will not insert empty block')
else:
@@ -642,16 +647,28 @@ class Core:
'''
Introduces our node into the network by telling X many nodes our HS address
'''
- announceAmount = 2
- nodeList = self.listAdders()
- if len(nodeList) == 0:
- for i in self.bootstrapList:
- if self._utils.validateID(i):
- self.addAddress(i)
- nodeList.append(i)
- if announceAmount > len(nodeList):
- announceAmount = len(nodeList)
- for i in range(announceAmount):
- self.daemonQueueAdd('announceNode', nodeList[i])
- events.event('introduction', onionr = None)
+
+ if(self._utils.isCommunicatorRunning()):
+ announceAmount = 2
+ nodeList = self.listAdders()
+
+ if len(nodeList) == 0:
+ for i in self.bootstrapList:
+ if self._utils.validateID(i):
+ self.addAddress(i)
+ nodeList.append(i)
+
+ if announceAmount > len(nodeList):
+ announceAmount = len(nodeList)
+
+ for i in range(announceAmount):
+ self.daemonQueueAdd('announceNode', nodeList[i])
+
+ events.event('introduction', onionr = None)
+
+ return True
+ else:
+ logger.error('Onionr daemon is not running.')
+ return False
+
return
diff --git a/onionr/default-plugins/pluginmanager/main.py b/onionr/default-plugins/pluginmanager/main.py
index 9bf7229a..cfcf1911 100644
--- a/onionr/default-plugins/pluginmanager/main.py
+++ b/onionr/default-plugins/pluginmanager/main.py
@@ -99,17 +99,17 @@ def commandInstallPlugin():
return True
elif valid_hash and real_block:
blockhash = str(pkobh)
- logger.debug('Using block ' + blockhash + '...')
+ logger.debug('Using block %s...' % blockhash)
elif valid_key and not real_key:
logger.error('Public key not found. Try adding the node by address manually, if possible.')
logger.debug('Is valid key, but the key is not a known one.')
elif valid_key and real_key:
publickey = str(pkobh)
- logger.debug('Using public key ' + publickey + '...')
+ logger.debug('Using public key %s...' % publickey)
saveKey(pluginname, pkobh)
else:
- logger.error('Unknown data \"' + str(pkobh) + '\"; must be public key or block hash.')
+ logger.error('Unknown data "%s"; must be public key or block hash.' % str(pkobh))
return
else:
help()
diff --git a/onionr/logger.py b/onionr/logger.py
index 23ede687..990a8b95 100644
--- a/onionr/logger.py
+++ b/onionr/logger.py
@@ -18,7 +18,7 @@
along with this program. If not, see .
'''
-import re, sys, time
+import re, sys, time, traceback
class colors:
'''
@@ -220,9 +220,19 @@ def error(data, error=None, timestamp=True):
if get_level() <= LEVEL_ERROR:
log('-', data, colors.fg.red, timestamp=timestamp)
if not error is None:
- debug('Error details: ' + str(error))
+ debug('Error: ' + str(error) + parse_error())
# fatal: when the something so bad has happened that the prorgam must stop
def fatal(data, timestamp=True):
if get_level() <= LEVEL_FATAL:
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp=timestamp)
+
+# returns a formatted error message
+def parse_error():
+ details = traceback.extract_tb(sys.exc_info()[2])
+ output = ''
+
+ for line in details:
+ output += '\n ... module %s in %s:%i' % (line[2], line[0], line[1])
+
+ return output
diff --git a/onionr/onionr.py b/onionr/onionr.py
index b89b9d58..a8fe223a 100755
--- a/onionr/onionr.py
+++ b/onionr/onionr.py
@@ -203,13 +203,13 @@ class Onionr:
'disable-plugin': 'Disables and stops a plugin',
'reload-plugin': 'Reloads a plugin',
'create-plugin': 'Creates directory structure for a plugin',
- 'add-peer': 'Adds a peer (?)',
+ 'add-peer': 'Adds a peer to database',
'list-peers': 'Displays a list of peers',
'add-msg': 'Broadcasts a message to the Onionr network',
'pm': 'Adds a private message to block',
'get-pms': 'Shows private messages sent to you',
'addfile': 'Create an Onionr block from a file',
- 'introduce': 'Introduce your node to the public Onionr network (DAEMON MUST BE RUNNING)',
+ 'introduce': 'Introduce your node to the public Onionr network',
}
# initialize plugins
@@ -293,11 +293,11 @@ class Onionr:
Displays the Onionr version
'''
- logger.info('Onionr ' + ONIONR_VERSION + ' (' + platform.machine() + ') - API v' + API_VERSION)
+ logger.info('Onionr %s (%s) - API v%s' % (ONIONR_VERSION, platform.machine(), API_VERSION))
if verbosity >= 1:
logger.info(ONIONR_TAGLINE)
if verbosity >= 2:
- logger.info('Running on ' + platform.platform() + ' ' + platform.release())
+ logger.info('Running on %s %s' % (platform.platform(), platform.release()))
return
@@ -323,7 +323,7 @@ class Onionr:
except KeyboardInterrupt:
pass
else:
- logger.info("Sending message to " + peer)
+ logger.info("Sending message to: " + logger.colors.underline + peer)
self.onionrUtils.sendPM(peer, message)
@@ -355,6 +355,7 @@ class Onionr:
'''
Adds a Onionr node address
'''
+
try:
newAddress = sys.argv[2]
except:
@@ -374,22 +375,25 @@ class Onionr:
'''
while True:
-
- messageToAdd = logger.readline('Broadcast message to network: ')
- if len(messageToAdd) >= 1:
- break
+ try:
+ messageToAdd = logger.readline('Broadcast message to network: ')
+ if len(messageToAdd) >= 1:
+ break
+ except KeyboardInterrupt:
+ return
#addedHash = self.onionrCore.setData(messageToAdd)
addedHash = self.onionrCore.insertBlock(messageToAdd, header='txt')
#self.onionrCore.addToBlockDB(addedHash, selfInsert=True)
#self.onionrCore.setBlockType(addedHash, 'txt')
- logger.info("inserted your message as block: " + addedHash)
+ logger.info("Message inserted as as block %s" % addedHash)
return
def getPMs(self):
'''
display PMs sent to us
'''
+
self.onionrUtils.loadPMs()
def enablePlugin(self):
@@ -399,10 +403,10 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
- logger.info('Enabling plugin \"' + plugin_name + '\"...')
+ logger.info('Enabling plugin "%s"...' % plugin_name)
plugins.enable(plugin_name, self)
else:
- logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' ')
+ logger.info('%s %s ' % (sys.argv[0], sys.argv[1]))
return
@@ -413,10 +417,10 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
- logger.info('Disabling plugin \"' + plugin_name + '\"...')
+ logger.info('Disabling plugin "%s"...' % plugin_name)
plugins.disable(plugin_name, self)
else:
- logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' ')
+ logger.info('%s %s ' % (sys.argv[0], sys.argv[1]))
return
@@ -427,7 +431,7 @@ class Onionr:
if len(sys.argv) >= 3:
plugin_name = sys.argv[2]
- logger.info('Reloading plugin \"' + plugin_name + '\"...')
+ logger.info('Reloading plugin "%s"...' % plugin_name)
plugins.stop(plugin_name, self)
plugins.start(plugin_name, self)
else:
@@ -446,21 +450,21 @@ class Onionr:
plugin_name = re.sub('[^0-9a-zA-Z]+', '', str(sys.argv[2]).lower())
if not plugins.exists(plugin_name):
- logger.info('Creating plugin \"' + plugin_name + '\"...')
+ logger.info('Creating plugin "%s"...' % plugin_name)
os.makedirs(plugins.get_plugins_folder(plugin_name))
with open(plugins.get_plugins_folder(plugin_name) + '/main.py', 'a') as main:
main.write(open('static-data/default_plugin.txt').read().replace('$user', os.getlogin()).replace('$date', datetime.datetime.now().strftime('%Y-%m-%d')))
- logger.info('Enabling plugin \"' + plugin_name + '\"...')
+ logger.info('Enabling plugin "%s"...' % plugin_name)
plugins.enable(plugin_name, self)
else:
- logger.warn('Cannot create plugin directory structure; plugin "' + plugin_name + '" exists.')
+ logger.warn('Cannot create plugin directory structure; plugin "%s" exists.' % plugin_name)
except Exception as e:
logger.error('Failed to create plugin directory structure.', e)
else:
- logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' ')
+ logger.info('%s %s ' % (sys.argv[0], sys.argv[1]))
return
@@ -523,15 +527,18 @@ class Onionr:
Shutdown the Onionr daemon
'''
- logger.warn('Killing the running daemon')
- events.event('daemon_stop', onionr = self)
- net = NetController(config.get('client')['port'])
+ logger.warn('Killing the running daemon...', timestamp = False)
try:
- self.onionrUtils.localCommand('shutdown')
- except requests.exceptions.ConnectionError:
- pass
- self.onionrCore.daemonQueueAdd('shutdown')
- net.killTor()
+ events.event('daemon_stop', onionr = self)
+ net = NetController(config.get('client')['port'])
+ try:
+ self.onionrUtils.localCommand('shutdown')
+ except requests.exceptions.ConnectionError:
+ pass
+ self.onionrCore.daemonQueueAdd('shutdown')
+ net.killTor()
+ except Exception as e:
+ logger.error('Failed to shutdown daemon.', error = e, timestamp = False)
return
@@ -539,6 +546,7 @@ class Onionr:
'''
Displays statistics and exits
'''
+
logger.info('Our pubkey: ' + self.onionrCore._crypto.pubKey)
logger.info('Our address: ' + self.get_hostname())
return
diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py
index 0c770fcf..4fbb30e8 100644
--- a/onionr/onionrutils.py
+++ b/onionr/onionrutils.py
@@ -59,14 +59,14 @@ class OnionrUtils:
sign = self._core._crypto.edSign(message, self._core._crypto.privKey, encodeResult=True)
#encrypted = self._core._crypto.pubKeyEncrypt(message, pubkey, anonymous=True, encodedData=True).decode()
-
+
payload['sig'] = sign
payload['msg'] = message
payload = json.dumps(payload)
message = payload
encrypted = self._core._crypto.pubKeyEncrypt(message, pubkey, anonymous=True, encodedData=True).decode()
-
+
block = self._core.insertBlock(encrypted, header='pm', sign=False)
if block == '':
logger.error('Could not send PM')
@@ -383,7 +383,7 @@ class OnionrUtils:
except Exception as error:
logger.error('Failed to open block ' + str(i) + '.', error=error)
return
-
+
def getPeerByHashId(self, hash):
'''
Return the pubkey of the user if known from the hash
@@ -398,4 +398,26 @@ class OnionrUtils:
for row in c.execute('SELECT ID FROM peers where hashID=?', command):
if row[0] != '':
retData = row[0]
- return retData
\ No newline at end of file
+ return retData
+
+ def isCommunicatorRunning(self, timeout = 5, interval = 0.1):
+ try:
+ runcheck_file = 'data/.runcheck'
+
+ if os.path.isfile(runcheck_file):
+ os.remove(runcheck_file)
+ logger.debug('%s file appears to have existed before the run check.' % runcheck_file, timestamp = False)
+
+ self._core.daemonQueueAdd('runCheck')
+ starttime = time.time()
+
+ while True:
+ time.sleep(interval)
+ if os.path.isfile(runcheck_file):
+ os.remove(runcheck_file)
+
+ return True
+ elif time.time() - starttime >= timeout:
+ return False
+ except:
+ return False