Implemented request and response API
This commit is contained in:
		
							parent
							
								
									69930e5652
								
							
						
					
					
						commit
						1dc6655017
					
				
							
								
								
									
										283
									
								
								Examples/Request.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								Examples/Request.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,283 @@ | ||||
| ########################################################## | ||||
| # This RNS example demonstrates how to set perform       # | ||||
| # requests and receive responses over a link.            # | ||||
| ########################################################## | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import time | ||||
| import random | ||||
| import argparse | ||||
| import RNS | ||||
| 
 | ||||
| # Let's define an app name. We'll use this for all | ||||
| # destinations we create. Since this echo example | ||||
| # is part of a range of example utilities, we'll put | ||||
| # them all within the app namespace "example_utilities" | ||||
| APP_NAME = "example_utilities" | ||||
| 
 | ||||
| ########################################################## | ||||
| #### Server Part ######################################### | ||||
| ########################################################## | ||||
| 
 | ||||
| # A reference to the latest client link that connected | ||||
| latest_client_link = None | ||||
| 
 | ||||
| def random_text_generator(path, data, request_id, remote_identity_hash, requested_at): | ||||
|     RNS.log("Generating response to request "+RNS.prettyhexrep(request_id)) | ||||
|     texts = ["They looked up", "On each full moon", "Becky was upset", "I’ll stay away from it", "The pet shop stocks everything"] | ||||
|     return texts[random.randint(0, len(texts)-1)] | ||||
| 
 | ||||
| # This initialisation is executed when the users chooses | ||||
| # to run as a server | ||||
| def server(configpath): | ||||
|     # We must first initialise Reticulum | ||||
|     reticulum = RNS.Reticulum(configpath) | ||||
|      | ||||
|     # Randomly create a new identity for our link example | ||||
|     server_identity = RNS.Identity() | ||||
| 
 | ||||
|     # We create a destination that clients can connect to. We | ||||
|     # want clients to create links to this destination, so we | ||||
|     # need to create a "single" destination type. | ||||
|     server_destination = RNS.Destination( | ||||
|         server_identity, | ||||
|         RNS.Destination.IN, | ||||
|         RNS.Destination.SINGLE, | ||||
|         APP_NAME, | ||||
|         "requestexample" | ||||
|     ) | ||||
| 
 | ||||
|     # We configure a function that will get called every time | ||||
|     # a new client creates a link to this destination. | ||||
|     server_destination.set_link_established_callback(client_connected) | ||||
| 
 | ||||
|     # We register a request handler for handling incoming | ||||
|     # requests over any established links. | ||||
|     server_destination.register_request_handler( | ||||
|         "/random/text", | ||||
|         response_generator = random_text_generator, | ||||
|         allow = RNS.Destination.ALLOW_ALL | ||||
|     ) | ||||
| 
 | ||||
|     # Everything's ready! | ||||
|     # Let's Wait for client requests or user input | ||||
|     server_loop(server_destination) | ||||
| 
 | ||||
| def server_loop(destination): | ||||
|     # Let the user know that everything is ready | ||||
|     RNS.log( | ||||
|         "Request example "+ | ||||
|         RNS.prettyhexrep(destination.hash)+ | ||||
|         " running, waiting for a connection." | ||||
|     ) | ||||
| 
 | ||||
|     RNS.log("Hit enter to manually send an announce (Ctrl-C to quit)") | ||||
| 
 | ||||
|     # We enter a loop that runs until the users exits. | ||||
|     # If the user hits enter, we will announce our server | ||||
|     # destination on the network, which will let clients | ||||
|     # know how to create messages directed towards it. | ||||
|     while True: | ||||
|         entered = input() | ||||
|         destination.announce() | ||||
|         RNS.log("Sent announce from "+RNS.prettyhexrep(destination.hash)) | ||||
| 
 | ||||
| # When a client establishes a link to our server | ||||
| # destination, this function will be called with | ||||
| # a reference to the link. | ||||
| def client_connected(link): | ||||
|     global latest_client_link | ||||
| 
 | ||||
|     RNS.log("Client connected") | ||||
|     link.set_link_closed_callback(client_disconnected) | ||||
|     latest_client_link = link | ||||
| 
 | ||||
| def client_disconnected(link): | ||||
|     RNS.log("Client disconnected") | ||||
| 
 | ||||
| 
 | ||||
| ########################################################## | ||||
| #### Client Part ######################################### | ||||
| ########################################################## | ||||
| 
 | ||||
| # A reference to the server link | ||||
| server_link = None | ||||
| 
 | ||||
| # This initialisation is executed when the users chooses | ||||
| # to run as a client | ||||
| def client(destination_hexhash, configpath): | ||||
|     # We need a binary representation of the destination | ||||
|     # hash that was entered on the command line | ||||
|     try: | ||||
|         if len(destination_hexhash) != 20: | ||||
|             raise ValueError("Destination length is invalid, must be 20 hexadecimal characters (10 bytes)") | ||||
|         destination_hash = bytes.fromhex(destination_hexhash) | ||||
|     except: | ||||
|         RNS.log("Invalid destination entered. Check your input!\n") | ||||
|         exit() | ||||
| 
 | ||||
|     # We must first initialise Reticulum | ||||
|     reticulum = RNS.Reticulum(configpath) | ||||
| 
 | ||||
|     # Check if we know a path to the destination | ||||
|     if not RNS.Transport.has_path(destination_hash): | ||||
|         RNS.log("Destination is not yet known. Requesting path and waiting for announce to arrive...") | ||||
|         RNS.Transport.request_path(destination_hash) | ||||
|         while not RNS.Transport.has_path(destination_hash): | ||||
|             time.sleep(0.1) | ||||
| 
 | ||||
|     # Recall the server identity | ||||
|     server_identity = RNS.Identity.recall(destination_hash) | ||||
| 
 | ||||
|     # Inform the user that we'll begin connecting | ||||
|     RNS.log("Establishing link with server...") | ||||
| 
 | ||||
|     # When the server identity is known, we set | ||||
|     # up a destination | ||||
|     server_destination = RNS.Destination( | ||||
|         server_identity, | ||||
|         RNS.Destination.OUT, | ||||
|         RNS.Destination.SINGLE, | ||||
|         APP_NAME, | ||||
|         "requestexample" | ||||
|     ) | ||||
| 
 | ||||
|     # And create a link | ||||
|     link = RNS.Link(server_destination) | ||||
| 
 | ||||
|     # We'll set up functions to inform the | ||||
|     # user when the link is established or closed | ||||
|     link.set_link_established_callback(link_established) | ||||
|     link.set_link_closed_callback(link_closed) | ||||
| 
 | ||||
|     # Everything is set up, so let's enter a loop | ||||
|     # for the user to interact with the example | ||||
|     client_loop() | ||||
| 
 | ||||
| def client_loop(): | ||||
|     global server_link | ||||
| 
 | ||||
|     # Wait for the link to become active | ||||
|     while not server_link: | ||||
|         time.sleep(0.1) | ||||
| 
 | ||||
|     should_quit = False | ||||
|     while not should_quit: | ||||
|         try: | ||||
|             print("> ", end=" ") | ||||
|             text = input() | ||||
| 
 | ||||
