Merge branch 'master' into c
This commit is contained in:
commit
e3f2097882
10
README.md
10
README.md
|
@ -19,9 +19,9 @@ pseudo-mailing list:
|
||||||
BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh
|
BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh
|
||||||
|
|
||||||
|
|
||||||
references
|
References
|
||||||
----------
|
----------
|
||||||
* [project website](https://bitmessage.org)
|
* [Project Website](https://bitmessage.org)
|
||||||
* [protocol specification](https://bitmessage.org/wiki/Protocol_specification)
|
* [Protocol Specification](https://bitmessage.org/wiki/Protocol_specification)
|
||||||
* [whitepaper](https://bitmessage.org/bitmessage.pdf)
|
* [Whitepaper](https://bitmessage.org/bitmessage.pdf)
|
||||||
* [installation](https://bitmessage.org/wiki/Compiling_instructions)
|
* [Installation](https://bitmessage.org/wiki/Compiling_instructions)
|
||||||
|
|
|
@ -42,14 +42,12 @@ def decodeBase58(string, alphabet=ALPHABET):
|
||||||
- `alphabet`: The alphabet to use for encoding
|
- `alphabet`: The alphabet to use for encoding
|
||||||
"""
|
"""
|
||||||
base = len(alphabet)
|
base = len(alphabet)
|
||||||
strlen = len(string)
|
|
||||||
num = 0
|
num = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
power = strlen - 1
|
|
||||||
for char in string:
|
for char in string:
|
||||||
num += alphabet.index(char) * (base ** power)
|
num *= base
|
||||||
power -= 1
|
num += alphabet.index(char)
|
||||||
except:
|
except:
|
||||||
#character not found (like a space character or a 0)
|
#character not found (like a space character or a 0)
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -25,6 +25,7 @@ import shared
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
from addresses import *
|
from addresses import *
|
||||||
from pyelliptic.openssl import OpenSSL
|
from pyelliptic.openssl import OpenSSL
|
||||||
|
import l10n
|
||||||
|
|
||||||
quit = False
|
quit = False
|
||||||
menutab = 1
|
menutab = 1
|
||||||
|
@ -210,7 +211,7 @@ def drawtab(stdscr):
|
||||||
stdscr.addstr(8+i, 18, str(item).ljust(2))
|
stdscr.addstr(8+i, 18, str(item).ljust(2))
|
||||||
|
|
||||||
# Uptime and processing data
|
# Uptime and processing data
|
||||||
stdscr.addstr(6, 35, "Since startup on "+unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(startuptime)))))
|
stdscr.addstr(6, 35, "Since startup on "+l10n.formatTimestamp(startuptime, False))
|
||||||
stdscr.addstr(7, 40, "Processed "+str(shared.numberOfMessagesProcessed).ljust(4)+" person-to-person messages.")
|
stdscr.addstr(7, 40, "Processed "+str(shared.numberOfMessagesProcessed).ljust(4)+" person-to-person messages.")
|
||||||
stdscr.addstr(8, 40, "Processed "+str(shared.numberOfBroadcastsProcessed).ljust(4)+" broadcast messages.")
|
stdscr.addstr(8, 40, "Processed "+str(shared.numberOfBroadcastsProcessed).ljust(4)+" broadcast messages.")
|
||||||
stdscr.addstr(9, 40, "Processed "+str(shared.numberOfPubkeysProcessed).ljust(4)+" public keys.")
|
stdscr.addstr(9, 40, "Processed "+str(shared.numberOfPubkeysProcessed).ljust(4)+" public keys.")
|
||||||
|
@ -851,8 +852,7 @@ def loadInbox():
|
||||||
|
|
||||||
# Load into array
|
# Load into array
|
||||||
inbox.append([msgid, tolabel, toaddr, fromlabel, fromaddr, subject,
|
inbox.append([msgid, tolabel, toaddr, fromlabel, fromaddr, subject,
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(received))),
|
l10n.formatTimestamp(received, False), read])
|
||||||
read])
|
|
||||||
inbox.reverse()
|
inbox.reverse()
|
||||||
def loadSent():
|
def loadSent():
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
@ -902,20 +902,20 @@ def loadSent():
|
||||||
elif status == "msgqueued":
|
elif status == "msgqueued":
|
||||||
statstr = "Message queued"
|
statstr = "Message queued"
|
||||||
elif status == "msgsent":
|
elif status == "msgsent":
|
||||||
t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))
|
t = l10n.formatTimestamp(lastactiontime, False)
|
||||||
statstr = "Message sent at "+t+".Waiting for acknowledgement."
|
statstr = "Message sent at "+t+".Waiting for acknowledgement."
|
||||||
elif status == "msgsentnoackexpected":
|
elif status == "msgsentnoackexpected":
|
||||||
t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))
|
t = l10n.formatTimestamp(lastactiontime, False)
|
||||||
statstr = "Message sent at "+t+"."
|
statstr = "Message sent at "+t+"."
|
||||||
elif status == "doingmsgpow":
|
elif status == "doingmsgpow":
|
||||||
statstr = "The proof of work required to send the message has been queued."
|
statstr = "The proof of work required to send the message has been queued."
|
||||||
elif status == "askreceived":
|
elif status == "askreceived":
|
||||||
t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))
|
t = l10n.formatTimestamp(lastactiontime, False)
|
||||||
statstr = "Acknowledgment of the message received at "+t+"."
|
statstr = "Acknowledgment of the message received at "+t+"."
|
||||||
elif status == "broadcastqueued":
|
elif status == "broadcastqueued":
|
||||||
statstr = "Broadcast queued."
|
statstr = "Broadcast queued."
|
||||||
elif status == "broadcastsent":
|
elif status == "broadcastsent":
|
||||||
t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))
|
t = l10n.formatTimestamp(lastactiontime, False)
|
||||||
statstr = "Broadcast sent at "+t+"."
|
statstr = "Broadcast sent at "+t+"."
|
||||||
elif status == "forcepow":
|
elif status == "forcepow":
|
||||||
statstr = "Forced difficulty override. Message will start sending soon."
|
statstr = "Forced difficulty override. Message will start sending soon."
|
||||||
|
@ -924,12 +924,12 @@ def loadSent():
|
||||||
elif status == "toodifficult":
|
elif status == "toodifficult":
|
||||||
statstr = "Error: The work demanded by the recipient is more difficult than you are willing to do."
|
statstr = "Error: The work demanded by the recipient is more difficult than you are willing to do."
|
||||||
else:
|
else:
|
||||||
t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))
|
t = l10n.formatTimestamp(lastactiontime, False)
|
||||||
statstr = "Unknown status "+status+" at "+t+"."
|
statstr = "Unknown status "+status+" at "+t+"."
|
||||||
|
|
||||||
# Load into array
|
# Load into array
|
||||||
sentbox.append([tolabel, toaddr, fromlabel, fromaddr, subject, statstr, ackdata,
|
sentbox.append([tolabel, toaddr, fromlabel, fromaddr, subject, statstr, ackdata,
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))])
|
l10n.formatTimestamp(lastactiontime, False)])
|
||||||
sentbox.reverse()
|
sentbox.reverse()
|
||||||
def loadAddrBook():
|
def loadAddrBook():
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
|
|
@ -9,6 +9,26 @@
|
||||||
|
|
||||||
# The software version variable is now held in shared.py
|
# The software version variable is now held in shared.py
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
#Version check
|
||||||
|
#Older versions of Python don't support the print function while Python 3 doesn't
|
||||||
|
#like the print statement, so we use sys.stdout for the version check. After this
|
||||||
|
#check we can then use the print function in the remainder of this file. Currently
|
||||||
|
#in order to use logging, a lot of unnecessary code needs to be executed which could
|
||||||
|
#potentially render this version check useless. So logging won't be used here until
|
||||||
|
#there is a more efficient way to configure logging
|
||||||
|
if sys.hexversion >= 0x3000000:
|
||||||
|
msg = "PyBitmessage does not support Python 3. Python 2.7.3 or later is required. Your version: %s" % sys.version
|
||||||
|
#logger.critical(msg)
|
||||||
|
sys.stdout.write(msg)
|
||||||
|
sys.exit(0)
|
||||||
|
if sys.hexversion < 0x20703F0:
|
||||||
|
msg = "You should use Python 2.7.3 or greater (but not Python 3). Your version: %s" % sys.version
|
||||||
|
#logger.critical(msg)
|
||||||
|
sys.stdout.write(msg)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
import signal # Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
|
import signal # Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
|
||||||
# The next 3 are used for the API
|
# The next 3 are used for the API
|
||||||
import singleton
|
import singleton
|
||||||
|
@ -46,15 +66,7 @@ import helper_generic
|
||||||
|
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# OSX python version check
|
|
||||||
import sys
|
|
||||||
if 'win' in sys.platform:
|
|
||||||
if float("{1}.{2}".format(*sys.version_info)) < 7.5:
|
|
||||||
msg = "You should use python 2.7.5 or greater. Your version: %s", "{0}.{1}.{2}".format(*sys.version_info)
|
|
||||||
logger.critical(msg)
|
|
||||||
print msg
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def connectToStream(streamNumber):
|
def connectToStream(streamNumber):
|
||||||
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
|
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
|
||||||
|
@ -200,7 +212,7 @@ class Main:
|
||||||
apiNotifyPath = ''
|
apiNotifyPath = ''
|
||||||
if apiNotifyPath != '':
|
if apiNotifyPath != '':
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Trying to call', apiNotifyPath
|
print('Trying to call', apiNotifyPath)
|
||||||
|
|
||||||
call([apiNotifyPath, "startingUp"])
|
call([apiNotifyPath, "startingUp"])
|
||||||
singleAPIThread = singleAPI()
|
singleAPIThread = singleAPI()
|
||||||
|
@ -222,15 +234,15 @@ class Main:
|
||||||
try:
|
try:
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
|
print('PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon')
|
||||||
print 'Error message:', err
|
print('Error message:', err)
|
||||||
print 'You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.'
|
print('You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.')
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
import bitmessageqt
|
import bitmessageqt
|
||||||
bitmessageqt.run()
|
bitmessageqt.run()
|
||||||
else:
|
else:
|
||||||
print 'Running with curses'
|
print('Running with curses')
|
||||||
import bitmessagecurses
|
import bitmessagecurses
|
||||||
bitmessagecurses.runwrapper()
|
bitmessagecurses.runwrapper()
|
||||||
else:
|
else:
|
||||||
|
@ -238,16 +250,16 @@ class Main:
|
||||||
|
|
||||||
if daemon:
|
if daemon:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Running as a daemon. The main program should exit this thread.'
|
print('Running as a daemon. The main program should exit this thread.')
|
||||||
else:
|
else:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Running as a daemon. You can use Ctrl+C to exit.'
|
print('Running as a daemon. You can use Ctrl+C to exit.')
|
||||||
while True:
|
while True:
|
||||||
time.sleep(20)
|
time.sleep(20)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Stopping Bitmessage Deamon.'
|
print('Stopping Bitmessage Deamon.')
|
||||||
shared.doCleanShutdown()
|
shared.doCleanShutdown()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
try:
|
|
||||||
import locale
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
withMessagingMenu = False
|
withMessagingMenu = False
|
||||||
try:
|
try:
|
||||||
from gi.repository import MessagingMenu
|
from gi.repository import MessagingMenu
|
||||||
|
@ -40,6 +35,7 @@ from debug import logger
|
||||||
import subprocess
|
import subprocess
|
||||||
import datetime
|
import datetime
|
||||||
from helper_sql import *
|
from helper_sql import *
|
||||||
|
import l10n
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
@ -482,6 +478,10 @@ class MyForm(QtGui.QMainWindow):
|
||||||
# startup for linux
|
# startup for linux
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
self.totalNumberOfBytesReceived = 0
|
||||||
|
self.totalNumberOfBytesSent = 0
|
||||||
|
|
||||||
self.ui.labelSendBroadcastWarning.setVisible(False)
|
self.ui.labelSendBroadcastWarning.setVisible(False)
|
||||||
|
|
||||||
self.timer = QtCore.QTimer()
|
self.timer = QtCore.QTimer()
|
||||||
|
@ -574,7 +574,7 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.statusbar = self.statusBar()
|
self.statusbar = self.statusBar()
|
||||||
self.statusbar.insertPermanentWidget(0, self.ui.pushButtonStatusIcon)
|
self.statusbar.insertPermanentWidget(0, self.ui.pushButtonStatusIcon)
|
||||||
self.ui.labelStartupTime.setText(_translate("MainWindow", "Since startup on %1").arg(
|
self.ui.labelStartupTime.setText(_translate("MainWindow", "Since startup on %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))),'utf-8')))
|
l10n.formatTimestamp()))
|
||||||
self.numberOfMessagesProcessed = 0
|
self.numberOfMessagesProcessed = 0
|
||||||
self.numberOfBroadcastsProcessed = 0
|
self.numberOfBroadcastsProcessed = 0
|
||||||
self.numberOfPubkeysProcessed = 0
|
self.numberOfPubkeysProcessed = 0
|
||||||
|
@ -833,34 +833,34 @@ class MyForm(QtGui.QMainWindow):
|
||||||
"MainWindow", "Queued.")
|
"MainWindow", "Queued.")
|
||||||
elif status == 'msgsent':
|
elif status == 'msgsent':
|
||||||
statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg(
|
statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'msgsentnoackexpected':
|
elif status == 'msgsentnoackexpected':
|
||||||
statusText = _translate("MainWindow", "Message sent. Sent at %1").arg(
|
statusText = _translate("MainWindow", "Message sent. Sent at %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'doingmsgpow':
|
elif status == 'doingmsgpow':
|
||||||
statusText = _translate(
|
statusText = _translate(
|
||||||
"MainWindow", "Need to do work to send message. Work is queued.")
|
"MainWindow", "Need to do work to send message. Work is queued.")
|
||||||
elif status == 'ackreceived':
|
elif status == 'ackreceived':
|
||||||
statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg(
|
statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'broadcastqueued':
|
elif status == 'broadcastqueued':
|
||||||
statusText = _translate(
|
statusText = _translate(
|
||||||
"MainWindow", "Broadcast queued.")
|
"MainWindow", "Broadcast queued.")
|
||||||
elif status == 'broadcastsent':
|
elif status == 'broadcastsent':
|
||||||
statusText = _translate("MainWindow", "Broadcast on %1").arg(unicode(strftime(
|
statusText = _translate("MainWindow", "Broadcast on %1").arg(
|
||||||
shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'toodifficult':
|
elif status == 'toodifficult':
|
||||||
statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg(
|
statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'badkey':
|
elif status == 'badkey':
|
||||||
statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg(
|
statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
elif status == 'forcepow':
|
elif status == 'forcepow':
|
||||||
statusText = _translate(
|
statusText = _translate(
|
||||||
"MainWindow", "Forced difficulty override. Send should start soon.")
|
"MainWindow", "Forced difficulty override. Send should start soon.")
|
||||||
else:
|
else:
|
||||||
statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg(unicode(
|
statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg(
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
l10n.formatTimestamp(lastactiontime))
|
||||||
newItem = myTableWidgetItem(statusText)
|
newItem = myTableWidgetItem(statusText)
|
||||||
newItem.setToolTip(statusText)
|
newItem.setToolTip(statusText)
|
||||||
newItem.setData(Qt.UserRole, QByteArray(ackdata))
|
newItem.setData(Qt.UserRole, QByteArray(ackdata))
|
||||||
|
@ -967,10 +967,8 @@ class MyForm(QtGui.QMainWindow):
|
||||||
subject_item.setFont(font)
|
subject_item.setFont(font)
|
||||||
self.ui.tableWidgetInbox.setItem(0, 2, subject_item)
|
self.ui.tableWidgetInbox.setItem(0, 2, subject_item)
|
||||||
# time received
|
# time received
|
||||||
time_item = myTableWidgetItem(unicode(strftime(shared.config.get(
|
time_item = myTableWidgetItem(l10n.formatTimestamp(received))
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(received))), 'utf-8'))
|
time_item.setToolTip(l10n.formatTimestamp(received))
|
||||||
time_item.setToolTip(unicode(strftime(shared.config.get(
|
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(received))), 'utf-8'))
|
|
||||||
time_item.setData(Qt.UserRole, QByteArray(msgid))
|
time_item.setData(Qt.UserRole, QByteArray(msgid))
|
||||||
time_item.setData(33, int(received))
|
time_item.setData(33, int(received))
|
||||||
time_item.setFlags(
|
time_item.setFlags(
|
||||||
|
@ -1468,6 +1466,31 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.ui.labelPubkeyCount.setText(_translate(
|
self.ui.labelPubkeyCount.setText(_translate(
|
||||||
"MainWindow", "Processed %1 public keys.").arg(str(shared.numberOfPubkeysProcessed)))
|
"MainWindow", "Processed %1 public keys.").arg(str(shared.numberOfPubkeysProcessed)))
|
||||||
|
|
||||||
|
def formatBytes(self, num):
|
||||||
|
for x in ['bytes','KB','MB','GB']:
|
||||||
|
if num < 1000.0:
|
||||||
|
return "%3.0f %s" % (num, x)
|
||||||
|
num /= 1000.0
|
||||||
|
return "%3.0f %s" % (num, 'TB')
|
||||||
|
|
||||||
|
def formatByteRate(self, num):
|
||||||
|
num /= 1000
|
||||||
|
return "%4.0f KB" % num
|
||||||
|
|
||||||
|
def updateNumberOfBytes(self):
|
||||||
|
"""
|
||||||
|
This function is run every two seconds, so we divide the rate of bytes
|
||||||
|
sent and received by 2.
|
||||||
|
"""
|
||||||
|
self.ui.labelBytesRecvCount.setText(_translate(
|
||||||
|
"MainWindow", "Down: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesReceived/2), self.formatBytes(self.totalNumberOfBytesReceived)))
|
||||||
|
self.ui.labelBytesSentCount.setText(_translate(
|
||||||
|
"MainWindow", "Up: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesSent/2), self.formatBytes(self.totalNumberOfBytesSent)))
|
||||||
|
self.totalNumberOfBytesReceived += shared.numberOfBytesReceived
|
||||||
|
self.totalNumberOfBytesSent += shared.numberOfBytesSent
|
||||||
|
shared.numberOfBytesReceived = 0
|
||||||
|
shared.numberOfBytesSent = 0
|
||||||
|
|
||||||
def updateNetworkStatusTab(self):
|
def updateNetworkStatusTab(self):
|
||||||
# print 'updating network status tab'
|
# print 'updating network status tab'
|
||||||
totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages).
|
totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages).
|
||||||
|
@ -1521,6 +1544,7 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.ui.labelLookupsPerSecond.setText(_translate(
|
self.ui.labelLookupsPerSecond.setText(_translate(
|
||||||
"MainWindow", "Inventory lookups per second: %1").arg(str(shared.numberOfInventoryLookupsPerformed/2)))
|
"MainWindow", "Inventory lookups per second: %1").arg(str(shared.numberOfInventoryLookupsPerformed/2)))
|
||||||
shared.numberOfInventoryLookupsPerformed = 0
|
shared.numberOfInventoryLookupsPerformed = 0
|
||||||
|
self.updateNumberOfBytes()
|
||||||
|
|
||||||
# Indicates whether or not there is a connection to the Bitmessage network
|
# Indicates whether or not there is a connection to the Bitmessage network
|
||||||
connected = False
|
connected = False
|
||||||
|
@ -2032,12 +2056,9 @@ class MyForm(QtGui.QMainWindow):
|
||||||
self.ui.tableWidgetSent.setItem(0, 2, newItem)
|
self.ui.tableWidgetSent.setItem(0, 2, newItem)
|
||||||
# newItem = QtGui.QTableWidgetItem('Doing work necessary to send
|
# newItem = QtGui.QTableWidgetItem('Doing work necessary to send
|
||||||
# broadcast...'+
|
# broadcast...'+
|
||||||
# unicode(strftime(shared.config.get('bitmessagesettings',
|
# l10n.formatTimestamp())
|
||||||
# 'timeformat'),localtime(int(time.time()))),'utf-8'))
|
newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp()))
|
||||||
newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(unicode(strftime(shared.config.get(
|
newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp()))
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))
|
|
||||||
newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(unicode(strftime(shared.config.get(
|
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))
|
|
||||||
newItem.setData(Qt.UserRole, QByteArray(ackdata))
|
newItem.setData(Qt.UserRole, QByteArray(ackdata))
|
||||||
newItem.setData(33, int(time.time()))
|
newItem.setData(33, int(time.time()))
|
||||||
self.ui.tableWidgetSent.setItem(0, 3, newItem)
|
self.ui.tableWidgetSent.setItem(0, 3, newItem)
|
||||||
|
@ -2104,10 +2125,8 @@ class MyForm(QtGui.QMainWindow):
|
||||||
#newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed.
|
#newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed.
|
||||||
newItem.setFont(font)
|
newItem.setFont(font)
|
||||||
self.ui.tableWidgetInbox.setItem(0, 2, newItem)
|
self.ui.tableWidgetInbox.setItem(0, 2, newItem)
|
||||||
newItem = myTableWidgetItem(unicode(strftime(shared.config.get(
|
newItem = myTableWidgetItem(l10n.formatTimestamp())
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))
|
newItem.setToolTip(l10n.formatTimestamp())
|
||||||
newItem.setToolTip(unicode(strftime(shared.config.get(
|
|
||||||
'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))
|
|
||||||
newItem.setData(Qt.UserRole, QByteArray(inventoryHash))
|
newItem.setData(Qt.UserRole, QByteArray(inventoryHash))
|
||||||
newItem.setData(33, int(time.time()))
|
newItem.setData(33, int(time.time()))
|
||||||
newItem.setFont(font)
|
newItem.setFont(font)
|
||||||
|
@ -3781,52 +3800,12 @@ def run():
|
||||||
app = QtGui.QApplication(sys.argv)
|
app = QtGui.QApplication(sys.argv)
|
||||||
translator = QtCore.QTranslator()
|
translator = QtCore.QTranslator()
|
||||||
|
|
||||||
try:
|
translationpath = os.path.join(
|
||||||
locale_countrycode = str(locale.getdefaultlocale()[0])
|
getattr(sys, '_MEIPASS', ''),
|
||||||
except:
|
'translations',
|
||||||
# The above is not compatible with all versions of OSX.
|
'bitmessage_' + l10n.getTranslationLanguage()
|
||||||
locale_countrycode = "en_US" # Default to english.
|
)
|
||||||
locale_lang = locale_countrycode[0:2]
|
translator.load(translationpath)
|
||||||
user_countrycode = str(shared.config.get('bitmessagesettings', 'userlocale'))
|
|
||||||
user_lang = user_countrycode[0:2]
|
|
||||||
try:
|
|
||||||
translation_path = os.path.join(sys._MEIPASS, "translations/bitmessage_")
|
|
||||||
except Exception, e:
|
|
||||||
translation_path = "translations/bitmessage_"
|
|
||||||
|
|
||||||
if shared.config.get('bitmessagesettings', 'userlocale') == 'system':
|
|
||||||
# try to detect the users locale otherwise fallback to English
|
|
||||||
try:
|
|
||||||
# try the users full locale, e.g. 'en_US':
|
|
||||||
# since we usually only provide languages, not localozations
|
|
||||||
# this will usually fail
|
|
||||||
translator.load(translation_path + locale_countrycode)
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
# try the users locale language, e.g. 'en':
|
|
||||||
# since we usually only provide languages, not localozations
|
|
||||||
# this will usually succeed
|
|
||||||
translator.load(translation_path + locale_lang)
|
|
||||||
except:
|
|
||||||
# as English is already the default language, we don't
|
|
||||||
# need to do anything. No need to translate.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
# check if the user input is a valid translation file:
|
|
||||||
# since user_countrycode will be usually set by the combobox
|
|
||||||
# it will usually just be a language code
|
|
||||||
translator.load(translation_path + user_countrycode)
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
# check if the user lang is a valid translation file:
|
|
||||||
# this is only needed if the user manually set his 'userlocale'
|
|
||||||
# in the keys.dat to a countrycode (e.g. 'de_CH')
|
|
||||||
translator.load(translation_path + user_lang)
|
|
||||||
except:
|
|
||||||
# as English is already the default language, we don't
|
|
||||||
# need to do anything. No need to translate.
|
|
||||||
pass
|
|
||||||
|
|
||||||
QtGui.QApplication.installTranslator(translator)
|
QtGui.QApplication.installTranslator(translator)
|
||||||
app.setStyleSheet("QStatusBar::item { border: 0px solid black }")
|
app.setStyleSheet("QStatusBar::item { border: 0px solid black }")
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'bitmessageui.ui'
|
# Form implementation generated from reading ui file 'bitmessageui.ui'
|
||||||
#
|
#
|
||||||
# Created: Sat Nov 2 18:01:09 2013
|
# Created: Fri Aug 01 15:30:14 2014
|
||||||
# by: PyQt4 UI code generator 4.10
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
@ -431,15 +431,21 @@ class Ui_MainWindow(object):
|
||||||
self.labelBroadcastCount.setGeometry(QtCore.QRect(350, 150, 351, 16))
|
self.labelBroadcastCount.setGeometry(QtCore.QRect(350, 150, 351, 16))
|
||||||
self.labelBroadcastCount.setObjectName(_fromUtf8("labelBroadcastCount"))
|
self.labelBroadcastCount.setObjectName(_fromUtf8("labelBroadcastCount"))
|
||||||
self.labelLookupsPerSecond = QtGui.QLabel(self.networkstatus)
|
self.labelLookupsPerSecond = QtGui.QLabel(self.networkstatus)
|
||||||
self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 210, 291, 16))
|
self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 250, 291, 16))
|
||||||
self.labelLookupsPerSecond.setObjectName(_fromUtf8("labelLookupsPerSecond"))
|
self.labelLookupsPerSecond.setObjectName(_fromUtf8("labelLookupsPerSecond"))
|
||||||
|
self.labelBytesRecvCount = QtGui.QLabel(self.networkstatus)
|
||||||
|
self.labelBytesRecvCount.setGeometry(QtCore.QRect(350, 210, 251, 16))
|
||||||
|
self.labelBytesRecvCount.setObjectName(_fromUtf8("labelBytesRecvCount"))
|
||||||
|
self.labelBytesSentCount = QtGui.QLabel(self.networkstatus)
|
||||||
|
self.labelBytesSentCount.setGeometry(QtCore.QRect(350, 230, 251, 16))
|
||||||
|
self.labelBytesSentCount.setObjectName(_fromUtf8("labelBytesSentCount"))
|
||||||
icon9 = QtGui.QIcon()
|
icon9 = QtGui.QIcon()
|
||||||
icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
self.tabWidget.addTab(self.networkstatus, icon9, _fromUtf8(""))
|
self.tabWidget.addTab(self.networkstatus, icon9, _fromUtf8(""))
|
||||||
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
|
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtGui.QMenuBar(MainWindow)
|
self.menubar = QtGui.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 21))
|
||||||
self.menubar.setObjectName(_fromUtf8("menubar"))
|
self.menubar.setObjectName(_fromUtf8("menubar"))
|
||||||
self.menuFile = QtGui.QMenu(self.menubar)
|
self.menuFile = QtGui.QMenu(self.menubar)
|
||||||
self.menuFile.setObjectName(_fromUtf8("menuFile"))
|
self.menuFile.setObjectName(_fromUtf8("menuFile"))
|
||||||
|
@ -557,8 +563,8 @@ class Ui_MainWindow(object):
|
||||||
self.textEditMessage.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
self.textEditMessage.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
|
||||||
"p, li { white-space: pre-wrap; }\n"
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
"</style></head><body style=\" font-family:\'Sans\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
|
||||||
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\';\"><br /></p></body></html>", None))
|
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", None))
|
||||||
self.label.setText(_translate("MainWindow", "To:", None))
|
self.label.setText(_translate("MainWindow", "To:", None))
|
||||||
self.label_2.setText(_translate("MainWindow", "From:", None))
|
self.label_2.setText(_translate("MainWindow", "From:", None))
|
||||||
self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None))
|
self.radioButtonBroadcast.setText(_translate("MainWindow", "Broadcast to everyone who is subscribed to your address", None))
|
||||||
|
@ -625,6 +631,8 @@ class Ui_MainWindow(object):
|
||||||
self.labelPubkeyCount.setText(_translate("MainWindow", "Processed 0 public key.", None))
|
self.labelPubkeyCount.setText(_translate("MainWindow", "Processed 0 public key.", None))
|
||||||
self.labelBroadcastCount.setText(_translate("MainWindow", "Processed 0 broadcast.", None))
|
self.labelBroadcastCount.setText(_translate("MainWindow", "Processed 0 broadcast.", None))
|
||||||
self.labelLookupsPerSecond.setText(_translate("MainWindow", "Inventory lookups per second: 0", None))
|
self.labelLookupsPerSecond.setText(_translate("MainWindow", "Inventory lookups per second: 0", None))
|
||||||
|
self.labelBytesRecvCount.setText(_translate("MainWindow", "Down: 0 KB/s", None))
|
||||||
|
self.labelBytesSentCount.setText(_translate("MainWindow", "Up: 0 KB/s", None))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.networkstatus), _translate("MainWindow", "Network Status", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.networkstatus), _translate("MainWindow", "Network Status", None))
|
||||||
self.menuFile.setTitle(_translate("MainWindow", "File", None))
|
self.menuFile.setTitle(_translate("MainWindow", "File", None))
|
||||||
self.menuSettings.setTitle(_translate("MainWindow", "Settings", None))
|
self.menuSettings.setTitle(_translate("MainWindow", "Settings", None))
|
||||||
|
|
|
@ -278,8 +278,8 @@
|
||||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
p, li { white-space: pre-wrap; }
|
p, li { white-space: pre-wrap; }
|
||||||
</style></head><body style=" font-family:'Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2';"><br /></p></body></html></string>
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -1035,7 +1035,7 @@ p, li { white-space: pre-wrap; }
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>320</x>
|
<x>320</x>
|
||||||
<y>210</y>
|
<y>250</y>
|
||||||
<width>291</width>
|
<width>291</width>
|
||||||
<height>16</height>
|
<height>16</height>
|
||||||
</rect>
|
</rect>
|
||||||
|
@ -1044,6 +1044,32 @@ p, li { white-space: pre-wrap; }
|
||||||
<string>Inventory lookups per second: 0</string>
|
<string>Inventory lookups per second: 0</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QLabel" name="labelBytesRecvCount">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>350</x>
|
||||||
|
<y>210</y>
|
||||||
|
<width>251</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Down: 0 KB/s</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="labelBytesSentCount">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>350</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>251</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Up: 0 KB/s</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -1055,7 +1081,7 @@ p, li { white-space: pre-wrap; }
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>885</width>
|
<width>885</width>
|
||||||
<height>27</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
name = "Bitmessage"
|
name = "Bitmessage"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
mainscript = ["bitmessagemain.py"]
|
mainscript = ["bitmessagemain.py"]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
|
|
@ -19,6 +19,7 @@ import helper_sent
|
||||||
from helper_sql import *
|
from helper_sql import *
|
||||||
import tr
|
import tr
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
import l10n
|
||||||
|
|
||||||
|
|
||||||
class objectProcessor(threading.Thread):
|
class objectProcessor(threading.Thread):
|
||||||
|
@ -421,8 +422,7 @@ class objectProcessor(threading.Thread):
|
||||||
del shared.ackdataForWhichImWatching[data[readPosition:]]
|
del shared.ackdataForWhichImWatching[data[readPosition:]]
|
||||||
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
|
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
|
||||||
'ackreceived', data[readPosition:])
|
'ackreceived', data[readPosition:])
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[readPosition:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(unicode(
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[readPosition:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
|
||||||
time.strftime(shared.config.get('bitmessagesettings', 'timeformat'), time.localtime(int(time.time()))), 'utf-8')))))
|
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
logger.info('This was NOT an acknowledgement bound for me.')
|
logger.info('This was NOT an acknowledgement bound for me.')
|
||||||
|
|
|
@ -62,19 +62,21 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'ID of the receiveDataThread is', str(id(self)) + '. The size of the shared.connectedHostsList is now', len(shared.connectedHostsList)
|
print 'receiveDataThread starting. ID', str(id(self)) + '. The size of the shared.connectedHostsList is now', len(shared.connectedHostsList)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
dataLen = len(self.data)
|
dataLen = len(self.data)
|
||||||
try:
|
try:
|
||||||
self.data += self.sock.recv(4096)
|
dataRecv = self.sock.recv(4096)
|
||||||
|
self.data += dataRecv
|
||||||
|
shared.numberOfBytesReceived += len(dataRecv)
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Timeout occurred waiting for data from', self.peer, '. Closing receiveData thread. (ID:', str(id(self)) + ')'
|
print 'Timeout occurred waiting for data from', self.peer, '. Closing receiveData thread. (ID:', str(id(self)) + ')'
|
||||||
break
|
break
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'sock.recv error. Closing receiveData thread (HOST:', self.peer, 'ID:', str(id(self)) + ').', err
|
print 'sock.recv error. Closing receiveData thread (' + str(self.peer) + ', Thread ID:', str(id(self)) + ').', err
|
||||||
break
|
break
|
||||||
# print 'Received', repr(self.data)
|
# print 'Received', repr(self.data)
|
||||||
if len(self.data) == dataLen: # If self.sock.recv returned no data:
|
if len(self.data) == dataLen: # If self.sock.recv returned no data:
|
||||||
|
@ -90,7 +92,7 @@ class receiveDataThread(threading.Thread):
|
||||||
print 'removed self (a receiveDataThread) from selfInitiatedConnections'
|
print 'removed self (a receiveDataThread) from selfInitiatedConnections'
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer)) # commands the corresponding sendDataThread to shut itself down.
|
self.sendDataThreadQueue.put((0, 'shutdown','no data')) # commands the corresponding sendDataThread to shut itself down.
|
||||||
try:
|
try:
|
||||||
del shared.connectedHostsList[self.peer.host]
|
del shared.connectedHostsList[self.peer.host]
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
@ -104,47 +106,33 @@ class receiveDataThread(threading.Thread):
|
||||||
pass
|
pass
|
||||||
shared.UISignalQueue.put(('updateNetworkStatusTab', 'no data'))
|
shared.UISignalQueue.put(('updateNetworkStatusTab', 'no data'))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'The size of the connectedHostsList is now:', len(shared.connectedHostsList)
|
print 'receiveDataThread ending. ID', str(id(self)) + '. The size of the shared.connectedHostsList is now', len(shared.connectedHostsList)
|
||||||
|
|
||||||
|
|
||||||
def processData(self):
|
def processData(self):
|
||||||
# if shared.verbose >= 3:
|
|
||||||
# with shared.printLock:
|
|
||||||
# print 'self.data is currently ', repr(self.data)
|
|
||||||
#
|
|
||||||
if len(self.data) < shared.Header.size: # if so little of the data has arrived that we can't even read the checksum then wait for more data.
|
if len(self.data) < shared.Header.size: # if so little of the data has arrived that we can't even read the checksum then wait for more data.
|
||||||
return
|
return
|
||||||
#Use a memoryview so we don't copy data unnecessarily
|
|
||||||
view = memoryview(self.data)
|
magic,command,payloadLength,checksum = shared.Header.unpack(self.data[:shared.Header.size])
|
||||||
magic,command,payloadLength,checksum = shared.Header.unpack(view[:shared.Header.size])
|
|
||||||
view = view[shared.Header.size:]
|
|
||||||
if magic != 0xE9BEB4D9:
|
if magic != 0xE9BEB4D9:
|
||||||
#if shared.verbose >= 1:
|
|
||||||
# with shared.printLock:
|
|
||||||
# print 'The magic bytes were not correct. First 40 bytes of data: ' + repr(self.data[0:40])
|
|
||||||
|
|
||||||
self.data = ""
|
self.data = ""
|
||||||
return
|
return
|
||||||
if payloadLength > 20000000:
|
if payloadLength > 20000000:
|
||||||
logger.info('The incoming message, which we have not yet download, is too large. Ignoring it. (unfortunately there is no way to tell the other node to stop sending it except to disconnect.) Message size: %s' % payloadLength)
|
logger.info('The incoming message, which we have not yet download, is too large. Ignoring it. (unfortunately there is no way to tell the other node to stop sending it except to disconnect.) Message size: %s' % payloadLength)
|
||||||
self.data = view[payloadLength:].tobytes()
|
self.data = self.data[payloadLength + shared.Header.size:]
|
||||||
del view,magic,command,payloadLength,checksum # we don't need these anymore and better to clean them now before the recursive call rather than after
|
del magic,command,payloadLength,checksum # we don't need these anymore and better to clean them now before the recursive call rather than after
|
||||||
self.processData()
|
self.processData()
|
||||||
return
|
return
|
||||||
if len(view) < payloadLength: # check if the whole message has arrived yet.
|
if len(self.data) < payloadLength + shared.Header.size: # check if the whole message has arrived yet.
|
||||||
return
|
return
|
||||||
payload = view[:payloadLength]
|
payload = self.data[shared.Header.size:payloadLength + shared.Header.size]
|
||||||
if checksum != hashlib.sha512(payload).digest()[0:4]: # test the checksum in the message.
|
if checksum != hashlib.sha512(payload).digest()[0:4]: # test the checksum in the message.
|
||||||
print 'Checksum incorrect. Clearing this message.'
|
print 'Checksum incorrect. Clearing this message.'
|
||||||
self.data = view[payloadLength:].tobytes()
|
self.data = self.data[payloadLength + shared.Header.size:]
|
||||||
del view,magic,command,payloadLength,checksum,payload #again better to clean up before the recursive call
|
del magic,command,payloadLength,checksum,payload # better to clean up before the recursive call
|
||||||
self.processData()
|
self.processData()
|
||||||
return
|
return
|
||||||
|
|
||||||
#We can now revert back to bytestrings and take this message out
|
|
||||||
payload = payload.tobytes()
|
|
||||||
self.data = view[payloadLength:].tobytes()
|
|
||||||
del view,magic,payloadLength,checksum
|
|
||||||
# The time we've last seen this node is obviously right now since we
|
# The time we've last seen this node is obviously right now since we
|
||||||
# just received valid data from it. So update the knownNodes list so
|
# just received valid data from it. So update the knownNodes list so
|
||||||
# that other peers can be made aware of its existance.
|
# that other peers can be made aware of its existance.
|
||||||
|
@ -185,8 +173,11 @@ class receiveDataThread(threading.Thread):
|
||||||
# pass
|
# pass
|
||||||
#elif command == 'alert':
|
#elif command == 'alert':
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
|
del payload
|
||||||
|
self.data = self.data[payloadLength + shared.Header.size:] # take this message out and then process the next message
|
||||||
|
|
||||||
if self.data == '':
|
if self.data == '': # if there are no more messages
|
||||||
while len(self.objectsThatWeHaveYetToGetFromThisPeer) > 0:
|
while len(self.objectsThatWeHaveYetToGetFromThisPeer) > 0:
|
||||||
shared.numberOfInventoryLookupsPerformed += 1
|
shared.numberOfInventoryLookupsPerformed += 1
|
||||||
objectHash, = random.sample(
|
objectHash, = random.sample(
|
||||||
|
@ -194,24 +185,22 @@ class receiveDataThread(threading.Thread):
|
||||||
if objectHash in shared.inventory:
|
if objectHash in shared.inventory:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Inventory (in memory) already has object listed in inv message.'
|
print 'Inventory (in memory) already has object listed in inv message.'
|
||||||
|
|
||||||
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
||||||
objectHash]
|
objectHash]
|
||||||
elif shared.isInSqlInventory(objectHash):
|
elif shared.isInSqlInventory(objectHash):
|
||||||
if shared.verbose >= 3:
|
if shared.verbose >= 3:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Inventory (SQL on disk) already has object listed in inv message.'
|
print 'Inventory (SQL on disk) already has object listed in inv message.'
|
||||||
|
|
||||||
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
||||||
objectHash]
|
objectHash]
|
||||||
else:
|
else:
|
||||||
|
# We don't have the object in our inventory. Let's request it.
|
||||||
self.sendgetdata(objectHash)
|
self.sendgetdata(objectHash)
|
||||||
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
del self.objectsThatWeHaveYetToGetFromThisPeer[
|
||||||
objectHash] # It is possible that the remote node might not respond with the object. In that case, we'll very likely get it from someone else anyway.
|
objectHash] # It is possible that the remote node might not respond with the object. In that case, we'll very likely get it from someone else anyway.
|
||||||
if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0:
|
if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now', len(self.objectsThatWeHaveYetToGetFromThisPeer)
|
print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now 0'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[
|
del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[
|
||||||
self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together.
|
self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together.
|
||||||
|
@ -219,9 +208,9 @@ class receiveDataThread(threading.Thread):
|
||||||
pass
|
pass
|
||||||
break
|
break
|
||||||
if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0:
|
if len(self.objectsThatWeHaveYetToGetFromThisPeer) == 0:
|
||||||
|
# We had objectsThatWeHaveYetToGetFromThisPeer but the loop ran, they were all in our inventory, and now we don't have any to get anymore.
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now', len(self.objectsThatWeHaveYetToGetFromThisPeer)
|
print '(concerning', str(self.peer) + ')', 'number of objectsThatWeHaveYetToGetFromThisPeer is now 0'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[
|
del shared.numberOfObjectsThatWeHaveYetToGetPerPeer[
|
||||||
self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together.
|
self.peer] # this data structure is maintained so that we can keep track of how many total objects, across all connections, are currently outstanding. If it goes too high it can indicate that we are under attack by multiple nodes working together.
|
||||||
|
@ -237,12 +226,14 @@ class receiveDataThread(threading.Thread):
|
||||||
|
|
||||||
|
|
||||||
def sendpong(self):
|
def sendpong(self):
|
||||||
print 'Sending pong'
|
with shared.printLock:
|
||||||
|
print 'Sending pong'
|
||||||
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('pong')))
|
self.sendDataThreadQueue.put((0, 'sendRawData', shared.CreatePacket('pong')))
|
||||||
|
|
||||||
|
|
||||||
def recverack(self):
|
def recverack(self):
|
||||||
print 'verack received'
|
with shared.printLock:
|
||||||
|
print 'verack received'
|
||||||
self.verackReceived = True
|
self.verackReceived = True
|
||||||
if self.verackSent:
|
if self.verackSent:
|
||||||
# We have thus both sent and received a verack.
|
# We have thus both sent and received a verack.
|
||||||
|
@ -277,7 +268,7 @@ class receiveDataThread(threading.Thread):
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'We are connected to too many people. Closing connection.'
|
print 'We are connected to too many people. Closing connection.'
|
||||||
|
|
||||||
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
|
self.sendDataThreadQueue.put((0, 'shutdown','no data'))
|
||||||
return
|
return
|
||||||
self.sendBigInv()
|
self.sendBigInv()
|
||||||
|
|
||||||
|
@ -740,7 +731,7 @@ class receiveDataThread(threading.Thread):
|
||||||
return
|
return
|
||||||
self.remoteProtocolVersion, = unpack('>L', data[:4])
|
self.remoteProtocolVersion, = unpack('>L', data[:4])
|
||||||
if self.remoteProtocolVersion <= 1:
|
if self.remoteProtocolVersion <= 1:
|
||||||
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
|
self.sendDataThreadQueue.put((0, 'shutdown','no data'))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Closing connection to old protocol version 1 node: ', self.peer
|
print 'Closing connection to old protocol version 1 node: ', self.peer
|
||||||
return
|
return
|
||||||
|
@ -763,7 +754,7 @@ class receiveDataThread(threading.Thread):
|
||||||
print 'Remote node useragent:', useragent, ' stream number:', self.streamNumber
|
print 'Remote node useragent:', useragent, ' stream number:', self.streamNumber
|
||||||
|
|
||||||
if self.streamNumber != 1:
|
if self.streamNumber != 1:
|
||||||
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
|
self.sendDataThreadQueue.put((0, 'shutdown','no data'))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Closed connection to', self.peer, 'because they are interested in stream', self.streamNumber, '.'
|
print 'Closed connection to', self.peer, 'because they are interested in stream', self.streamNumber, '.'
|
||||||
return
|
return
|
||||||
|
@ -774,7 +765,7 @@ class receiveDataThread(threading.Thread):
|
||||||
if not self.initiatedConnection:
|
if not self.initiatedConnection:
|
||||||
self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber))
|
self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber))
|
||||||
if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
|
if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
|
||||||
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
|
self.sendDataThreadQueue.put((0, 'shutdown','no data'))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Closing connection to myself: ', self.peer
|
print 'Closing connection to myself: ', self.peer
|
||||||
return
|
return
|
||||||
|
|
|
@ -20,9 +20,6 @@ class sendDataThread(threading.Thread):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.sendDataThreadQueue = sendDataThreadQueue
|
self.sendDataThreadQueue = sendDataThreadQueue
|
||||||
shared.sendDataQueues.append(self.sendDataThreadQueue)
|
shared.sendDataQueues.append(self.sendDataThreadQueue)
|
||||||
with shared.printLock:
|
|
||||||
print 'The length of sendDataQueues at sendDataThread init is:', len(shared.sendDataQueues)
|
|
||||||
|
|
||||||
self.data = ''
|
self.data = ''
|
||||||
self.objectHashHolderInstance = objectHashHolder(self.sendDataThreadQueue)
|
self.objectHashHolderInstance = objectHashHolder(self.sendDataThreadQueue)
|
||||||
self.objectHashHolderInstance.start()
|
self.objectHashHolderInstance.start()
|
||||||
|
@ -56,7 +53,7 @@ class sendDataThread(threading.Thread):
|
||||||
print 'Sending version packet: ', repr(datatosend)
|
print 'Sending version packet: ', repr(datatosend)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(datatosend)
|
self.sendBytes(datatosend)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
# if not 'Bad file descriptor' in err:
|
# if not 'Bad file descriptor' in err:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
|
@ -64,16 +61,23 @@ class sendDataThread(threading.Thread):
|
||||||
|
|
||||||
self.versionSent = 1
|
self.versionSent = 1
|
||||||
|
|
||||||
|
def sendBytes(self, data):
|
||||||
|
self.sock.sendall(data)
|
||||||
|
shared.numberOfBytesSent += len(data)
|
||||||
|
self.lastTimeISentData = int(time.time())
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
with shared.printLock:
|
||||||
|
print 'sendDataThread starting. ID:', str(id(self))+'. Number of queues in sendDataQueues:', len(shared.sendDataQueues)
|
||||||
while True:
|
while True:
|
||||||
deststream, command, data = self.sendDataThreadQueue.get()
|
deststream, command, data = self.sendDataThreadQueue.get()
|
||||||
|
|
||||||
if deststream == self.streamNumber or deststream == 0:
|
if deststream == self.streamNumber or deststream == 0:
|
||||||
if command == 'shutdown':
|
if command == 'shutdown':
|
||||||
if data == self.peer or data == 'all':
|
with shared.printLock:
|
||||||
with shared.printLock:
|
print 'sendDataThread (associated with', self.peer, ') ID:', id(self), 'shutting down now.'
|
||||||
print 'sendDataThread (associated with', self.peer, ') ID:', id(self), 'shutting down now.'
|
break
|
||||||
break
|
|
||||||
# When you receive an incoming connection, a sendDataThread is
|
# When you receive an incoming connection, a sendDataThread is
|
||||||
# created even though you don't yet know what stream number the
|
# created even though you don't yet know what stream number the
|
||||||
# remote peer is interested in. They will tell you in a version
|
# remote peer is interested in. They will tell you in a version
|
||||||
|
@ -92,49 +96,44 @@ class sendDataThread(threading.Thread):
|
||||||
elif command == 'advertisepeer':
|
elif command == 'advertisepeer':
|
||||||
self.objectHashHolderInstance.holdPeer(data)
|
self.objectHashHolderInstance.holdPeer(data)
|
||||||
elif command == 'sendaddr':
|
elif command == 'sendaddr':
|
||||||
if not self.connectionIsOrWasFullyEstablished:
|
if self.connectionIsOrWasFullyEstablished: # only send addr messages if we have send and heard a verack from the remote node
|
||||||
# not sending addr because we haven't sent and heard a verack from the remote node yet
|
numberOfAddressesInAddrMessage = len(data)
|
||||||
return
|
payload = ''
|
||||||
numberOfAddressesInAddrMessage = len(
|
for hostDetails in data:
|
||||||
data)
|
timeLastReceivedMessageFromThisNode, streamNumber, services, host, port = hostDetails
|
||||||
payload = ''
|
payload += pack(
|
||||||
for hostDetails in data:
|
'>Q', timeLastReceivedMessageFromThisNode) # now uses 64-bit time
|
||||||
timeLastReceivedMessageFromThisNode, streamNumber, services, host, port = hostDetails
|
payload += pack('>I', streamNumber)
|
||||||
payload += pack(
|
payload += pack(
|
||||||
'>Q', timeLastReceivedMessageFromThisNode) # now uses 64-bit time
|
'>q', services) # service bit flags offered by this node
|
||||||
payload += pack('>I', streamNumber)
|
payload += shared.encodeHost(host)
|
||||||
payload += pack(
|
payload += pack('>H', port)
|
||||||
'>q', services) # service bit flags offered by this node
|
|
||||||
payload += shared.encodeHost(host)
|
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
||||||
payload += pack('>H', port)
|
packet = shared.CreatePacket('addr', payload)
|
||||||
|
try:
|
||||||
payload = encodeVarint(numberOfAddressesInAddrMessage) + payload
|
self.sendBytes(packet)
|
||||||
packet = shared.CreatePacket('addr', payload)
|
except:
|
||||||
try:
|
with shared.printLock:
|
||||||
self.sock.sendall(packet)
|
print 'sendaddr: self.sock.sendall failed'
|
||||||
self.lastTimeISentData = int(time.time())
|
break
|
||||||
except:
|
|
||||||
print 'sendaddr: self.sock.sendall failed'
|
|
||||||
break
|
|
||||||
elif command == 'advertiseobject':
|
elif command == 'advertiseobject':
|
||||||
self.objectHashHolderInstance.holdHash(data)
|
self.objectHashHolderInstance.holdHash(data)
|
||||||
elif command == 'sendinv':
|
elif command == 'sendinv':
|
||||||
if not self.connectionIsOrWasFullyEstablished:
|
if self.connectionIsOrWasFullyEstablished: # only send inv messages if we have send and heard a verack from the remote node
|
||||||
# not sending inv because we haven't sent and heard a verack from the remote node yet
|
payload = ''
|
||||||
return
|
for hash in data:
|
||||||
payload = ''
|
if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
|
||||||
for hash in data:
|
payload += hash
|
||||||
if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
|
if payload != '':
|
||||||
payload += hash
|
payload = encodeVarint(len(payload)/32) + payload
|
||||||
if payload != '':
|
packet = shared.CreatePacket('inv', payload)
|
||||||
payload = encodeVarint(len(payload)/32) + payload
|
try:
|
||||||
packet = shared.CreatePacket('inv', payload)
|
self.sendBytes(packet)
|
||||||
try:
|
except:
|
||||||
self.sock.sendall(packet)
|
with shared.printLock:
|
||||||
self.lastTimeISentData = int(time.time())
|
print 'sendinv: self.sock.sendall failed'
|
||||||
except:
|
break
|
||||||
print 'sendinv: self.sock.sendall failed'
|
|
||||||
break
|
|
||||||
elif command == 'pong':
|
elif command == 'pong':
|
||||||
self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware.clear() # To save memory, let us clear this data structure from time to time. As its function is to help us keep from sending inv messages to peers which sent us the same inv message mere seconds earlier, it will be fine to clear this data structure from time to time.
|
self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware.clear() # To save memory, let us clear this data structure from time to time. As its function is to help us keep from sending inv messages to peers which sent us the same inv message mere seconds earlier, it will be fine to clear this data structure from time to time.
|
||||||
if self.lastTimeISentData < (int(time.time()) - 298):
|
if self.lastTimeISentData < (int(time.time()) - 298):
|
||||||
|
@ -143,17 +142,17 @@ class sendDataThread(threading.Thread):
|
||||||
print 'Sending pong to', self.peer, 'to keep connection alive.'
|
print 'Sending pong to', self.peer, 'to keep connection alive.'
|
||||||
packet = shared.CreatePacket('pong')
|
packet = shared.CreatePacket('pong')
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(packet)
|
self.sendBytes(packet)
|
||||||
self.lastTimeISentData = int(time.time())
|
|
||||||
except:
|
except:
|
||||||
print 'send pong failed'
|
with shared.printLock:
|
||||||
|
print 'send pong failed'
|
||||||
break
|
break
|
||||||
elif command == 'sendRawData':
|
elif command == 'sendRawData':
|
||||||
try:
|
try:
|
||||||
self.sock.sendall(data)
|
self.sendBytes(data)
|
||||||
self.lastTimeISentData = int(time.time())
|
|
||||||
except:
|
except:
|
||||||
print 'Sending of data to', self.peer, 'failed. sendDataThread thread', self, 'ending now.'
|
with shared.printLock:
|
||||||
|
print 'Sending of data to', self.peer, 'failed. sendDataThread thread', self, 'ending now.'
|
||||||
break
|
break
|
||||||
elif command == 'connectionIsOrWasFullyEstablished':
|
elif command == 'connectionIsOrWasFullyEstablished':
|
||||||
self.connectionIsOrWasFullyEstablished = True
|
self.connectionIsOrWasFullyEstablished = True
|
||||||
|
@ -168,5 +167,5 @@ class sendDataThread(threading.Thread):
|
||||||
pass
|
pass
|
||||||
shared.sendDataQueues.remove(self.sendDataThreadQueue)
|
shared.sendDataQueues.remove(self.sendDataThreadQueue)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Number of queues remaining in sendDataQueues:', len(shared.sendDataQueues)
|
print 'sendDataThread ending. ID:', str(id(self))+'. Number of queues in sendDataQueues:', len(shared.sendDataQueues)
|
||||||
self.objectHashHolderInstance.close()
|
self.objectHashHolderInstance.close()
|
||||||
|
|
|
@ -13,6 +13,7 @@ from debug import logger
|
||||||
from helper_sql import *
|
from helper_sql import *
|
||||||
import helper_inbox
|
import helper_inbox
|
||||||
from helper_generic import addDataPadding
|
from helper_generic import addDataPadding
|
||||||
|
import l10n
|
||||||
|
|
||||||
# This thread, of which there is only one, does the heavy lifting:
|
# This thread, of which there is only one, does the heavy lifting:
|
||||||
# calculating POWs.
|
# calculating POWs.
|
||||||
|
@ -440,8 +441,7 @@ class singleWorker(threading.Thread):
|
||||||
shared.broadcastToSendDataQueues((
|
shared.broadcastToSendDataQueues((
|
||||||
streamNumber, 'advertiseobject', inventoryHash))
|
streamNumber, 'advertiseobject', inventoryHash))
|
||||||
|
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Broadcast sent on %1").arg(unicode(
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Broadcast sent on %1").arg(l10n.formatTimestamp()))))
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
|
|
||||||
|
|
||||||
# Update the status of the message in the 'sent' table to have
|
# Update the status of the message in the 'sent' table to have
|
||||||
# a 'broadcastsent' status
|
# a 'broadcastsent' status
|
||||||
|
@ -616,7 +616,7 @@ class singleWorker(threading.Thread):
|
||||||
if shared.isBitSetWithinBitfield(behaviorBitfield,30): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message..
|
if shared.isBitSetWithinBitfield(behaviorBitfield,30): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message..
|
||||||
if not shared.safeConfigGetBoolean('bitmessagesettings','willinglysendtomobile'): # if we are Not willing to include the receiver's RIPE hash on the message..
|
if not shared.safeConfigGetBoolean('bitmessagesettings','willinglysendtomobile'): # if we are Not willing to include the receiver's RIPE hash on the message..
|
||||||
logger.info('The receiver is a mobile user but the sender (you) has not selected that you are willing to send to mobiles. Aborting send.')
|
logger.info('The receiver is a mobile user but the sender (you) has not selected that you are willing to send to mobiles. Aborting send.')
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')))))
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(l10n.formatTimestamp()))))
|
||||||
# if the human changes their setting and then sends another message or restarts their client, this one will send at that time.
|
# if the human changes their setting and then sends another message or restarts their client, this one will send at that time.
|
||||||
continue
|
continue
|
||||||
readPosition += 4 # to bypass the bitfield of behaviors
|
readPosition += 4 # to bypass the bitfield of behaviors
|
||||||
|
@ -655,7 +655,7 @@ class singleWorker(threading.Thread):
|
||||||
'''UPDATE sent SET status='toodifficult' WHERE ackdata=? ''',
|
'''UPDATE sent SET status='toodifficult' WHERE ackdata=? ''',
|
||||||
ackdata)
|
ackdata)
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do.").arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(str(float(
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Problem: The work demanded by the recipient (%1 and %2) is more difficult than you are willing to do.").arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(str(float(
|
||||||
requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes)).arg(unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
|
requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes)).arg(l10n.formatTimestamp()))))
|
||||||
continue
|
continue
|
||||||
else: # if we are sending a message to ourselves or a chan..
|
else: # if we are sending a message to ourselves or a chan..
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
|
@ -666,7 +666,7 @@ class singleWorker(threading.Thread):
|
||||||
privEncryptionKeyBase58 = shared.config.get(
|
privEncryptionKeyBase58 = shared.config.get(
|
||||||
toaddress, 'privencryptionkey')
|
toaddress, 'privencryptionkey')
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1').arg(unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')))))
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: You are trying to send a message to yourself or a chan but your encryption key could not be found in the keys.dat file. Could not encrypt message. %1').arg(l10n.formatTimestamp()))))
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
'Error within sendMsg. Could not read the keys from the keys.dat file for our own address. %s\n' % err)
|
'Error within sendMsg. Could not read the keys from the keys.dat file for our own address. %s\n' % err)
|
||||||
|
@ -803,7 +803,7 @@ class singleWorker(threading.Thread):
|
||||||
encrypted = highlevelcrypto.encrypt(payload,"04"+pubEncryptionKeyBase256.encode('hex'))
|
encrypted = highlevelcrypto.encrypt(payload,"04"+pubEncryptionKeyBase256.encode('hex'))
|
||||||
except:
|
except:
|
||||||
sqlExecute('''UPDATE sent SET status='badkey' WHERE ackdata=?''', ackdata)
|
sqlExecute('''UPDATE sent SET status='badkey' WHERE ackdata=?''', ackdata)
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1').arg(unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'),localtime(int(time.time()))),'utf-8')))))
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1').arg(l10n.formatTimestamp()))))
|
||||||
continue
|
continue
|
||||||
encryptedPayload = embeddedTime + encodeVarint(toStreamNumber) + encrypted
|
encryptedPayload = embeddedTime + encodeVarint(toStreamNumber) + encrypted
|
||||||
target = 2**64 / ((len(encryptedPayload)+requiredPayloadLengthExtraBytes+8) * requiredAverageProofOfWorkNonceTrialsPerByte)
|
target = 2**64 / ((len(encryptedPayload)+requiredPayloadLengthExtraBytes+8) * requiredAverageProofOfWorkNonceTrialsPerByte)
|
||||||
|
@ -828,12 +828,10 @@ class singleWorker(threading.Thread):
|
||||||
objectType, toStreamNumber, encryptedPayload, int(time.time()),'')
|
objectType, toStreamNumber, encryptedPayload, int(time.time()),'')
|
||||||
shared.inventorySets[toStreamNumber].add(inventoryHash)
|
shared.inventorySets[toStreamNumber].add(inventoryHash)
|
||||||
if shared.config.has_section(toaddress):
|
if shared.config.has_section(toaddress):
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Sent on %1").arg(unicode(
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Sent on %1").arg(l10n.formatTimestamp()))))
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
|
|
||||||
else:
|
else:
|
||||||
# not sending to a chan or one of my addresses
|
# not sending to a chan or one of my addresses
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Waiting for acknowledgement. Sent on %1").arg(unicode(
|
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (ackdata, tr.translateText("MainWindow", "Message sent. Waiting for acknowledgement. Sent on %1").arg(l10n.formatTimestamp()))))
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
|
|
||||||
print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex')
|
print 'Broadcasting inv for my msg(within sendmsg function):', inventoryHash.encode('hex')
|
||||||
shared.broadcastToSendDataQueues((
|
shared.broadcastToSendDataQueues((
|
||||||
toStreamNumber, 'advertiseobject', inventoryHash))
|
toStreamNumber, 'advertiseobject', inventoryHash))
|
||||||
|
@ -926,8 +924,7 @@ class singleWorker(threading.Thread):
|
||||||
|
|
||||||
shared.UISignalQueue.put((
|
shared.UISignalQueue.put((
|
||||||
'updateStatusBar', tr.translateText("MainWindow",'Broacasting the public key request. This program will auto-retry if they are offline.')))
|
'updateStatusBar', tr.translateText("MainWindow",'Broacasting the public key request. This program will auto-retry if they are offline.')))
|
||||||
shared.UISignalQueue.put(('updateSentItemStatusByHash', (ripe, tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(unicode(
|
shared.UISignalQueue.put(('updateSentItemStatusByHash', (ripe, tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp()))))
|
||||||
strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')))))
|
|
||||||
|
|
||||||
def generateFullAckMessage(self, ackdata, toStreamNumber):
|
def generateFullAckMessage(self, ackdata, toStreamNumber):
|
||||||
embeddedTime = pack('>Q', (int(time.time()) + random.randrange(
|
embeddedTime = pack('>Q', (int(time.time()) + random.randrange(
|
||||||
|
|
93
src/l10n.py
Normal file
93
src/l10n.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
|
import shared
|
||||||
|
|
||||||
|
|
||||||
|
#logger = logging.getLogger(__name__)
|
||||||
|
logger = logging.getLogger('file_only')
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_ENCODING = 'ISO8859-1'
|
||||||
|
DEFAULT_LANGUAGE = 'en_US'
|
||||||
|
DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||||
|
|
||||||
|
encoding = DEFAULT_ENCODING
|
||||||
|
language = DEFAULT_LANGUAGE
|
||||||
|
|
||||||
|
try:
|
||||||
|
import locale
|
||||||
|
encoding = locale.getpreferredencoding(True) or DEFAULT_ENCODING
|
||||||
|
language = locale.getlocale()[0] or locale.getdefaultlocale()[0] or DEFAULT_LANGUAGE
|
||||||
|
except:
|
||||||
|
logger.exception('Could not determine language or encoding')
|
||||||
|
|
||||||
|
|
||||||
|
if shared.config.has_option('bitmessagesettings', 'timeformat'):
|
||||||
|
time_format = shared.config.get('bitmessagesettings', 'timeformat')
|
||||||
|
#Test the format string
|
||||||
|
try:
|
||||||
|
time.strftime(time_format)
|
||||||
|
except:
|
||||||
|
logger.exception('Could not format timestamp')
|
||||||
|
time_format = DEFAULT_TIME_FORMAT
|
||||||
|
else:
|
||||||
|
time_format = DEFAULT_TIME_FORMAT
|
||||||
|
|
||||||
|
#It seems some systems lie about the encoding they use so we perform
|
||||||
|
#comprehensive decoding tests
|
||||||
|
if time_format != DEFAULT_TIME_FORMAT:
|
||||||
|
try:
|
||||||
|
#Check day names
|
||||||
|
for i in xrange(7):
|
||||||
|
unicode(time.strftime(time_format, (0, 0, 0, 0, 0, 0, i, 0, 0)), encoding)
|
||||||
|
#Check month names
|
||||||
|
for i in xrange(1, 13):
|
||||||
|
unicode(time.strftime(time_format, (0, i, 0, 0, 0, 0, 0, 0, 0)), encoding)
|
||||||
|
#Check AM/PM
|
||||||
|
unicode(time.strftime(time_format, (0, 0, 0, 11, 0, 0, 0, 0, 0)), encoding)
|
||||||
|
unicode(time.strftime(time_format, (0, 0, 0, 13, 0, 0, 0, 0, 0)), encoding)
|
||||||
|
#Check DST
|
||||||
|
unicode(time.strftime(time_format, (0, 0, 0, 0, 0, 0, 0, 0, 1)), encoding)
|
||||||
|
except:
|
||||||
|
logger.exception('Could not decode locale formatted timestamp')
|
||||||
|
time_format = DEFAULT_TIME_FORMAT
|
||||||
|
encoding = DEFAULT_ENCODING
|
||||||
|
|
||||||
|
|
||||||
|
def formatTimestamp(timestamp = None, as_unicode = True):
|
||||||
|
#For some reason some timestamps are strings so we need to sanitize.
|
||||||
|
if timestamp is not None and not isinstance(timestamp, int):
|
||||||
|
try:
|
||||||
|
timestamp = int(timestamp)
|
||||||
|
except:
|
||||||
|
timestamp = None
|
||||||
|
|
||||||
|
#timestamp can't be less than 0.
|
||||||
|
if timestamp is not None and timestamp < 0:
|
||||||
|
timestamp = None
|
||||||
|
|
||||||
|
if timestamp is None:
|
||||||
|
timestring = time.strftime(time_format)
|
||||||
|
else:
|
||||||
|
#In case timestamp is too far in the future
|
||||||
|
try:
|
||||||
|
timestring = time.strftime(time_format, time.localtime(timestamp))
|
||||||
|
except ValueError:
|
||||||
|
timestring = time.strftime(time_format)
|
||||||
|
|
||||||
|
if as_unicode:
|
||||||
|
return unicode(timestring, encoding)
|
||||||
|
return timestring
|
||||||
|
|
||||||
|
def getTranslationLanguage():
|
||||||
|
userlocale = None
|
||||||
|
if shared.config.has_option('bitmessagesettings', 'userlocale'):
|
||||||
|
userlocale = shared.config.get('bitmessagesettings', 'userlocale')
|
||||||
|
|
||||||
|
if userlocale in [None, '', 'system']:
|
||||||
|
return language
|
||||||
|
|
||||||
|
return userlocale
|
||||||
|
|
|
@ -437,8 +437,10 @@ class ECC:
|
||||||
iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
|
iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
|
||||||
ctx = Cipher(key_e, iv, 1, ciphername)
|
ctx = Cipher(key_e, iv, 1, ciphername)
|
||||||
ciphertext = ctx.ciphering(data)
|
ciphertext = ctx.ciphering(data)
|
||||||
|
#ciphertext = iv + pubkey + ctx.ciphering(data) # We will switch to this line after an upgrade period
|
||||||
mac = hmac_sha256(key_m, ciphertext)
|
mac = hmac_sha256(key_m, ciphertext)
|
||||||
return iv + pubkey + ciphertext + mac
|
return iv + pubkey + ciphertext + mac
|
||||||
|
#return ciphertext + mac # We will switch to this line after an upgrade period.
|
||||||
|
|
||||||
def decrypt(self, data, ciphername='aes-256-cbc'):
|
def decrypt(self, data, ciphername='aes-256-cbc'):
|
||||||
"""
|
"""
|
||||||
|
@ -454,7 +456,14 @@ class ECC:
|
||||||
mac = data[i:]
|
mac = data[i:]
|
||||||
key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
|
key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
|
||||||
key_e, key_m = key[:32], key[32:]
|
key_e, key_m = key[:32], key[32:]
|
||||||
|
"""
|
||||||
|
pyelliptic was changed slightly so that the hmac covers the
|
||||||
|
iv and pubkey. So let's have an upgrade period where we support
|
||||||
|
both the old and the new hmac'ing algorithms.
|
||||||
|
https://github.com/yann2192/pyelliptic/issues/17
|
||||||
|
"""
|
||||||
if hmac_sha256(key_m, ciphertext) != mac:
|
if hmac_sha256(key_m, ciphertext) != mac:
|
||||||
raise RuntimeError("Fail to verify data")
|
if hmac_sha256(key_m, data[:len(data) - 32]) != mac:
|
||||||
|
raise RuntimeError("Fail to verify data")
|
||||||
ctx = Cipher(key_e, iv, 0, ciphername)
|
ctx = Cipher(key_e, iv, 0, ciphername)
|
||||||
return ctx.ciphering(ciphertext)
|
return ctx.ciphering(ciphertext)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
softwareVersion = '0.4.2'
|
softwareVersion = '0.4.3'
|
||||||
verbose = 1
|
verbose = 1
|
||||||
maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 # Equals two days and 12 hours.
|
maximumAgeOfAnObjectThatIAmWillingToAccept = 216000 # Equals two days and 12 hours.
|
||||||
lengthOfTimeToLeaveObjectsInInventory = 237600 # Equals two days and 18 hours. This should be longer than maximumAgeOfAnObjectThatIAmWillingToAccept so that we don't process messages twice.
|
lengthOfTimeToLeaveObjectsInInventory = 237600 # Equals two days and 18 hours. This should be longer than maximumAgeOfAnObjectThatIAmWillingToAccept so that we don't process messages twice.
|
||||||
|
@ -71,6 +71,8 @@ numberOfMessagesProcessed = 0
|
||||||
numberOfBroadcastsProcessed = 0
|
numberOfBroadcastsProcessed = 0
|
||||||
numberOfPubkeysProcessed = 0
|
numberOfPubkeysProcessed = 0
|
||||||
numberOfInventoryLookupsPerformed = 0
|
numberOfInventoryLookupsPerformed = 0
|
||||||
|
numberOfBytesReceived = 0
|
||||||
|
numberOfBytesSent = 0
|
||||||
daemon = False
|
daemon = False
|
||||||
clibAvaible = False
|
clibAvaible = False
|
||||||
inventorySets = {} # key = streamNumer, value = a set which holds the inventory object hashes that we are aware of. This is used whenever we receive an inv message from a peer to check to see what items are new to us. We don't delete things out of it; instead, the singleCleaner thread clears and refills it every couple hours.
|
inventorySets = {} # key = streamNumer, value = a set which holds the inventory object hashes that we are aware of. This is used whenever we receive an inv message from a peer to check to see what items are new to us. We don't delete things out of it; instead, the singleCleaner thread clears and refills it every couple hours.
|
||||||
|
@ -328,7 +330,7 @@ def isProofOfWorkSufficient(
|
||||||
def doCleanShutdown():
|
def doCleanShutdown():
|
||||||
global shutdown
|
global shutdown
|
||||||
shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit.
|
shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit.
|
||||||
broadcastToSendDataQueues((0, 'shutdown', 'all'))
|
broadcastToSendDataQueues((0, 'shutdown', 'no data'))
|
||||||
with shared.objectProcessorQueueSizeLock:
|
with shared.objectProcessorQueueSizeLock:
|
||||||
data = 'no data'
|
data = 'no data'
|
||||||
shared.objectProcessorQueueSize += len(data)
|
shared.objectProcessorQueueSize += len(data)
|
||||||
|
|
Reference in New Issue
Block a user