Message Expire #548

Merged
Atheros1 merged 17 commits from master into master 2013-11-06 05:47:19 +01:00
7 changed files with 121 additions and 71 deletions
Showing only changes of commit d487b522cf - Show all commits

View File

@ -2036,23 +2036,34 @@ class MyForm(QtGui.QMainWindow):
if float(self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) >= 1 or float(self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) == 0:
shared.config.set('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes)))
#my implementation starts here,it was a line here
time_period = (int(str(self.settingsDialogInstance.ui.lineEditHours.text())) * 60 * 60 + int(str(self.settingsDialogInstance.ui.lineEditDays.text())) * 24 * 60 * 60 +
int(str(self.settingsDialogInstance.ui.lineEditMonths.text())) * (60 * 60 * 24 *365)/12)
if time_period < shared.maximumAgeOfAnObjectThatIAmWillingToAccept * 2:
QMessageBox.about(self, _translate("MainWindow", "Error"), _translate(
"MainWindow", "You must insert a time period longer than 5 days."))
shared.config.set('bitmessagesettings', 'hours', '0')
shared.config.set('bitmessagesettings', 'days', '5')
shared.config.set('bitmessagesettings', 'months', '0')
else:
shared.config.set('bitmessagesettings', 'hours', str(
#my implementation starts here,it was a line here.JOHN
if ((self.settingsDialogInstance.ui.lineEditHours.text()=='') and (self.settingsDialogInstance.ui.lineEditDays.text()=='') and (self.settingsDialogInstance.ui.lineEditMonths.text()=='')):
if (((shared.config.get('bitmessagesettings', 'hours')) != str(self.settingsDialogInstance.ui.lineEditHours.text())) or #if we update the time period from one time period(f.e 1/0/0) to default -/-/,inform the user that restart is needed in order his changes to take effect.JOHN
((shared.config.get('bitmessagesettings', 'days')) != str(self.settingsDialogInstance.ui.lineEditDays.text())) or
((shared.config.get('bitmessagesettings', 'months')) != str(self.settingsDialogInstance.ui.lineEditMonths.text()))) :
QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
"MainWindow", "You must restart Bitmessage for the time period change to take effect."))
shared.config.set('bitmessagesettings', 'hours', '')#give default values to fields..this default situation is special and thats why its needs special treatment ;).JOHN
shared.config.set('bitmessagesettings', 'days', '')#these commands update each field in the keys.dat file.JOHN
shared.config.set('bitmessagesettings', 'months', '')
shared.config.set('bitmessagesettings', 'timeperiod', '-1')
else:#So,if all time period fields(hours,months,days) have valid values(valid values---> 0/0/0, 0/3/2, -/-/-, no valid--> -/0/5, 5/-/-), you can calculate the time period
shared.config.set('bitmessagesettings', 'timeperiod', str(int(str(self.settingsDialogInstance.ui.lineEditHours.text())) * 60 * 60 + int(str(self.settingsDialogInstance.ui.lineEditDays.text())) * 24 * 60 * 60 +
int(str(self.settingsDialogInstance.ui.lineEditMonths.text())) * (60 * 60 * 24 *365)/12))
if (((shared.config.get('bitmessagesettings', 'hours')) != str(self.settingsDialogInstance.ui.lineEditHours.text())) or#inform user tha he needs to restart bitmessage in order his changes to take effect.JOHN
((shared.config.get('bitmessagesettings', 'days')) != str(self.settingsDialogInstance.ui.lineEditDays.text())) or
((shared.config.get('bitmessagesettings', 'months')) != str(self.settingsDialogInstance.ui.lineEditMonths.text()))) :
QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
"MainWindow", "You must restart Bitmessage for the time period change to take effect."))
shared.config.set('bitmessagesettings', 'hours', str(#this three commands update the fields of this new setting in keys.dat file.JOHN
self.settingsDialogInstance.ui.lineEditHours.text()))
shared.config.set('bitmessagesettings', 'days', str(
shared.config.set('bitmessagesettings', 'days', str(
self.settingsDialogInstance.ui.lineEditDays.text()))
shared.config.set('bitmessagesettings', 'months', str(
shared.config.set('bitmessagesettings', 'months', str(
self.settingsDialogInstance.ui.lineEditMonths.text()))
#my implementation stops here, there is a line
#my implementation stops here, there is a line.JOHN
# if str(self.settingsDialogInstance.ui.comboBoxMaxCores.currentText()) == 'All':
# shared.config.set('bitmessagesettings', 'maxcores', '99999')
@ -2990,13 +3001,13 @@ class settingsDialog(QtGui.QDialog):
QtCore.QObject.connect(self.ui.pushButtonNamecoinTest, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonNamecoinTest)
#Adjust tab
self.ui.lineEditHours.setText(str(
#Adjusting time period for resending messages tab.JOHN
self.ui.lineEditHours.setText(str(#Giving values to edit boxes in the UI.JOHN
shared.config.get('bitmessagesettings', 'hours')))
self.ui.lineEditDays.setText(str(
shared.config.get('bitmessagesettings', 'days')))
self.ui.lineEditMonths.setText(str(
shared.config.get('bitmessagesettings', 'months')))
shared.config.get('bitmessagesettings', 'months')))#JOHN.
#'System' tab removed for now.

View File

@ -320,8 +320,8 @@ class Ui_settingsDialog(object):
self.gridLayout.addWidget(self.tabWidgetSettings, 0, 0, 1, 1)
#this line existed before
#my new implementation starts here
self.tabResendingMessagesAdjustment=QtGui.QWidget()
self.tabResendingMessagesAdjustment.setObjectName(_fromUtf8("tabResendingMessagesAdjustment"))
self.tabResendingMessagesAdjustment=QtGui.QWidget()#all these lines are for the UI implementation, I dont think that you need special explanation about them.JOHN
self.tabResendingMessagesAdjustment.setObjectName(_fromUtf8("tabResendingMessagesAdjustment"))#Please note that approximately 58 line codes added to setting.ui also responsible for the UI.JOHN
self.gridLayout_9 = QtGui.QGridLayout(self.tabResendingMessagesAdjustment)
self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9"))
self.label_19 = QtGui.QLabel(self.tabResendingMessagesAdjustment)
@ -335,11 +335,11 @@ class Ui_settingsDialog(object):
self.label_20 = QtGui.QLabel(self.tabResendingMessagesAdjustment)
self.label_20.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label_20.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_20.setObjectName(_fromUtf8("label_20"))
self.label_20.setObjectName(_fromUtf8("label_20"))#This are Qt code..I just add a label to my tab.JOHN
self.gridLayout_9.addWidget(self.label_20, 2, 0, 1, 1)
self.lineEditHours = QtGui.QLineEdit(self.tabResendingMessagesAdjustment)
self.lineEditHours.setMaximumSize(QtCore.QSize(33, 16777))
self.lineEditHours.setObjectName(_fromUtf8("lineEditHours"))
self.lineEditHours.setObjectName(_fromUtf8("lineEditHours"))##This are Qt code..I just add a edit box to my tab.JOHN
self.gridLayout_9.addWidget(self.lineEditHours, 2, 1, 1, 1)
self.label_22 = QtGui.QLabel(self.tabResendingMessagesAdjustment)
self.label_22.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
@ -424,9 +424,9 @@ class Ui_settingsDialog(object):
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tab), _translate("settingsDialog", "Demanded difficulty", None))
self.label_15.setText(_translate("settingsDialog", "Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.", None))
self.label_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None))
#my new implementation starts here,it wasn't line here
#my new implementation starts here,it wasn't line here.Too simple to explain :D..JOHN
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabResendingMessagesAdjustment), _translate("settingsDialog", "Adjusting time period for resending messages", None))
self.label_19.setText(_translate("settingsDialog", "<html><head/><body><p>If you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever. Messages will continue to be sent after 4, 8,16 days and so on until the receiver get them. </p><p> Here you can adjust Bitmessage to stop trying to send messages after X hours/days/months. This time period needs to be longer than 5 days.</p></body></html>", None))
self.label_19.setText(_translate("settingsDialog", "<html><head/><body><p>If you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever. Messages will continue to be sent after 4, 8,16 days and so on until the receiver get them. </p><p> Here you can adjust Bitmessage to stop trying to send messages after X hours/days/months.</p></body></html>", None))
self.label_20.setText(_translate("settingsDialog", "Time in hours/days/months:", None))
self.label_22.setText(_translate("settingsDialog", "/", None))
self.label_23.setText(_translate("settingsDialog", "/", None))

