return(firstByte,1)#the 1 is the length of the varint
iffirstByte==253:
a,=unpack('>H',data[1:3])
return(a,3)
# encodes 253 to 65535
iflen(data)<3:
raisevarintDecodeError('The first byte of this varint as an integer is %s but the total length is only %s. It needs to be at least 3.'%(firstByte,len(data)))
encodedValue,=unpack('>H',data[1:3])
ifencodedValue<253:
raisevarintDecodeError('This varint does not encode the value with the lowest possible number of bytes.')
return(encodedValue,3)
iffirstByte==254:
a,=unpack('>I',data[1:5])
return(a,5)
# encodes 65536 to 4294967295
iflen(data)<5:
raisevarintDecodeError('The first byte of this varint as an integer is %s but the total length is only %s. It needs to be at least 5.'%(firstByte,len(data)))
encodedValue,=unpack('>I',data[1:5])
ifencodedValue<65536:
raisevarintDecodeError('This varint does not encode the value with the lowest possible number of bytes.')
return(encodedValue,5)
iffirstByte==255:
a,=unpack('>Q',data[1:9])
return(a,9)
# encodes 4294967296 to 18446744073709551615
iflen(data)<9:
raisevarintDecodeError('The first byte of this varint as an integer is %s but the total length is only %s. It needs to be at least 9.'%(firstByte,len(data)))
encodedValue,=unpack('>Q',data[1:9])
ifencodedValue<4294967296:
raisevarintDecodeError('This varint does not encode the value with the lowest possible number of bytes.')
QMessageBox.about(self,_translate("MainWindow","Message too long"),_translate(
"MainWindow","The message that you are trying to send is too long by %1 bytes. (The maximum is 261644 bytes). Please cut it down before sending.").arg(len(message)-(2**18-500)))
return
ifself.ui.radioButtonSpecific.isChecked():# To send a message to specific people (rather than broadcast)
toAddressesList=[s.strip()
forsintoAddresses.replace(',',';').split(';')]
@ -1873,6 +1881,9 @@ class MyForm(QtGui.QMainWindow):
elifstatus=='ripetoolong':
self.statusBar().showMessage(_translate(
"MainWindow","Error: Some data encoded in the address %1 is too long. There might be something wrong with the software of your acquaintance.").arg(toAddress))
elifstatus=='varintmalformed':
self.statusBar().showMessage(_translate(
"MainWindow","Error: Some data encoded in the address %1 is malformed. There might be something wrong with the software of your acquaintance.").arg(toAddress))
else:
self.statusBar().showMessage(_translate(
"MainWindow","Error: Something is wrong with the address %1.").arg(toAddress))
@ -2211,10 +2222,10 @@ class MyForm(QtGui.QMainWindow):
# It might now be possible to send msgs which were previously marked as toodifficult.
# Let us change them to 'msgqueued'. The singleWorker will try to send them and will again
# mark them as toodifficult if the receiver's required difficulty is still higher than
# we are willing to do.
sqlExecute('''UPDATE sent SET status='msgqueued' WHERE status='toodifficult'''')
shared.workerQueue.put(('sendmessage',''))
#start:UI setting to stop trying to send messages after X days/months
# I'm open to changing this UI to something else if someone has a better idea.
if((self.settingsDialogInstance.ui.lineEditDays.text()=='')and(self.settingsDialogInstance.ui.lineEditMonths.text()=='')):#We need to handle this special case. Bitmessage has its default behavior. The input is blank/blank
@ -3429,7 +3469,12 @@ class settingsDialog(QtGui.QDialog):
fromsubprocessimportcall# used when the API must execute an outside program
from pyelliptic.opensslimportOpenSSL
import traceback
frompyelliptic.opensslimportOpenSSL
importhighlevelcrypto
fromaddressesimport*
importhelper_generic
@ -51,18 +52,23 @@ class objectProcessor(threading.Thread):
whileTrue:
objectType,data=shared.objectProcessorQueue.get()
ifobjectType=='getpubkey':
self.processgetpubkey(data)
elifobjectType=='pubkey':
self.processpubkey(data)
elifobjectType=='msg':
self.processmsg(data)
elifobjectType=='broadcast':
self.processbroadcast(data)
elifobjectType=='checkShutdownVariable':# is more of a command, not an object type. Is used to get this thread past the queue.get() so that it will check the shutdown variable.
pass
else:
logger.critical('Error! Bug! The class_objectProcessor was passed an object type it doesn\'t recognize: %s'%str(objectType))
try:
ifobjectType==0:# getpubkey
self.processgetpubkey(data)
elifobjectType==1:#pubkey
self.processpubkey(data)
elifobjectType==2:#msg
self.processmsg(data)
elifobjectType==3:#broadcast
self.processbroadcast(data)
elifobjectType=='checkShutdownVariable':# is more of a command, not an object type. Is used to get this thread past the queue.get() so that it will check the shutdown variable.
pass
else:
logger.critical('Error! Bug! The class_objectProcessor was passed an object type it doesn\'t recognize: %s'%str(objectType))
exceptvarintDecodeErrorase:
logger.debug("There was a problem with a varint while processing an object. Some details: %s"%e)
exceptExceptionase:
logger.critical("Critical error within objectProcessorThread: \n%s"%traceback.format_exc())
withshared.objectProcessorQueueSizeLock:
shared.objectProcessorQueueSize-=len(data)# We maintain objectProcessorQueueSize so that we will slow down requesting objects if too much data accumulates in the queue.
@ -83,17 +89,7 @@ class objectProcessor(threading.Thread):
@ -147,7 +143,7 @@ class objectProcessor(threading.Thread):
myAddress,'lastpubkeysendtime'))
except:
lastPubkeySendTime=0
iflastPubkeySendTime>time.time()-shared.lengthOfTimeToHoldOnToAllPubkeys:# If the last time we sent our pubkey was more recent than 28 days ago...
iflastPubkeySendTime>time.time()-2419200:# If the last time we sent our pubkey was more recent than 28 days ago...
logger.info('Found getpubkey-requested-item in my list of EC hashes BUT we already sent it recently. Ignoring request. The lastPubkeySendTime is: %s'%lastPubkeySendTime)
return
logger.info('Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.')
@ -166,17 +162,8 @@ class objectProcessor(threading.Thread):
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
'ackreceived',data[readPosition:])
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(data[readPosition:],tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
'ackreceived',data[-32:])
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(data[-32:],tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(l10n.formatTimestamp()))))
return
else:
logger.info('This was NOT an acknowledgement bound for me.')
@ -430,17 +378,35 @@ class objectProcessor(threading.Thread):
# This is not an acknowledgement bound for me. See if it is a message
# bound for me by trying to decrypt it with my private keys.
# This can be simplified quite a bit after 1416175200: # Sun, 16 Nov 2014 22:00:00 GMT
toRipe=key# This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data.
initialDecryptionSuccessful=True
logger.info('EC decryption successful using key associated with ripe hash: %s'%key.encode('hex'))
logger.info('EC decryption successful using key associated with ripe hash: %s. msg did NOT specify version.'%key.encode('hex'))
# We didn't bypass a msg version above as it is commented out.
# But the decryption was successful. Which means that there
# wasn't a msg version byte include in this msg.
msgObjectContainedVersion=False
break
exceptExceptionaserr:
pass
# print 'cryptorObject.decrypt Exception:', err
# What if a client sent us a msg with
# a msg version included? We didn't bypass it above. So
# let's try to decrypt the msg assuming that it is present.
try:
decryptedData=cryptorObject.decrypt(data[readPosition+1:])# notice that we offset by 1 byte compared to the attempt above.
toRipe=key# This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data.
initialDecryptionSuccessful=True
logger.info('EC decryption successful using key associated with ripe hash: %s. msg DID specifiy version.'%key.encode('hex'))
# There IS a msg version byte include in this msg.
msgObjectContainedVersion=True
break
exceptExceptionaserr:
pass
ifnotinitialDecryptionSuccessful:
# This is not a message bound for me.
logger.info('Length of time program spent failing to decrypt this message: %s seconds.'%(time.time()-messageProcessingStartTime,))
@ -450,12 +416,15 @@ class objectProcessor(threading.Thread):
toAddress=shared.myAddressesByHash[
toRipe]# Look up my address based on the RIPE hash.
readPosition=0
messageVersion,messageVersionLength=decodeVarint(
decryptedData[readPosition:readPosition+10])
readPosition+=messageVersionLength
ifmessageVersion!=1:
logger.info('Cannot understand message versions other than one. Ignoring message.')
return
ifnotmsgObjectContainedVersion:# by which I mean "if the msg object didn't have the msg version outside of the encryption". This confusingness will be removed after the protocol v3 upgrade period.