|             # Check if we should quit the example | ||||
|             if text == "quit" or text == "q" or text == "exit": | ||||
|                 should_quit = True | ||||
|                 server_link.teardown() | ||||
| 
 | ||||
|             else: | ||||
|                 server_link.request( | ||||
|                     "/random/text", | ||||
|                     data = None, | ||||
|                     response_callback = got_response, | ||||
|                     failed_callback = request_failed | ||||
|                 ) | ||||
| 
 | ||||
| 
 | ||||
|         except Exception as e: | ||||
|             RNS.log("Error while sending request over the link: "+str(e)) | ||||
|             should_quit = True | ||||
|             server_link.teardown() | ||||
| 
 | ||||
| def got_response(request_receipt): | ||||
|     request_id = request_receipt.request_id | ||||
|     response = request_receipt.response | ||||
| 
 | ||||
|     RNS.log("Got response for request "+RNS.prettyhexrep(request_id)+": "+str(response)) | ||||
| 
 | ||||
| def request_received(request_receipt): | ||||
|     RNS.log("The request "+RNS.prettyhexrep(request_receipt.request_id)+" was received by the remote peer.") | ||||
| 
 | ||||
| def request_failed(request_receipt): | ||||
|     RNS.log("The request "+RNS.prettyhexrep(request_receipt.request_id)+" failed.") | ||||
| 
 | ||||
| 
 | ||||
| # This function is called when a link | ||||
| # has been established with the server | ||||
| def link_established(link): | ||||
|     # We store a reference to the link | ||||
|     # instance for later use | ||||
|     global server_link | ||||
|     server_link = link | ||||
| 
 | ||||
|     # Inform the user that the server is | ||||
|     # connected | ||||
|     RNS.log("Link established with server, hit enter to perform a request, or type in \"quit\" to quit") | ||||
| 
 | ||||
| # When a link is closed, we'll inform the | ||||
| # user, and exit the program | ||||
| def link_closed(link): | ||||
|     if link.teardown_reason == RNS.Link.TIMEOUT: | ||||
|         RNS.log("The link timed out, exiting now") | ||||
|     elif link.teardown_reason == RNS.Link.DESTINATION_CLOSED: | ||||
|         RNS.log("The link was closed by the server, exiting now") | ||||
|     else: | ||||
|         RNS.log("Link closed, exiting now") | ||||
|      | ||||
|     RNS.Reticulum.exit_handler() | ||||
|     time.sleep(1.5) | ||||
|     os._exit(0) | ||||
| 
 | ||||
| 
 | ||||
| ########################################################## | ||||
| #### Program Startup ##################################### | ||||
| ########################################################## | ||||
| 
 | ||||
| # This part of the program runs at startup, | ||||
| # and parses input of from the user, and then | ||||
| # starts up the desired program mode. | ||||
| if __name__ == "__main__": | ||||
|     try: | ||||
|         parser = argparse.ArgumentParser(description="Simple request/response example") | ||||
| 
 | ||||
|         parser.add_argument( | ||||
|             "-s", | ||||
|             "--server", | ||||
|             action="store_true", | ||||
|             help="wait for incoming requests from clients" | ||||
|         ) | ||||
| 
 | ||||
|         parser.add_argument( | ||||
|             "--config", | ||||
|             action="store", | ||||
|             default=None, | ||||
|             help="path to alternative Reticulum config directory", | ||||
|             type=str | ||||
|         ) | ||||
| 
 | ||||
|         parser.add_argument( | ||||
|             "destination", | ||||
|             nargs="?", | ||||
|             default=None, | ||||
|             help="hexadecimal hash of the server destination", | ||||
|             type=str | ||||
|         ) | ||||
| 
 | ||||
|         args = parser.parse_args() | ||||
| 
 | ||||
|         if args.config: | ||||
|             configarg = args.config | ||||
|         else: | ||||
|             configarg = None | ||||
| 
 | ||||
|         if args.server: | ||||
|             server(configarg) | ||||
|         else: | ||||
|             if (args.destination == None): | ||||
|                 print("") | ||||
|                 parser.print_help() | ||||
|                 print("") | ||||
|             else: | ||||
|                 client(args.destination, configarg) | ||||
| 
 | ||||
|     except KeyboardInterrupt: | ||||
|         print("") | ||||
|         exit() | ||||
| @ -40,6 +40,11 @@ class Destination: | ||||
|     PROVE_ALL  = 0x23 | ||||
|     proof_strategies = [PROVE_NONE, PROVE_APP, PROVE_ALL] | ||||
| 
 | ||||
|     ALLOW_NONE = 0x00 | ||||
|     ALLOW_ALL  = 0x01 | ||||
|     ALLOW_LIST = 0x02 | ||||
|     request_policies = [ALLOW_NONE, ALLOW_ALL, ALLOW_LIST] | ||||
| 
 | ||||
|     IN         = 0x11; | ||||
|     OUT        = 0x12; | ||||
|     directions = [IN, OUT] | ||||
| @ -97,6 +102,7 @@ class Destination: | ||||
|         if not type in Destination.types: raise ValueError("Unknown destination type") | ||||
|         if not direction in Destination.directions: raise ValueError("Unknown destination direction") | ||||
|         self.callbacks = Callbacks() | ||||
|         self.request_handlers = {} | ||||
|         self.type = type | ||||
|         self.direction = direction | ||||
|         self.proof_strategy = Destination.PROVE_NONE | ||||
| @ -208,6 +214,45 @@ class Destination: | ||||
|         else: | ||||
|             self.proof_strategy = proof_strategy | ||||
| 
 | ||||
| 
 | ||||
|     def register_request_handler(self, path, response_generator = None, allow = ALLOW_NONE, allowed_list = None): | ||||
|         """ | ||||
|         Registers a request handler. | ||||
| 
 | ||||
|         :param path: The path for the request handler to be registered. | ||||
|         :param response_generator: A function or method with the signature *response_generator(path, data, request_id, remote_identity_hash, requested_at)* to be called. Whatever this funcion returns will be sent as a response to the requester. If the function returns ``None``, no response will be sent. | ||||
|         :param allow: One of ``RNS.Destination.ALLOW_NONE``, ``RNS.Destination.ALLOW_ALL`` or ``RNS.Destination.ALLOW_LIST``. If ``RNS.Destination.ALLOW_LIST`` is set, the request handler will only respond to requests for identified peers in the supplied list. | ||||
|         :param allowed_list: A list of *bytes-like* :ref:`RNS.Identity<api-identity>` hashes. | ||||
|         :raises: ``ValueError`` if any of the supplied arguments are invalid. | ||||
|         """ | ||||
|         if path == None or path == "": | ||||
|             raise ValueError("Invalid path specified") | ||||
|         elif not callable(response_generator): | ||||
|             raise ValueError("Invalid response generator specified") | ||||
|         elif not allow in Destination.request_policies: | ||||
|             raise ValueError("Invalid request policy") | ||||
|         else: | ||||
|             path_hash = RNS.Identity.truncated_hash(path.encode("utf-8")) | ||||
|             request_handler = [path, response_generator, allow, allowed_list] | ||||
|             self.request_handlers[path_hash] = request_handler | ||||
| 
 | ||||
| 
 | ||||
|     def deregister_request_handler(self, path): | ||||
|         """ | ||||
|         Deregisters a request handler. | ||||
| 
 | ||||
|         :param path: The path for the request handler to be deregistered. | ||||
|         :returns: True if the handler was deregistered, otherwise False. | ||||
|         """ | ||||
|         path_hash = RNS.Identity.truncated_hash(path.encode("utf-8")) | ||||
|         if path_hash in self.request_handlers: | ||||
|             self.request_handlers.pop(path_hash) | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|     def receive(self, packet): | ||||
|         if packet.packet_type == RNS.Packet.LINKREQUEST: | ||||
|             plaintext = packet.data | ||||
|  | ||||
							
								
								
									
										141
									
								
								RNS/Link.py
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								RNS/Link.py
									
									
									
									
									
								
							| @ -110,6 +110,7 @@ class Link: | ||||
|         self.resource_strategy = Link.ACCEPT_NONE | ||||
|         self.outgoing_resources = [] | ||||
|         self.incoming_resources = [] | ||||
|         self.pending_requests   = [] | ||||
|         self.last_inbound = 0 | ||||
|         self.last_outbound = 0 | ||||
|         self.tx = 0 | ||||
| @ -265,6 +266,26 @@ class Link: | ||||
|             self.had_outbound() | ||||
| 
 | ||||
| 
 | ||||
|     def request(self, path, data = None, response_callback = None, failed_callback = None): | ||||
|         """ | ||||
|         Sends a request to the remote peer. | ||||
| 
 | ||||
|         :param path: The request path. | ||||
|         :param response_callback: A function or method with the signature *response_callback(request_receipt)* to be called when a response is received. See the :ref:`Request Example<example-request>` for more info. | ||||
|         :param failed_callback: A function or method with the signature *failed_callback(request_receipt)* to be called when a request fails. See the :ref:`Request Example<example-request>` for more info. | ||||
|         """ | ||||
|         request_path_hash = RNS.Identity.truncated_hash(path.encode("utf-8")) | ||||
|         unpacked_request  = [time.time(), request_path_hash, data] | ||||
|         packed_request    = umsgpack.packb(unpacked_request) | ||||
| 
 | ||||
|         if len(packed_request) <= Link.MDU: | ||||
|             request_packet   = RNS.Packet(self, packed_request, RNS.Packet.DATA, context = RNS.Packet.REQUEST) | ||||
|             return RequestReceipt(self, request_packet.send(), response_callback, failed_callback) | ||||
|         else: | ||||
|             # TODO: Implement sending requests as Resources | ||||
|             raise IOError("Request size of "+str(len(packed_request))+" exceeds MDU of "+str(Link.MDU)+" bytes") | ||||
| 
 | ||||
| 
 | ||||
|     def rtt_packet(self, packet): | ||||
|         try: | ||||
|             # TODO: This is crude, we should use the delta | ||||
| @ -467,6 +488,70 @@ class Link: | ||||
|                                 if self.callbacks.remote_identified != None: | ||||
|                                     self.callbacks.remote_identified(self.__remote_identity) | ||||
| 
 | ||||
|                     elif packet.context == RNS.Packet.REQUEST: | ||||
|                         try: | ||||
|                             request_id = packet.getTruncatedHash() | ||||
|                             packed_request = self.decrypt(packet.data) | ||||
|                             unpacked_request = umsgpack.unpackb(packed_request) | ||||
|                             requested_at = unpacked_request[0] | ||||
|                             path_hash    = unpacked_request[1] | ||||
|                             request_data = unpacked_request[2] | ||||
| 
 | ||||
|                             if path_hash in self.destination.request_handlers: | ||||
|                                 request_handler = self.destination.request_handlers[path_hash] | ||||
|                                 path               = request_handler[0] | ||||
|                                 response_generator = request_handler[1] | ||||
|                                 allow              = request_handler[2] | ||||
|                                 allowed_list       = request_handler[3] | ||||
| 
 | ||||
|                                 allowed = False | ||||
|                                 if not allow == RNS.Destination.ALLOW_NONE: | ||||
|                                     if allow == RNS.Destination.ALLOW_LIST: | ||||
|                                         if self.__remote_identity in allowed_list: | ||||
|                                             allowed = True | ||||
|                                     elif allow == RNS.Destination.ALLOW_ALL: | ||||
|                                         allowed = True | ||||
| 
 | ||||
|                                 if allowed: | ||||
|                                     response = response_generator(path, request_data, request_id, self.__remote_identity, requested_at) | ||||
|                                     if response != None: | ||||
|                                         packed_response = umsgpack.packb([request_id, True, response]) | ||||
| 
 | ||||
|                                         if len(packed_response) <= Link.MDU: | ||||
|                                             RNS.Packet(self, packed_response, RNS.Packet.DATA, context = RNS.Packet.RESPONSE).send() | ||||
|                                         else: | ||||
|                                             # TODO: Implement transfer as resource | ||||
|                                             packed_response = umsgpack.packb([request_id, False, None]) | ||||
|                                             raise Exception("Response transfer as resource not implemented") | ||||
| 
 | ||||
|                         except Exception as e: | ||||
|                             RNS.log("Error occurred while handling request. The contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|                     elif packet.context == RNS.Packet.RESPONSE: | ||||
|                         packed_response = self.decrypt(packet.data) | ||||
|                         unpacked_response = umsgpack.unpackb(packed_response) | ||||
|                         request_id = unpacked_response[0] | ||||
| 
 | ||||
|                         if unpacked_response[1] == True: | ||||
|                             remove = None | ||||
|                             for pending_request in self.pending_requests: | ||||
|                                 if pending_request.request_id == request_id: | ||||
|                                     response_data = unpacked_response[2] | ||||
|                                     remove = pending_request | ||||
|                                     try: | ||||
|                                         pending_request.response_received(response_data) | ||||
|                                     except Exception as e: | ||||
|                                         RNS.log("Error occurred while handling response. The contained exception was: "+str(e), RNS.LOG_ERROR) | ||||
| 
 | ||||
|                                     break | ||||
| 
 | ||||
|                             if remove != None: | ||||
|                                 self.pending_requests.remove(remove) | ||||
| 
 | ||||
|                         else: | ||||
|                             # TODO: Implement receiving responses as Resources | ||||
|                             raise Exception("Response transfer as resource not implemented") | ||||
| 
 | ||||
|                     elif packet.context == RNS.Packet.LRRTT: | ||||
|                         if not self.initiator: | ||||
|                             self.rtt_packet(packet) | ||||
| @ -691,4 +776,58 @@ class Link: | ||||
|         return self.__encryption_disabled | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return RNS.prettyhexrep(self.link_id) | ||||
|         return RNS.prettyhexrep(self.link_id) | ||||
| 
 | ||||
| 
 | ||||
| class RequestReceipt(): | ||||
|     FAILED    = 0x00 | ||||
|     SENT      = 0x01 | ||||
|     DELIVERED = 0x02 | ||||
|     READY     = 0x03 | ||||
| 
 | ||||
|     def __init__(self, link, packet_receipt, response_callback = None, failed_callback = None): | ||||
|         self.hash               = packet_receipt.truncated_hash | ||||
|         self.link               = link | ||||
|         self.request_id         = self.hash | ||||
| 
 | ||||
|         self.response           = None | ||||
|         self.status             = RequestReceipt.SENT | ||||
|         self.sent_at            = time.time() | ||||
|         self.timeout            = RNS.Packet.TIMEOUT | ||||
|         self.concluded_at       = None | ||||
| 
 | ||||
|         self.callbacks          = RequestReceiptCallbacks() | ||||
|         self.callbacks.response = response_callback | ||||
|         self.callbacks.failed   = failed_callback | ||||
| 
 | ||||
|         self.packet_receipt = packet_receipt | ||||
|         self.packet_receipt.set_timeout_callback(self.request_timed_out) | ||||
| 
 | ||||
|         self.link.pending_requests.append(self) | ||||
| 
 | ||||
| 
 | ||||
|     def request_timed_out(self, packet_receipt): | ||||
|         self.status = RequestReceipt.FAILED | ||||
|         self.concluded_at = time.time() | ||||
|         self.link.pending_requests.remove(self) | ||||
| 
 | ||||
|         if self.callbacks.failed != None: | ||||
|             self.callbacks.failed(self) | ||||
| 
 | ||||
|     def response_received(self, response): | ||||
|         self.response = response | ||||
| 
 | ||||
|         self.packet_receipt.status = RNS.PacketReceipt.DELIVERED | ||||
|         self.packet_receipt.proved = True | ||||
|         self.packet_receipt.concluded_at = time.time() | ||||
|         if self.packet_receipt.callbacks.delivery != None: | ||||
|             self.packet_receipt.callbacks.delivery(self) | ||||
| 
 | ||||
|         if self.callbacks.response != None: | ||||
|             self.callbacks.response(self) | ||||
| 
 | ||||
| 
 | ||||
| class RequestReceiptCallbacks: | ||||
|     def __init__(self): | ||||
|         self.response = None | ||||
|         self.failed   = None | ||||
| @ -41,7 +41,7 @@ class Packet: | ||||
|     HEADER_4     = 0x03     # Reserved | ||||
|     header_types = [HEADER_1, HEADER_2, HEADER_3, HEADER_4] | ||||
| 
 | ||||
|     # Data packet context types | ||||
|     # Packet context types | ||||
|     NONE           = 0x00   # Generic data packet | ||||
|     RESOURCE       = 0x01   # Packet is part of a resource | ||||
|     RESOURCE_ADV   = 0x02   # Packet is a resource advertisement | ||||
| @ -68,7 +68,6 @@ class Packet: | ||||
|     HEADER_MAXSIZE = RNS.Reticulum.HEADER_MAXSIZE | ||||
|     MDU            = RNS.Reticulum.MDU | ||||
| 
 | ||||
|     # TODO: Update this | ||||
|     # With an MTU of 500, the maximum of data we can | ||||
|     # send in a single encrypted packet is given by | ||||
|     # the below calculation; 383 bytes. | ||||
| @ -326,15 +325,16 @@ class PacketReceipt: | ||||
| 
 | ||||
|     # Creates a new packet receipt from a sent packet | ||||
|     def __init__(self, packet): | ||||
|         self.hash    = packet.get_hash() | ||||
|         self.sent    = True | ||||
|         self.sent_at = time.time() | ||||
|         self.timeout = Packet.TIMEOUT | ||||
|         self.proved  = False | ||||
|         self.status  = PacketReceipt.SENT | ||||
|         self.destination = packet.destination | ||||
|         self.callbacks   = PacketReceiptCallbacks() | ||||
|         self.concluded_at = None | ||||
|         self.hash           = packet.get_hash() | ||||
|         self.truncated_hash = packet.getTruncatedHash() | ||||
|         self.sent           = True | ||||
|         self.sent_at        = time.time() | ||||
|         self.timeout        = Packet.TIMEOUT | ||||
|         self.proved         = False | ||||
|         self.status         = PacketReceipt.SENT | ||||
|         self.destination    = packet.destination | ||||
|         self.callbacks      = PacketReceiptCallbacks() | ||||
|         self.concluded_at   = None | ||||
| 
 | ||||
|     def get_status(self): | ||||
|         """ | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| # Sphinx build info version 1 | ||||
| # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. | ||||
| config: 205a0b937612ce08d1a58b1cbb471256 | ||||
| config: 966ae7177c1d48c9ee15971994c623b5 | ||||
| tags: 645f666f9bcd5a90fca523b33c5a78b7 | ||||
|  | ||||
| @ -80,6 +80,17 @@ the link has been established. | ||||
| 
 | ||||
| This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Identify.py>`_. | ||||
| 
 | ||||
| .. _example-request: | ||||
| 
 | ||||
| Requests & Responses | ||||
| ==================== | ||||
| 
 | ||||
| The *Request* example explores sendig requests and receiving responses. | ||||
| 
 | ||||
| .. literalinclude:: ../../Examples/Request.py | ||||
| 
 | ||||
| This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py>`_. | ||||
| 
 | ||||
| .. _example-filetransfer: | ||||
| 
 | ||||
| Filetransfer | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| var DOCUMENTATION_OPTIONS = { | ||||
|     URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), | ||||
|     VERSION: '0.2.1 beta', | ||||
|     VERSION: '0.2.2 beta', | ||||
|     LANGUAGE: 'None', | ||||
|     COLLAPSE_INDEX: false, | ||||
|     BUILDER: 'html', | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Examples — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Examples — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -27,7 +27,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="reference.html" title="API Reference" | ||||
|              accesskey="P">previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Examples</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -1362,6 +1362,295 @@ the link has been established.</p> | ||||
| </div> | ||||
| <p>This example can also be found at <a class="reference external" href="https://github.com/markqvist/Reticulum/blob/master/Examples/Identify.py">https://github.com/markqvist/Reticulum/blob/master/Examples/Identify.py</a>.</p> | ||||
| </div> | ||||
| <div class="section" id="requests-responses"> | ||||
| <span id="example-request"></span><h2>Requests & Responses<a class="headerlink" href="#requests-responses" title="Permalink to this headline">¶</a></h2> | ||||
| <p>The <em>Request</em> example explores sendig requests and receiving responses.</p> | ||||
| <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span> | ||||
| <span class="c1"># This RNS example demonstrates how to set perform       #</span> | ||||
| <span class="c1"># requests and receive responses over a link.            #</span> | ||||
| <span class="c1">##########################################################</span> | ||||
| 
 | ||||
| <span class="kn">import</span> <span class="nn">os</span> | ||||
| <span class="kn">import</span> <span class="nn">sys</span> | ||||
| <span class="kn">import</span> <span class="nn">time</span> | ||||
| <span class="kn">import</span> <span class="nn">random</span> | ||||
| <span class="kn">import</span> <span class="nn">argparse</span> | ||||
| <span class="kn">import</span> <span class="nn">RNS</span> | ||||
| 
 | ||||
| <span class="c1"># Let's define an app name. We'll use this for all</span> | ||||
| <span class="c1"># destinations we create. Since this echo example</span> | ||||
| <span class="c1"># is part of a range of example utilities, we'll put</span> | ||||
| <span class="c1"># them all within the app namespace "example_utilities"</span> | ||||
| <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">"example_utilities"</span> | ||||
| 
 | ||||
| <span class="c1">##########################################################</span> | ||||
| <span class="c1">#### Server Part #########################################</span> | ||||
| <span class="c1">##########################################################</span> | ||||
| 
 | ||||
| <span class="c1"># A reference to the latest client link that connected</span> | ||||
| <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">random_text_generator</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">remote_identity_hash</span><span class="p">,</span> <span class="n">requested_at</span><span class="p">):</span> | ||||
|     <span class="n">texts</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"They looked up"</span><span class="p">,</span> <span class="s2">"On each full moon"</span><span class="p">,</span> <span class="s2">"Becky was upset"</span><span class="p">,</span> <span class="s2">"I’ll stay away from it"</span><span class="p">,</span> <span class="s2">"The pet shop stocks everything"</span><span class="p">]</span> | ||||
|     <span class="k">return</span> <span class="n">texts</span><span class="p">[</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">texts</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)]</span> | ||||
| 
 | ||||
| <span class="c1"># This initialisation is executed when the users chooses</span> | ||||
| <span class="c1"># to run as a server</span> | ||||
| <span class="k">def</span> <span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span> | ||||
|     <span class="c1"># We must first initialise Reticulum</span> | ||||
|     <span class="n">reticulum</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="p">(</span><span class="n">configpath</span><span class="p">)</span> | ||||
|      | ||||
|     <span class="c1"># Randomly create a new identity for our link example</span> | ||||
|     <span class="n">server_identity</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Identity</span><span class="p">()</span> | ||||
| 
 | ||||
|     <span class="c1"># We create a destination that clients can connect to. We</span> | ||||
|     <span class="c1"># want clients to create links to this destination, so we</span> | ||||
|     <span class="c1"># need to create a "single" destination type.</span> | ||||
|     <span class="n">server_destination</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="p">(</span> | ||||
|         <span class="n">server_identity</span><span class="p">,</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">IN</span><span class="p">,</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">SINGLE</span><span class="p">,</span> | ||||
|         <span class="n">APP_NAME</span><span class="p">,</span> | ||||
|         <span class="s2">"requestexample"</span> | ||||
|     <span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># We configure a function that will get called every time</span> | ||||
|     <span class="c1"># a new client creates a link to this destination.</span> | ||||
|     <span class="n">server_destination</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># We register a request handler for handling incoming</span> | ||||
|     <span class="c1"># requests over any established links.</span> | ||||
|     <span class="n">server_destination</span><span class="o">.</span><span class="n">register_request_handler</span><span class="p">(</span> | ||||
|         <span class="s2">"/random/text"</span><span class="p">,</span> | ||||
|         <span class="n">response_generator</span> <span class="o">=</span> <span class="n">random_text_generator</span><span class="p">,</span> | ||||
|         <span class="n">allow</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">ALLOW_ALL</span> | ||||
|     <span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># Everything's ready!</span> | ||||
|     <span class="c1"># Let's Wait for client requests or user input</span> | ||||
|     <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span> | ||||
|     <span class="c1"># Let the user know that everything is ready</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span> | ||||
|         <span class="s2">"Request example "</span><span class="o">+</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">destination</span><span class="o">.</span><span class="n">hash</span><span class="p">)</span><span class="o">+</span> | ||||
|         <span class="s2">" running, waiting for a connection."</span> | ||||
|     <span class="p">)</span> | ||||
| 
 | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Hit enter to manually send an announce (Ctrl-C to quit)"</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># We enter a loop that runs until the users exits.</span> | ||||
|     <span class="c1"># If the user hits enter, we will announce our server</span> | ||||
|     <span class="c1"># destination on the network, which will let clients</span> | ||||
|     <span class="c1"># know how to create messages directed towards it.</span> | ||||
|     <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> | ||||
|         <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span> | ||||
|         <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Sent announce from "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">destination</span><span class="o">.</span><span class="n">hash</span><span class="p">))</span> | ||||
| 
 | ||||
| <span class="c1"># When a client establishes a link to our server</span> | ||||
| <span class="c1"># destination, this function will be called with</span> | ||||
| <span class="c1"># a reference to the link.</span> | ||||
| <span class="k">def</span> <span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span> | ||||
|     <span class="k">global</span> <span class="n">latest_client_link</span> | ||||
| 
 | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client connected"</span><span class="p">)</span> | ||||
|     <span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span> | ||||
|     <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Client disconnected"</span><span class="p">)</span> | ||||
| 
 | ||||
| 
 | ||||
| <span class="c1">##########################################################</span> | ||||
| <span class="c1">#### Client Part #########################################</span> | ||||
| <span class="c1">##########################################################</span> | ||||
| 
 | ||||
| <span class="c1"># A reference to the server link</span> | ||||
| <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span> | ||||
| 
 | ||||
| <span class="c1"># This initialisation is executed when the users chooses</span> | ||||
| <span class="c1"># to run as a client</span> | ||||
| <span class="k">def</span> <span class="nf">client</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">,</span> <span class="n">configpath</span><span class="p">):</span> | ||||
|     <span class="c1"># We need a binary representation of the destination</span> | ||||
|     <span class="c1"># hash that was entered on the command line</span> | ||||
|     <span class="k">try</span><span class="p">:</span> | ||||
|         <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">20</span><span class="p">:</span> | ||||
|             <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Destination length is invalid, must be 20 hexadecimal characters (10 bytes)"</span><span class="p">)</span> | ||||
|         <span class="n">destination_hash</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">)</span> | ||||
|     <span class="k">except</span><span class="p">:</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span> | ||||
|         <span class="n">exit</span><span class="p">()</span> | ||||
| 
 | ||||
|     <span class="c1"># We must first initialise Reticulum</span> | ||||
|     <span class="n">reticulum</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="p">(</span><span class="n">configpath</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># Check if we know a path to the destination</span> | ||||
|     <span class="k">if</span> <span class="ow">not</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">has_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">):</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Destination is not yet known. Requesting path and waiting for announce to arrive..."</span><span class="p">)</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">request_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">)</span> | ||||
|         <span class="k">while</span> <span class="ow">not</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">has_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">):</span> | ||||
|             <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># Recall the server identity</span> | ||||
|     <span class="n">server_identity</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Identity</span><span class="o">.</span><span class="n">recall</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># Inform the user that we'll begin connecting</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Establishing link with server..."</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># When the server identity is known, we set</span> | ||||
|     <span class="c1"># up a destination</span> | ||||
|     <span class="n">server_destination</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="p">(</span> | ||||
|         <span class="n">server_identity</span><span class="p">,</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">OUT</span><span class="p">,</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">SINGLE</span><span class="p">,</span> | ||||
|         <span class="n">APP_NAME</span><span class="p">,</span> | ||||
|         <span class="s2">"requestexample"</span> | ||||
|     <span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># And create a link</span> | ||||
|     <span class="n">link</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># We'll set up functions to inform the</span> | ||||
|     <span class="c1"># user when the link is established or closed</span> | ||||
|     <span class="n">link</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span> | ||||
|     <span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="c1"># Everything is set up, so let's enter a loop</span> | ||||
|     <span class="c1"># for the user to interact with the example</span> | ||||
|     <span class="n">client_loop</span><span class="p">()</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">client_loop</span><span class="p">():</span> | ||||
|     <span class="k">global</span> <span class="n">server_link</span> | ||||
| 
 | ||||
|     <span class="c1"># Wait for the link to become active</span> | ||||
|     <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span> | ||||
|         <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span> | ||||
|     <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span> | ||||
|         <span class="k">try</span><span class="p">:</span> | ||||
|             <span class="nb">print</span><span class="p">(</span><span class="s2">"> "</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span> | ||||
|             <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span> | ||||
| 
 | ||||
|             <span class="c1"># Check if we should quit the example</span> | ||||
|             <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">"quit"</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">"q"</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">"exit"</span><span class="p">:</span> | ||||
|                 <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span> | ||||
|                 <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span> | ||||
| 
 | ||||
|             <span class="k">else</span><span class="p">:</span> | ||||
|                 <span class="n">server_link</span><span class="o">.</span><span class="n">request</span><span class="p">(</span> | ||||
|                     <span class="s2">"/random/text"</span><span class="p">,</span> | ||||
|                     <span class="n">data</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> | ||||
|                     <span class="n">response_callback</span> <span class="o">=</span> <span class="n">got_response</span><span class="p">,</span> | ||||
|                     <span class="n">failed_callback</span> <span class="o">=</span> <span class="n">request_failed</span> | ||||
|                 <span class="p">)</span> | ||||
| 
 | ||||
| 
 | ||||
|         <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> | ||||
|             <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Error while sending request over the link: "</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span> | ||||
|             <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span> | ||||
|             <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">got_response</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span> | ||||
|     <span class="n">request_id</span> <span class="o">=</span> <span class="n">request_receipt</span><span class="o">.</span><span class="n">request_id</span> | ||||
|     <span class="n">response</span> <span class="o">=</span> <span class="n">request_receipt</span><span class="o">.</span><span class="n">response</span> | ||||
| 
 | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Got response for request "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">request_id</span><span class="p">)</span><span class="o">+</span><span class="s2">": "</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">response</span><span class="p">))</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">request_received</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"The request "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">request_receipt</span><span class="o">.</span><span class="n">request_id</span><span class="p">)</span><span class="o">+</span><span class="s2">" was received by the remote peer."</span><span class="p">)</span> | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">request_failed</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"The request "</span><span class="o">+</span><span class="n">RNS</span><span class="o">.</span><span class="n">prettyhexrep</span><span class="p">(</span><span class="n">request_receipt</span><span class="o">.</span><span class="n">request_id</span><span class="p">)</span><span class="o">+</span><span class="s2">" failed."</span><span class="p">)</span> | ||||
| 
 | ||||
| 
 | ||||
| <span class="c1"># This function is called when a link</span> | ||||
| <span class="c1"># has been established with the server</span> | ||||
| <span class="k">def</span> <span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span> | ||||
|     <span class="c1"># We store a reference to the link</span> | ||||
|     <span class="c1"># instance for later use</span> | ||||
|     <span class="k">global</span> <span class="n">server_link</span> | ||||
|     <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span> | ||||
| 
 | ||||
|     <span class="c1"># Inform the user that the server is</span> | ||||
|     <span class="c1"># connected</span> | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Link established with server, hit enter to perform a request, or type in </span><span class="se">\"</span><span class="s2">quit</span><span class="se">\"</span><span class="s2"> to quit"</span><span class="p">)</span> | ||||
| 
 | ||||
| <span class="c1"># When a link is closed, we'll inform the</span> | ||||
| <span class="c1"># user, and exit the program</span> | ||||
| <span class="k">def</span> <span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span> | ||||
|     <span class="k">if</span> <span class="n">link</span><span class="o">.</span><span class="n">teardown_reason</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">TIMEOUT</span><span class="p">:</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"The link timed out, exiting now"</span><span class="p">)</span> | ||||
|     <span class="k">elif</span> <span class="n">link</span><span class="o">.</span><span class="n">teardown_reason</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">DESTINATION_CLOSED</span><span class="p">:</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"The link was closed by the server, exiting now"</span><span class="p">)</span> | ||||
|     <span class="k">else</span><span class="p">:</span> | ||||
|         <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">"Link closed, exiting now"</span><span class="p">)</span> | ||||
|      | ||||
|     <span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">exit_handler</span><span class="p">()</span> | ||||
|     <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span> | ||||
|     <span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> | ||||
| 
 | ||||
| 
 | ||||
| <span class="c1">##########################################################</span> | ||||
| <span class="c1">#### Program Startup #####################################</span> | ||||
| <span class="c1">##########################################################</span> | ||||
| 
 | ||||
| <span class="c1"># This part of the program runs at startup,</span> | ||||
| <span class="c1"># and parses input of from the user, and then</span> | ||||
| <span class="c1"># starts up the desired program mode.</span> | ||||
| <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span> | ||||
|     <span class="k">try</span><span class="p">:</span> | ||||
|         <span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">"Simple request/response example"</span><span class="p">)</span> | ||||
| 
 | ||||
|         <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span> | ||||
|             <span class="s2">"-s"</span><span class="p">,</span> | ||||
|             <span class="s2">"--server"</span><span class="p">,</span> | ||||
|             <span class="n">action</span><span class="o">=</span><span class="s2">"store_true"</span><span class="p">,</span> | ||||
|             <span class="n">help</span><span class="o">=</span><span class="s2">"wait for incoming requests from clients"</span> | ||||
|         <span class="p">)</span> | ||||
| 
 | ||||
|         <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span> | ||||
|             <span class="s2">"--config"</span><span class="p">,</span> | ||||
|             <span class="n">action</span><span class="o">=</span><span class="s2">"store"</span><span class="p">,</span> | ||||
|             <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> | ||||
|             <span class="n">help</span><span class="o">=</span><span class="s2">"path to alternative Reticulum config directory"</span><span class="p">,</span> | ||||
|             <span class="nb">type</span><span class="o">=</span><span class="nb">str</span> | ||||
|         <span class="p">)</span> | ||||
| 
 | ||||
|         <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span> | ||||
|             <span class="s2">"destination"</span><span class="p">,</span> | ||||
|             <span class="n">nargs</span><span class="o">=</span><span class="s2">"?"</span><span class="p">,</span> | ||||
|             <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> | ||||
|             <span class="n">help</span><span class="o">=</span><span class="s2">"hexadecimal hash of the server destination"</span><span class="p">,</span> | ||||
|             <span class="nb">type</span><span class="o">=</span><span class="nb">str</span> | ||||
|         <span class="p">)</span> | ||||
| 
 | ||||
|         <span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> | ||||
| 
 | ||||
|         <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span> | ||||
|             <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span> | ||||
|         <span class="k">else</span><span class="p">:</span> | ||||
|             <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span> | ||||
| 
 | ||||
|         <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span> | ||||
|             <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span> | ||||
|         <span class="k">else</span><span class="p">:</span> | ||||
|             <span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">destination</span> <span class="o">==</span> <span class="kc">None</span><span class="p">):</span> | ||||
|                 <span class="nb">print</span><span class="p">(</span><span class="s2">""</span><span class="p">)</span> | ||||
|                 <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span> | ||||
|                 <span class="nb">print</span><span class="p">(</span><span class="s2">""</span><span class="p">)</span> | ||||
|             <span class="k">else</span><span class="p">:</span> | ||||
|                 <span class="n">client</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">destination</span><span class="p">,</span> <span class="n">configarg</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span> | ||||
|         <span class="nb">print</span><span class="p">(</span><span class="s2">""</span><span class="p">)</span> | ||||
|         <span class="n">exit</span><span class="p">()</span> | ||||
| </pre></div> | ||||
| </div> | ||||
| <p>This example can also be found at <a class="reference external" href="https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py">https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py</a>.</p> | ||||
| </div> | ||||
| <div class="section" id="filetransfer"> | ||||
| <span id="example-filetransfer"></span><h2>Filetransfer<a class="headerlink" href="#filetransfer" title="Permalink to this headline">¶</a></h2> | ||||
| <p>The <em>Filetransfer</em> example implements a basic file-server program that | ||||
| @ -1504,7 +1793,12 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer | ||||
| 
 | ||||
| <span class="k">def</span> <span class="nf">client_request</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">packet</span><span class="p">):</span> | ||||
|     <span class="k">global</span> <span class="n">serve_path</span> | ||||
|     <span class="n">filename</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"utf-8"</span><span class="p">)</span> | ||||
| 
 | ||||
|     <span class="k">try</span><span class="p">:</span> | ||||
|         <span class="n">filename</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"utf-8"</span><span class="p">)</span> | ||||
|     <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> | ||||
|         <span class="n">filename</span> <span class="o">=</span> <span class="kc">None</span> | ||||
| 
 | ||||
|     <span class="k">if</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">list_files</span><span class="p">():</span> | ||||
|         <span class="k">try</span><span class="p">:</span> | ||||
|             <span class="c1"># If we have the requested file, we'll</span> | ||||
| @ -1986,6 +2280,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer | ||||
| <li><a class="reference internal" href="#echo">Echo</a></li> | ||||
| <li><a class="reference internal" href="#link">Link</a></li> | ||||
| <li><a class="reference internal" href="#example-identify">Identification</a></li> | ||||
| <li><a class="reference internal" href="#requests-responses">Requests & Responses</a></li> | ||||
| <li><a class="reference internal" href="#filetransfer">Filetransfer</a></li> | ||||
| </ul> | ||||
| </li> | ||||
| @ -2024,7 +2319,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer | ||||
|         <li class="right" > | ||||
|           <a href="reference.html" title="API Reference" | ||||
|              >previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Examples</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Index — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Index — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -23,7 +23,7 @@ | ||||
|         <li class="right" style="margin-right: 10px"> | ||||
|           <a href="#" title="General Index" | ||||
|              accesskey="I">index</a></li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Index</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -103,6 +103,8 @@ | ||||
|   </ul></td> | ||||
|   <td style="width: 33%; vertical-align: top;"><ul> | ||||
|       <li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Destination.deregister_request_handler">deregister_request_handler() (RNS.Destination method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a> | ||||
| </li> | ||||
| @ -261,9 +263,13 @@ | ||||
|       <li><a href="reference.html#RNS.Identity.recall_app_data">recall_app_data() (RNS.Identity static method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Transport.register_announce_handler">register_announce_handler() (RNS.Transport static method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Destination.register_request_handler">register_request_handler() (RNS.Destination method)</a> | ||||
| </li> | ||||
|   </ul></td> | ||||
|   <td style="width: 33%; vertical-align: top;"><ul> | ||||
|       <li><a href="reference.html#RNS.Link.request">request() (RNS.Link method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Transport.request_path">request_path() (RNS.Transport static method)</a> | ||||
| </li> | ||||
|       <li><a href="reference.html#RNS.Packet.resend">resend() (RNS.Packet method)</a> | ||||
| @ -381,7 +387,7 @@ | ||||
|         <li class="right" style="margin-right: 10px"> | ||||
|           <a href="#" title="General Index" | ||||
|              >index</a></li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Index</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Getting Started Fast — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Getting Started Fast — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -31,7 +31,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="whatis.html" title="What is Reticulum?" | ||||
|              accesskey="P">previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -166,7 +166,7 @@ don’t use pip, but try this recipe:</p> | ||||
|         <li class="right" > | ||||
|           <a href="whatis.html" title="What is Reticulum?" | ||||
|              >previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Reticulum Network Stack Manual — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Reticulum Network Stack Manual — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -27,7 +27,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="whatis.html" title="What is Reticulum?" | ||||
|              accesskey="N">next</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -104,6 +104,7 @@ the development of Reticulum itself.</p> | ||||
| <li class="toctree-l2"><a class="reference internal" href="examples.html#echo">Echo</a></li> | ||||
| <li class="toctree-l2"><a class="reference internal" href="examples.html#link">Link</a></li> | ||||
| <li class="toctree-l2"><a class="reference internal" href="examples.html#example-identify">Identification</a></li> | ||||
| <li class="toctree-l2"><a class="reference internal" href="examples.html#requests-responses">Requests & Responses</a></li> | ||||
| <li class="toctree-l2"><a class="reference internal" href="examples.html#filetransfer">Filetransfer</a></li> | ||||
| </ul> | ||||
| </li> | ||||
| @ -166,7 +167,7 @@ the development of Reticulum itself.</p> | ||||
|         <li class="right" > | ||||
|           <a href="whatis.html" title="What is Reticulum?" | ||||
|              >next</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Manual</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>API Reference — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>API Reference — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -31,7 +31,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="understanding.html" title="Understanding Reticulum" | ||||
|              accesskey="P">previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">API Reference</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -508,6 +508,39 @@ proofs should be returned for received packets.</p> | ||||
| </dl> | ||||
| </dd></dl> | ||||
| 
 | ||||
| <dl class="py method"> | ||||
| <dt class="sig sig-object py" id="RNS.Destination.register_request_handler"> | ||||
| <span class="sig-name descname"><span class="pre">register_request_handler</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">response_generator</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">allow</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">allowed_list</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.register_request_handler" title="Permalink to this definition">¶</a></dt> | ||||
| <dd><p>Registers a request handler.</p> | ||||
| <dl class="field-list simple"> | ||||
| <dt class="field-odd">Parameters</dt> | ||||
| <dd class="field-odd"><ul class="simple"> | ||||
| <li><p><strong>path</strong> – The path for the request handler to be registered.</p></li> | ||||
| <li><p><strong>response_generator</strong> – A function or method with the signature <em>response_generator(path, data, remote_identity_hash, requested_at)</em> to be called. Whatever this funcion returns will be sent as a response to the requester. If the function returns <code class="docutils literal notranslate"><span class="pre">None</span></code>, no response will be sent.</p></li> | ||||
| <li><p><strong>allow</strong> – One of <code class="docutils literal notranslate"><span class="pre">RNS.Destination.ALLOW_NONE</span></code>, <code class="docutils literal notranslate"><span class="pre">RNS.Destination.ALLOW_ALL</span></code> or <code class="docutils literal notranslate"><span class="pre">RNS.Destination.ALLOW_LIST</span></code>. If <code class="docutils literal notranslate"><span class="pre">RNS.Destination.ALLOW_LIST</span></code> is set, the request handler will only respond to requests for identified peers in the supplied list.</p></li> | ||||
| <li><p><strong>allowed_list</strong> – A list of <em>bytes-like</em> <a class="reference internal" href="#api-identity"><span class="std std-ref">RNS.Identity</span></a> hashes.</p></li> | ||||
| </ul> | ||||
| </dd> | ||||
| <dt class="field-even">Raises</dt> | ||||
| <dd class="field-even"><p><code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if any of the supplied arguments are invalid.</p> | ||||
| </dd> | ||||
| </dl> | ||||
| </dd></dl> | ||||
| 
 | ||||
| <dl class="py method"> | ||||
| <dt class="sig sig-object py" id="RNS.Destination.deregister_request_handler"> | ||||
| <span class="sig-name descname"><span class="pre">deregister_request_handler</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.deregister_request_handler" title="Permalink to this definition">¶</a></dt> | ||||
| <dd><p>Deregisters a request handler.</p> | ||||
| <dl class="field-list simple"> | ||||
| <dt class="field-odd">Parameters</dt> | ||||
| <dd class="field-odd"><p><strong>path</strong> – The path for the request handler to be deregistered.</p> | ||||
| </dd> | ||||
| <dt class="field-even">Returns</dt> | ||||
| <dd class="field-even"><p>True if the handler was deregistered, otherwise False.</p> | ||||
| </dd> | ||||
| </dl> | ||||
| </dd></dl> | ||||
| 
 | ||||
| <dl class="py method"> | ||||
| <dt class="sig sig-object py" id="RNS.Destination.create_keys"> | ||||
| <span class="sig-name descname"><span class="pre">create_keys</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Destination.create_keys" title="Permalink to this definition">¶</a></dt> | ||||
| @ -785,6 +818,21 @@ thus preserved. This method can be used for authentication.</p> | ||||
| </dl> | ||||
| </dd></dl> | ||||
| 
 | ||||
| <dl class="py method"> | ||||
| <dt class="sig sig-object py" id="RNS.Link.request"> | ||||
| <span class="sig-name descname"><span class="pre">request</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">response_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">failed_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.request" title="Permalink to this definition">¶</a></dt> | ||||
| <dd><p>Sends a request to the remote peer.</p> | ||||
| <dl class="field-list simple"> | ||||
| <dt class="field-odd">Parameters</dt> | ||||
| <dd class="field-odd"><ul class="simple"> | ||||
| <li><p><strong>path</strong> – The request path.</p></li> | ||||
| <li><p><strong>response_callback</strong> – A function or method with the signature <em>response_callback(request_receipt)</em> to be called when a response is received. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li> | ||||
| <li><p><strong>failed_callback</strong> – A function or method with the signature <em>failed_callback(request_receipt)</em> to be called when a request fails. See the <a class="reference internal" href="examples.html#example-request"><span class="std std-ref">Request Example</span></a> for more info.</p></li> | ||||
| </ul> | ||||
| </dd> | ||||
| </dl> | ||||
| </dd></dl> | ||||
| 
 | ||||
| <dl class="py method"> | ||||
| <dt class="sig sig-object py" id="RNS.Link.no_inbound_for"> | ||||
| <span class="sig-name descname"><span class="pre">no_inbound_for</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#RNS.Link.no_inbound_for" title="Permalink to this definition">¶</a></dt> | ||||
| @ -934,7 +982,7 @@ compression, coordination and checksumming.</p> | ||||
| <dl class="field-list simple"> | ||||
| <dt class="field-odd">Parameters</dt> | ||||
| <dd class="field-odd"><ul class="simple"> | ||||
| <li><p><strong>data</strong> – The data to be transferred. Can be <em>bytes</em> or an open <em>file handle</em>. See the <span class="xref std std-ref">Filetransfer Example</span> for details.</p></li> | ||||
| <li><p><strong>data</strong> – The data to be transferred. Can be <em>bytes</em> or an open <em>file handle</em>. See the <a class="reference internal" href="examples.html#example-filetransfer"><span class="std std-ref">Filetransfer Example</span></a> for details.</p></li> | ||||
| <li><p><strong>link</strong> – The <a class="reference internal" href="#api-link"><span class="std std-ref">RNS.Link</span></a> instance on which to transfer the data.</p></li> | ||||
| <li><p><strong>advertise</strong> – Whether to automatically advertise the resource. Can be <em>True</em> or <em>False</em>.</p></li> | ||||
| <li><p><strong>auto_compress</strong> – Whether to auto-compress the resource. Can be <em>True</em> or <em>False</em>.</p></li> | ||||
| @ -1094,7 +1142,7 @@ will announce it.</p> | ||||
|         <li class="right" > | ||||
|           <a href="understanding.html" title="Understanding Reticulum" | ||||
|              >previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">API Reference</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Search — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Search — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -29,7 +29,7 @@ | ||||
|         <li class="right" style="margin-right: 10px"> | ||||
|           <a href="genindex.html" title="General Index" | ||||
|              accesskey="I">index</a></li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Search</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -85,7 +85,7 @@ | ||||
|         <li class="right" style="margin-right: 10px"> | ||||
|           <a href="genindex.html" title="General Index" | ||||
|              >index</a></li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Search</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>Understanding Reticulum — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>Understanding Reticulum — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -31,7 +31,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="gettingstartedfast.html" title="Getting Started Fast" | ||||
|              accesskey="P">previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -853,7 +853,7 @@ proof           11 | ||||
|         <li class="right" > | ||||
|           <a href="gettingstartedfast.html" title="Getting Started Fast" | ||||
|              >previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title>What is Reticulum? — Reticulum Network Stack 0.2.1 beta documentation</title> | ||||
|     <title>What is Reticulum? — Reticulum Network Stack 0.2.2 beta documentation</title> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> | ||||
|     <link rel="stylesheet" type="text/css" href="_static/classic.css" /> | ||||
|      | ||||
| @ -31,7 +31,7 @@ | ||||
|         <li class="right" > | ||||
|           <a href="index.html" title="Reticulum Network Stack Manual" | ||||
|              accesskey="P">previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>  | ||||
|       </ul> | ||||
|     </div>   | ||||
| @ -182,7 +182,7 @@ network, and vice versa.</p> | ||||
|         <li class="right" > | ||||
|           <a href="index.html" title="Reticulum Network Stack Manual" | ||||
|              >previous</a> |</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.1 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.2 beta documentation</a> »</li> | ||||
|         <li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>  | ||||
|       </ul> | ||||
|     </div> | ||||
|  | ||||
| @ -22,7 +22,7 @@ copyright = '2021, Mark Qvist' | ||||
| author = 'Mark Qvist' | ||||
| 
 | ||||
| # The full version, including alpha/beta/rc tags | ||||
| release = '0.2.1 beta' | ||||
| release = '0.2.2 beta' | ||||
| 
 | ||||
| 
 | ||||
| # -- General configuration --------------------------------------------------- | ||||
|  | ||||
| @ -80,6 +80,17 @@ the link has been established. | ||||
| 
 | ||||
| This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Identify.py>`_. | ||||
| 
 | ||||
| .. _example-request: | ||||
| 
 | ||||
| Requests & Responses | ||||
| ==================== | ||||
| 
 | ||||
| The *Request* example explores sendig requests and receiving responses. | ||||
| 
 | ||||
| .. literalinclude:: ../../Examples/Request.py | ||||
| 
 | ||||
| This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py>`_. | ||||
| 
 | ||||
| .. _example-filetransfer: | ||||
| 
 | ||||
| Filetransfer | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user