View File

@ -10,16 +10,16 @@ from debug import logger
'''The singleCleaner class is a timer-driven thread that cleans data structures to free memory, resends messages when a remote node doesn't respond, and sends pong messages to keep connections alive if the network isn't busy.
It cleans these data structures in memory:
inventory (moves data to the on-disk sql database)
inventorySets (clears then reloads data out of sql database)
inventory (moves data to the on-disk sql database)
inventorySets (clears then reloads data out of sql database)
It cleans these tables on the disk:
inventory (clears data more than 2 days and 12 hours old)
pubkeys (clears pubkeys older than 4 weeks old which we have not used personally)
inventory (clears data more than 2 days and 12 hours old)
pubkeys (clears pubkeys older than 4 weeks old which we have not used personally)
It resends messages when there has been no response:
resends getpubkey messages in 4 days (then 8 days, then 16 days, etc...)
resends msg messages in 4 days (then 8 days, then 16 days, etc...)
resends getpubkey messages in 4 days (then 8 days, then 16 days, etc...)
resends msg messages in 4 days (then 8 days, then 16 days, etc...)
'''
@ -52,7 +52,7 @@ class singleCleaner(threading.Thread):
del shared.inventory[hash]
shared.UISignalQueue.put(('updateStatusBar', ''))
shared.broadcastToSendDataQueues((
0, 'pong', 'no data')) # commands the sendData threads to send out a pong message if they haven't sent anything else in the last five minutes. The socket timeout-time is 10 minutes.
0, 'pong', 'no data')) # commands the sendData threads to send out a pong message if they haven't sent anything else in the last five minutes. The socket timeout-time is 10 minutes.
# If we are running as a daemon then we are going to fill up the UI
# queue which will never be handled by a UI. We should clear it to
# save memory.
@ -65,7 +65,7 @@ class singleCleaner(threading.Thread):
# inventory (clears pubkeys after 28 days and everything else
# after 2 days and 12 hours)
sqlExecute(
'''DELETE FROM inventory WHERE (receivedtime<? AND objecttype<>'pubkey') OR (receivedtime<? AND objecttype='pubkey') ''',
'''DELETE FROM inventory WHERE (receivedtime<? AND objecttype<>'pubkey') OR (receivedtime<? AND objecttype='pubkey') ''',
int(time.time()) - shared.lengthOfTimeToLeaveObjectsInInventory,
int(time.time()) - shared.lengthOfTimeToHoldOnToAllPubkeys)
@ -75,7 +75,7 @@ class singleCleaner(threading.Thread):
int(time.time()) - shared.lengthOfTimeToHoldOnToAllPubkeys)
queryreturn = sqlQuery(
'''select toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent') ''') # If the message's folder='trash' then we'll ignore it.
'''select toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent') ''') # If the message's folder='trash' then we'll ignore it.
for row in queryreturn:
if len(row) < 5:
with shared.printLock:
@ -86,35 +86,68 @@ class singleCleaner(threading.Thread):
break
toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber = row
if status == 'awaitingpubkey':
if int(time.time()) - lastactiontime > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))):
print 'It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.'
try:
del shared.neededPubkeys[
toripe] # We need to take this entry out of the shared.neededPubkeys structure because the shared.workerQueue checks to see whether the entry is already present and will not do the POW and send the message because it assumes that it has already done it recently.
except:
pass
if int(shared.config.get('bitmessagesettings', 'timeperiod'))> -1:#My implemenentation starts here.In this file I just added 4 lines.Two here and other two above.The default value of timeperiod is -1.This means that bitmessage resends messages every 5 days(they say 4 but actually is 5)for ever. If user changes the time period, timeperiod variable will have a specific value so the next if will be executed.JOHN
if (int(time.time()) - lastactiontime) > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))) and ((int(time.time()) - lastactiontime) < int(shared.config.get('bitmessagesettings', 'timeperiod'))):#This line does the magic.This if checks if the time that the public key was sent is longer than 5 days. Then it sends the it again. But with this extra AND it will not send it if this time is shorter than timeperiod.JOHN
print 'It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.'
try:
del shared.neededPubkeys[
toripe] # We need to take this entry out of the shared.neededPubkeys structure because the shared.workerQueue checks to see whether the entry is already present and will not do the POW and send the message because it assumes that it has already done it recently.
except:
pass
shared.UISignalQueue.put((
'updateStatusBar', 'Doing work necessary to again attempt to request a public key...'))
t = ()
sqlExecute(
'''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=?, status='msgqueued' WHERE toripe=?''',
int(time.time()),
pubkeyretrynumber + 1,
toripe)
shared.workerQueue.put(('sendmessage', ''))
else: # status == msgsent
if int(time.time()) - lastactiontime > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (msgretrynumber))):
print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.'
sqlExecute(
shared.UISignalQueue.put((
'updateStatusBar', 'Doing work necessary to again attempt to request a public key...'))
t = ()
sqlExecute(
'''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=?, status='msgqueued' WHERE toripe=?''',
int(time.time()),
pubkeyretrynumber + 1,
toripe)
shared.workerQueue.put(('sendmessage', ''))
else:#first it wasn't an else statement here, I put it for this setting. I just copy-paste the code again. If someone has any suggestion how we can do this without this if-else just say it.JOHN
if int(time.time()) - lastactiontime > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))):
print 'It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.'
try:
del shared.neededPubkeys[
toripe] # We need to take this entry out of the shared.neededPubkeys structure because the shared.workerQueue checks to see whether the entry is already present and will not do the POW and send the message because it assumes that it has already done it recently.
except:
pass
shared.UISignalQueue.put((
'updateStatusBar', 'Doing work necessary to again attempt to request a public key...'))
t = ()
sqlExecute(
'''UPDATE sent SET lastactiontime=?, pubkeyretrynumber=?, status='msgqueued' WHERE toripe=?''',
int(time.time()),
pubkeyretrynumber + 1,
toripe)
shared.workerQueue.put(('sendmessage', ''))
else: # status == msgsent
if int(shared.config.get('bitmessagesettings', 'timeperiod'))> -1:#same thing here but for the message.Actually this is the most important thing in the whole feature!.JOHN
if (int(time.time()) - lastactiontime) > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))) and ((int(time.time()) - lastactiontime) < int(shared.config.get('bitmessagesettings', 'timeperiod'))):#same thing here.My implementation in this file stops here.JOHN
print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.'
sqlExecute(
'''UPDATE sent SET lastactiontime=?, msgretrynumber=?, status=? WHERE ackdata=?''',
int(time.time()),
msgretrynumber + 1,
'msgqueued',
ackdata)
shared.workerQueue.put(('sendmessage', ''))
shared.UISignalQueue.put((
shared.workerQueue.put(('sendmessage', ''))
shared.UISignalQueue.put((
'updateStatusBar', 'Doing work necessary to again attempt to deliver a message...'))
else:
if int(time.time()) - lastactiontime > (shared.maximumAgeOfAnObjectThatIAmWillingToAccept * (2 ** (pubkeyretrynumber))):
print 'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.'
sqlExecute(
'''UPDATE sent SET lastactiontime=?, msgretrynumber=?, status=? WHERE ackdata=?''',
int(time.time()),
msgretrynumber + 1,
'msgqueued',
ackdata)
shared.workerQueue.put(('sendmessage', ''))
shared.UISignalQueue.put((
'updateStatusBar', 'Doing work necessary to again attempt to deliver a message...'))
# Let's also clear and reload shared.inventorySets to keep it from
# taking up an unnecessary amount of memory.

View File

@ -256,18 +256,20 @@ class sqlThread(threading.Thread):
# Are you hoping to add a new option to the keys.dat file of existing
# Bitmessage users? Add it right above this line!
#my new implementation starts here
if shared.config.getint('bitmessagesettings', 'settingsversion') == 6:
#my new implementation starts here, the most of these comment will be deleted, they are just for documentation
if shared.config.getint('bitmessagesettings', 'settingsversion') == 7:#this is the version that all we have,if you see your keys.dat file this is your version.JOHN
shared.config.set(#in order to not have to change your keys.dat file I update it with the new lines. I add to your keys.dat three new default fields.JOHN
'bitmessagesettings', 'hours', '')# hours, days, months have no value.This means that bitmessage works as before. It re-sends mails every 4,8,16 days..forever.JOHN
shared.config.set(
'bitmessagesettings', 'hours', '0')
'bitmessagesettings', 'days', '')
shared.config.set(
'bitmessagesettings', 'days', '5')
'bitmessagesettings', 'months', '')
shared.config.set(
'bitmessagesettings', 'months', '0')
shared.config.set('bitmessagesettings', 'settingsversion', '7')
'bitmessagesettings', 'timeperiod', '-1')#time period has default value -1. This is used for checking in class_singleCleaner. If you leave default the time period or after you change it(f.i 1/0/0), again you set it with its default value(-/-/-) this variable will be -1.JOHN
shared.config.set('bitmessagesettings', 'settingsversion', '8') #We update the version.If I leave it 7 every time that Bitmessage starts your setting will be lost.The default values(-/-/-) will be loaded all the time ;).That was juicy.JOHN
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
#my new implementation stops here
#my new implementation in this file stops here
try:
testpayload = '\x00\x00'

