2020-08-19 13:01:37 +00:00
|
|
|
import os,time,sys,logging
|
2020-08-17 13:33:26 +00:00
|
|
|
from pathlib import Path
|
2020-08-20 00:34:14 +00:00
|
|
|
import asyncio,time
|
2020-08-19 13:01:37 +00:00
|
|
|
# handler = logging.StreamHandler()
|
|
|
|
# formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
|
|
|
|
# handler.setFormatter(formatter)
|
|
|
|
# logger = logging.getLogger(__file__)
|
|
|
|
# logger.addHandler(handler)
|
|
|
|
# logger.setLevel(logging.DEBUG)
|
|
|
|
sys.path.append('../p2p')
|
|
|
|
# logger.info(os.getcwd(), sys.path)
|
2020-08-22 00:27:20 +00:00
|
|
|
BSEP=b'\n\n\n\n'
|
|
|
|
BSEP2=b'\t\n\t\n'
|
|
|
|
BSEP3=b'\r\r\r\r'
|
2020-08-21 13:29:46 +00:00
|
|
|
NODE_SLEEP_FOR=1
|
2020-08-19 13:01:37 +00:00
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
try:
|
|
|
|
from .crypto import *
|
|
|
|
from .p2p import *
|
|
|
|
from .kad import *
|
2020-08-20 15:48:08 +00:00
|
|
|
except (ModuleNotFoundError,ImportError):
|
2020-08-19 12:06:44 +00:00
|
|
|
from crypto import *
|
|
|
|
from p2p import *
|
2020-08-20 15:48:08 +00:00
|
|
|
from kad import *
|
2020-08-17 20:40:48 +00:00
|
|
|
from pathlib import Path
|
|
|
|
from functools import partial
|
2020-08-17 13:33:26 +00:00
|
|
|
|
|
|
|
# works better with tor?
|
|
|
|
import json
|
|
|
|
jsonify = json.dumps
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-17 13:33:26 +00:00
|
|
|
# Start server
|
|
|
|
|
|
|
|
DEBUG = True
|
|
|
|
UPLOAD_DIR = 'uploads/'
|
|
|
|
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-18 15:14:19 +00:00
|
|
|
# PORT_SPEAK = 8468
|
2020-08-19 14:07:12 +00:00
|
|
|
PORT_LISTEN = 5639
|
2020-08-17 13:33:26 +00:00
|
|
|
|
|
|
|
# Api Functions
|
2020-08-18 14:32:10 +00:00
|
|
|
from threading import Thread
|
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
NODES_PRIME = [("128.232.229.63",8467), ("68.66.241.111",8467)]
|
|
|
|
#68.66.224.46
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
home = str(Path.home())
|
|
|
|
KEYDIR = os.path.join(home,'.komrade','.keys')
|
|
|
|
if not os.path.exists(KEYDIR): os.makedirs(KEYDIR)
|
|
|
|
|
|
|
|
|
2020-08-17 13:33:26 +00:00
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
async def _getdb(self=None,port=PORT_LISTEN):
|
2020-08-21 08:18:20 +00:00
|
|
|
from kademlia.network import Server
|
2020-08-21 11:11:50 +00:00
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
if self: self.log('starting server..')
|
2020-08-19 15:13:49 +00:00
|
|
|
|
|
|
|
import os
|
2020-08-20 15:48:08 +00:00
|
|
|
if self: self.log(os.getcwd())
|
2020-08-21 08:18:20 +00:00
|
|
|
node = Server() #fn='../p2p/data.db',log=(self.log if self else print)))
|
2020-08-19 11:30:23 +00:00
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
if self: self.log('listening..')
|
2020-08-19 11:30:23 +00:00
|
|
|
await node.listen(port)
|
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
if self: self.log('bootstrapping server..')
|
2020-08-19 11:30:23 +00:00
|
|
|
await node.bootstrap(NODES_PRIME)
|
2020-08-21 16:12:40 +00:00
|
|
|
self.log('NODE:',node)
|
2020-08-19 11:30:23 +00:00
|
|
|
return node
|
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
def logg(*x):
|
|
|
|
print(*x)
|
2020-08-19 12:06:44 +00:00
|
|
|
|
2020-08-17 16:23:40 +00:00
|
|
|
class Api(object):
|
2020-08-21 15:22:30 +00:00
|
|
|
def __init__(self,user=None,log=None):
|
|
|
|
self.log = log if log is not None else logg
|
|
|
|
self.username = user
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
def private_key(self):
|
|
|
|
if self.username:
|
2020-08-21 15:46:33 +00:00
|
|
|
pass
|
2020-08-17 16:23:40 +00:00
|
|
|
|
2020-08-21 07:41:34 +00:00
|
|
|
async def connect_forever(self,port=PORT_LISTEN,save_every=10):
|
2020-08-19 14:07:12 +00:00
|
|
|
try:
|
|
|
|
i = 0
|
2020-08-20 20:08:47 +00:00
|
|
|
self._node = await self.connect(port=port)
|
2020-08-19 14:07:12 +00:00
|
|
|
while True:
|
2020-08-21 21:15:20 +00:00
|
|
|
if not i%60: self.log(f'Node status (tick {i}): {self._node}')
|
2020-08-21 07:41:34 +00:00
|
|
|
if i and not i%save_every: await self.flush()
|
2020-08-20 01:39:26 +00:00
|
|
|
i += 1
|
2020-08-21 16:15:42 +00:00
|
|
|
await asyncio.sleep(NODE_SLEEP_FOR)
|
|
|
|
# asyncio.sleep(0)
|
2020-08-21 05:31:42 +00:00
|
|
|
except (asyncio.CancelledError,KeyboardInterrupt) as e:
|
2020-08-20 09:51:57 +00:00
|
|
|
self.log('P2P node cancelled', e)
|
2020-08-20 22:04:21 +00:00
|
|
|
await self.flush()
|
2020-08-19 14:07:12 +00:00
|
|
|
finally:
|
|
|
|
# when canceled, print that it finished
|
2020-08-20 09:51:57 +00:00
|
|
|
self.log('P2P node shutting down')
|
2020-08-21 05:31:42 +00:00
|
|
|
pass
|
2020-08-21 16:12:40 +00:00
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
@property
|
|
|
|
async def node(self):
|
2020-08-21 16:12:40 +00:00
|
|
|
# while not hasattr(self,'_node'):
|
|
|
|
# self.log('[API] waiting forr connection...')
|
|
|
|
# await asyncio.sleep(1)
|
|
|
|
# return self._node
|
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
if not hasattr(self,'_node'):
|
2020-08-21 16:12:40 +00:00
|
|
|
await self.connect()
|
2020-08-19 14:07:12 +00:00
|
|
|
return self._node
|
|
|
|
|
|
|
|
async def connect(self,port=PORT_LISTEN):
|
|
|
|
self.log('connecting...')
|
2020-08-21 16:12:40 +00:00
|
|
|
node = await _getdb(self,port)
|
|
|
|
self.log(f'connect() has node {node}')
|
|
|
|
self._node = node
|
|
|
|
return node
|
2020-08-19 14:07:12 +00:00
|
|
|
|
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
|
2020-08-21 15:46:33 +00:00
|
|
|
async def get(self,key_or_keys,decode_data=True):
|
2020-08-21 21:15:20 +00:00
|
|
|
self.log(f'get({key_or_keys},decode_data={decode_data}) --> ...')
|
2020-08-17 16:23:40 +00:00
|
|
|
async def _get():
|
2020-08-19 14:07:12 +00:00
|
|
|
node=await self.node
|
2020-08-20 21:10:59 +00:00
|
|
|
res=None
|
2020-08-17 20:40:48 +00:00
|
|
|
if type(key_or_keys) in {list,tuple,dict}:
|
|
|
|
keys = key_or_keys
|
|
|
|
|
2020-08-20 18:26:33 +00:00
|
|
|
tasks=[]
|
|
|
|
for key in keys:
|
2020-08-20 21:10:59 +00:00
|
|
|
val = await node.get(key)
|
2020-08-21 15:46:33 +00:00
|
|
|
task = self.decode_data(val) if decode_data else val
|
2020-08-20 21:10:59 +00:00
|
|
|
tasks.append(task)
|
2020-08-20 18:26:33 +00:00
|
|
|
res = await asyncio.gather(*tasks)
|
|
|
|
else:
|
2020-08-20 21:10:59 +00:00
|
|
|
key=key_or_keys
|
|
|
|
val = await node.get(key)
|
2020-08-21 15:46:33 +00:00
|
|
|
res = await self.decode_data(val) if decode_data else val
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log('wtf is val =',val)
|
|
|
|
self.log('wtf is res =',val)
|
2020-08-17 20:40:48 +00:00
|
|
|
|
2020-08-21 21:15:20 +00:00
|
|
|
self.log(f'_get({key_or_keys}) --> {res}')
|
2020-08-20 21:10:59 +00:00
|
|
|
return res
|
2020-08-19 14:07:12 +00:00
|
|
|
return await _get()
|
2020-08-20 00:34:14 +00:00
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
def encode_data(self,val,sep=BSEP,sep2=BSEP2,do_encrypt=True,receiver_pubkey=None,private_signature_key=None):
|
2020-08-20 00:34:14 +00:00
|
|
|
"""
|
|
|
|
What do we want to store with
|
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
1) [Encrypted payload:]
|
|
|
|
1) Timestamp
|
|
|
|
2) Public key of sender
|
|
|
|
3) Public key of recipient
|
|
|
|
4) AES-encrypted Value
|
|
|
|
2) [Decryption tools]
|
|
|
|
1) AES-decryption key
|
|
|
|
2) AES decryption IV value
|
|
|
|
5) Signature of value by author
|
2020-08-20 00:34:14 +00:00
|
|
|
"""
|
2020-08-20 08:55:50 +00:00
|
|
|
import time
|
2020-08-20 00:34:14 +00:00
|
|
|
timestamp=time.time()
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
# check input
|
|
|
|
if not receiver_pubkey:
|
|
|
|
self.log('we need a receiver !!')
|
|
|
|
return None
|
2020-08-20 00:34:14 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# convert val to bytes
|
|
|
|
if type(val)!=bytes: val = bytes(val,'utf-8')
|
|
|
|
value_bytes=base64.b64encode(val)
|
2020-08-20 01:39:26 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# sign
|
2020-08-21 15:22:30 +00:00
|
|
|
private_signature_key = private_signature_key if private_signature_key is not None else self.private_key
|
|
|
|
signature = sign(value_bytes, private_signature_key)
|
|
|
|
public_sender_key = private_signature_key.public_key()
|
|
|
|
sender_pubkey_b = serialize_pubkey(public_sender_key)
|
2020-08-20 00:34:14 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# Verify!
|
2020-08-21 15:22:30 +00:00
|
|
|
authentic = verify_signature(signature, value_bytes, sender_pubkey_b)
|
2020-08-20 15:09:43 +00:00
|
|
|
if not authentic:
|
|
|
|
self.log('message is inauthentic for set??',authentic)
|
|
|
|
return None
|
2020-08-20 00:34:14 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# encrypt?
|
2020-08-20 08:55:50 +00:00
|
|
|
receiver_pubkey_b = serialize_pubkey(receiver_pubkey)
|
2020-08-20 15:09:43 +00:00
|
|
|
time_b=str(timestamp).encode()
|
|
|
|
msg=value_bytes
|
2020-08-20 08:55:50 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# whole binary package
|
|
|
|
WDV = [
|
2020-08-20 08:55:50 +00:00
|
|
|
time_b,
|
|
|
|
sender_pubkey_b,
|
2020-08-20 15:09:43 +00:00
|
|
|
receiver_pubkey_b,
|
|
|
|
msg,
|
2020-08-20 08:55:50 +00:00
|
|
|
signature
|
2020-08-20 15:09:43 +00:00
|
|
|
]
|
|
|
|
payload = sep2.join(WDV)
|
|
|
|
|
|
|
|
res = aes_rsa_encrypt(payload,receiver_pubkey)
|
|
|
|
if res is None: return None
|
|
|
|
payload_encr_aes, payload_encr_aes_key, payload_encr_aes_iv = res
|
|
|
|
|
|
|
|
decryption_tools = sep2.join([
|
|
|
|
payload_encr_aes_key,
|
|
|
|
payload_encr_aes_iv
|
2020-08-20 08:55:50 +00:00
|
|
|
])
|
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
final_packet = sep.join([
|
|
|
|
payload_encr_aes,
|
|
|
|
decryption_tools
|
|
|
|
])
|
|
|
|
|
2020-08-22 00:37:37 +00:00
|
|
|
print('FINAL PACKET:',final_packet,type(final_packet))
|
2020-08-20 15:09:43 +00:00
|
|
|
return final_packet
|
2020-08-20 00:34:14 +00:00
|
|
|
|
2020-08-22 00:27:20 +00:00
|
|
|
|
|
|
|
|
2020-08-21 21:15:20 +00:00
|
|
|
async def decode_data(self,entire_packet_orig,sep=BSEP,private_key=None,sep2=BSEP2):
|
|
|
|
if entire_packet_orig is None: return entire_packet_orig
|
2020-08-22 00:27:20 +00:00
|
|
|
import binascii
|
|
|
|
entire_packet = entire_packet_orig
|
|
|
|
|
2020-08-22 00:37:37 +00:00
|
|
|
self.log('PACKED =',entire_packet,type(entire_packet))
|
2020-08-22 00:27:20 +00:00
|
|
|
|
2020-08-21 21:15:20 +00:00
|
|
|
self.log('????',type(entire_packet))
|
|
|
|
self.log(entire_packet)
|
2020-08-20 08:55:50 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# get data
|
2020-08-21 21:15:20 +00:00
|
|
|
try:
|
2020-08-22 00:27:20 +00:00
|
|
|
encrypted_payload, decryption_tools = split_binary(entire_packet, sep=sep) #entire_packet.split(sep)
|
|
|
|
decryption_tools=split_binary(decryption_tools,sep=sep2)
|
|
|
|
except AssertionError as e:
|
|
|
|
|
|
|
|
self.log('!! decode_data() got incorrect format:',e)
|
2020-08-21 21:15:20 +00:00
|
|
|
return entire_packet_orig
|
2020-08-20 15:09:43 +00:00
|
|
|
|
|
|
|
# ### FIRST LINE OF PROTECTION
|
|
|
|
# # is the receiver's public id in our list of public IDs?
|
|
|
|
# to_pub = load_pubkey(to_pub_b)
|
|
|
|
# oktogo=False
|
|
|
|
# CORRECT_PUB_KEY=None
|
|
|
|
# CORRECT_PRIV_KEY=None
|
|
|
|
# for privkey,pubkey in self.keys():
|
|
|
|
# if pubkey.public_numbers() == to_pub.public_numbers():
|
|
|
|
# oktogo=True
|
|
|
|
# CORRECT_PUB_KEY = pubkey
|
|
|
|
# CORRECT_PRIV_KEY = privkey
|
|
|
|
# break
|
|
|
|
# if not oktogo: return None
|
|
|
|
|
2020-08-20 01:39:26 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
|
|
|
|
### SECOND LINE OF PROTECTION
|
|
|
|
# first try to decrypt sender to see if we have access to this
|
|
|
|
# def _decrypt_aes_rsa(args):
|
|
|
|
# val_encr,val_encr_key,iv = args
|
|
|
|
# val = aes_rsa_decrypt(val_encr,val_encr_key,iv,CORRECT_PRIV_KEY)
|
|
|
|
# return val
|
|
|
|
# from_pub_decr = _decrypt_rsa(*sender_encr)
|
|
|
|
# if not from_pub_decr: return None
|
|
|
|
# from_pub = load_pubkey(from_pub_b)
|
2020-08-20 08:55:50 +00:00
|
|
|
|
2020-08-20 01:39:26 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
### NEW FIRST LINE: Try to decrypt!
|
|
|
|
val=None
|
|
|
|
for keyname,privkey,pubkey in self.keys():
|
|
|
|
try:
|
|
|
|
val = aes_rsa_decrypt(encrypted_payload,privkey,*decryption_tools)
|
|
|
|
#self.log('decrypted =',val)
|
|
|
|
break
|
|
|
|
except ValueError as e:
|
|
|
|
self.log(keyname,'did not work!') #,privkey,pubkey)
|
|
|
|
pass
|
|
|
|
if not val:
|
|
|
|
self.log('Content not intended for us')
|
|
|
|
return None
|
|
|
|
|
|
|
|
#stop
|
|
|
|
|
|
|
|
### THIRD LINE: SIGNATURE VERIFICATION
|
|
|
|
# can we decrypt signature?
|
|
|
|
val_array = val.split(sep2)
|
2020-08-20 21:50:58 +00:00
|
|
|
# self.log('val_array =',val_array)
|
2020-08-20 15:09:43 +00:00
|
|
|
time_b,sender_pubkey_b,receiver_pubkey_b,msg,signature = val_array
|
|
|
|
if not signature: return None
|
|
|
|
sender_pubkey=load_pubkey(sender_pubkey_b)
|
|
|
|
authentic = verify_signature(signature,msg,sender_pubkey)
|
2020-08-20 01:39:26 +00:00
|
|
|
if not authentic:
|
|
|
|
self.log('inauthentic message!')
|
2020-08-20 15:09:43 +00:00
|
|
|
return None
|
2020-08-20 01:39:26 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
|
|
|
|
# ### FOURTH LINE: CONTENT ENCRYPTION
|
|
|
|
# if private_key is None:
|
|
|
|
# private_key=self.private_key_global
|
2020-08-20 09:51:57 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# val_encr = base64.b64decode(val_encr)
|
|
|
|
# val_encr_key = base64.b64decode(val_encr_key)
|
2020-08-20 09:51:57 +00:00
|
|
|
# self.log(f"""decrypting
|
|
|
|
# val_encr = {val_encr}
|
|
|
|
# val_encr_key = {val_encr_key}
|
|
|
|
# iv = {iv}
|
|
|
|
# private_key = {private_key}
|
|
|
|
# """)
|
2020-08-20 15:09:43 +00:00
|
|
|
|
2020-08-20 09:51:57 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
# val = _decrypt_aes()
|
2020-08-20 08:55:50 +00:00
|
|
|
# self.log('val after decryption = ',val)
|
2020-08-20 15:09:43 +00:00
|
|
|
# valdec = base64.b64decode(val)
|
2020-08-20 11:48:26 +00:00
|
|
|
|
2020-08-20 08:55:50 +00:00
|
|
|
WDV={
|
|
|
|
'time':float(time_b.decode()),
|
2020-08-21 11:11:50 +00:00
|
|
|
'val':base64.b64decode(msg),
|
2020-08-20 15:09:43 +00:00
|
|
|
'to':receiver_pubkey_b,
|
|
|
|
'from':sender_pubkey_b,
|
2020-08-20 08:55:50 +00:00
|
|
|
'sign':signature
|
|
|
|
}
|
|
|
|
|
2020-08-20 21:50:58 +00:00
|
|
|
# self.log('GOT WDV:',WDV)
|
2020-08-20 08:55:50 +00:00
|
|
|
return WDV
|
|
|
|
|
|
|
|
|
|
|
|
#,signature
|
2020-08-20 01:39:26 +00:00
|
|
|
|
2020-08-22 05:08:40 +00:00
|
|
|
# async def set_on_channel(self,key_or_keys,value_or_values):
|
|
|
|
# tasks=[]
|
|
|
|
# if type(channel_or_channels) not in {list,tuple}:
|
|
|
|
# channels=[channel_or_channels]
|
|
|
|
# else:
|
|
|
|
# channels=channel_or_channels
|
|
|
|
|
|
|
|
# for channel in channels:
|
|
|
|
# uri =
|
|
|
|
# tasks.append(self.set)
|
|
|
|
|
|
|
|
# if type(channel_or_channels) == str:
|
|
|
|
# return await self.set(self,key_or_keys,value_or_values,channel_or_channels)
|
|
|
|
# elif type(channel_or_channels) ==
|
2020-08-19 14:27:12 +00:00
|
|
|
|
2020-08-22 05:08:40 +00:00
|
|
|
async def set(self,key_or_keys,value_or_values,private_signature_key=None,encode_data=True,encrypt_for_pubkey=None):
|
2020-08-21 21:15:20 +00:00
|
|
|
self.log(f'api.set({key_or_keys}) --> {type(value_or_values)}')
|
2020-08-19 14:27:12 +00:00
|
|
|
async def _set():
|
2020-08-19 11:14:52 +00:00
|
|
|
# self.log('async _set()',self.node)
|
2020-08-19 11:30:23 +00:00
|
|
|
# node=self.node
|
2020-08-19 14:07:12 +00:00
|
|
|
#node=await _getdb(self)
|
|
|
|
node=await self.node
|
2020-08-21 15:46:33 +00:00
|
|
|
|
2020-08-22 05:08:40 +00:00
|
|
|
def proc(key,value):
|
|
|
|
if encode_data and encrypt_for_pubkey is not None:
|
|
|
|
x = self.encode_data(value,private_signature_key=private_signature_key,
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
x = value
|
|
|
|
self.log('set encoded data =',x)
|
|
|
|
return x
|
2020-08-21 15:46:33 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
if type(key_or_keys) in {list,tuple,dict}:
|
|
|
|
keys = key_or_keys
|
|
|
|
values = value_or_values
|
|
|
|
assert len(keys)==len(values)
|
2020-08-21 15:22:30 +00:00
|
|
|
tasks=[
|
|
|
|
node.set(
|
|
|
|
key,
|
2020-08-22 05:08:40 +00:00
|
|
|
proc(key,value)
|
2020-08-21 15:22:30 +00:00
|
|
|
)
|
|
|
|
for key,value in zip(keys,values)
|
|
|
|
]
|
|
|
|
res = await asyncio.gather(*tasks)
|
2020-08-19 10:29:56 +00:00
|
|
|
# self.log('RES?',res)
|
2020-08-17 20:40:48 +00:00
|
|
|
else:
|
|
|
|
key = key_or_keys
|
|
|
|
value = value_or_values
|
2020-08-22 05:08:40 +00:00
|
|
|
res = await node.set(key,proc(key,value))
|
2020-08-17 20:40:48 +00:00
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
#node.stop()
|
2020-08-17 20:40:48 +00:00
|
|
|
return res
|
2020-08-18 17:25:15 +00:00
|
|
|
|
2020-08-19 14:27:12 +00:00
|
|
|
return await _set()
|
2020-08-18 17:25:15 +00:00
|
|
|
|
2020-08-21 15:46:33 +00:00
|
|
|
async def get_json(self,key_or_keys,decode_data=True):
|
2020-08-20 08:55:50 +00:00
|
|
|
|
2020-08-20 21:51:51 +00:00
|
|
|
def jsonize(entry):
|
|
|
|
# self.log('jsonize!',entry)
|
2020-08-20 17:43:28 +00:00
|
|
|
if not entry: return entry
|
2020-08-20 08:55:50 +00:00
|
|
|
if not 'val' in entry: return entry
|
|
|
|
val=entry['val']
|
2020-08-20 11:48:26 +00:00
|
|
|
try:
|
|
|
|
dat=json.loads(val) if val else val
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
dat=val
|
2020-08-20 21:50:58 +00:00
|
|
|
# self.log('dat??',dat)
|
2020-08-20 08:55:50 +00:00
|
|
|
entry['val']=dat
|
|
|
|
return entry
|
|
|
|
|
2020-08-20 18:26:33 +00:00
|
|
|
def jsonize_res(res):
|
|
|
|
# parse differently?
|
|
|
|
if type(res)==list:
|
|
|
|
jsonl=[jsonize(entry) for entry in res]
|
|
|
|
return jsonl
|
|
|
|
else:
|
|
|
|
entry = res
|
|
|
|
return jsonize(entry)
|
|
|
|
|
|
|
|
# if key_or_keys.startsiwth('/post/'):
|
2020-08-21 15:46:33 +00:00
|
|
|
res = await self.get(key_or_keys,decode_data=decode_data)
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log('get_json() got from get():',res)
|
2020-08-20 22:04:21 +00:00
|
|
|
#self.log('get_json() got',res)
|
2020-08-20 18:26:33 +00:00
|
|
|
if not res: return None
|
2020-08-20 21:10:59 +00:00
|
|
|
return jsonize_res(res)
|
2020-08-20 18:26:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
|
2020-08-22 05:08:40 +00:00
|
|
|
async def set_json(self,key,value,private_signature_key=None,encode_data=True,encrypt_for_pubkey=None):
|
2020-08-17 20:40:48 +00:00
|
|
|
value_json = jsonify(value)
|
2020-08-19 10:29:56 +00:00
|
|
|
# self.log('OH NO!',sys.getsizeof(value_json))
|
2020-08-22 05:08:40 +00:00
|
|
|
return await self.set(key,value_json,private_signature_key=private_signature_key,
|
|
|
|
encode_data=encode_data,encrypt_for_pubkey=encrypt_for_pubkey)
|
2020-08-17 16:23:40 +00:00
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
async def has(self,key):
|
|
|
|
val=await self.get(key)
|
|
|
|
return val is not None
|
2020-08-17 16:23:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
## PERSONS
|
2020-08-19 19:33:25 +00:00
|
|
|
async def get_person(self,username):
|
2020-08-21 15:46:33 +00:00
|
|
|
return await self.get('/person/'+username,decode_data=False)
|
2020-08-17 16:23:40 +00:00
|
|
|
|
2020-08-21 15:46:33 +00:00
|
|
|
async def set_person(self,username,pem_public_key):
|
2020-08-20 08:55:50 +00:00
|
|
|
# pem_public_key = save_public_key(public_key,return_instead=True)
|
2020-08-21 15:22:30 +00:00
|
|
|
#obj = {'name':username, 'public_key':pem_public_key}
|
|
|
|
# await self.set_json('/person/'+username,obj)
|
2020-08-21 15:46:33 +00:00
|
|
|
await self.set('/person/'+username,pem_public_key,
|
|
|
|
private_signature_key=None,encode_data=False)
|
|
|
|
|
2020-08-17 16:23:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Register
|
2020-08-21 15:22:30 +00:00
|
|
|
async def register(self,name,passkey=None):
|
|
|
|
# if not (name and passkey): return {'error':'Name and password needed'}
|
2020-08-19 19:33:25 +00:00
|
|
|
person = await self.get_person(name)
|
2020-08-21 17:52:21 +00:00
|
|
|
if person is not None:
|
|
|
|
# try to log in
|
|
|
|
self.log('my keys',self.keys.keys())
|
|
|
|
if not name in self.keys:
|
|
|
|
return {'error':'Person already exists'}
|
|
|
|
|
|
|
|
# test 3 conditions
|
|
|
|
privkey=self.keys[name]
|
|
|
|
pubkey=load_pubkey(person)
|
|
|
|
|
|
|
|
if simple_lock_test(privkey,pubkey):
|
|
|
|
self.username=name
|
|
|
|
return {'success':'Logging back in...'}
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
private_key = generate_rsa_key()
|
|
|
|
public_key = private_key.public_key()
|
|
|
|
pem_private_key = serialize_privkey(private_key, password=passkey)# save_private_key(private_key,password=passkey,return_instead=True)
|
|
|
|
pem_public_key = serialize_pubkey(public_key)
|
|
|
|
|
|
|
|
# save pub key in db
|
2020-08-21 15:46:33 +00:00
|
|
|
await self.set_person(name,pem_public_key)
|
|
|
|
# save priv key on hardware
|
|
|
|
fn_privkey = os.path.join(KEYDIR,f'.{name}.key')
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-21 15:46:33 +00:00
|
|
|
self.log('priv key =',pem_private_key)
|
|
|
|
write_key_b(pem_private_key, fn_privkey)
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
# good
|
2020-08-21 17:52:21 +00:00
|
|
|
return {'success':'Person created ...', 'username':name}
|
2020-08-20 01:39:26 +00:00
|
|
|
|
|
|
|
|
2020-08-17 16:23:40 +00:00
|
|
|
def load_private_key(self,password):
|
2020-08-21 15:22:30 +00:00
|
|
|
#if not self.app_storage.exists('_keys'): return {'error':'No login keys present on this device'}
|
2020-08-17 16:23:40 +00:00
|
|
|
pem_private_key=self.app_storage.get('_keys').get('private')
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('my private key ====',pem_private_key)
|
2020-08-17 16:23:40 +00:00
|
|
|
try:
|
2020-08-20 08:55:50 +00:00
|
|
|
return {'success':load_privkey(pem_private_key,password)}
|
2020-08-17 16:23:40 +00:00
|
|
|
except ValueError as e:
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('!!',e)
|
2020-08-19 20:15:38 +00:00
|
|
|
return {'error':'Incorrect password'}
|
2020-08-17 16:23:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## LOGIN
|
2020-08-19 19:33:25 +00:00
|
|
|
async def login(self,name,passkey):
|
2020-08-17 16:23:40 +00:00
|
|
|
# verify input
|
|
|
|
if not (name and passkey):
|
|
|
|
return {'error':'Name and password required'}
|
|
|
|
|
|
|
|
# try to load private key
|
2020-08-19 19:33:25 +00:00
|
|
|
private_key_dat = self.load_private_key(passkey)
|
|
|
|
if 'error' in private_key_dat:
|
|
|
|
return {'error':private_key_dat['error']}
|
|
|
|
if not 'success' in private_key_dat:
|
|
|
|
return {'error':'Incorrect password?'}
|
2020-08-20 00:34:14 +00:00
|
|
|
self._private_key = private_key = private_key_dat['success']
|
2020-08-17 16:23:40 +00:00
|
|
|
|
|
|
|
# see if user exists
|
2020-08-19 19:33:25 +00:00
|
|
|
person = await self.get_person(name)
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log(person)
|
2020-08-17 16:23:40 +00:00
|
|
|
if person is None:
|
|
|
|
return {'error':'Login failed'}
|
|
|
|
|
|
|
|
# verify keys
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('got person =',person)
|
2020-08-17 16:23:40 +00:00
|
|
|
person_public_key_pem = person['public_key']
|
2020-08-20 08:55:50 +00:00
|
|
|
public_key = load_pubkey(person_public_key_pem) #load_public_key(person_public_key_pem.encode())
|
2020-08-20 00:34:14 +00:00
|
|
|
self._public_key = real_public_key = private_key.public_key()
|
2020-08-17 16:23:40 +00:00
|
|
|
|
|
|
|
#log('PUBLIC',public_key.public_numbers())
|
|
|
|
#log('REAL PUBLIC',real_public_key.public_numbers())
|
|
|
|
|
|
|
|
if public_key.public_numbers() != real_public_key.public_numbers():
|
2020-08-19 19:33:25 +00:00
|
|
|
return {'error':'Keys do not match!'}
|
2020-08-17 16:23:40 +00:00
|
|
|
return {'success':'Login successful', 'username':name}
|
2020-08-20 09:51:57 +00:00
|
|
|
|
2020-08-20 15:09:43 +00:00
|
|
|
#@property
|
2020-08-21 15:22:30 +00:00
|
|
|
def get_keys(self):
|
2020-08-21 15:46:33 +00:00
|
|
|
res={}
|
|
|
|
for priv_key_fn in os.listdir(KEYDIR):
|
2020-08-21 16:30:28 +00:00
|
|
|
if (not priv_key_fn.startswith('.') or not priv_key_fn.endswith('.key')): continue
|
2020-08-21 15:46:33 +00:00
|
|
|
fnfn = os.path.join(KEYDIR,priv_key_fn)
|
2020-08-21 16:30:28 +00:00
|
|
|
print(fnfn)
|
2020-08-21 15:46:33 +00:00
|
|
|
priv_key=load_privkey_fn(fnfn)
|
2020-08-21 21:15:20 +00:00
|
|
|
#pub_key=priv_key.public_key()
|
2020-08-21 16:30:28 +00:00
|
|
|
name_key= '.'.join(priv_key_fn.split('.')[1:-1])
|
2020-08-21 21:15:20 +00:00
|
|
|
res[name_key] = priv_key
|
2020-08-21 17:52:21 +00:00
|
|
|
self.log(f'[API] found key {name_key} and added to keychain')
|
2020-08-21 15:22:30 +00:00
|
|
|
return res
|
2020-08-21 15:46:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
@property
|
2020-08-21 16:30:28 +00:00
|
|
|
def keys(self):
|
2020-08-21 15:46:33 +00:00
|
|
|
if not hasattr(self,'_keys'): self._keys = self.get_keys()
|
|
|
|
return self._keys
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-20 01:39:26 +00:00
|
|
|
|
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
async def append_json(self,key,data):
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log(f'appending to uri {key}')
|
2020-08-22 05:08:40 +00:00
|
|
|
|
|
|
|
# get sofar
|
|
|
|
sofar=await self.get_json_val(key, decode_data=False)
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log(f'sofar = {sofar}')
|
2020-08-17 20:40:48 +00:00
|
|
|
if sofar is None: sofar = []
|
2020-08-20 21:10:59 +00:00
|
|
|
if type(sofar)!=list: sofar=[sofar]
|
|
|
|
if type(data)!=list: data=[data]
|
2020-08-22 05:08:40 +00:00
|
|
|
|
2020-08-20 21:10:59 +00:00
|
|
|
new=sofar + data
|
2020-08-22 05:08:40 +00:00
|
|
|
if await self.set_json(key, new, encode_data=False):
|
2020-08-17 20:40:48 +00:00
|
|
|
return {'success':'Length increased to %s' % len(new)}
|
2020-08-22 05:08:40 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
return {'error':'Could not append json'}
|
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
async def upload(self,filename,file_id=None, uri='/file/',uri_part='/part/'):
|
2020-08-17 20:40:48 +00:00
|
|
|
import sys
|
|
|
|
|
|
|
|
if not file_id: file_id = get_random_id()
|
|
|
|
part_ids = []
|
|
|
|
part_keys = []
|
|
|
|
parts=[]
|
|
|
|
PARTS=[]
|
|
|
|
buffer_size=100
|
2020-08-20 11:48:26 +00:00
|
|
|
for part in bytes_from_file(filename,chunksize=1024*2):
|
2020-08-17 20:40:48 +00:00
|
|
|
part_id = get_random_id()
|
|
|
|
part_ids.append(part_id)
|
|
|
|
part_key='/part/'+part_id
|
|
|
|
part_keys.append(part_key)
|
|
|
|
parts.append(part)
|
|
|
|
# PARTS.append(part)
|
|
|
|
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('part!:',sys.getsizeof(part))
|
2020-08-17 20:40:48 +00:00
|
|
|
#self.set(part_key,part)
|
|
|
|
|
|
|
|
if len(parts)>=buffer_size:
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('setting...')
|
2020-08-19 19:33:25 +00:00
|
|
|
await self.set(part_keys,parts)
|
2020-08-17 20:40:48 +00:00
|
|
|
part_keys=[]
|
|
|
|
PARTS+=parts
|
|
|
|
parts=[]
|
|
|
|
|
|
|
|
# set all parts
|
|
|
|
#self.set(part_keys,PARTS)
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('# parts:',len(PARTS))
|
2020-08-20 10:59:53 +00:00
|
|
|
if parts and part_keys:
|
|
|
|
await self.set(part_keys, parts)
|
2020-08-17 20:40:48 +00:00
|
|
|
|
|
|
|
# how many parts?
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('# pieces!',len(part_ids))
|
2020-08-17 20:40:48 +00:00
|
|
|
|
|
|
|
file_store = {'ext':os.path.splitext(filename)[-1][1:], 'parts':part_ids}
|
2020-08-20 22:04:21 +00:00
|
|
|
# self.log('FILE STORE??',file_store)
|
2020-08-19 19:33:25 +00:00
|
|
|
await self.set_json(uri+file_id,file_store)
|
2020-08-17 20:40:48 +00:00
|
|
|
|
|
|
|
# file_store['data'].seek(0)
|
|
|
|
file_store['id']=file_id
|
|
|
|
return file_store
|
2020-08-17 16:23:40 +00:00
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
async def download(self,file_id):
|
2020-08-20 10:59:53 +00:00
|
|
|
self.log('file_id =',file_id)
|
2020-08-20 17:43:28 +00:00
|
|
|
file_store = await self.get_json_val('/file/'+file_id)
|
2020-08-20 10:59:53 +00:00
|
|
|
self.log('file_store =',file_store)
|
2020-08-17 22:06:31 +00:00
|
|
|
if file_store is None: return
|
|
|
|
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('file_store!?',file_store)
|
2020-08-17 22:06:31 +00:00
|
|
|
keys = ['/part/'+x for x in file_store['parts']]
|
2020-08-20 11:48:26 +00:00
|
|
|
|
2020-08-20 17:43:28 +00:00
|
|
|
#time,pieces,pub,sign = await self.get_json_val(keys)
|
|
|
|
pieces = await self.get_json_val(keys)
|
2020-08-20 11:48:26 +00:00
|
|
|
self.log('pieces = ',pieces)
|
2020-08-17 22:06:31 +00:00
|
|
|
file_store['parts_data']=pieces
|
|
|
|
return file_store
|
|
|
|
|
2020-08-20 17:43:28 +00:00
|
|
|
#def get_current_event_id(self):
|
|
|
|
# return self.get_json_val(self,'/current/event/id')
|
2020-08-20 15:48:08 +00:00
|
|
|
|
2020-08-20 17:43:28 +00:00
|
|
|
# def get_uri(self):
|
|
|
|
# event_id = self.get_current_event_id()
|
|
|
|
# event_id=1 if event_id is None else int(event_id)
|
|
|
|
# return f'/post/{event_id}'
|
2020-08-17 22:06:31 +00:00
|
|
|
|
2020-08-20 21:45:30 +00:00
|
|
|
async def flush(self):
|
|
|
|
self.log('saving back to db file...')
|
|
|
|
node = await self.node
|
|
|
|
node.storage.dump()
|
|
|
|
self.log('DONE saving back to db file...')
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-22 00:27:20 +00:00
|
|
|
async def post(self,data,add_to_outbox=True):
|
2020-08-17 20:40:48 +00:00
|
|
|
post_id=get_random_id()
|
2020-08-22 00:27:20 +00:00
|
|
|
tasks = []
|
2020-08-22 05:08:40 +00:00
|
|
|
#self.log(f'post() added post {post_id}')
|
|
|
|
#task = self.set_json('/post/'+post_id, data, )
|
2020-08-22 00:27:20 +00:00
|
|
|
tasks.append(task)
|
|
|
|
|
|
|
|
# res = await
|
|
|
|
# if not res:
|
|
|
|
# self.log('!! error, couldn\'t set post json')
|
|
|
|
# return
|
2020-08-21 21:15:20 +00:00
|
|
|
|
|
|
|
# ## add to inbox
|
2020-08-22 05:08:40 +00:00
|
|
|
post_ids=[]
|
2020-08-22 00:27:20 +00:00
|
|
|
for channel in data.get('to_channels',[]):
|
|
|
|
self.log('ADDING TO CHANNEL??',channel)
|
2020-08-22 05:08:40 +00:00
|
|
|
|
|
|
|
## add per channel
|
|
|
|
post_id = get_random_id()
|
|
|
|
post_ids.append(post_ids)
|
|
|
|
uri = '/'+os.path.join('post',channel,post_id)
|
|
|
|
task = self.set_json(uri, data)
|
|
|
|
|
|
|
|
# add to inbox
|
2020-08-22 00:27:20 +00:00
|
|
|
task=self.append_json(f'/inbox/{channel}',post_id)
|
|
|
|
tasks.append(task)
|
2020-08-20 17:43:28 +00:00
|
|
|
|
2020-08-22 05:08:40 +00:00
|
|
|
# add to outbox
|
|
|
|
if add_to_outbox:
|
|
|
|
un=data.get('author')
|
|
|
|
if un:
|
|
|
|
task = self.append_json(f'/outbox/{un}', post_id)
|
|
|
|
tasks.append(task)
|
2020-08-22 00:27:20 +00:00
|
|
|
|
|
|
|
self.log('gathering tasks')
|
|
|
|
res = await asyncio.gather(*tasks)
|
|
|
|
self.log('done with tasks')
|
2020-08-17 13:33:26 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
if res:
|
2020-08-20 21:45:30 +00:00
|
|
|
asyncio.create_task(self.flush())
|
2020-08-22 05:08:40 +00:00
|
|
|
return {'success':'Posted! %s' % post_ids, 'post_id':post_ids}
|
2020-08-17 20:40:48 +00:00
|
|
|
return {'error':'Post failed'}
|
2020-08-17 13:33:26 +00:00
|
|
|
|
2020-08-21 15:46:33 +00:00
|
|
|
async def get_json_val(self,uri,decode_data=True):
|
|
|
|
res=await self.get_json(uri,decode_data=decode_data)
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log('get_json_val() got from get_json():',res)
|
|
|
|
|
|
|
|
r=res
|
2020-08-20 11:48:26 +00:00
|
|
|
if type(res) == dict:
|
2020-08-20 18:26:33 +00:00
|
|
|
r=res.get('val',None) if res is not None else None
|
2020-08-20 09:51:57 +00:00
|
|
|
elif type(res) == list:
|
2020-08-20 18:26:33 +00:00
|
|
|
r=[x.get('val',None) for x in res if x is not None]
|
2020-08-22 00:27:20 +00:00
|
|
|
elif type(res) == str:
|
|
|
|
r=json.loads(res)
|
2020-08-21 13:12:13 +00:00
|
|
|
self.log(f'get_json_val() --> {r}')
|
2020-08-20 11:48:26 +00:00
|
|
|
return r
|
2020-08-20 09:51:57 +00:00
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
async def get_post(self,post_id):
|
2020-08-21 15:46:33 +00:00
|
|
|
return await self.get_json_val(post_id,decode_data=True)
|
2020-08-17 13:33:26 +00:00
|
|
|
|
2020-08-21 21:15:20 +00:00
|
|
|
async def get_posts(self,uri='/inbox/earth'):
|
2020-08-20 17:43:28 +00:00
|
|
|
# index = await self.get_json_val('/posts'+uri)
|
2020-08-21 13:12:13 +00:00
|
|
|
self.log(f'api.get_posts(uri={uri}) --> ...')
|
2020-08-22 00:27:20 +00:00
|
|
|
index = await self.get(uri,decode_data=True)
|
2020-08-22 00:37:37 +00:00
|
|
|
if not index: return []
|
|
|
|
|
2020-08-22 00:27:20 +00:00
|
|
|
self.log('first index =',index)
|
|
|
|
index = json.loads(index)
|
|
|
|
self.log('got index?',index,type(index))
|
2020-08-21 13:12:13 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
if index is None: return []
|
2020-08-20 18:26:33 +00:00
|
|
|
if type(index)!=list: index=[index]
|
2020-08-21 21:15:20 +00:00
|
|
|
|
2020-08-20 18:26:33 +00:00
|
|
|
index = [x for x in index if x is not None]
|
2020-08-21 07:27:27 +00:00
|
|
|
|
|
|
|
## get full json
|
2020-08-22 00:27:20 +00:00
|
|
|
x = await self.get(['/post/'+x for x in index])
|
|
|
|
return [y for y in x if y is not None]
|
2020-08-21 07:27:27 +00:00
|
|
|
|
2020-08-17 13:33:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
## func
|
|
|
|
|
|
|
|
def bytes_from_file(filename,chunksize=8192):
|
|
|
|
with open(filename, 'rb') as f:
|
|
|
|
while True:
|
|
|
|
piece = f.read(chunksize)
|
|
|
|
if not piece:
|
|
|
|
break
|
|
|
|
yield piece
|
2020-08-17 13:33:26 +00:00
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
def get_random_id():
|
|
|
|
import uuid
|
|
|
|
return uuid.uuid4().hex
|
|
|
|
|
2020-08-17 13:33:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-17 20:40:48 +00:00
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
def test_api():
|
2020-08-20 15:48:08 +00:00
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
# api.set(['a','b','c'],[1,2,3])
|
2020-08-20 15:48:08 +00:00
|
|
|
async def run():
|
2020-08-20 16:31:17 +00:00
|
|
|
api = Api()
|
2020-08-20 15:48:08 +00:00
|
|
|
# await api.connect()
|
|
|
|
|
|
|
|
#await api.set_json('whattttt',{'aaaaa':12222})
|
|
|
|
#await api.set_json('whattttt',[111])
|
|
|
|
#await api.set_json('whattttt',[111])
|
|
|
|
|
|
|
|
#val = await api.get_json('whattttt')
|
|
|
|
|
2020-08-20 16:31:17 +00:00
|
|
|
server = await _getdb(api)
|
2020-08-20 15:48:08 +00:00
|
|
|
await server.set('a',1)
|
2020-08-20 16:31:17 +00:00
|
|
|
print(await server.get('a'))
|
|
|
|
await asyncio.sleep(5)
|
2020-08-20 15:48:08 +00:00
|
|
|
await server.set('a',2)
|
2020-08-20 16:31:17 +00:00
|
|
|
|
|
|
|
print(await server.get('a'))
|
|
|
|
await asyncio.sleep(5)
|
|
|
|
|
2020-08-20 15:48:08 +00:00
|
|
|
await server.set('a',str([2,3,4,5]))
|
2020-08-20 16:31:17 +00:00
|
|
|
print(await server.get('a'))
|
|
|
|
await asyncio.sleep(5)
|
2020-08-20 15:48:08 +00:00
|
|
|
|
|
|
|
val = await server.get('a')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(f'VAL = {val}')
|
|
|
|
return val
|
|
|
|
|
|
|
|
asyncio.run(run())
|
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
|
|
|
|
def test_basic():
|
|
|
|
import asyncio
|
|
|
|
from kademlia.network import Server
|
2020-08-19 12:06:44 +00:00
|
|
|
|
2020-08-19 12:11:48 +00:00
|
|
|
#api = Api()
|
2020-08-19 12:06:44 +00:00
|
|
|
|
|
|
|
# not working!
|
2020-08-19 12:11:48 +00:00
|
|
|
#api.set_json('my key',{'a':'value'})
|
2020-08-19 12:06:44 +00:00
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
async def run():
|
|
|
|
# Create a node and start listening on port 5678
|
|
|
|
node = Server()
|
|
|
|
await node.listen(5678)
|
|
|
|
|
|
|
|
# Bootstrap the node by connecting to other known nodes, in this case
|
|
|
|
# replace 123.123.123.123 with the IP of another node and optionally
|
|
|
|
# give as many ip/port combos as you can for other nodes.
|
|
|
|
await node.bootstrap(NODES_PRIME)
|
|
|
|
|
|
|
|
# set a value for the key "my-key" on the network
|
|
|
|
await node.set("my-key", "my awesome value")
|
2020-08-20 15:48:08 +00:00
|
|
|
await node.set("my-key", "my awesome value2")
|
|
|
|
await node.set("my-key", "my awesome value3")
|
2020-08-19 13:01:37 +00:00
|
|
|
|
2020-08-20 17:10:05 +00:00
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
# get the value associated with "my-key" from the network
|
|
|
|
result = await node.get("my-key")
|
|
|
|
|
|
|
|
print(result)
|
|
|
|
return result
|
|
|
|
|
|
|
|
res = asyncio.run(run())
|
|
|
|
print('res = ',res)
|
|
|
|
# res = asyncio.run(node.set(key,value))
|
|
|
|
# print(res)
|
|
|
|
|
|
|
|
def test_provided_eg():
|
|
|
|
import asyncio
|
|
|
|
from kademlia.network import Server
|
|
|
|
|
|
|
|
async def run():
|
|
|
|
# Create a node and start listening on port 5678
|
|
|
|
node = Server()
|
|
|
|
await node.listen(5678)
|
|
|
|
|
|
|
|
# Bootstrap the node by connecting to other known nodes, in this case
|
|
|
|
# replace 123.123.123.123 with the IP of another node and optionally
|
|
|
|
# give as many ip/port combos as you can for other nodes.
|
|
|
|
await node.bootstrap(NODES_PRIME)
|
|
|
|
|
|
|
|
# set a value for the key "my-key" on the network
|
|
|
|
await node.set("my-key", "my awesome value")
|
|
|
|
|
|
|
|
# get the value associated with "my-key" from the network
|
|
|
|
result = await node.get("my-key")
|
|
|
|
|
|
|
|
print(result)
|
|
|
|
|
|
|
|
asyncio.run(run())
|
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-21 16:12:40 +00:00
|
|
|
async def lonely_selfless_node():
|
|
|
|
from api import Api,PORT_LISTEN
|
|
|
|
API = Api()
|
|
|
|
return await API.connect_forever(8467)
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
def boot_lonely_selfless_node(port=8467):
|
2020-08-21 16:12:40 +00:00
|
|
|
API = Api()
|
|
|
|
asyncio.run(API.connect_forever())
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
|
2020-08-21 16:12:40 +00:00
|
|
|
def init_entities(usernames = ['earth']):
|
2020-08-21 15:22:30 +00:00
|
|
|
## make global entity called earth
|
|
|
|
|
2020-08-21 16:12:40 +00:00
|
|
|
#loop=asyncio.new_event_loop()
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-21 16:12:40 +00:00
|
|
|
async def register(username):
|
|
|
|
API = Api()
|
|
|
|
#await API.connect_forever()
|
2020-08-21 16:30:28 +00:00
|
|
|
#await API.register(username)
|
|
|
|
print(API.keys)
|
2020-08-21 15:46:33 +00:00
|
|
|
print('done')
|
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-21 16:12:40 +00:00
|
|
|
for un in usernames:
|
|
|
|
asyncio.run(register(un))
|
|
|
|
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-22 00:27:20 +00:00
|
|
|
def split_binary(data, sep=BSEP):
|
|
|
|
seplen = len(BSEP)
|
|
|
|
res=[]
|
|
|
|
stack=None
|
|
|
|
print('!!',data[:4],seplen,sep)
|
2020-08-21 15:22:30 +00:00
|
|
|
|
2020-08-22 00:27:20 +00:00
|
|
|
cutoffs=[]
|
|
|
|
for i in range(0, len(data)):
|
|
|
|
seg=data[i:i+seplen]
|
|
|
|
print(i,seg,sep,stack)
|
|
|
|
if seg==sep:
|
|
|
|
# split_piece = data[:i+seplen]
|
|
|
|
print('!')
|
|
|
|
cutoff_lasttime = cutoffs[-1][-1] if cutoffs and cutoffs else 0
|
|
|
|
cutoff = (cutoff_lasttime-seplen, i)
|
|
|
|
print(cutoff)
|
|
|
|
cutoffs.append(cutoff)
|
|
|
|
stack = data[cutoff[0] if cutoff[0]>0 else 0: cutoff[1]]
|
|
|
|
print(stack)
|
|
|
|
res += [stack]
|
|
|
|
stack = None
|
|
|
|
|
|
|
|
cutoff_lasttime = cutoffs[-1][-1] if cutoffs and cutoffs else 0
|
|
|
|
print(cutoff_lasttime)
|
|
|
|
stack = data[cutoff_lasttime+seplen :]
|
|
|
|
res+=[stack]
|
|
|
|
print('RES:',res)
|
|
|
|
return res
|
2020-08-21 15:22:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-19 12:06:44 +00:00
|
|
|
if __name__=='__main__':
|
2020-08-22 00:27:20 +00:00
|
|
|
#init_entities()
|
|
|
|
|
|
|
|
res = split_binary(b'eeeehey||||whatsueep',b'||||')
|
|
|
|
print(res)
|