sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',*t)
self.possibleNewPubkey(ripe =ripe)
self.possibleNewPubkey(address)
ifaddressVersion==4:
iflen(data)<350:# sanity check.
@ -296,7 +298,7 @@ class objectProcessor(threading.Thread):
# At this point we know that we have been waiting on this pubkey.
# This function will command the workerThread to start work on
# the messages that require it.
self.possibleNewPubkey(address=toAddress)
self.possibleNewPubkey(toAddress)
# Display timing data
timeRequiredToProcessPubkey=time.time(
@ -325,8 +327,10 @@ class objectProcessor(threading.Thread):
ifdata[-32:]inshared.ackdataForWhichImWatching:
logger.info('This msg IS an acknowledgement bound for me.')
delshared.ackdataForWhichImWatching[data[-32:]]
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
'ackreceived',data[-32:])
sqlExecute('UPDATE sent SET status=?, lastactiontime=? WHERE ackdata=?',
'ackreceived',
int(time.time()),
data[-32:])
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(data[-32:],tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
return
else:
@ -441,7 +445,7 @@ class objectProcessor(threading.Thread):
# person.
sqlExecute(
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
ripe.digest(),
fromAddress,
sendersAddressVersionNumber,
decryptedData[:endOfThePublicKeyPosition],
int(time.time()),
@ -450,10 +454,7 @@ class objectProcessor(threading.Thread):
# Check to see whether we happen to be awaiting this
# pubkey in order to send a message. If we are, it will do the POW
# and send it.
ifsendersAddressVersionNumber<=3:
self.possibleNewPubkey(ripe=ripe.digest())
elifsendersAddressVersionNumber>=4:
self.possibleNewPubkey(address=fromAddress)
self.possibleNewPubkey(fromAddress)
# If this message is bound for one of my version 3 addresses (or
# higher), then we must check to make sure it meets our demanded
@ -548,8 +549,25 @@ class objectProcessor(threading.Thread):
@ -801,8 +818,8 @@ class objectProcessor(threading.Thread):
"""
logger.info('We have been awaiting the arrival of this pubkey.')
sqlExecute(
'''UPDATE sent SET status='doingmsgpow' WHERE toripe=? AND (status='awaitingpubkey' or status='doingpubkeypow') and folder='sent'''',
ripe)
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='awaitingpubkey' or status='doingpubkeypow') AND folder='sent'''',
# Let us resend getpubkey objects if we have not yet heard a pubkey, and also msg objects if we have not yet heard an acknowledgement
queryreturn=sqlQuery(
'''select toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, pubkeyretrynumber, msgretrynumber FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent' AND lastactiontime>?) ''',
int(time.time())-shared.maximumLengthOfTimeToBotherResendingMessages)# If the message's folder='trash' then we'll ignore it.
'''select toaddress, ackdata, status FROM sent WHERE ((status='awaitingpubkey' OR status='msgsent') AND folder='sent' AND sleeptill<? AND senttime>?) ''',
# Let's also clear and reload shared.inventorySets to keep it from
# taking up an unnecessary amount of memory.
@ -126,32 +126,26 @@ class singleCleaner(threading.Thread):
time.sleep(300)
defresendPubkey(pubkeyretrynumber,toripe):
print'It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.'
defresendPubkeyRequest(address):
logger.debug('It has been a long time and we haven\'t heard a response to our getpubkey request. Sending again.')
try:
delshared.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.
address]# 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)
'''UPDATE sent SET status='msgqueued' WHERE toaddress=?''',
address)
shared.workerQueue.put(('sendmessage',''))
defresendMsg(msgretrynumber,ackdata):
print'It has been a long time and we haven\'t heard an acknowledgement to our msg. Sending again.'
defresendMsg(ackdata):
logger.debug('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)
'''UPDATE sent SET status='msgqueued' WHERE ackdata=?''',
ackdata)
shared.workerQueue.put(('sendmessage',''))
shared.UISignalQueue.put((
'updateStatusBar','Doing work necessary to again attempt to deliver a message...'))
@ -479,12 +485,12 @@ class singleWorker(threading.Thread):
# Select just one msg that needs work.
queryreturn=sqlQuery(
'''SELECT toaddress, toripe, fromaddress, subject, message, ackdata, status FROM sent WHERE (status='msgqueued' or status='doingmsgpow' or status='forcepow') and folder='sent' LIMIT 1''')
'''SELECT toaddress, fromaddress, subject, message, ackdata, status, ttl, retrynumber FROM sent WHERE (status='msgqueued' or status='doingmsgpow' or status='forcepow') and folder='sent' LIMIT 1''')
iflen(queryreturn)==0:# if there is no work to do then
break# break out of this sendMsg loop and
# wait for something to get put in the shared.workerQueue.
@ -496,38 +502,45 @@ class singleWorker(threading.Thread):
# because the user could not have overridden the message about the POW being
# too difficult without knowing the required difficulty.
pass
elifstatus=='doingmsgpow':
# We wouldn't have set the status to doingmsgpow if we didn't already have the pubkey
# so let's assume that we have it.
pass
# If we are sending a message to ourselves or a chan then we won't need an entry in the pubkeys table; we can calculate the needed pubkey using the private keys in our keys.dat file.
elifshared.config.has_section(toaddress):
sqlExecute(
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued'''',
toaddress)
status='doingmsgpow'
else:
elif status =='msgqueued':
# Let's see if we already have the pubkey in our pubkeys table
queryreturn=sqlQuery(
'''SELECT hash FROM pubkeys WHERE hash=? AND addressversion=?''',toRipe,toAddressVersionNumber)
'''SELECT address FROM pubkeys WHERE address=?''',toaddress)
ifqueryreturn!=[]:# If we have the needed pubkey in the pubkey table already,
# set the status of this msg to doingmsgpow
sqlExecute(
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND status='msgqueued'''',
toaddress)
status='doingmsgpow'
# mark the pubkey as 'usedpersonally' so that we don't delete it later
# mark the pubkey as 'usedpersonally' so that we don't delete it later. If the pubkey version
# is >= 4 then usedpersonally will already be set to yes because we'll only ever have
# usedpersonally v4 pubkeys in the pubkeys table.
sqlExecute(
'''UPDATE pubkeys SET usedpersonally='yes' WHERE hash=? and addressversion=?''',
toRipe,
toAddressVersionNumber)
'''UPDATE pubkeys SET usedpersonally='yes' WHERE address=?''',
toaddress)
else:# We don't have the needed pubkey in the pubkeys table already.
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
toaddress)
delshared.neededPubkeys[tag]
continue # We'll start back at the beginning, pick up this msg, mark the pubkey as 'usedpersonally', and then send the msg.
break
#else: # There was something wrong with this pubkey object even
# though it had the correct tag- almost certainly because
# of malicious behavior or a badly programmed client. If
# of malicious behavior or a badly programmed client. If
# there are any other pubkeys in our inventory with the correct
# tag then we'll try to decrypt those.
@ -572,21 +585,27 @@ class singleWorker(threading.Thread):
ifshared.decryptAndCheckPubkeyPayload(payload,toaddress)=='successful':#if valid, this function also puts it in the pubkeys table.
needToRequestPubkey=False
sqlExecute(
'''UPDATE sent SET status='doingmsgpow' WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
'''UPDATE sent SET status='doingmsgpow', retrynumber=0 WHERE toaddress=? AND (status='msgqueued' or status='awaitingpubkey' or status='doingpubkeypow')''',
toaddress)
delshared.neededPubkeys[tag]
continue # We'll start back at the beginning, pick up this msg, mark the pubkey as 'usedpersonally', and then send the msg.
break
ifneedToRequestPubkey:
sqlExecute(
'''UPDATE sent SET status='doingpubkeypow' WHERE toaddress=? AND status='msgqueued'''',
toaddress,tr.translateText("MainWindow",'Sending a request for the recipient\'s encryption key.'))))
self.requestPubKey(toaddress)
continue#on with the next msg on which we can do some work
# At this point we know that we have the necessary pubkey in the pubkeys table.
TTL=int(28*24*60*60+random.randrange(-300,300))# 28 days from now plus or minus five minutes
ifretryNumber==0:
ifTTL>28*24*60*60:
TTL=28*24*60*60
else:
TTL=28*24*60*60
TTL=int(TTL+random.randrange(-300,300))# add some randomness to the TTL
embeddedTime=int(time.time()+TTL)
ifnotshared.config.has_section(toaddress):# if we aren't sending this to ourselves or a chan
@ -600,9 +619,8 @@ class singleWorker(threading.Thread):
# the required proof of work difficulty is too hard then we'll
# abort.
queryreturn=sqlQuery(
'SELECT transmitdata FROM pubkeys WHERE hash=? and addressversion=?',
toRipe,
toAddressVersionNumber)
'SELECT transmitdata FROM pubkeys WHERE address=?',
toaddress)
forrowinqueryreturn:
pubkeyPayload,=row
@ -752,7 +770,7 @@ class singleWorker(threading.Thread):
fullAckPayload=''
else:
fullAckPayload=self.generateFullAckMessage(
ackdata,toStreamNumber) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out.
ackdata,toStreamNumber, TTL) # The fullAckPayload is a normal msg protocol message with the proof of work already completed that the receiver of this message can easily send out.
sqlExecute('''UPDATE sent SET msgid=?, status=?, retrynumber=?, sleeptill=?, lastactiontime=? WHERE ackdata=?''',
inventoryHash,
newStatus,
retryNumber+1,
sleepTill,
int(time.time()),
ackdata)
# If we are sending to ourselves or a chan, let's put the message in
# our own inbox.
@ -848,10 +874,18 @@ class singleWorker(threading.Thread):
withshared.printLock:
sys.stderr.write('Very abnormal error occurred in requestPubKey. toAddress is: '+repr(
toAddress)+'. Please report this error to Atheros.')
return
queryReturn=sqlQuery(
'''SELECT retrynumber FROM sent WHERE toaddress=? AND (status='doingpubkeypow' OR status='awaitingpubkey') LIMIT 1''',
toAddress)
iflen(queryReturn)==0:
logger.critical("BUG: Why are we requesting the pubkey for %s if there are no messages in the sent folder to that address?"%toAddress)
return
retryNumber=queryReturn[0][0]
ifaddressVersionNumber<=3:
shared.neededPubkeys[ripe]=0
shared.neededPubkeys[toAddress]=0
elifaddressVersionNumber>=4:
# If the user just clicked 'send' then the tag (and other information) will already
# be in the neededPubkeys dictionary. But if we are recovering from a restart
@ -861,7 +895,11 @@ class singleWorker(threading.Thread):
iftagnotinshared.neededPubkeys:
shared.neededPubkeys[tag]=(toAddress,highlevelcrypto.makeCryptor(privEncryptionKey.encode('hex')))# We'll need this for when we receive a pubkey reply: it will be encrypted and we'll need to decrypt it.
TTL=int(2.5*24*60*60+random.randrange(-300,300))# 2.5 days from now plus or minus five minutes
ifretryNumber==0:
TTL=2.5*24*60*60# 2.5 days. This was chosen fairly arbitrarily.
else:
TTL=28*24*60*60
TTL=TTL+random.randrange(-300,300)# add some randomness to the TTL
'''UPDATE sent SET status='awaitingpubkey' WHERE toaddress=? AND status='doingpubkeypow'''',
'''UPDATE sent SET lastactiontime=?, status='awaitingpubkey', retrynumber=?, sleeptill=? WHERE toaddress=? AND (status='doingpubkeypow' OR status='awaitingpubkey') ''',
int(time.time()),
retryNumber+1,
sleeptill,
toAddress)
shared.UISignalQueue.put((
'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(l10n.formatTimestamp()))))
shared.UISignalQueue.put(('updateSentItemStatusByToAddress',(toAddress,tr.translateText("MainWindow",'Sending public key request. Waiting for reply. Requested at %1').arg(l10n.formatTimestamp()))))
# We'll also need a `sleeptill` field and a `ttl` field. Also we can combine
# the pubkeyretrynumber and msgretrynumber into one.
item='''SELECT value FROM settings WHERE key='version';'''
parameters=''
self.cur.execute(item,parameters)
currentVersion=int(self.cur.fetchall()[0][0])
ifcurrentVersion==9:
logger.info('In messages.dat database, making TTL-related changes: combining the pubkeyretrynumber and msgretrynumber fields into the retrynumber field and adding the sleeptill and ttl fields...')