#!/bin/python import os import io import shutil import argparse import time import RNS # from io import BufferedReader # import io # import LXMF # class Fetcher: # # DEFAULT_PATH = "/page/index.mu" # DEFAULT_TIMEOUT = 10 # DEFAULT_CACHE_TIME = 12*60*60 # NO_PATH = 0x00 # PATH_REQUESTED = 0x01 # ESTABLISHING_LINK = 0x02 # LINK_TIMEOUT = 0x03 # LINK_ESTABLISHED = 0x04 # REQUESTING = 0x05 # REQUEST_SENT = 0x06 # REQUEST_FAILED = 0x07 # REQUEST_TIMEOUT = 0x08 # RECEIVING_RESPONSE = 0x09 # DISCONECTED = 0xFE # DONE = 0xFF # def retrieve_url(self, url, request_data = None): # self.previous_destination_hash = self.destination_hash # self.previous_path = self.path # destination_hash = None # path = None # components = url.split(":") # if len(components) == 1: # if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2: # try: # destination_hash = bytes.fromhex(components[0]) # except Exception as e: # raise ValueError("Malformed URL") # # path = Browser.DEFAULT_PATH # else: # raise ValueError("Malformed URL") # elif len(components) == 2: # if len(components[0]) == (RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2: # try: # destination_hash = bytes.fromhex(components[0]) # except Exception as e: # raise ValueError("Malformed URL") # path = components[1] # # if len(path) == 0: # # path = Browser.DEFAULT_PATH # else: # if len(components[0]) == 0: # if self.destination_hash != None: # destination_hash = self.destination_hash # path = components[1] # if len(path) == 0: # path = Browser.DEFAULT_PATH # else: # raise ValueError("Malformed URL") # else: # raise ValueError("Malformed URL") # else: # raise ValueError("Malformed URL") # if destination_hash != None and path != None: # if path.startswith("/file/"): # if destination_hash != self.loopback: # if destination_hash == self.destination_hash: # self.download_file(destination_hash, path) # else: # RNS.log("Cannot request file download from a node that is not currently connected.", RNS.LOG_ERROR) # RNS.log("The requested URL was: "+str(url), RNS.LOG_ERROR) # else: # self.download_local_file(path) # else: # self.set_destination_hash(destination_hash) # self.set_path(path) # self.set_request_data(request_data) # self.load_page() # def download_file(self, destination_hash, path): # if self.link == None or self.link.destination.hash != self.destination_hash: # if not RNS.Transport.has_path(self.destination_hash): # self.status = Browser.NO_PATH # self.update_display() # RNS.Transport.request_path(self.destination_hash) # self.status = Browser.PATH_REQUESTED # self.update_display() # pr_time = time.time()+RNS.Transport.first_hop_timeout(self.destination_hash) # while not RNS.Transport.has_path(self.destination_hash): # now = time.time() # if now > pr_time+self.timeout: # self.request_timeout() # return # time.sleep(0.25) # self.status = Browser.ESTABLISHING_LINK # self.update_display() # identity = RNS.Identity.recall(self.destination_hash) # destination = RNS.Destination( # identity, # RNS.Destination.OUT, # RNS.Destination.SINGLE, # self.app_name, # self.aspects # ) # self.link = RNS.Link(destination, established_callback = self.link_established, closed_callback = self.link_closed) # while self.status == Browser.ESTABLISHING_LINK: # time.sleep(0.1) # if self.status != Browser.LINK_ESTABLISHED: # return # self.update_display() # if self.link != None and self.link.destination.hash == self.destination_hash: # # Send the request # self.status = Browser.REQUESTING # self.response_progress = 0 # self.response_speed = None # self.progress_updated_at = None # self.previous_progress = 0 # self.response_size = None # self.response_transfer_size = None # self.saved_file_name = None # self.update_display() # receipt = self.link.request( # path, # data = None, # response_callback = self.file_received, # failed_callback = self.request_failed, # progress_callback = self.response_progressed # ) # if receipt: # self.last_request_receipt = receipt # self.last_request_id = receipt.request_id # self.status = Browser.REQUEST_SENT # self.update_display() # else: # self.link.teardown() # global server link server_link = None file = None # outdir = None def link_established(link): global server_link server_link = link print("link established") def link_closed(): print("link closed") def file_received(request_receipt): global file file = True global outdir try: if type(request_receipt.response) == io.BufferedReader: if request_receipt.metadata != None: file_name = os.path.basename(request_receipt.metadata["name"].decode("utf-8")) file_handle = request_receipt.response file_destination = outdir+"/"+file_name counter = 0 while os.path.isfile(file_destination): counter += 1 file_destination = outdir+"/"+file_name+"."+str(counter) shutil.move(file_handle.name, file_destination) else: file_name = request_receipt.response[0] file_data = request_receipt.response[1] file_destination_name = os.path.basename(file_name) file_destination = "."+"/"+file_destination_name counter = 0 while os.path.isfile(file_destination): counter += 1 file_destination = outdir+"/"+file_destination_name+"."+str(counter) fh = open(file_destination, "wb") fh.write(file_data) fh.close() # self.saved_file_name = file_destination.replace(self.app.downloads_path+"/", "", 1) # self.status = Browser.DONE # self.response_progress = 0 # self.response_speed = None # self.progress_updated_at = None # self.previous_progress = 0 # self.update_display() except Exception as e: RNS.log("An error occurred while handling file response. The contained exception was: "+str(e), RNS.LOG_ERROR) print("file received") def request_failed(req_receipt): print("request failed") # print(str(e)) def response_progressed(req_receipt): # print("response progressed") return parser = argparse.ArgumentParser(description="request a resource from a target node") parser.add_argument("URL", help="the LXMF URL of the resource to be fetched") parser.add_argument("OUTDIR", help="the output directory to place the file") args = parser.parse_args() arglist = args.URL.split(":") dest_hash = arglist[0] resource_path = arglist[1] print(dest_hash) print(resource_path) outdir = args.OUTDIR r = RNS.Reticulum() RNS.loglevel = RNS.LOG_DEBUG # router = LXMF.LXMRouter(storagepath="./tmp2") # router.register_delivery_callback(delivery_callback) ident = RNS.Identity() dest_hash = bytes.fromhex(dest_hash) dest_ident = RNS.Identity.recall(dest_hash) # need these to connect to a nomadnetwork node app_name = "nomadnetwork" aspects = "node" destination = RNS.Destination( dest_ident, RNS.Destination.OUT, RNS.Destination.SINGLE, app_name, aspects ) # with open(args.GCODE_FILE, "rb") as f: # contents = f.read() # content_size = len(contents) # Look up the path to the destination. print("looking up path to destination...") if not RNS.Transport.has_path(dest_hash): RNS.Transport.request_path(dest_hash) while not RNS.Transport.has_path(dest_hash): time.sleep(0.1) # establish link link = RNS.Link(destination, established_callback = link_established, closed_callback = link_closed) while not server_link: time.sleep(0.1) receipt = link.request( resource_path, data = None, response_callback = file_received, failed_callback = request_failed, progress_callback = response_progressed ) while not file: time.sleep(0.1) # if receipt: # last_request_receipt = receipt # last_request_id = receipt.request_id # # status = Browser.REQUEST_SENT # # update_display() # else: # link.teardown() # print(ident)