Added some API commands for use with a mobile app #391

Merged
Atheros1 merged 10 commits from master into master 2013-08-09 20:25:14 +02:00
5 changed files with 64 additions and 49 deletions
Showing only changes of commit d51fe37a66 - Show all commits

View File

@ -747,6 +747,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if len(params) != 1: if len(params) != 1:
return 'API Error 0000: I need 1 parameter!' return 'API Error 0000: I need 1 parameter!'
encryptedPayload, = params encryptedPayload, = params
encryptedPayload = encryptedPayload.decode('hex')
inventoryHash = calculateInventoryHash(encryptedPayload) inventoryHash = calculateInventoryHash(encryptedPayload)
objectType = 'msg' objectType = 'msg'
shared.inventory[inventoryHash] = ( shared.inventory[inventoryHash] = (
@ -754,15 +755,16 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
with shared.printLock: with shared.printLock:
print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', inventoryHash.encode('hex') print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', inventoryHash.encode('hex')
shared.broadcastToSendDataQueues(( shared.broadcastToSendDataQueues((
streamNumber, 'sendinv', inventoryHash)) toStreamNumber, 'sendinv', inventoryHash))
elif method == 'disseminatePubkey': elif method == 'disseminatePubkey':
# The device issuing this command to PyBitmessage supplies a pubkey object that has # The device issuing this command to PyBitmessage supplies a pubkey object that has
# already had the necessary proof of work done for it to be disseminated to the rest of the # already had the necessary proof of work done for it to be disseminated to the rest of the
# Bitmessage network. PyBitmessage accepts this pubkey object and sends it out to the # Bitmessage network. PyBitmessage accepts this pubkey object and sends it out to the
# rest of the Bitmessage network, as if it had generated the pubkey object itself. # rest of the Bitmessage network as if it had generated the pubkey object itself.
if len(params) != 1: if len(params) != 1:
return 'API Error 0000: I need 1 parameter!' return 'API Error 0000: I need 1 parameter!'
payload, = params payload, = params
payload = payload.decode('hex')
inventoryHash = calculateInventoryHash(payload) inventoryHash = calculateInventoryHash(payload)
objectType = 'pubkey' objectType = 'pubkey'
shared.inventory[inventoryHash] = ( shared.inventory[inventoryHash] = (
@ -772,30 +774,40 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
shared.broadcastToSendDataQueues(( shared.broadcastToSendDataQueues((
streamNumber, 'sendinv', inventoryHash)) streamNumber, 'sendinv', inventoryHash))
elif method == 'getMessageDataByDestinationRIPEHash': elif method == 'getMessageDataByDestinationRIPEHash':
# Method will eventually be used by a particular Android app. # Method will eventually be used by a particular Android app to
# select relevant messages.
if len(params) != 1: if len(params) != 1:
return 'API Error 0000: I need 1 parameter!' return 'API Error 0000: I need 1 parameter!'
hash, = params requestedHash, = params
#if len(hash) != 40: if len(requestedHash) != 40:
# return 'API Error 0019: The length of hash should be 20 bytes (encoded in hex thus 40 characters).' return 'API Error 0019: The length of hash should be 20 bytes (encoded in hex thus 40 characters).'
print repr(hash) requestedHash = requestedHash.decode('hex')
hash = hash.decode('hex')
print repr(hash)
with shared.sqlLock:
shared.sqlSubmitQueue.put('''PRAGMA case_sensitive_like = true''')
shared.sqlSubmitQueue.put('')
queryreturn = shared.sqlReturnQueue.get()
hash = string.replace(hash,'e','ee') # This is not a particularly commonly used API function. Before we
hash = string.replace(hash,'%','e%') # use it we'll need to fill out a field in our inventory database
hash = string.replace(hash,'_','e_') # which is blank by default (first20bytesofencryptedmessage).
print 'searching for hash:', repr(hash) parameters = ''
parameters = ('%'+ hash + '%',)
with shared.sqlLock: with shared.sqlLock:
shared.sqlSubmitQueue.put('''SELECT payload FROM inventory WHERE hash LIKE ? ESCAPE'e'; ''') shared.sqlSubmitQueue.put('''SELECT hash, payload FROM inventory WHERE first20bytesofencryptedmessage = '' and objecttype = 'msg' ; ''')
shared.sqlSubmitQueue.put(parameters) shared.sqlSubmitQueue.put(parameters)
queryreturn = shared.sqlReturnQueue.get() queryreturn = shared.sqlReturnQueue.get()
for row in queryreturn:
hash, payload = row
readPosition = 16 # Nonce length + time length
readPosition += decodeVarint(payload[readPosition:readPosition+10])[1] # Stream Number length
t = (payload[readPosition:readPosition+20],hash)
shared.sqlSubmitQueue.put('''UPDATE inventory SET first20bytesofencryptedmessage=? WHERE hash=?; ''')
shared.sqlSubmitQueue.put(t)
shared.sqlReturnQueue.get()
parameters = (requestedHash,)
with shared.sqlLock:
shared.sqlSubmitQueue.put('commit')
shared.sqlSubmitQueue.put('''SELECT payload FROM inventory WHERE first20bytesofencryptedmessage = ?''')
shared.sqlSubmitQueue.put(parameters)
queryreturn = shared.sqlReturnQueue.get()
data = '{"receivedMessageDatas":[' data = '{"receivedMessageDatas":['
for row in queryreturn: for row in queryreturn:
payload, = row payload, = row
@ -824,11 +836,8 @@ class singleAPI(threading.Thread):
se.register_introspection_functions() se.register_introspection_functions()
se.serve_forever() se.serve_forever()
selfInitiatedConnections = {}
# This is a list of current connections (the thread pointers at least) # This is a list of current connections (the thread pointers at least)
selfInitiatedConnections = {}
if shared.useVeryEasyProofOfWorkForTesting: if shared.useVeryEasyProofOfWorkForTesting:

View File

@ -33,9 +33,9 @@ class singleCleaner(threading.Thread):
for hash, storedValue in shared.inventory.items(): for hash, storedValue in shared.inventory.items():
objectType, streamNumber, payload, receivedTime = storedValue objectType, streamNumber, payload, receivedTime = storedValue
if int(time.time()) - 3600 > receivedTime: if int(time.time()) - 3600 > receivedTime:
t = (hash, objectType, streamNumber, payload, receivedTime) t = (hash, objectType, streamNumber, payload, receivedTime,'')
shared.sqlSubmitQueue.put( shared.sqlSubmitQueue.put(
'''INSERT INTO inventory VALUES (?,?,?,?,?)''') '''INSERT INTO inventory VALUES (?,?,?,?,?,?)''')
shared.sqlSubmitQueue.put(t) shared.sqlSubmitQueue.put(t)
shared.sqlReturnQueue.get() shared.sqlReturnQueue.get()
del shared.inventory[hash] del shared.inventory[hash]

View File

@ -46,7 +46,7 @@ class sqlThread(threading.Thread):
self.cur.execute( self.cur.execute(
'''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)''' ) '''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)''' )
self.cur.execute( self.cur.execute(
'''CREATE TABLE inventory (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE)''' ) '''CREATE TABLE inventory (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer, first20bytesofencryptedmessage blob, UNIQUE(hash) ON CONFLICT REPLACE)''' )
self.cur.execute( self.cur.execute(
'''CREATE TABLE knownnodes (timelastseen int, stream int, services blob, host blob, port blob, UNIQUE(host, stream, port) ON CONFLICT REPLACE)''' ) '''CREATE TABLE knownnodes (timelastseen int, stream int, services blob, host blob, port blob, UNIQUE(host, stream, port) ON CONFLICT REPLACE)''' )
# This table isn't used in the program yet but I # This table isn't used in the program yet but I
@ -55,7 +55,7 @@ class sqlThread(threading.Thread):
'''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''') '''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
self.cur.execute( self.cur.execute(
'''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''' ) '''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''' )
self.cur.execute( '''INSERT INTO settings VALUES('version','1')''') self.cur.execute( '''INSERT INTO settings VALUES('version','2')''')
self.cur.execute( '''INSERT INTO settings VALUES('lastvacuumtime',?)''', ( self.cur.execute( '''INSERT INTO settings VALUES('lastvacuumtime',?)''', (
int(time.time()),)) int(time.time()),))
self.conn.commit() self.conn.commit()
@ -190,13 +190,18 @@ class sqlThread(threading.Thread):
if not shared.config.has_option('bitmessagesettings', 'sockslisten'): if not shared.config.has_option('bitmessagesettings', 'sockslisten'):
shared.config.set('bitmessagesettings', 'sockslisten', 'false') shared.config.set('bitmessagesettings', 'sockslisten', 'false')
# Some prewritten code for future use whenever we need to modify the database # Add a new column to the inventory table to store the first 20 bytes of encrypted messages to support Android app
"""item = '''SELECT value FROM settings WHERE key='version';''' item = '''SELECT value FROM settings WHERE key='version';'''
parameters = '' parameters = ''
self.cur.execute(item, parameters) self.cur.execute(item, parameters)
if self.cur.fetchall()[0][0] == 1: if int(self.cur.fetchall()[0][0]) == 1:
do something print 'upgrading database'
increment the version to 2""" item = '''ALTER TABLE inventory ADD first20bytesofencryptedmessage blob DEFAULT '' '''
parameters = ''
self.cur.execute(item, parameters)
item = '''update settings set value=? WHERE key='version';'''
parameters = (2,)
self.cur.execute(item, parameters)
try: try:
testpayload = '\x00\x00' testpayload = '\x00\x00'

View File

@ -54,13 +54,13 @@ def readPubkeys():
def readInventory(): def readInventory():
print 'Printing everything in inventory table:' print 'Printing everything in inventory table:'
item = '''select hash, objecttype, streamnumber, payload, receivedtime from inventory''' item = '''select hash, objecttype, streamnumber, payload, receivedtime, first20bytesofencryptedmessage from inventory where objecttype = 'msg' '''
parameters = '' parameters = ''
cur.execute(item, parameters) cur.execute(item, parameters)
output = cur.fetchall() output = cur.fetchall()
for row in output: for row in output[:50]:
hash, objecttype, streamnumber, payload, receivedtime = row hash, objecttype, streamnumber, payload, receivedtime, first20bytesofencryptedmessage = row
print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime)),'utf-8') print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', 'first20bytesofencryptedmessage:', first20bytesofencryptedmessage.encode('hex'), '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime)),'utf-8')
def readInventory2(): def readInventory2():
searchValue = ' ' searchValue = ' '
@ -74,15 +74,17 @@ def readInventory2():
searchValue = string.replace(searchValue,'_','e_') searchValue = string.replace(searchValue,'_','e_')
print 'Printing subset of inventory table:' print 'Printing subset of inventory table:'
item = '''SELECT * FROM inventory WHERE hash LIKE ? ESCAPE'e'; ''' item = '''SELECT substr(payload,20) FROM inventory'''
parameters = ('%'+ searchValue + '%',) #parameters = ('%'+ searchValue + '%',)
print repr(parameters), len(parameters[0]) #print repr(parameters), len(parameters[0])
parameters = ''
cur.execute(item, parameters) cur.execute(item, parameters)
output = cur.fetchall() output = cur.fetchall()
print 'Number of results:', len(output) print 'Number of results:', len(output)
for row in output[:20]: for row in output[:100]:
hash, objecttype, streamnumber, payload, receivedtime = row print row
print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime)),'utf-8') #hash, objecttype, streamnumber, payload, receivedtime = row
#print 'Hash:', hash.encode('hex'), objecttype, streamnumber, '\t', payload.encode('hex'), '\t', unicode(strftime('%a, %d %b %Y %I:%M %p',localtime(receivedtime)),'utf-8')
print 'done' print 'done'
@ -125,9 +127,9 @@ def vacuum():
#readSent() #readSent()
#readPubkeys() #readPubkeys()
#readSubscriptions() #readSubscriptions()
#readInventory() readInventory()
#vacuum() #will defragment and clean empty space from the messages.dat file. #vacuum() #will defragment and clean empty space from the messages.dat file.
readInventory2() #readInventory2()

View File

@ -243,8 +243,7 @@ def reloadMyAddressHashes():
myAddressesByHash[hash] = addressInKeysFile myAddressesByHash[hash] = addressInKeysFile
else: else:
logger.error('Error in reloadMyAddressHashes: Can\'t handle address ' logger.error('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2 or 3.\n')
'versions other than 2 or 3.\n')
if not keyfileSecure: if not keyfileSecure:
fixSensitiveFilePermissions(appdata + 'keys.dat', hasEnabledKeys) fixSensitiveFilePermissions(appdata + 'keys.dat', hasEnabledKeys)
@ -320,8 +319,8 @@ def flushInventory():
sqlLock.acquire() sqlLock.acquire()
for hash, storedValue in inventory.items(): for hash, storedValue in inventory.items():
objectType, streamNumber, payload, receivedTime = storedValue objectType, streamNumber, payload, receivedTime = storedValue
t = (hash,objectType,streamNumber,payload,receivedTime) t = (hash,objectType,streamNumber,payload,receivedTime,'')
sqlSubmitQueue.put('''INSERT INTO inventory VALUES (?,?,?,?,?)''') sqlSubmitQueue.put('''INSERT INTO inventory VALUES (?,?,?,?,?,?)''')
sqlSubmitQueue.put(t) sqlSubmitQueue.put(t)
sqlReturnQueue.get() sqlReturnQueue.get()
del inventory[hash] del inventory[hash]