View File

@ -25,7 +25,7 @@ def knownNodes():
shared.knownNodes[stream][peer] = time
except:
shared.knownNodes = defaultKnownNodes.createDefaultKnownNodes(shared.appdata)
if shared.config.getint('bitmessagesettings', 'settingsversion') > 7:
if shared.config.getint('bitmessagesettings', 'settingsversion') > 8:
print 'Bitmessage cannot read future versions of the keys file (keys.dat). Run the newer version of Bitmessage.'
raise SystemExit

View File

@ -91,12 +91,16 @@ def loadConfig():
# existing users. To do that, search the class_sqlThread.py file for the
# text: "right above this line!"
#my implementation starts here. JOHN
shared.config.set(
'bitmessagesettings', 'hours', '0')
'bitmessagesettings', 'hours', '')#here I am adding the new default settings. The first time that the program is going to run these values will be loaded(UI and keys.dat also :) ).JOHN
shared.config.set(
'bitmessagesettings', 'days', '5')
'bitmessagesettings', 'days', '')
shared.config.set(
'bitmessagesettings', 'months', '0')
'bitmessagesettings', 'months', '')
shared.config.set(
'bitmessagesettings', 'timeperiod', '-1')
#my implementation in this file stops here.JOHN
ensureNamecoinOptions()

View File

@ -1,9 +1,9 @@
softwareVersion = '0.4.0'
verbose = 1
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.
maximumAgeOfAnObjectThatIAmWillingToAccept = 1800 # 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.
lengthOfTimeToHoldOnToAllPubkeys = 2419200 # Equals 4 weeks. You could make this longer if you want but making it shorter would not be advisable because there is a very small possibility that it could keep you from obtaining a needed pubkey for a period of time.
maximumAgeOfObjectsThatIAdvertiseToOthers = 216000 # Equals two days and 12 hours
maximumAgeOfObjectsThatIAdvertiseToOthers = 1800 # Equals two days and 12 hours
maximumAgeOfNodesThatIAdvertiseToOthers = 10800 # Equals three hours
useVeryEasyProofOfWorkForTesting = False # If you set this to True while on the normal network, you won't be able to send or sometimes receive messages.