Implemented paper message handling
This commit is contained in:
parent
540aa1a496
commit
edbb887d81
3 changed files with 78 additions and 8 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
|
import base64
|
||||||
import atexit
|
import atexit
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
@ -85,6 +86,7 @@ class LXMRouter:
|
||||||
self.propagation_transfer_last_result = None
|
self.propagation_transfer_last_result = None
|
||||||
self.propagation_transfer_max_messages = None
|
self.propagation_transfer_max_messages = None
|
||||||
self.locally_delivered_transient_ids = {}
|
self.locally_delivered_transient_ids = {}
|
||||||
|
self.locally_processed_transient_ids = {}
|
||||||
|
|
||||||
if identity == None:
|
if identity == None:
|
||||||
identity = RNS.Identity()
|
identity = RNS.Identity()
|
||||||
|
|
@ -105,7 +107,6 @@ class LXMRouter:
|
||||||
|
|
||||||
self.peers = {}
|
self.peers = {}
|
||||||
self.propagation_entries = {}
|
self.propagation_entries = {}
|
||||||
self.propagated_ids = {}
|
|
||||||
|
|
||||||
RNS.Transport.register_announce_handler(LXMFDeliveryAnnounceHandler(self))
|
RNS.Transport.register_announce_handler(LXMFDeliveryAnnounceHandler(self))
|
||||||
RNS.Transport.register_announce_handler(LXMFPropagationAnnounceHandler(self))
|
RNS.Transport.register_announce_handler(LXMFPropagationAnnounceHandler(self))
|
||||||
|
|
@ -118,7 +119,14 @@ class LXMRouter:
|
||||||
data = locally_delivered_file.read()
|
data = locally_delivered_file.read()
|
||||||
self.locally_delivered_transient_ids = msgpack.unpackb(data)
|
self.locally_delivered_transient_ids = msgpack.unpackb(data)
|
||||||
locally_delivered_file.close()
|
locally_delivered_file.close()
|
||||||
self.clean_transient_id_cache()
|
|
||||||
|
if os.path.isfile(self.storagepath+"/locally_processed"):
|
||||||
|
locally_processed_file = open(self.storagepath+"/locally_processed", "rb")
|
||||||
|
data = locally_processed_file.read()
|
||||||
|
self.locally_processed_transient_ids = msgpack.unpackb(data)
|
||||||
|
locally_processed_file.close()
|
||||||
|
|
||||||
|
self.clean_transient_id_caches()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not load locally delivered message ID cache from storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not load locally delivered message ID cache from storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
@ -424,7 +432,7 @@ class LXMRouter:
|
||||||
self.clean_links()
|
self.clean_links()
|
||||||
|
|
||||||
if self.processing_count % LXMRouter.JOB_TRANSIENT_INTERVAL == 0:
|
if self.processing_count % LXMRouter.JOB_TRANSIENT_INTERVAL == 0:
|
||||||
self.clean_transient_id_cache()
|
self.clean_transient_id_caches()
|
||||||
|
|
||||||
if self.processing_count % LXMRouter.JOB_STORE_INTERVAL == 0:
|
if self.processing_count % LXMRouter.JOB_STORE_INTERVAL == 0:
|
||||||
self.clean_message_store()
|
self.clean_message_store()
|
||||||
|
|
@ -458,7 +466,7 @@ class LXMRouter:
|
||||||
self.acknowledge_sync_completion()
|
self.acknowledge_sync_completion()
|
||||||
RNS.log("Cleaned outbound propagation link", RNS.LOG_DEBUG)
|
RNS.log("Cleaned outbound propagation link", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def clean_transient_id_cache(self):
|
def clean_transient_id_caches(self):
|
||||||
now = time.time()
|
now = time.time()
|
||||||
removed_entries = []
|
removed_entries = []
|
||||||
for transient_id in self.locally_delivered_transient_ids:
|
for transient_id in self.locally_delivered_transient_ids:
|
||||||
|
|
@ -470,6 +478,16 @@ class LXMRouter:
|
||||||
self.locally_delivered_transient_ids.pop(transient_id)
|
self.locally_delivered_transient_ids.pop(transient_id)
|
||||||
RNS.log("Cleaned "+RNS.prettyhexrep(transient_id)+" from local delivery cache", RNS.LOG_DEBUG)
|
RNS.log("Cleaned "+RNS.prettyhexrep(transient_id)+" from local delivery cache", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
|
removed_entries = []
|
||||||
|
for transient_id in self.locally_processed_transient_ids:
|
||||||
|
timestamp = self.locally_processed_transient_ids[transient_id]
|
||||||
|
if now > timestamp+LXMRouter.MESSAGE_EXPIRY*1.25:
|
||||||
|
removed_entries.append(transient_id)
|
||||||
|
|
||||||
|
for transient_id in removed_entries:
|
||||||
|
self.locally_processed_transient_ids.pop(transient_id)
|
||||||
|
RNS.log("Cleaned "+RNS.prettyhexrep(transient_id)+" from locally processed cache", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def clean_message_store(self):
|
def clean_message_store(self):
|
||||||
# Check and remove expired messages
|
# Check and remove expired messages
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
|
@ -571,6 +589,18 @@ class LXMRouter:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not save locally delivered message ID cache to storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not save locally delivered message ID cache to storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
def save_locally_processed_transient_ids(self):
|
||||||
|
try:
|
||||||
|
if not os.path.isdir(self.storagepath):
|
||||||
|
os.makedirs(self.storagepath)
|
||||||
|
|
||||||
|
locally_processed_file = open(self.storagepath+"/locally_processed", "wb")
|
||||||
|
locally_processed_file.write(msgpack.packb(self.locally_processed_transient_ids))
|
||||||
|
locally_processed_file.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Could not save locally processed message ID cache to storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
def exit_handler(self):
|
def exit_handler(self):
|
||||||
if self.propagation_node:
|
if self.propagation_node:
|
||||||
try:
|
try:
|
||||||
|
|
@ -589,6 +619,7 @@ class LXMRouter:
|
||||||
RNS.log("Could not save propagation node peers to storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not save propagation node peers to storage. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
self.save_locally_delivered_transient_ids()
|
self.save_locally_delivered_transient_ids()
|
||||||
|
self.save_locally_processed_transient_ids()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<LXMRouter "+RNS.hexrep(self.identity.hash, delimit=False)+">"
|
return "<LXMRouter "+RNS.hexrep(self.identity.hash, delimit=False)+">"
|
||||||
|
|
@ -1012,15 +1043,18 @@ class LXMRouter:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Error while unpacking received propagation resource", RNS.LOG_DEBUG)
|
RNS.log("Error while unpacking received propagation resource", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
def lxmf_propagation(self, lxmf_data):
|
def lxmf_propagation(self, lxmf_data, signal_local_delivery=None, signal_duplicate=None):
|
||||||
try:
|
try:
|
||||||
if len(lxmf_data) >= LXMessage.LXMF_OVERHEAD:
|
if len(lxmf_data) >= LXMessage.LXMF_OVERHEAD:
|
||||||
transient_id = RNS.Identity.full_hash(lxmf_data)
|
transient_id = RNS.Identity.full_hash(lxmf_data)
|
||||||
if not transient_id in self.propagation_entries and not transient_id in self.propagated_ids:
|
|
||||||
|
if not transient_id in self.propagation_entries and not transient_id in self.locally_processed_transient_ids:
|
||||||
received = time.time()
|
received = time.time()
|
||||||
propagation_entry = [transient_id, received, lxmf_data]
|
propagation_entry = [transient_id, received, lxmf_data]
|
||||||
destination_hash = lxmf_data[:LXMessage.DESTINATION_LENGTH]
|
destination_hash = lxmf_data[:LXMessage.DESTINATION_LENGTH]
|
||||||
|
|
||||||
|
self.locally_processed_transient_ids[transient_id] = received
|
||||||
|
|
||||||
if destination_hash in self.delivery_destinations:
|
if destination_hash in self.delivery_destinations:
|
||||||
delivery_destination = self.delivery_destinations[destination_hash]
|
delivery_destination = self.delivery_destinations[destination_hash]
|
||||||
encrypted_lxmf_data = lxmf_data[LXMessage.DESTINATION_LENGTH:]
|
encrypted_lxmf_data = lxmf_data[LXMessage.DESTINATION_LENGTH:]
|
||||||
|
|
@ -1029,6 +1063,9 @@ class LXMRouter:
|
||||||
self.lxmf_delivery(delivery_data, delivery_destination.type)
|
self.lxmf_delivery(delivery_data, delivery_destination.type)
|
||||||
self.locally_delivered_transient_ids[transient_id] = time.time()
|
self.locally_delivered_transient_ids[transient_id] = time.time()
|
||||||
|
|
||||||
|
if signal_local_delivery != None:
|
||||||
|
return signal_local_delivery
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if self.propagation_node:
|
if self.propagation_node:
|
||||||
file_path = self.messagepath+"/"+RNS.hexrep(transient_id, delimit=False)+"_"+str(received)
|
file_path = self.messagepath+"/"+RNS.hexrep(transient_id, delimit=False)+"_"+str(received)
|
||||||
|
|
@ -1043,8 +1080,19 @@ class LXMRouter:
|
||||||
peer = self.peers[peer_id]
|
peer = self.peers[peer_id]
|
||||||
peer.handle_message(transient_id)
|
peer.handle_message(transient_id)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# TODO: Add message to sneakernet queues when implemented
|
||||||
|
RNS.log("Received propagated LXMF message "+RNS.prettyhexrep(transient_id)+", but this instance is not hosting a propagation node, discarding message.", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
if signal_duplicate != None:
|
||||||
|
return signal_duplicate
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -1052,6 +1100,28 @@ class LXMRouter:
|
||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def ingest_lxm_url(self, url, signal_local_delivery=None, signal_duplicate=None):
|
||||||
|
try:
|
||||||
|
if not url.lower().startswith("lxm://"):
|
||||||
|
RNS.log("Cannot ingest LXM, invalid URL provided.", RNS.LOG_ERROR)
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
lxmf_data = base64.urlsafe_b64decode(url.replace(LXMessage.URL_PROTO_SPECIFIER+"://", "").replace("/", "")+"==")
|
||||||
|
transient_id = RNS.Identity.full_hash(lxmf_data)
|
||||||
|
|
||||||
|
router_propagation_result = self.lxmf_propagation(lxmf_data, signal_local_delivery=signal_local_delivery, signal_duplicate=signal_duplicate)
|
||||||
|
if router_propagation_result != False:
|
||||||
|
RNS.log("LXM with transient ID "+RNS.prettyhexrep(transient_id)+" was ingested.", RNS.LOG_DEBUG)
|
||||||
|
return router_propagation_result
|
||||||
|
else:
|
||||||
|
RNS.log("No valid LXM could be ingested from the provided URL", RNS.LOG_DEBUG)
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Error while decoding URL-encoded LXMF message. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
return False
|
||||||
|
|
||||||
def fail_message(self, lxmessage):
|
def fail_message(self, lxmessage):
|
||||||
RNS.log(str(lxmessage)+" failed to send", RNS.LOG_DEBUG)
|
RNS.log(str(lxmessage)+" failed to send", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ class LXMessage:
|
||||||
paper_content_limit = LXMessage.PAPER_MDU
|
paper_content_limit = LXMessage.PAPER_MDU
|
||||||
|
|
||||||
encrypted_data = self.__destination.encrypt(self.packed[LXMessage.DESTINATION_LENGTH:])
|
encrypted_data = self.__destination.encrypt(self.packed[LXMessage.DESTINATION_LENGTH:])
|
||||||
self.paper_packed = msgpack.packb(self.packed[:LXMessage.DESTINATION_LENGTH]+encrypted_data)
|
self.paper_packed = self.packed[:LXMessage.DESTINATION_LENGTH]+encrypted_data
|
||||||
|
|
||||||
content_size = len(self.paper_packed)
|
content_size = len(self.paper_packed)
|
||||||
if content_size <= paper_content_limit:
|
if content_size <= paper_content_limit:
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.2.4"
|
__version__ = "0.2.5"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue