2021-05-16 15:40:49 -06:00
<!DOCTYPE html>
< html >
< head >
< meta charset = "utf-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" / >
< title > Examples — Reticulum Network Stack 0.2.0 beta documentation< / title >
< link rel = "stylesheet" type = "text/css" href = "_static/pygments.css" / >
< link rel = "stylesheet" type = "text/css" href = "_static/classic.css" / >
< script data-url_root = "./" id = "documentation_options" src = "_static/documentation_options.js" > < / script >
< script src = "_static/jquery.js" > < / script >
< script src = "_static/underscore.js" > < / script >
< script src = "_static/doctools.js" > < / script >
< link rel = "index" title = "Index" href = "genindex.html" / >
< link rel = "search" title = "Search" href = "search.html" / >
< link rel = "next" title = "API Reference" href = "reference.html" / >
< link rel = "prev" title = "Getting Started Fast" href = "gettingstartedfast.html" / >
< / head > < body >
< div class = "related" role = "navigation" aria-label = "related navigation" >
< h3 > Navigation< / h3 >
< ul >
< li class = "right" style = "margin-right: 10px" >
< a href = "genindex.html" title = "General Index"
accesskey="I">index< / a > < / li >
< li class = "right" >
< a href = "reference.html" title = "API Reference"
accesskey="N">next< / a > |< / li >
< 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.0 beta documentation< / a > » < / li >
< li class = "nav-item nav-item-this" > < a href = "" > Examples< / a > < / li >
< / ul >
< / div >
< div class = "document" >
< div class = "documentwrapper" >
< div class = "bodywrapper" >
< div class = "body" role = "main" >
< div class = "section" id = "examples" >
< span id = "examples-main" > < / span > < h1 > Examples< a class = "headerlink" href = "#examples" title = "Permalink to this headline" > ¶< / a > < / h1 >
< p > A number of examples are included in the source distribution of Reticulum.
You can use these examples to learn how to write your own programs.< / p >
< div class = "section" id = "minimal" >
< span id = "example-minimal" > < / span > < h2 > Minimal< a class = "headerlink" href = "#minimal" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > The < em > Minimal< / em > example demonstrates the bare-minimum setup required to connect to
a Reticulum network from your program. In about five lines of code, you will
have the Reticulum Network Stack initialised, and ready to pass traffic in your
program.< / p >
2021-05-17 06:10:47 -06:00
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates a minimal setup, that #< / span >
< span class = "c1" > # will start up the Reticulum Network Stack, generate a #< / span >
< span class = "c1" > # new destination, and let the user send an announce. #< / span >
< span class = "c1" > ##########################################################< / 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 basic 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" > # This initialisation is executed when the program is started< / span >
< span class = "k" > def< / span > < span class = "nf" > program_setup< / 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 example< / span >
< span class = "n" > 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" > # Using the identity we just created, we create a destination.< / span >
< span class = "c1" > # Destinations are endpoints in Reticulum, that can be addressed< / span >
< span class = "c1" > # and communicated with. Destinations can also announce their< / span >
< span class = "c1" > # existence, which will let the network know they are reachable< / span >
< span class = "c1" > # and autoomatically create paths to them, from anywhere else< / span >
< span class = "c1" > # in the network.< / span >
< span class = "n" > 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" > 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" > " minimalsample" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We configure the destination to automatically prove all< / span >
< span class = "c1" > # packets adressed to it. By doing this, RNS will automatically< / span >
< span class = "c1" > # generate a proof for each incoming packet and transmit it< / span >
< span class = "c1" > # back to the sender of that packet. This will let anyone that< / span >
< span class = "c1" > # tries to communicate with the destination know whether their< / span >
< span class = "c1" > # communication was received correctly.< / span >
< span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > set_proof_strategy< / 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" > PROVE_ALL< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything' s ready!< / span >
< span class = "c1" > # Let' s hand over control to the announce loop< / span >
< span class = "n" > announceLoop< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > announceLoop< / 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" > " Minimal 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, 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" > ##########################################################< / span >
< span class = "c1" > #### Program Startup #####################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This part of the program gets run at startup,< / span >
< span class = "c1" > # and parses input from the user, and then starts< / span >
< span class = "c1" > # 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" > " Bare minimum example to start Reticulum and create a destination" < / 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" > 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 = "n" > program_setup< / 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/Minimal.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Minimal.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / div >
< div class = "section" id = "announce" >
< span id = "example-announce" > < / span > < h2 > Announce< a class = "headerlink" href = "#announce" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > The < em > Announce< / em > example builds upon the previous example by exploring how to
announce a destination on the network, and how to let your program receive
notifications about announces from relevant destinations.< / p >
2021-05-17 06:10:47 -06:00
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates setting up announce #< / span >
< span class = "c1" > # callbacks, which will let an application receive a #< / span >
< span class = "c1" > # notification when an announce relevant for it arrives #< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "kn" > import< / span > < span class = "nn" > argparse< / span >
< span class = "kn" > import< / span > < span class = "nn" > random< / 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 basic 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" > # We initialise two lists of strings to use as app_data< / span >
< span class = "n" > fruits< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s2" > " Peach" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Quince" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Date palm" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Tangerine" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Pomelo" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Carambola" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Grape" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Passion fruit" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Prune" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Cranberry" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Strawberry" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Papaya" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Pomegranate" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Avocado" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Mango" < / span > < span class = "p" > ]< / span >
< span class = "n" > noble_gases< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s2" > " Helium" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Neon" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Argon" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Krypton" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Xenon" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Radon" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Oganesson" < / span > < span class = "p" > ]< / span >
< span class = "c1" > # This initialisation is executed when the program is started< / span >
< span class = "k" > def< / span > < span class = "nf" > program_setup< / 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 example< / span >
< span class = "n" > 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" > # Using the identity we just created, we create two destinations< / span >
< span class = "c1" > # in the " example_utilities.announcesample" application space.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # Destinations are endpoints in Reticulum, that can be addressed< / span >
< span class = "c1" > # and communicated with. Destinations can also announce their< / span >
< span class = "c1" > # existence, which will let the network know they are reachable< / span >
< span class = "c1" > # and autoomatically create paths to them, from anywhere else< / span >
< span class = "c1" > # in the network.< / span >
< span class = "n" > destination_1< / 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" > 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" > " announcesample" < / span > < span class = "p" > ,< / span > < span class = "s2" > " fruits" < / span > < span class = "p" > )< / span >
< span class = "n" > destination_2< / 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" > 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" > " announcesample" < / span > < span class = "p" > ,< / span > < span class = "s2" > " noble_gases" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We configure the destinations to automatically prove all< / span >
< span class = "c1" > # packets adressed to it. By doing this, RNS will automatically< / span >
< span class = "c1" > # generate a proof for each incoming packet and transmit it< / span >
< span class = "c1" > # back to the sender of that packet. This will let anyone that< / span >
< span class = "c1" > # tries to communicate with the destination know whether their< / span >
< span class = "c1" > # communication was received correctly.< / span >
< span class = "n" > destination_1< / span > < span class = "o" > .< / span > < span class = "n" > set_proof_strategy< / 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" > PROVE_ALL< / span > < span class = "p" > )< / span >
< span class = "n" > destination_2< / span > < span class = "o" > .< / span > < span class = "n" > set_proof_strategy< / 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" > PROVE_ALL< / span > < span class = "p" > )< / span >
< span class = "c1" > # We create an announce handler and configure it to only ask for< / span >
< span class = "c1" > # announces from " example_utilities.announcesample.fruits" .< / span >
< span class = "c1" > # Try changing the filter and see what happens.< / span >
< span class = "n" > announce_handler< / span > < span class = "o" > =< / span > < span class = "n" > ExampleAnnounceHandler< / span > < span class = "p" > (< / span > < span class = "n" > aspect_filter< / span > < span class = "o" > =< / span > < span class = "s2" > " example_utilities.announcesample.fruits" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We register the announce handler with Reticulum< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Transport< / span > < span class = "o" > .< / span > < span class = "n" > register_announce_handler< / span > < span class = "p" > (< / span > < span class = "n" > announce_handler< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything' s ready!< / span >
< span class = "c1" > # Let' s hand over control to the announce loop< / span >
< span class = "n" > announceLoop< / span > < span class = "p" > (< / span > < span class = "n" > destination_1< / span > < span class = "p" > ,< / span > < span class = "n" > destination_2< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > announceLoop< / span > < span class = "p" > (< / span > < span class = "n" > destination_1< / span > < span class = "p" > ,< / span > < span class = "n" > destination_2< / 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" > " Announce example running, 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 = "c1" > # Randomly select a fruit< / span >
< span class = "n" > fruit< / span > < span class = "o" > =< / span > < span class = "n" > fruits< / 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" > fruits< / span > < span class = "p" > )< / span > < span class = "o" > -< / span > < span class = "mi" > 1< / span > < span class = "p" > )]< / span >
< span class = "c1" > # Send the announce including the app data< / span >
< span class = "n" > destination_1< / span > < span class = "o" > .< / span > < span class = "n" > announce< / span > < span class = "p" > (< / span > < span class = "n" > app_data< / span > < span class = "o" > =< / span > < span class = "n" > fruit< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / 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_1< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " (" < / span > < span class = "o" > +< / span > < span class = "n" > destination_1< / span > < span class = "o" > .< / span > < span class = "n" > name< / span > < span class = "o" > +< / span > < span class = "s2" > " )" < / span > < span class = "p" > )< / span >
< span class = "c1" > # Randomly select a noble gas< / span >
< span class = "n" > noble_gas< / span > < span class = "o" > =< / span > < span class = "n" > noble_gases< / 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" > noble_gases< / span > < span class = "p" > )< / span > < span class = "o" > -< / span > < span class = "mi" > 1< / span > < span class = "p" > )]< / span >
< span class = "c1" > # Send the announce including the app data< / span >
< span class = "n" > destination_2< / span > < span class = "o" > .< / span > < span class = "n" > announce< / span > < span class = "p" > (< / span > < span class = "n" > app_data< / span > < span class = "o" > =< / span > < span class = "n" > noble_gas< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / 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_2< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " (" < / span > < span class = "o" > +< / span > < span class = "n" > destination_2< / span > < span class = "o" > .< / span > < span class = "n" > name< / span > < span class = "o" > +< / span > < span class = "s2" > " )" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We will need to define an announce handler class that< / span >
< span class = "c1" > # Reticulum can message when an announce arrives.< / span >
< span class = "k" > class< / span > < span class = "nc" > ExampleAnnounceHandler< / span > < span class = "p" > :< / span >
< span class = "c1" > # The initialisation method takes the optional< / span >
< span class = "c1" > # aspect_filter argument. If aspect_filter is set to< / span >
< span class = "c1" > # None, all announces will be passed to the instance.< / span >
< span class = "c1" > # If only some announces are wanted, it can be set to< / span >
< span class = "c1" > # an aspect string.< / span >
< span class = "k" > def< / span > < span class = "fm" > __init__< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ,< / span > < span class = "n" > aspect_filter< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ):< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > aspect_filter< / span > < span class = "o" > =< / span > < span class = "n" > aspect_filter< / span >
< span class = "c1" > # This method will be called by Reticulums Transport< / span >
< span class = "c1" > # system when an announce arrives that matches the< / span >
< span class = "c1" > # configured aspect filter. Filters must be specific,< / span >
< span class = "c1" > # and cannot use wildcards.< / span >
< span class = "k" > def< / span > < span class = "nf" > received_announce< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ,< / span > < span class = "n" > destination_hash< / span > < span class = "p" > ,< / span > < span class = "n" > announced_identity< / span > < span class = "p" > ,< / span > < span class = "n" > app_data< / 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" > " Received an 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_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" > " The announce contained the following app data: " < / span > < span class = "o" > +< / span > < span class = "n" > app_data< / 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 = "c1" > ##########################################################< / span >
< span class = "c1" > #### Program Startup #####################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This part of the program gets run at startup,< / span >
< span class = "c1" > # and parses input from the user, and then starts< / span >
< span class = "c1" > # 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" > " Reticulum example that demonstrates announces and announce handlers" < / 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" > 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 = "n" > program_setup< / 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/Announce.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Announce.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / div >
< div class = "section" id = "broadcast" >
< span id = "example-broadcast" > < / span > < h2 > Broadcast< a class = "headerlink" href = "#broadcast" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > The < em > Broadcast< / em > example explores how to transmit plaintext broadcast messages
over the network.< / p >
2021-05-17 06:10:47 -06:00
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates broadcasting unencrypted #< / span >
< span class = "c1" > # information to any listening destinations. #< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "kn" > import< / span > < span class = "nn" > sys< / 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 basic 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" > # This initialisation is executed when the program is started< / span >
< span class = "k" > def< / span > < span class = "nf" > program_setup< / span > < span class = "p" > (< / span > < span class = "n" > configpath< / span > < span class = "p" > ,< / span > < span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "kc" > None< / 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" > # If the user did not select a " channel" we use< / span >
< span class = "c1" > # a default one called " public_information" .< / span >
< span class = "c1" > # This " channel" is added to the destination name-< / span >
< span class = "c1" > # space, so the user can select different broadcast< / span >
< span class = "c1" > # channels.< / span >
< span class = "k" > if< / span > < span class = "n" > channel< / span > < span class = "o" > ==< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "s2" > " public_information" < / span >
< span class = "c1" > # We create a PLAIN destination. This is an uncencrypted endpoint< / span >
< span class = "c1" > # that anyone can listen to and send information to.< / span >
< span class = "n" > broadcast_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 = "kc" > None< / 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" > PLAIN< / span > < span class = "p" > ,< / span > < span class = "n" > APP_NAME< / span > < span class = "p" > ,< / span > < span class = "s2" > " broadcast" < / span > < span class = "p" > ,< / span > < span class = "n" > channel< / span > < span class = "p" > )< / span >
< span class = "c1" > # We specify a callback that will get called every time< / span >
< span class = "c1" > # the destination receives data.< / span >
< span class = "n" > broadcast_destination< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_callback< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything' s ready!< / span >
< span class = "c1" > # Let' s hand over control to the main loop< / span >
< span class = "n" > broadcastLoop< / span > < span class = "p" > (< / span > < span class = "n" > broadcast_destination< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > ,< / span > < span class = "n" > packet< / span > < span class = "p" > ):< / span >
< span class = "c1" > # Simply print out the received data< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " Received data: " < / span > < span class = "o" > +< / span > < span class = "n" > data< / 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 = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \r\n< / 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" > sys< / span > < span class = "o" > .< / span > < span class = "n" > stdout< / span > < span class = "o" > .< / span > < span class = "n" > flush< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > broadcastLoop< / 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" > " Broadcast 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, enter text and hit enter to broadcast (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 send the information< / span >
< span class = "c1" > # that the user entered into the prompt.< / span >
< span class = "k" > while< / span > < span class = "kc" > True< / 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" > entered< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "n" > entered< / span > < span class = "o" > !=< / span > < span class = "s2" > " " < / span > < span class = "p" > :< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > entered< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / span > < span class = "p" > )< / span >
< span class = "n" > packet< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
< span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > send< / 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 gets run at startup,< / span >
< span class = "c1" > # and parses input from the user, and then starts< / span >
< span class = "c1" > # the program.< / 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" > " Reticulum example that demonstrates sending and receiving unencrypted broadcasts" < / 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" > " --channel" < / 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" > " broadcast channel name" < / 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" > channel< / span > < span class = "p" > :< / span >
< span class = "n" > channelarg< / span > < span class = "o" > =< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > channel< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > channelarg< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > program_setup< / span > < span class = "p" > (< / span > < span class = "n" > configarg< / span > < span class = "p" > ,< / span > < span class = "n" > channelarg< / 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/Broadcast.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Broadcast.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / div >
< div class = "section" id = "echo" >
< span id = "example-echo" > < / span > < h2 > Echo< a class = "headerlink" href = "#echo" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > The < em > Echo< / em > example demonstrates communication between two destinations using
the Packet interface.< / p >
2021-05-17 06:10:47 -06:00
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates a simple client/server #< / span >
< span class = "c1" > # echo utility. A client can send an echo request to the #< / span >
< span class = "c1" > # server, and the server will respond by proving receipt #< / span >
< span class = "c1" > # of the packet. #< / span >
< span class = "c1" > ##########################################################< / 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" > # 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 echo server< / 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 query. We want< / span >
< span class = "c1" > # to be able to verify echo replies to our clients, so we< / span >
< span class = "c1" > # create a " single" destination that can receive encrypted< / span >
< span class = "c1" > # messages. This way the client can send a request and be< / span >
< span class = "c1" > # certain that no-one else than this destination was able< / span >
< span class = "c1" > # to read it. < / span >
< span class = "n" > echo_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" > " echo" < / span > < span class = "p" > ,< / span > < span class = "s2" > " request" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We configure the destination to automatically prove all< / span >
< span class = "c1" > # packets adressed to it. By doing this, RNS will automatically< / span >
< span class = "c1" > # generate a proof for each incoming packet and transmit it< / span >
< span class = "c1" > # back to the sender of that packet.< / span >
< span class = "n" > echo_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_proof_strategy< / 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" > PROVE_ALL< / span > < span class = "p" > )< / span >
< span class = "c1" > # Tell the destination which function in our program to< / span >
< span class = "c1" > # run when a packet is received. We do this so we can< / span >
< span class = "c1" > # print a log message when the server receives a request< / span >
< span class = "n" > echo_destination< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > server_callback< / 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" > announceLoop< / span > < span class = "p" > (< / span > < span class = "n" > echo_destination< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > announceLoop< / 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" > " Echo server " < / 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, 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 = "k" > def< / span > < span class = "nf" > server_callback< / 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 = "c1" > # Tell the user that we received an echo request, and< / span >
< span class = "c1" > # that we are going to send a reply to the requester.< / span >
< span class = "c1" > # Sending the proof is handled automatically, since we< / span >
< span class = "c1" > # set up the destination to prove all incoming packets.< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Received packet from echo client, proof sent" < / span > < span class = "p" > )< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Client Part #########################################< / span >
< span class = "c1" > ##########################################################< / 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 = "n" > timeout< / span > < span class = "o" > =< / span > < span class = "kc" > None< / 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" > # We override the loglevel to provide feedback when< / span >
< span class = "c1" > # an announce is received< / span >
< span class = "k" > if< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > loglevel< / span > < span class = "o" > < < / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_INFO< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > loglevel< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_INFO< / span >
< span class = "c1" > # Tell the user that the client is ready!< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Echo client ready, hit enter to send echo request to " < / span > < span class = "o" > +< / span > < span class = "n" > destination_hexhash< / span > < span class = "o" > +< / span > < span class = "s2" > " (Ctrl-C to quit)" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We enter a loop that runs until the user exits.< / span >
< span class = "c1" > # If the user hits enter, we will try to send an< / span >
< span class = "c1" > # echo request to the destination specified on the< / span >
< span class = "c1" > # command line.< / span >
< span class = "k" > while< / span > < span class = "kc" > True< / span > < span class = "p" > :< / span >
< span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Let' s first check if RNS knows a path to the destination.< / span >
< span class = "c1" > # If it does, we' ll load the server identity and create a packet< / span >
< span class = "k" > if< / 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 = "c1" > # To address the server, we need to know it' s public< / span >
< span class = "c1" > # key, so we check if Reticulum knows this destination.< / span >
< span class = "c1" > # This is done by calling the " recall" method of the< / span >
< span class = "c1" > # Identity module. If the destination is known, it will< / span >
< span class = "c1" > # return an Identity instance that can be used in< / span >
< span class = "c1" > # outgoing destinations.< / 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" > # We got the correct identity instance from the< / span >
< span class = "c1" > # recall method, so let' s create an outgoing< / span >
< span class = "c1" > # destination. We use the naming convention:< / span >
< span class = "c1" > # example_utilities.echo.request< / span >
< span class = "c1" > # This matches the naming we specified in the< / span >
< span class = "c1" > # server part of the code.< / span >
< span class = "n" > request_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" > " echo" < / span > < span class = "p" > ,< / span > < span class = "s2" > " request" < / span > < span class = "p" > )< / span >
< span class = "c1" > # The destination is ready, so let' s create a packet.< / span >
< span class = "c1" > # We set the destination to the request_destination< / span >
< span class = "c1" > # that was just created, and the only data we add< / span >
< span class = "c1" > # is a random hash.< / span >
< span class = "n" > echo_request< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > request_destination< / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Identity< / span > < span class = "o" > .< / span > < span class = "n" > get_random_hash< / span > < span class = "p" > ())< / span >
< span class = "c1" > # Send the packet! If the packet is successfully< / span >
< span class = "c1" > # sent, it will return a PacketReceipt instance.< / span >
< span class = "n" > packet_receipt< / span > < span class = "o" > =< / span > < span class = "n" > echo_request< / span > < span class = "o" > .< / span > < span class = "n" > send< / span > < span class = "p" > ()< / span >
< span class = "c1" > # If the user specified a timeout, we set this< / span >
< span class = "c1" > # timeout on the packet receipt, and configure< / span >
< span class = "c1" > # a callback function, that will get called if< / span >
< span class = "c1" > # the packet times out.< / span >
< span class = "k" > if< / span > < span class = "n" > timeout< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > packet_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_timeout< / span > < span class = "p" > (< / span > < span class = "n" > timeout< / span > < span class = "p" > )< / span >
< span class = "n" > packet_receipt< / span > < span class = "o" > .< / span > < span class = "n" > timeout_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_timed_out< / span > < span class = "p" > )< / span >
< span class = "c1" > # We can then set a delivery callback on the receipt.< / span >
< span class = "c1" > # This will get automatically called when a proof for< / span >
< span class = "c1" > # this specific packet is received from the destination.< / span >
< span class = "n" > packet_receipt< / span > < span class = "o" > .< / span > < span class = "n" > delivery_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_delivered< / span > < span class = "p" > )< / span >
< span class = "c1" > # Tell the user that the echo request was sent< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Sent echo request to " < / 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_destination< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > ))< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "c1" > # If we do not know this destination, tell the< / span >
< span class = "c1" > # user to wait for an announce to arrive.< / 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..." < / 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 = "c1" > # This function is called when our reply destination< / span >
< span class = "c1" > # receives a proof packet.< / span >
< span class = "k" > def< / span > < span class = "nf" > packet_delivered< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > PacketReceipt< / span > < span class = "o" > .< / span > < span class = "n" > DELIVERED< / span > < span class = "p" > :< / span >
< span class = "n" > rtt< / span > < span class = "o" > =< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > rtt< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > rtt< / span > < span class = "o" > > =< / span > < span class = "mi" > 1< / span > < span class = "p" > ):< / span >
< span class = "n" > rtt< / span > < span class = "o" > =< / span > < span class = "nb" > round< / span > < span class = "p" > (< / span > < span class = "n" > rtt< / span > < span class = "p" > ,< / span > < span class = "mi" > 3< / span > < span class = "p" > )< / span >
< span class = "n" > rttstring< / span > < span class = "o" > =< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > rtt< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " seconds" < / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > rtt< / span > < span class = "o" > =< / span > < span class = "nb" > round< / span > < span class = "p" > (< / span > < span class = "n" > rtt< / span > < span class = "o" > *< / span > < span class = "mi" > 1000< / span > < span class = "p" > ,< / span > < span class = "mi" > 3< / span > < span class = "p" > )< / span >
< span class = "n" > rttstring< / span > < span class = "o" > =< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > rtt< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " milliseconds" < / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Valid reply received 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" > receipt< / span > < span class = "o" > .< / 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" > " , round-trip time is " < / span > < span class = "o" > +< / span > < span class = "n" > rttstring< / span > < span class = "p" > )< / span >
< span class = "c1" > # This function is called if a packet times out.< / span >
< span class = "k" > def< / span > < span class = "nf" > packet_timed_out< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > PacketReceipt< / span > < span class = "o" > .< / span > < span class = "n" > FAILED< / 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" > " Packet " < / 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" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " timed out" < / 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 gets run at startup,< / span >
< span class = "c1" > # and parses input from the user, and then starts< / span >
< span class = "c1" > # 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 echo server and client utility" < / 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 packets 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" > " -t" < / span > < span class = "p" > ,< / span > < span class = "s2" > " --timeout" < / 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" > metavar< / span > < span class = "o" > =< / span > < span class = "s2" > " s" < / 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" > " set a reply timeout in seconds" < / span > < span class = "p" > ,< / span > < span class = "nb" > type< / span > < span class = "o" > =< / span > < span class = "nb" > float< / 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" > server< / 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" > 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 = "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 = "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" > timeout< / span > < span class = "p" > :< / span >
< span class = "n" > timeoutarg< / span > < span class = "o" > =< / span > < span class = "nb" > float< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > timeout< / span > < span class = "p" > )< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > timeoutarg< / span > < span class = "o" > =< / span > < span class = "kc" > None< / 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 = "n" > timeout< / span > < span class = "o" > =< / span > < span class = "n" > timeoutarg< / 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/Echo.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Echo.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / div >
< div class = "section" id = "link" >
< span id = "example-link" > < / span > < h2 > Link< a class = "headerlink" href = "#link" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > The < em > Link< / em > example explores establishing an encrypted link to a remote
destination, and passing traffic back and forth over the link.< / p >
2021-05-17 06:10:47 -06:00
< 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 up a link to #< / span >
< span class = "c1" > # a destination, and pass data back and forth over it. #< / 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" > 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 = "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" > " linkexample" < / 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" > link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / 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" > " Link 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" > link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > server_packet_received< / 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 = "k" > def< / span > < span class = "nf" > server_packet_received< / 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" > latest_client_link< / span >
< span class = "c1" > # When data is received over any active link,< / span >
< span class = "c1" > # it will all be directed to the last client< / span >
< span class = "c1" > # that connected.< / span >
< span class = "n" > text< / 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 = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Received data on the link: " < / span > < span class = "o" > +< / span > < span class = "n" > text< / span > < span class = "p" > )< / span >
< span class = "n" > reply_text< / span > < span class = "o" > =< / span > < span class = "s2" > " I received < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > text< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > over the link" < / span >
< span class = "n" > reply_data< / span > < span class = "o" > =< / span > < span class = "n" > reply_text< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / span > < span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > latest_client_link< / span > < span class = "p" > ,< / span > < span class = "n" > reply_data< / span > < span class = "p" > )< / span > < span class = "o" > .< / span > < span class = "n" > send< / 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" > " linkexample" < / 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 set a callback that will get executed< / span >
< span class = "c1" > # every time a packet is received over the< / span >
< span class = "c1" > # link< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_packet_received< / span > < span class = "p" > )< / span >
< span class = "c1" > # We' ll also 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" > 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" > 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 = "c1" > # If not, send the entered text over the link< / span >
< span class = "k" > if< / span > < span class = "n" > text< / span > < span class = "o" > !=< / span > < span class = "s2" > " " < / span > < span class = "p" > :< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > text< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / span > < span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > server_link< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > )< / span > < span class = "o" > .< / span > < span class = "n" > send< / 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" > 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 = "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, enter some text to send, or < / 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" > # When a packet is received over the link, we< / span >
< span class = "c1" > # simply print out the data.< / span >
< span class = "k" > def< / span > < span class = "nf" > client_packet_received< / 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 = "n" > text< / 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 = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Received data on the link: " < / span > < span class = "o" > +< / span > < span class = "n" > text< / 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" > sys< / span > < span class = "o" > .< / span > < span class = "n" > stdout< / span > < span class = "o" > .< / span > < span class = "n" > flush< / 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 link 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 link 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/Link.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Link.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / 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
allow clients to connect and download files. The program uses the Resource
interface to efficiently pass files of any size over a Reticulum < a class = "reference internal" href = "reference.html#api-link" > < span class = "std std-ref" > Link< / span > < / a > .< / p >
2021-05-17 06:10:47 -06:00
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates a simple filetransfer #< / span >
< span class = "c1" > # server and client program. The server will serve a #< / span >
< span class = "c1" > # directory of files, and the clients can list and #< / span >
< span class = "c1" > # download files from the server. #< / span >
< span class = "c1" > # #< / span >
< span class = "c1" > # Please note that using RNS Resources for large file #< / span >
< span class = "c1" > # transfers is not recommended, since compression, #< / span >
< span class = "c1" > # encryption and hashmap sequencing can take a long time #< / span >
< span class = "c1" > # on systems with slow CPUs, which will probably result #< / span >
< span class = "c1" > # in the client timing out before the resource sender #< / span >
< span class = "c1" > # can complete preparing the resource. #< / span >
< span class = "c1" > # #< / span >
< span class = "c1" > # If you need to transfer large files, use the Bundle #< / span >
< span class = "c1" > # class instead, which will automatically slice the data #< / span >
< span class = "c1" > # into chunks suitable for packing as a Resource. #< / 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" > threading< / span >
< span class = "kn" > import< / span > < span class = "nn" > argparse< / span >
< span class = "kn" > import< / span > < span class = "nn" > RNS< / span >
< span class = "kn" > import< / span > < span class = "nn" > RNS.vendor.umsgpack< / span > < span class = "k" > as< / span > < span class = "nn" > umsgpack< / 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" > # We' ll also define a default timeout, in seconds< / span >
< span class = "n" > APP_TIMEOUT< / span > < span class = "o" > =< / span > < span class = "mf" > 45.0< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Server Part #########################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "n" > serve_path< / 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 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 = "n" > path< / 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 file server< / 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 = "k" > global< / span > < span class = "n" > serve_path< / span >
< span class = "n" > serve_path< / span > < span class = "o" > =< / span > < span class = "n" > path< / 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" > " filetransfer" < / span > < span class = "p" > ,< / span > < span class = "s2" > " server" < / 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" > link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / 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" > announceLoop< / span > < span class = "p" > (< / span > < span class = "n" > server_destination< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > announceLoop< / 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" > " File server " < / 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" < / 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" > # Here' s a convenience function for listing all files< / span >
< span class = "c1" > # in our served directory< / span >
< span class = "k" > def< / span > < span class = "nf" > list_files< / span > < span class = "p" > ():< / span >
< span class = "c1" > # We add all entries from the directory that are< / span >
< span class = "c1" > # actual files, and does not start with " ." < / span >
< span class = "k" > global< / span > < span class = "n" > serve_path< / span >
< span class = "k" > return< / span > < span class = "p" > [< / span > < span class = "n" > file< / span > < span class = "k" > for< / span > < span class = "n" > file< / span > < span class = "ow" > in< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > listdir< / span > < span class = "p" > (< / span > < span class = "n" > serve_path< / span > < span class = "p" > )< / span > < span class = "k" > if< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > isfile< / span > < span class = "p" > (< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > join< / span > < span class = "p" > (< / span > < span class = "n" > serve_path< / span > < span class = "p" > ,< / span > < span class = "n" > file< / span > < span class = "p" > ))< / span > < span class = "ow" > and< / span > < span class = "n" > file< / span > < span class = "p" > [:< / span > < span class = "mi" > 1< / span > < span class = "p" > ]< / span > < span class = "o" > !=< / span > < span class = "s2" > " ." < / 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. We then send the client< / span >
< span class = "c1" > # a list of files hosted on the server.< / 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 = "c1" > # Check if the served directory still exists< / span >
< span class = "k" > if< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > isdir< / span > < span class = "p" > (< / span > < span class = "n" > serve_path< / 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 connected, sending file list..." < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "c1" > # We pack a list of files for sending in a packet< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > umsgpack< / span > < span class = "o" > .< / span > < span class = "n" > packb< / span > < span class = "p" > (< / span > < span class = "n" > list_files< / span > < span class = "p" > ())< / span >
< span class = "c1" > # Check the size of the packed data< / span >
< span class = "k" > if< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )< / 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" > MDU< / span > < span class = "p" > :< / span >
< span class = "c1" > # If it fits in one packet, we will just< / span >
< span class = "c1" > # send it as a single packet over the link.< / span >
< span class = "n" > list_packet< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
< span class = "n" > list_receipt< / span > < span class = "o" > =< / span > < span class = "n" > list_packet< / span > < span class = "o" > .< / span > < span class = "n" > send< / span > < span class = "p" > ()< / span >
< span class = "n" > list_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_timeout< / span > < span class = "p" > (< / span > < span class = "n" > APP_TIMEOUT< / span > < span class = "p" > )< / span >
< span class = "n" > list_receipt< / span > < span class = "o" > .< / span > < span class = "n" > delivery_callback< / span > < span class = "p" > (< / span > < span class = "n" > list_delivered< / span > < span class = "p" > )< / span >
< span class = "n" > list_receipt< / span > < span class = "o" > .< / span > < span class = "n" > timeout_callback< / span > < span class = "p" > (< / span > < span class = "n" > list_timeout< / 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" > " Too many files in served directory!" < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / 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" > " You should implement a function to split the filelist over multiple packets." < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / 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" > " Hint: The client already supports it :)" < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / span > < span class = "p" > )< / span >
< span class = "c1" > # After this, we' re just going to keep the link< / span >
< span class = "c1" > # open until the client requests a file. We' ll< / span >
< span class = "c1" > # configure a function that get' s called when< / span >
< span class = "c1" > # the client sends a packet with a file request.< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_request< / 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" > " Client connected, but served path no longer exists!" < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / 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 = "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" > 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 >
< span class = "c1" > # read it and pack it as a resource< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client requested < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > filename< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "p" > )< / span >
< span class = "n" > file< / span > < span class = "o" > =< / span > < span class = "nb" > open< / span > < span class = "p" > (< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > join< / span > < span class = "p" > (< / span > < span class = "n" > serve_path< / span > < span class = "p" > ,< / span > < span class = "n" > filename< / span > < span class = "p" > ),< / span > < span class = "s2" > " rb" < / span > < span class = "p" > )< / span >
< span class = "n" > file_resource< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "p" > (< / span > < span class = "n" > file< / span > < span class = "p" > ,< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > link< / span > < span class = "p" > ,< / span > < span class = "n" > callback< / span > < span class = "o" > =< / span > < span class = "n" > resource_sending_concluded< / span > < span class = "p" > )< / span >
< span class = "n" > file_resource< / span > < span class = "o" > .< / span > < span class = "n" > filename< / span > < span class = "o" > =< / span > < span class = "n" > filename< / 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 = "c1" > # If somethign went wrong, we close< / span >
< span class = "c1" > # the link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while reading file < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > filename< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / span > < span class = "p" > )< / span >
< span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "k" > raise< / span > < span class = "n" > e< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "c1" > # If we don' t have it, we close the link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client requested an unknown file" < / span > < span class = "p" > )< / span >
< span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "c1" > # This function is called on the server when a< / span >
< span class = "c1" > # resource transfer concludes.< / span >
< span class = "k" > def< / span > < span class = "nf" > resource_sending_concluded< / span > < span class = "p" > (< / span > < span class = "n" > resource< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "nb" > hasattr< / span > < span class = "p" > (< / span > < span class = "n" > resource< / span > < span class = "p" > ,< / span > < span class = "s2" > " filename" < / span > < span class = "p" > ):< / span >
< span class = "n" > name< / span > < span class = "o" > =< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > filename< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > name< / span > < span class = "o" > =< / span > < span class = "s2" > " resource" < / span >
< span class = "k" > if< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "o" > .< / span > < span class = "n" > COMPLETE< / 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" > " Done sending < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > name< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > to client" < / span > < span class = "p" > )< / span >
< span class = "k" > elif< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "o" > .< / span > < span class = "n" > FAILED< / 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" > " Sending < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > name< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > to client failed" < / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > list_delivered< / span > < span class = "p" > (< / span > < span class = "n" > 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 file list was received by the client" < / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > list_timeout< / span > < span class = "p" > (< / span > < span class = "n" > 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" > " Sending list to client timed out, closing this link" < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > =< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > destination< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Client Part #########################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # We store a global list of files available on the server< / span >
< span class = "n" > server_files< / span > < span class = "o" > =< / span > < span class = "p" > []< / 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" > # And a reference to the current download< / span >
< span class = "n" > current_download< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > current_filename< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "c1" > # Variables to store download statistics< / span >
< span class = "n" > download_started< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "n" > download_finished< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "n" > download_time< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "n" > transfer_size< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "n" > file_size< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / 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" > " filetransfer" < / span > < span class = "p" > ,< / span > < span class = "s2" > " server" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We also want to automatically prove incoming packets< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_proof_strategy< / 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" > PROVE_ALL< / 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 expect any normal data packets on the link< / span >
< span class = "c1" > # to contain a list of served files, so we set< / span >
< span class = "c1" > # a callback accordingly< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > filelist_received< / span > < span class = "p" > )< / span >
< span class = "c1" > # We' ll also 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" > 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" > link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
< span class = "c1" > # And set the link to automatically begin< / span >
< span class = "c1" > # downloading advertised resources< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_resource_strategy< / span > < span class = "p" > (< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "o" > .< / span > < span class = "n" > ACCEPT_ALL< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > resource_started_callback< / span > < span class = "p" > (< / span > < span class = "n" > download_began< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > resource_concluded_callback< / span > < span class = "p" > (< / span > < span class = "n" > download_concluded< / span > < span class = "p" > )< / span >
< span class = "n" > menu< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Requests the specified file from the server< / span >
< span class = "k" > def< / span > < span class = "nf" > download< / span > < span class = "p" > (< / span > < span class = "n" > filename< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span > < span class = "p" > ,< / span > < span class = "n" > menu_mode< / span > < span class = "p" > ,< / span > < span class = "n" > current_filename< / span > < span class = "p" > ,< / span > < span class = "n" > transfer_size< / span > < span class = "p" > ,< / span > < span class = "n" > download_started< / span >
< span class = "n" > current_filename< / span > < span class = "o" > =< / span > < span class = "n" > filename< / span >
< span class = "n" > download_started< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "n" > transfer_size< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "c1" > # We just create a packet containing the< / span >
< span class = "c1" > # requested filename, and send it down the< / span >
< span class = "c1" > # link. We also specify we don' t need a< / span >
< span class = "c1" > # packet receipt.< / span >
< span class = "n" > request_packet< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Packet< / span > < span class = "p" > (< / span > < span class = "n" > server_link< / span > < span class = "p" > ,< / span > < span class = "n" > filename< / span > < span class = "o" > .< / span > < span class = "n" > encode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / span > < span class = "p" > ),< / span > < span class = "n" > create_receipt< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span > < span class = "p" > )< / span >
< span class = "n" > request_packet< / span > < span class = "o" > .< / span > < span class = "n" > send< / span > < span class = "p" > ()< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > ((< / span > < span class = "s2" > " Requested < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > filename< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > from server, waiting for download to begin..." < / span > < span class = "p" > ))< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " download_started" < / span >
< span class = "c1" > # This function runs a simple menu for the user< / span >
< span class = "c1" > # to select which files to download, or quit< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "k" > def< / span > < span class = "nf" > menu< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_files< / span > < span class = "p" > ,< / span > < span class = "n" > server_link< / span >
< span class = "c1" > # Wait until we have a filelist< / span >
< span class = "k" > while< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > server_files< / span > < span class = "p" > )< / span > < span class = "o" > ==< / span > < span class = "mi" > 0< / 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" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Ready!" < / 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.5< / span > < span class = "p" > )< / span >
< span class = "k" > global< / span > < span class = "n" > menu_mode< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " main" < / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "k" > while< / span > < span class = "p" > (< / span > < span class = "ow" > not< / span > < span class = "n" > should_quit< / span > < span class = "p" > ):< / span >
< span class = "n" > print_menu< / span > < span class = "p" > ()< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " main" < / span > < span class = "p" > :< / span >
< span class = "c1" > # Wait< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.25< / span > < span class = "p" > )< / span >
< span class = "n" > user_input< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "n" > user_input< / span > < span class = "o" > ==< / span > < span class = "s2" > " q" < / span > < span class = "ow" > or< / span > < span class = "n" > user_input< / span > < span class = "o" > ==< / span > < span class = "s2" > " quit" < / span > < span class = "ow" > or< / span > < span class = "n" > user_input< / 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 = "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 = "k" > if< / span > < span class = "n" > user_input< / span > < span class = "ow" > in< / span > < span class = "n" > server_files< / span > < span class = "p" > :< / span >
< span class = "n" > download< / span > < span class = "p" > (< / span > < span class = "n" > user_input< / span > < span class = "p" > )< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "mi" > 0< / span > < span class = "o" > < =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > user_input< / span > < span class = "p" > )< / span > < span class = "o" > < < / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > server_files< / span > < span class = "p" > ):< / span >
< span class = "n" > download< / span > < span class = "p" > (< / span > < span class = "n" > server_files< / span > < span class = "p" > [< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > user_input< / span > < span class = "p" > )])< / span >
< span class = "k" > except< / span > < span class = "p" > :< / span >
< span class = "k" > pass< / span >
< span class = "k" > if< / span > < span class = "n" > should_quit< / span > < span class = "p" > :< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Prints out menus or screens for the< / span >
< span class = "c1" > # various states of the client program.< / span >
< span class = "c1" > # It' s simple and quite uninteresting.< / span >
< span class = "c1" > # I won' t go into detail here. Just< / span >
< span class = "c1" > # strings basically.< / span >
< span class = "k" > def< / span > < span class = "nf" > print_menu< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > menu_mode< / span > < span class = "p" > ,< / span > < span class = "n" > download_time< / span > < span class = "p" > ,< / span > < span class = "n" > download_started< / span > < span class = "p" > ,< / span > < span class = "n" > download_finished< / span > < span class = "p" > ,< / span > < span class = "n" > transfer_size< / span > < span class = "p" > ,< / span > < span class = "n" > file_size< / span >
< span class = "k" > if< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " main" < / span > < span class = "p" > :< / span >
< span class = "n" > clear_screen< / span > < span class = "p" > ()< / span >
< span class = "n" > print_filelist< / span > < span class = "p" > ()< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " Select a file to download by entering name or number, or q to quit" < / 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 = "s1" > ' ' < / span > < span class = "p" > )< / span >
< span class = "k" > elif< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " download_started" < / span > < span class = "p" > :< / span >
< span class = "n" > download_began< / span > < span class = "o" > =< / span > < span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > time< / span > < span class = "p" > ()< / span >
< span class = "k" > while< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " download_started" < / 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 = "k" > if< / span > < span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > time< / span > < span class = "p" > ()< / span > < span class = "o" > > < / span > < span class = "n" > download_began< / span > < span class = "o" > +< / span > < span class = "n" > APP_TIMEOUT< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " The download timed out" < / 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 = "mi" > 1< / span > < span class = "p" > )< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " downloading" < / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " Download started" < / 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" > while< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " downloading" < / span > < span class = "p" > :< / span >
< span class = "k" > global< / span > < span class = "n" > current_download< / span >
< span class = "n" > percent< / span > < span class = "o" > =< / span > < span class = "nb" > round< / span > < span class = "p" > (< / span > < span class = "n" > current_download< / span > < span class = "o" > .< / span > < span class = "n" > progress< / span > < span class = "p" > ()< / span > < span class = "o" > *< / span > < span class = "mf" > 100.0< / span > < span class = "p" > ,< / span > < span class = "mi" > 1< / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > ((< / span > < span class = "s2" > " < / span > < span class = "se" > \r< / span > < span class = "s2" > Progress: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > percent< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " % " < / span > < span class = "p" > ),< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s1" > ' ' < / span > < span class = "p" > )< / span >
< span class = "n" > sys< / span > < span class = "o" > .< / span > < span class = "n" > stdout< / span > < span class = "o" > .< / span > < span class = "n" > flush< / 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 = "k" > if< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " save_error" < / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > ((< / span > < span class = "s2" > " < / span > < span class = "se" > \r< / span > < span class = "s2" > Progress: 100.0 %" < / span > < span class = "p" > ),< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s1" > ' ' < / span > < span class = "p" > )< / span >
< span class = "n" > sys< / span > < span class = "o" > .< / span > < span class = "n" > stdout< / span > < span class = "o" > .< / span > < span class = "n" > flush< / span > < span class = "p" > ()< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " Could not write downloaded file to disk" < / span > < span class = "p" > )< / span >
< span class = "n" > current_download< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "o" > .< / span > < span class = "n" > FAILED< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " download_concluded" < / span >
< span class = "k" > if< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " download_concluded" < / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "n" > current_download< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "o" > .< / span > < span class = "n" > COMPLETE< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > ((< / span > < span class = "s2" > " < / span > < span class = "se" > \r< / span > < span class = "s2" > Progress: 100.0 %" < / span > < span class = "p" > ),< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s1" > ' ' < / span > < span class = "p" > )< / span >
< span class = "n" > sys< / span > < span class = "o" > .< / span > < span class = "n" > stdout< / span > < span class = "o" > .< / span > < span class = "n" > flush< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Print statistics< / span >
< span class = "n" > hours< / span > < span class = "p" > ,< / span > < span class = "n" > rem< / span > < span class = "o" > =< / span > < span class = "nb" > divmod< / span > < span class = "p" > (< / span > < span class = "n" > download_time< / span > < span class = "p" > ,< / span > < span class = "mi" > 3600< / span > < span class = "p" > )< / span >
< span class = "n" > minutes< / span > < span class = "p" > ,< / span > < span class = "n" > seconds< / span > < span class = "o" > =< / span > < span class = "nb" > divmod< / span > < span class = "p" > (< / span > < span class = "n" > rem< / span > < span class = "p" > ,< / span > < span class = "mi" > 60< / span > < span class = "p" > )< / span >
< span class = "n" > timestring< / span > < span class = "o" > =< / span > < span class = "s2" > " < / span > < span class = "si" > {:0> 2}< / span > < span class = "s2" > :< / span > < span class = "si" > {:0> 2}< / span > < span class = "s2" > :< / span > < span class = "si" > {:05.2f}< / span > < span class = "s2" > " < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > hours< / span > < span class = "p" > ),< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > minutes< / span > < span class = "p" > ),< / span > < span class = "n" > seconds< / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " --- Statistics -----" < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > Time taken : " < / span > < span class = "o" > +< / span > < span class = "n" > timestring< / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > File size : " < / span > < span class = "o" > +< / span > < span class = "n" > size_str< / span > < span class = "p" > (< / span > < span class = "n" > file_size< / span > < span class = "p" > ))< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > Data transferred : " < / span > < span class = "o" > +< / span > < span class = "n" > size_str< / span > < span class = "p" > (< / span > < span class = "n" > transfer_size< / span > < span class = "p" > ))< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > Effective rate : " < / span > < span class = "o" > +< / span > < span class = "n" > size_str< / span > < span class = "p" > (< / span > < span class = "n" > file_size< / span > < span class = "o" > /< / span > < span class = "n" > download_time< / span > < span class = "p" > ,< / span > < span class = "n" > suffix< / span > < span class = "o" > =< / span > < span class = "s1" > ' b' < / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " /s" < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > Transfer rate : " < / span > < span class = "o" > +< / span > < span class = "n" > size_str< / span > < span class = "p" > (< / span > < span class = "n" > transfer_size< / span > < span class = "o" > /< / span > < span class = "n" > download_time< / span > < span class = "p" > ,< / span > < span class = "n" > suffix< / span > < span class = "o" > =< / span > < span class = "s1" > ' b' < / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " /s" < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " The download completed! Press enter to return to the menu." < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " The download failed! Press enter to return to the menu." < / span > < span class = "p" > )< / span >
< span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "n" > current_download< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " main" < / span >
< span class = "n" > print_menu< / span > < span class = "p" > ()< / span >
< span class = "c1" > # This function prints out a list of files< / span >
< span class = "c1" > # on the connected server.< / span >
< span class = "k" > def< / span > < span class = "nf" > print_filelist< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_files< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " Files on server:" < / span > < span class = "p" > )< / span >
< span class = "k" > for< / span > < span class = "n" > index< / span > < span class = "p" > ,< / span > < span class = "n" > file< / span > < span class = "ow" > in< / span > < span class = "nb" > enumerate< / span > < span class = "p" > (< / span > < span class = "n" > server_files< / span > < span class = "p" > ):< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " < / span > < span class = "se" > \t< / span > < span class = "s2" > (" < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > index< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " )< / span > < span class = "se" > \t< / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > file< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > filelist_received< / span > < span class = "p" > (< / span > < span class = "n" > filelist_data< / span > < span class = "p" > ,< / span > < span class = "n" > packet< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > server_files< / span > < span class = "p" > ,< / span > < span class = "n" > menu_mode< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "c1" > # Unpack the list and extend our< / span >
< span class = "c1" > # local list of available files< / span >
< span class = "n" > filelist< / span > < span class = "o" > =< / span > < span class = "n" > umsgpack< / span > < span class = "o" > .< / span > < span class = "n" > unpackb< / span > < span class = "p" > (< / span > < span class = "n" > filelist_data< / span > < span class = "p" > )< / span >
< span class = "k" > for< / span > < span class = "n" > file< / span > < span class = "ow" > in< / span > < span class = "n" > filelist< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "ow" > not< / span > < span class = "n" > file< / span > < span class = "ow" > in< / span > < span class = "n" > server_files< / span > < span class = "p" > :< / span >
< span class = "n" > server_files< / span > < span class = "o" > .< / span > < span class = "n" > append< / span > < span class = "p" > (< / span > < span class = "n" > file< / span > < span class = "p" > )< / span >
< span class = "c1" > # If the menu is already visible,< / span >
< span class = "c1" > # we' ll update it with what was< / span >
< span class = "c1" > # just received< / span >
< span class = "k" > if< / span > < span class = "n" > menu_mode< / span > < span class = "o" > ==< / span > < span class = "s2" > " main" < / span > < span class = "p" > :< / span >
< span class = "n" > print_menu< / 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 file list data received, closing link" < / span > < span class = "p" > )< / span >
< span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / 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" < / 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" > " Waiting for filelist..." < / span > < span class = "p" > )< / span >
< span class = "c1" > # And set up a small job to check for< / span >
< span class = "c1" > # a potential timeout in receiving the< / span >
< span class = "c1" > # file list< / span >
< span class = "n" > thread< / span > < span class = "o" > =< / span > < span class = "n" > threading< / span > < span class = "o" > .< / span > < span class = "n" > Thread< / span > < span class = "p" > (< / span > < span class = "n" > target< / span > < span class = "o" > =< / span > < span class = "n" > filelist_timeout_job< / span > < span class = "p" > )< / span >
< span class = "n" > thread< / span > < span class = "o" > .< / span > < span class = "n" > setDaemon< / span > < span class = "p" > (< / span > < span class = "kc" > True< / span > < span class = "p" > )< / span >
< span class = "n" > thread< / span > < span class = "o" > .< / span > < span class = "n" > start< / span > < span class = "p" > ()< / span >
< span class = "c1" > # This job just sleeps for the specified< / span >
< span class = "c1" > # time, and then checks if the file list< / span >
< span class = "c1" > # was received. If not, the program will< / span >
< span class = "c1" > # exit.< / span >
< span class = "k" > def< / span > < span class = "nf" > filelist_timeout_job< / 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 = "n" > APP_TIMEOUT< / span > < span class = "p" > )< / span >
< span class = "k" > global< / span > < span class = "n" > server_files< / span >
< span class = "k" > if< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > server_files< / span > < span class = "p" > )< / span > < span class = "o" > ==< / span > < span class = "mi" > 0< / 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" > " Timed out waiting for filelist, exiting" < / 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" > # 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" > # When RNS detects that the download has< / span >
< span class = "c1" > # started, we' ll update our menu state< / span >
< span class = "c1" > # so the user can be shown a progress of< / span >
< span class = "c1" > # the download.< / span >
< span class = "k" > def< / span > < span class = "nf" > download_began< / span > < span class = "p" > (< / span > < span class = "n" > resource< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > menu_mode< / span > < span class = "p" > ,< / span > < span class = "n" > current_download< / span > < span class = "p" > ,< / span > < span class = "n" > download_started< / span > < span class = "p" > ,< / span > < span class = "n" > transfer_size< / span > < span class = "p" > ,< / span > < span class = "n" > file_size< / span >
< span class = "n" > current_download< / span > < span class = "o" > =< / span > < span class = "n" > resource< / span >
< span class = "k" > if< / span > < span class = "n" > download_started< / span > < span class = "o" > ==< / span > < span class = "mi" > 0< / span > < span class = "p" > :< / span >
< span class = "n" > download_started< / span > < span class = "o" > =< / span > < span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > time< / span > < span class = "p" > ()< / span >
< span class = "n" > transfer_size< / span > < span class = "o" > +=< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > size< / span >
< span class = "n" > file_size< / span > < span class = "o" > =< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > total_size< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " downloading" < / span >
< span class = "c1" > # When the download concludes, successfully< / span >
< span class = "c1" > # or not, we' ll update our menu state and < / span >
< span class = "c1" > # inform the user about how it all went.< / span >
< span class = "k" > def< / span > < span class = "nf" > download_concluded< / span > < span class = "p" > (< / span > < span class = "n" > resource< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > menu_mode< / span > < span class = "p" > ,< / span > < span class = "n" > current_filename< / span > < span class = "p" > ,< / span > < span class = "n" > download_started< / span > < span class = "p" > ,< / span > < span class = "n" > download_finished< / span > < span class = "p" > ,< / span > < span class = "n" > download_time< / span >
< span class = "n" > download_finished< / span > < span class = "o" > =< / span > < span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > time< / span > < span class = "p" > ()< / span >
< span class = "n" > download_time< / span > < span class = "o" > =< / span > < span class = "n" > download_finished< / span > < span class = "o" > -< / span > < span class = "n" > download_started< / span >
< span class = "n" > saved_filename< / span > < span class = "o" > =< / span > < span class = "n" > current_filename< / span >
< span class = "k" > if< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > status< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Resource< / span > < span class = "o" > .< / span > < span class = "n" > COMPLETE< / span > < span class = "p" > :< / span >
< span class = "n" > counter< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span >
< span class = "k" > while< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > isfile< / span > < span class = "p" > (< / span > < span class = "n" > saved_filename< / span > < span class = "p" > ):< / span >
< span class = "n" > counter< / span > < span class = "o" > +=< / span > < span class = "mi" > 1< / span >
< span class = "n" > saved_filename< / span > < span class = "o" > =< / span > < span class = "n" > current_filename< / 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" > counter< / span > < span class = "p" > )< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "n" > file< / span > < span class = "o" > =< / span > < span class = "nb" > open< / span > < span class = "p" > (< / span > < span class = "n" > saved_filename< / span > < span class = "p" > ,< / span > < span class = "s2" > " wb" < / span > < span class = "p" > )< / span >
< span class = "n" > file< / span > < span class = "o" > .< / span > < span class = "n" > write< / span > < span class = "p" > (< / span > < span class = "n" > resource< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "o" > .< / span > < span class = "n" > read< / span > < span class = "p" > ())< / span >
< span class = "n" > file< / span > < span class = "o" > .< / span > < span class = "n" > close< / span > < span class = "p" > ()< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " download_concluded" < / span >
< span class = "k" > except< / span > < span class = "p" > :< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " save_error" < / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > menu_mode< / span > < span class = "o" > =< / span > < span class = "s2" > " download_concluded" < / span >
< span class = "c1" > # A convenience function for printing a human-< / span >
< span class = "c1" > # readable file size< / span >
< span class = "k" > def< / span > < span class = "nf" > size_str< / span > < span class = "p" > (< / span > < span class = "n" > num< / span > < span class = "p" > ,< / span > < span class = "n" > suffix< / span > < span class = "o" > =< / span > < span class = "s1" > ' B' < / span > < span class = "p" > ):< / span >
< span class = "n" > units< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s1" > ' ' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Ki' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Mi' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Gi' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Ti' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Pi' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Ei' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Zi' < / span > < span class = "p" > ]< / span >
< span class = "n" > last_unit< / span > < span class = "o" > =< / span > < span class = "s1" > ' Yi' < / span >
< span class = "k" > if< / span > < span class = "n" > suffix< / span > < span class = "o" > ==< / span > < span class = "s1" > ' b' < / span > < span class = "p" > :< / span >
< span class = "n" > num< / span > < span class = "o" > *=< / span > < span class = "mi" > 8< / span >
< span class = "n" > units< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s1" > ' ' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' K' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' M' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' G' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' T' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' P' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' E' < / span > < span class = "p" > ,< / span > < span class = "s1" > ' Z' < / span > < span class = "p" > ]< / span >
< span class = "n" > last_unit< / span > < span class = "o" > =< / span > < span class = "s1" > ' Y' < / span >
< span class = "k" > for< / span > < span class = "n" > unit< / span > < span class = "ow" > in< / span > < span class = "n" > units< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "nb" > abs< / span > < span class = "p" > (< / span > < span class = "n" > num< / span > < span class = "p" > )< / span > < span class = "o" > < < / span > < span class = "mf" > 1024.0< / span > < span class = "p" > :< / span >
< span class = "k" > return< / span > < span class = "s2" > " < / span > < span class = "si" > %3.2f< / span > < span class = "s2" > < / span > < span class = "si" > %s%s< / span > < span class = "s2" > " < / span > < span class = "o" > %< / span > < span class = "p" > (< / span > < span class = "n" > num< / span > < span class = "p" > ,< / span > < span class = "n" > unit< / span > < span class = "p" > ,< / span > < span class = "n" > suffix< / span > < span class = "p" > )< / span >
< span class = "n" > num< / span > < span class = "o" > /=< / span > < span class = "mf" > 1024.0< / span >
< span class = "k" > return< / span > < span class = "s2" > " < / span > < span class = "si" > %.2f< / span > < span class = "s2" > < / span > < span class = "si" > %s%s< / span > < span class = "s2" > " < / span > < span class = "o" > %< / span > < span class = "p" > (< / span > < span class = "n" > num< / span > < span class = "p" > ,< / span > < span class = "n" > last_unit< / span > < span class = "p" > ,< / span > < span class = "n" > suffix< / span > < span class = "p" > )< / span >
< span class = "c1" > # A convenience function for clearing the screen< / span >
< span class = "k" > def< / span > < span class = "nf" > clear_screen< / span > < span class = "p" > ():< / span >
< span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > system< / span > < span class = "p" > (< / span > < span class = "s1" > ' cls' < / span > < span class = "k" > if< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > name< / span > < span class = "o" > ==< / span > < span class = "s1" > ' nt' < / span > < span class = "k" > else< / span > < span class = "s1" > ' clear' < / 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 file transfer server and client utility" < / 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" > " --serve" < / 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" > metavar< / span > < span class = "o" > =< / span > < span class = "s2" > " dir" < / span > < span class = "p" > ,< / span > < span class = "n" > help< / span > < span class = "o" > =< / span > < span class = "s2" > " serve a directory of files to 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" > serve< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > path< / span > < span class = "o" > .< / span > < span class = "n" > isdir< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > serve< / 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 = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > serve< / 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" > " The specified directory does not exist" < / 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/Filetransfer.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Filetransfer.py< / a > .< / p >
2021-05-16 15:40:49 -06:00
< / div >
< / div >
< div class = "clearer" > < / div >
< / div >
< / div >
< / div >
< div class = "sphinxsidebar" role = "navigation" aria-label = "main navigation" >
< div class = "sphinxsidebarwrapper" >
< h3 > < a href = "index.html" > Table of Contents< / a > < / h3 >
< ul >
< li > < a class = "reference internal" href = "#" > Examples< / a > < ul >
< li > < a class = "reference internal" href = "#minimal" > Minimal< / a > < / li >
< li > < a class = "reference internal" href = "#announce" > Announce< / a > < / li >
< li > < a class = "reference internal" href = "#broadcast" > Broadcast< / a > < / li >
< 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 = "#filetransfer" > Filetransfer< / a > < / li >
< / ul >
< / li >
< / ul >
< h4 > Previous topic< / h4 >
< p class = "topless" > < a href = "gettingstartedfast.html"
title="previous chapter">Getting Started Fast< / a > < / p >
< h4 > Next topic< / h4 >
< p class = "topless" > < a href = "reference.html"
title="next chapter">API Reference< / a > < / p >
< div role = "note" aria-label = "source link" >
< h3 > This Page< / h3 >
< ul class = "this-page-menu" >
< li > < a href = "_sources/examples.rst.txt"
rel="nofollow">Show Source< / a > < / li >
< / ul >
< / div >
< div id = "searchbox" style = "display: none" role = "search" >
< h3 id = "searchlabel" > Quick search< / h3 >
< div class = "searchformwrapper" >
< form class = "search" action = "search.html" method = "get" >
< input type = "text" name = "q" aria-labelledby = "searchlabel" / >
< input type = "submit" value = "Go" / >
< / form >
< / div >
< / div >
< script > $ ( '#searchbox' ) . show ( 0 ) ; < / script >
< / div >
< / div >
< div class = "clearer" > < / div >
< / div >
< div class = "related" role = "navigation" aria-label = "related navigation" >
< h3 > Navigation< / h3 >
< ul >
< li class = "right" style = "margin-right: 10px" >
< a href = "genindex.html" title = "General Index"
>index< / a > < / li >
< li class = "right" >
< a href = "reference.html" title = "API Reference"
>next< / a > |< / li >
< 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.0 beta documentation< / a > » < / li >
< li class = "nav-item nav-item-this" > < a href = "" > Examples< / a > < / li >
< / ul >
< / div >
< div class = "footer" role = "contentinfo" >
© Copyright 2021, Mark Qvist.
Created using < a href = "https://www.sphinx-doc.org/" > Sphinx< / a > 4.0.1.
< / div >
< / body >
< / html >