2022-09-30 16:43:04 +00:00
<!doctype html>
< html class = "no-js" lang = "en" >
< head > < meta charset = "utf-8" / >
< meta name = "viewport" content = "width=device-width,initial-scale=1" / >
2024-06-01 14:32:58 +00:00
< meta name = "color-scheme" content = "light dark" > < meta name = "generator" content = "Docutils 0.18.1: http://docutils.sourceforge.net/" / >
2022-09-30 16:43:04 +00:00
< link rel = "index" title = "Index" href = "genindex.html" / > < link rel = "search" title = "Search" href = "search.html" / > < link rel = "next" title = "Support Reticulum" href = "support.html" / > < link rel = "prev" title = "Building Networks" href = "networks.html" / >
2024-05-05 17:56:33 +00:00
< meta name = "generator" content = "sphinx-5.3.0, furo 2022.09.29.dev1" / >
2024-11-20 19:50:08 +00:00
< title > Code Examples - Reticulum Network Stack 0.8.6 beta documentation< / title >
2024-05-05 17:56:33 +00:00
< link rel = "stylesheet" type = "text/css" href = "_static/pygments.css" / >
2023-06-29 14:52:06 +00:00
< link rel = "stylesheet" type = "text/css" href = "_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" / >
2024-05-05 17:56:33 +00:00
< link rel = "stylesheet" type = "text/css" href = "_static/copybutton.css" / >
2022-09-30 16:43:04 +00:00
< link rel = "stylesheet" type = "text/css" href = "_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" / >
2024-05-05 17:56:33 +00:00
< link rel = "stylesheet" type = "text/css" href = "_static/custom.css" / >
2022-09-30 16:43:04 +00:00
2021-05-16 21:40:49 +00:00
2022-09-29 22:02:15 +00:00
2022-09-30 16:43:04 +00:00
< style >
body {
--color-code-background: #f8f8f8;
--color-code-foreground: black;
}
@media not print {
body[data-theme="dark"] {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
--color-background-primary: #202b38;
--color-background-secondary: #161f27;
--color-foreground-primary: #dbdbdb;
--color-foreground-secondary: #a9b1ba;
--color-brand-primary: #41adff;
--color-background-hover: #161f27;
--color-api-name: #ffbe85;
--color-api-pre-name: #efae75;
}
@media (prefers-color-scheme: dark) {
body:not([data-theme="light"]) {
--color-code-background: #202020;
--color-code-foreground: #d0d0d0;
--color-background-primary: #202b38;
--color-background-secondary: #161f27;
--color-foreground-primary: #dbdbdb;
--color-foreground-secondary: #a9b1ba;
--color-brand-primary: #41adff;
--color-background-hover: #161f27;
--color-api-name: #ffbe85;
--color-api-pre-name: #efae75;
}
}
}
< / style > < / head >
< body >
2021-05-16 21:40:49 +00:00
2022-09-30 16:43:04 +00:00
< script >
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
< / script >
2021-05-16 21:40:49 +00:00
2022-09-30 16:43:04 +00:00
< svg xmlns = "http://www.w3.org/2000/svg" style = "display: none;" >
< symbol id = "svg-toc" viewBox = "0 0 24 24" >
< title > Contents< / title >
< svg stroke = "currentColor" fill = "currentColor" stroke-width = "0" viewBox = "0 0 1024 1024" >
< path d = "M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z" / >
< / svg >
< / symbol >
< symbol id = "svg-menu" viewBox = "0 0 24 24" >
< title > Menu< / title >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
< line x1 = "3" y1 = "12" x2 = "21" y2 = "12" > < / line >
< line x1 = "3" y1 = "6" x2 = "21" y2 = "6" > < / line >
< line x1 = "3" y1 = "18" x2 = "21" y2 = "18" > < / line >
< / svg >
< / symbol >
< symbol id = "svg-arrow-right" viewBox = "0 0 24 24" >
< title > Expand< / title >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
< polyline points = "9 18 15 12 9 6" > < / polyline >
< / svg >
< / symbol >
< symbol id = "svg-sun" viewBox = "0 0 24 24" >
< title > Light mode< / title >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
< circle cx = "12" cy = "12" r = "5" > < / circle >
< line x1 = "12" y1 = "1" x2 = "12" y2 = "3" > < / line >
< line x1 = "12" y1 = "21" x2 = "12" y2 = "23" > < / line >
< line x1 = "4.22" y1 = "4.22" x2 = "5.64" y2 = "5.64" > < / line >
< line x1 = "18.36" y1 = "18.36" x2 = "19.78" y2 = "19.78" > < / line >
< line x1 = "1" y1 = "12" x2 = "3" y2 = "12" > < / line >
< line x1 = "21" y1 = "12" x2 = "23" y2 = "12" > < / line >
< line x1 = "4.22" y1 = "19.78" x2 = "5.64" y2 = "18.36" > < / line >
< line x1 = "18.36" y1 = "5.64" x2 = "19.78" y2 = "4.22" > < / line >
< / svg >
< / symbol >
< symbol id = "svg-moon" viewBox = "0 0 24 24" >
< title > Dark mode< / title >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
< path stroke = "none" d = "M0 0h24v24H0z" fill = "none" / >
< path d = "M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" / >
< / svg >
< / symbol >
< symbol id = "svg-sun-half" viewBox = "0 0 24 24" >
< title > Auto light/dark mode< / title >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
< path stroke = "none" d = "M0 0h24v24H0z" fill = "none" / >
< circle cx = "12" cy = "12" r = "9" / >
< path d = "M13 12h5" / >
< path d = "M13 15h4" / >
< path d = "M13 18h1" / >
< path d = "M13 9h4" / >
< path d = "M13 6h1" / >
< / svg >
< / symbol >
< / svg >
< input type = "checkbox" class = "sidebar-toggle" name = "__navigation" id = "__navigation" >
< input type = "checkbox" class = "sidebar-toggle" name = "__toc" id = "__toc" >
< label class = "overlay sidebar-overlay" for = "__navigation" >
< div class = "visually-hidden" > Hide navigation sidebar< / div >
< / label >
< label class = "overlay toc-overlay" for = "__toc" >
< div class = "visually-hidden" > Hide table of contents sidebar< / div >
< / label >
< div class = "page" >
< header class = "mobile-header" >
< div class = "header-left" >
< label class = "nav-overlay-icon" for = "__navigation" >
< div class = "visually-hidden" > Toggle site navigation sidebar< / div >
< i class = "icon" > < svg > < use href = "#svg-menu" > < / use > < / svg > < / i >
< / label >
< / div >
< div class = "header-center" >
2024-11-20 19:50:08 +00:00
< a href = "index.html" > < div class = "brand" > Reticulum Network Stack 0.8.6 beta documentation< / div > < / a >
2022-09-30 16:43:04 +00:00
< / div >
< div class = "header-right" >
< div class = "theme-toggle-container theme-toggle-header" >
< button class = "theme-toggle" >
< div class = "visually-hidden" > Toggle Light / Dark / Auto color theme< / div >
< svg class = "theme-icon-when-auto" > < use href = "#svg-sun-half" > < / use > < / svg >
< svg class = "theme-icon-when-dark" > < use href = "#svg-moon" > < / use > < / svg >
< svg class = "theme-icon-when-light" > < use href = "#svg-sun" > < / use > < / svg >
< / button >
< / div >
< label class = "toc-overlay-icon toc-header-icon" for = "__toc" >
< div class = "visually-hidden" > Toggle table of contents sidebar< / div >
< i class = "icon" > < svg > < use href = "#svg-toc" > < / use > < / svg > < / i >
< / label >
< / div >
< / header >
< aside class = "sidebar-drawer" >
< div class = "sidebar-container" >
2024-05-05 17:56:33 +00:00
< div class = "sidebar-sticky" > < a class = "sidebar-brand centered" href = "index.html" >
2022-09-30 16:43:04 +00:00
< div class = "sidebar-logo-container" >
< img class = "sidebar-logo" src = "_static/rns_logo_512.png" alt = "Logo" / >
< / div >
2024-11-20 19:50:08 +00:00
< span class = "sidebar-brand-text" > Reticulum Network Stack 0.8.6 beta documentation< / span >
2022-09-30 16:43:04 +00:00
< / a > < form class = "sidebar-search-container" method = "get" action = "search.html" role = "search" >
2023-06-29 14:52:06 +00:00
< input class = "sidebar-search" placeholder = "Search" name = "q" aria-label = "Search" >
2022-09-30 16:43:04 +00:00
< input type = "hidden" name = "check_keywords" value = "yes" >
< input type = "hidden" name = "area" value = "default" >
< / form >
< div id = "searchbox" > < / div > < div class = "sidebar-scroll" > < div class = "sidebar-tree" >
< ul class = "current" >
< li class = "toctree-l1" > < a class = "reference internal" href = "whatis.html" > What is Reticulum?< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "gettingstartedfast.html" > Getting Started Fast< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "using.html" > Using Reticulum on Your System< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "understanding.html" > Understanding Reticulum< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "hardware.html" > Communications Hardware< / a > < / li >
2023-09-30 23:59:22 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "interfaces.html" > Configuring Interfaces< / a > < / li >
2022-09-30 16:43:04 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "networks.html" > Building Networks< / a > < / li >
< li class = "toctree-l1 current current-page" > < a class = "current reference internal" href = "#" > Code Examples< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "support.html" > Support Reticulum< / a > < / li >
< / ul >
< ul >
< li class = "toctree-l1" > < a class = "reference internal" href = "reference.html" > API Reference< / a > < / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
< / aside >
< div class = "main" >
< div class = "content" >
< div class = "article-container" >
< a href = "#" class = "back-to-top muted-link" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >
< path d = "M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z" > < / path >
< / svg >
< span > Back to top< / span >
< / a >
< div class = "content-icon-container" >
< div class = "theme-toggle-container theme-toggle-content" >
< button class = "theme-toggle" >
< div class = "visually-hidden" > Toggle Light / Dark / Auto color theme< / div >
< svg class = "theme-icon-when-auto" > < use href = "#svg-sun-half" > < / use > < / svg >
< svg class = "theme-icon-when-dark" > < use href = "#svg-moon" > < / use > < / svg >
< svg class = "theme-icon-when-light" > < use href = "#svg-sun" > < / use > < / svg >
< / button >
< / div >
< label class = "toc-overlay-icon toc-content-icon" for = "__toc" >
< div class = "visually-hidden" > Toggle table of contents sidebar< / div >
< i class = "icon" > < svg > < use href = "#svg-toc" > < / use > < / svg > < / i >
< / label >
< / div >
< article role = "main" >
< section id = "code-examples" >
< span id = "examples-main" > < / span > < h1 > Code Examples< a class = "headerlink" href = "#code-examples" title = "Permalink to this heading" > #< / a > < / h1 >
2021-05-16 21:40:49 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< section id = "minimal" >
2022-09-30 16:43:04 +00:00
< span id = "example-minimal" > < / span > < h2 > Minimal< a class = "headerlink" href = "#minimal" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< 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 12:10:47 +00: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 >
2023-09-30 00:54:48 +00:00
< span class = "c1" > # and automatically create paths to them, from anywhere else< / span >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # in the network.< / span >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # We configure the destination to automatically prove all< / span >
2023-09-30 00:54:48 +00:00
< span class = "c1" > # packets addressed to it. By doing this, RNS will automatically< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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" > " Minimal 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "announce" >
2022-09-30 16:43:04 +00:00
< span id = "example-announce" > < / span > < h2 > Announce< a class = "headerlink" href = "#announce" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< 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 12:10:47 +00: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 >
2021-12-08 19:42:48 +00:00
< 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" < / 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2023-09-30 00:54:48 +00:00
< span class = "c1" > # and automatically create paths to them, from anywhere else< / span >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # in the network.< / span >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # We configure the destinations to automatically prove all< / span >
2023-10-01 10:09:49 +00:00
< span class = "c1" > # packets addressed to it. By doing this, RNS will automatically< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 = "p" > )< / span >
2022-10-06 15:35:38 +00:00
< span class = "k" > if< / 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" > " 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 = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "broadcast" >
2022-09-30 16:43:04 +00:00
< span id = "example-broadcast" > < / span > < h2 > Broadcast< a class = "headerlink" href = "#broadcast" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< p > The < em > Broadcast< / em > example explores how to transmit plaintext broadcast messages
over the network.< / p >
2021-05-17 12:10:47 +00: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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # We specify a callback that will get called every time< / span >
< span class = "c1" > # the destination receives data.< / span >
2021-05-20 13:31:58 +00:00
< span class = "n" > broadcast_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_callback< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 demonstrating sending and receiving 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "echo" >
2022-09-30 16:43:04 +00:00
< span id = "example-echo" > < / span > < h2 > Echo< a class = "headerlink" href = "#echo" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< p > The < em > Echo< / em > example demonstrates communication between two destinations using
the Packet interface.< / p >
2021-05-17 12:10:47 +00: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 >
2021-10-15 17:26:53 +00:00
< span class = "k" > global< / span > < span class = "n" > reticulum< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2024-09-04 15:00:11 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< span class = "c1" > # We configure the destination to automatically prove all< / span >
2023-10-01 10:09:49 +00:00
< span class = "c1" > # packets addressed to it. By doing this, RNS will automatically< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > echo_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > server_callback< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "k" > global< / span > < span class = "n" > reticulum< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "n" > reception_stats< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span >
< span class = "k" > if< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > is_connected_to_shared_instance< / span > < span class = "p" > :< / span >
< span class = "n" > reception_rssi< / span > < span class = "o" > =< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > get_packet_rssi< / span > < span class = "p" > (< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > packet_hash< / span > < span class = "p" > )< / span >
< span class = "n" > reception_snr< / span > < span class = "o" > =< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > get_packet_snr< / span > < span class = "p" > (< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > packet_hash< / span > < span class = "p" > )< / span >
< span class = "k" > if< / span > < span class = "n" > reception_rssi< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [RSSI " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > reception_rssi< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dBm]" < / span >
< span class = "k" > if< / span > < span class = "n" > reception_snr< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [SNR " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > reception_snr< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dBm]" < / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > rssi< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [RSSI " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > rssi< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dBm]" < / span >
< span class = "k" > if< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > snr< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [SNR " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > snr< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dB]" < / 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 = "o" > +< / span > < span class = "n" > reception_stats< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "k" > global< / span > < span class = "n" > reticulum< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2022-07-01 19:15:15 +00:00
< span class = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / span > < span class = "p" > :< / span >
2021-05-17 15:04:01 +00:00
< span class = "k" > raise< / span > < span class = "ne" > ValueError< / span > < span class = "p" > (< / span >
2022-07-01 19:15:15 +00:00
< span class = "s2" > " Destination length is invalid, must be < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
2021-05-17 15:04:01 +00:00
< span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2022-07-01 19:15:15 +00:00
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Invalid destination entered. Check your input!" < / 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 = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \n< / span > < span class = "s2" > " < / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 20:35:10 +00:00
< span class = "n" > packet_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_timeout_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_timed_out< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > packet_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_delivery_callback< / span > < span class = "p" > (< / span > < span class = "n" > packet_delivered< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2023-03-02 11:47:55 +00:00
< 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 retry once an announce is received." < / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "k" > global< / span > < span class = "n" > reticulum< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > rtt< / span > < span class = "o" > =< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > get_rtt< / span > < span class = "p" > ()< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "n" > reception_stats< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span >
< span class = "k" > if< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > is_connected_to_shared_instance< / span > < span class = "p" > :< / span >
< span class = "n" > reception_rssi< / span > < span class = "o" > =< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > get_packet_rssi< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > packet_hash< / span > < span class = "p" > )< / span >
< span class = "n" > reception_snr< / span > < span class = "o" > =< / span > < span class = "n" > reticulum< / span > < span class = "o" > .< / span > < span class = "n" > get_packet_snr< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > packet_hash< / span > < span class = "p" > )< / span >
< span class = "k" > if< / span > < span class = "n" > reception_rssi< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [RSSI " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > reception_rssi< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dBm]" < / span >
< span class = "k" > if< / span > < span class = "n" > reception_snr< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [SNR " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > reception_snr< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dB]" < / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > rssi< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [RSSI " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > rssi< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dBm]" < / span >
< span class = "k" > if< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > snr< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > reception_stats< / span > < span class = "o" > +=< / span > < span class = "s2" > " [SNR " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > receipt< / span > < span class = "o" > .< / span > < span class = "n" > proof_packet< / span > < span class = "o" > .< / span > < span class = "n" > snr< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " dB]" < / span >
2021-05-17 15:04:01 +00:00
< 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 >
2021-10-15 17:26:53 +00:00
< span class = "s2" > " , round-trip time is " < / span > < span class = "o" > +< / span > < span class = "n" > rttstring< / span > < span class = "o" > +< / span >
< span class = "n" > reception_stats< / span >
2021-05-17 15:04:01 +00:00
< span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "link" >
2022-09-30 16:43:04 +00:00
< span id = "example-link" > < / span > < h2 > Link< a class = "headerlink" href = "#link" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< 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 12:10:47 +00: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 >
2024-09-04 15:00:11 +00:00
< span class = "c1" > # Randomly create a new identity for our link example< / span >
2024-08-29 21:46:10 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2024-09-04 15:00:11 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > server_packet_received< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2022-07-01 19:15:15 +00:00
< span class = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
< span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_packet_received< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< 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 = "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" > 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" > " Cannot send this packet, the data size of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / span > < span class = "p" > (< / 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 = "s2" > " bytes exceeds the link packet MDU of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / 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" > MDU< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " bytes" < / span > < span class = "p" > ,< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_ERROR< / span >
< span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
2021-05-20 13:31:58 +00:00
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while sending data over the link: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ))< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "example-identify" >
2022-09-30 16:43:04 +00:00
< span id = "identification" > < / span > < h2 > Identification< a class = "headerlink" href = "#example-identify" title = "Permalink to this heading" > #< / a > < / h2 >
2021-08-19 12:11:22 +00:00
< p > The < em > Identify< / em > example explores identifying an intiator of a link, once
the link has been established.< / p >
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates how to set up a link to #< / span >
< span class = "c1" > # a destination, and identify the initiator to it' s peer #< / 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" > " identifyexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # We configure a function that will get called every time< / span >
< span class = "c1" > # a new client creates a link to this destination.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
< span class = "c1" > # 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 identification example " < / span > < span class = "o" > +< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > )< / span > < span class = "o" > +< / span >
< span class = "s2" > " running, waiting for a connection." < / span >
< span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Hit enter to manually send an announce (Ctrl-C to quit)" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We enter a loop that runs until the users exits.< / span >
< span class = "c1" > # If the user hits enter, we will announce our server< / span >
< span class = "c1" > # destination on the network, which will let clients< / span >
< span class = "c1" > # know how to create messages directed towards it.< / span >
< span class = "k" > while< / span > < span class = "kc" > True< / span > < span class = "p" > :< / span >
< span class = "n" > entered< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > announce< / span > < span class = "p" > ()< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Sent announce from " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > ))< / span >
< span class = "c1" > # When a client establishes a link to our server< / span >
< span class = "c1" > # destination, this function will be called with< / span >
< span class = "c1" > # a reference to the link.< / span >
< span class = "k" > def< / span > < span class = "nf" > client_connected< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > latest_client_link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client connected" < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > server_packet_received< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_remote_identified_callback< / span > < span class = "p" > (< / span > < span class = "n" > remote_identified< / 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 >
2022-07-01 19:15:15 +00:00
< span class = "k" > def< / span > < span class = "nf" > remote_identified< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ,< / span > < span class = "n" > identity< / span > < span class = "p" > ):< / span >
2021-08-19 12:11:22 +00:00
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Remote identified as: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > identity< / 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" > # Get the originating identity for display< / span >
< span class = "n" > remote_peer< / span > < span class = "o" > =< / span > < span class = "s2" > " unidentified peer" < / span >
< span class = "k" > if< / span > < span class = "n" > packet< / span > < span class = "o" > .< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > get_remote_identity< / span > < span class = "p" > ()< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "n" > remote_peer< / span > < span class = "o" > =< / span > < span class = "nb" > str< / 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" > get_remote_identity< / span > < span class = "p" > ())< / 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 from " < / span > < span class = "o" > +< / span > < span class = "n" > remote_peer< / span > < span class = "o" > +< / span > < span class = "s2" > " : " < / 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 from " < / span > < span class = "o" > +< / span > < span class = "n" > remote_peer< / 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" > # A reference to the client identity< / span >
< span class = "n" > client_identity< / 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 = "k" > global< / span > < span class = "n" > client_identity< / 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 >
2022-07-01 19:15:15 +00:00
< span class = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
< span class = "p" > )< / span >
2021-08-19 12:11:22 +00:00
< 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" > # Create a new client identity< / span >
< span class = "n" > client_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 = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span >
< span class = "s2" > " Client created new identity " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > client_identity< / span > < span class = "p" > )< / 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" > " identifyexample" < / 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" > set_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" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything is set up, so let' s enter a loop< / span >
< span class = "c1" > # for the user to interact with the example< / span >
< span class = "n" > client_loop< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > client_loop< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span >
< span class = "c1" > # Wait for the link to become active< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > server_link< / span > < span class = "p" > :< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.1< / span > < span class = "p" > )< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > should_quit< / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " > " < / span > < span class = "p" > ,< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > text< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Check if we should quit the example< / span >
< span class = "k" > if< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " quit" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " q" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " exit" < / span > < span class = "p" > :< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "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 = "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 = "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" > 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" > " Cannot send this packet, the data size of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / span > < span class = "p" > (< / 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 = "s2" > " bytes exceeds the link packet MDU of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / 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" > MDU< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " bytes" < / 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 = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while sending data over the link: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ))< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "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 = "p" > ,< / span > < span class = "n" > client_identity< / 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, identifying to remote peer..." < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > identify< / span > < span class = "p" > (< / span > < span class = "n" > client_identity< / 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/Identify.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Identify.py< / a > .< / p >
2022-09-29 22:02:15 +00:00
< / section >
< section id = "requests-responses" >
2022-09-30 16:43:04 +00:00
< span id = "example-request" > < / span > < h2 > Requests & Responses< a class = "headerlink" href = "#requests-responses" title = "Permalink to this heading" > #< / a > < / h2 >
2021-08-20 21:29:06 +00:00
< p > The < em > Request< / em > example explores sendig requests and receiving responses.< / p >
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates how to set perform #< / span >
< span class = "c1" > # requests and receive responses over a link. #< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "kn" > import< / span > < span class = "nn" > os< / span >
< span class = "kn" > import< / span > < span class = "nn" > sys< / span >
< span class = "kn" > import< / span > < span class = "nn" > time< / span >
< span class = "kn" > import< / span > < span class = "nn" > random< / span >
< span class = "kn" > import< / span > < span class = "nn" > argparse< / span >
< span class = "kn" > import< / span > < span class = "nn" > RNS< / span >
< span class = "c1" > # Let' s define an app name. We' ll use this for all< / span >
< span class = "c1" > # destinations we create. Since this echo example< / span >
< span class = "c1" > # is part of a range of example utilities, we' ll put< / span >
< span class = "c1" > # them all within the app namespace " example_utilities" < / span >
< span class = "n" > APP_NAME< / span > < span class = "o" > =< / span > < span class = "s2" > " example_utilities" < / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Server Part #########################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # A reference to the latest client link that connected< / span >
< span class = "n" > latest_client_link< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
2023-02-09 10:52:54 +00:00
< span class = "k" > def< / span > < span class = "nf" > random_text_generator< / span > < span class = "p" > (< / span > < span class = "n" > path< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > ,< / span > < span class = "n" > request_id< / span > < span class = "p" > ,< / span > < span class = "n" > link_id< / span > < span class = "p" > ,< / span > < span class = "n" > remote_identity< / span > < span class = "p" > ,< / span > < span class = "n" > requested_at< / 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" > " Generating response to request " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > request_id< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " on link " < / 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" > link_id< / span > < span class = "p" > ))< / span >
2021-08-20 21:29:06 +00:00
< span class = "n" > texts< / span > < span class = "o" > =< / span > < span class = "p" > [< / span > < span class = "s2" > " They looked up" < / span > < span class = "p" > ,< / span > < span class = "s2" > " On each full moon" < / span > < span class = "p" > ,< / span > < span class = "s2" > " Becky was upset" < / span > < span class = "p" > ,< / span > < span class = "s2" > " I’ ll stay away from it" < / span > < span class = "p" > ,< / span > < span class = "s2" > " The pet shop stocks everything" < / span > < span class = "p" > ]< / span >
< span class = "k" > return< / span > < span class = "n" > texts< / span > < span class = "p" > [< / span > < span class = "n" > random< / span > < span class = "o" > .< / span > < span class = "n" > randint< / span > < span class = "p" > (< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > texts< / span > < span class = "p" > )< / span > < span class = "o" > -< / span > < span class = "mi" > 1< / span > < span class = "p" > )]< / span >
< span class = "c1" > # This initialisation is executed when the users chooses< / span >
< span class = "c1" > # to run as a server< / span >
< span class = "k" > def< / span > < span class = "nf" > server< / span > < span class = "p" > (< / span > < span class = "n" > configpath< / span > < span class = "p" > ):< / span >
< span class = "c1" > # We must first initialise Reticulum< / span >
< span class = "n" > reticulum< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Reticulum< / span > < span class = "p" > (< / span > < span class = "n" > configpath< / span > < span class = "p" > )< / span >
< span class = "c1" > # Randomly create a new identity for our link example< / span >
< span class = "n" > server_identity< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Identity< / span > < span class = "p" > ()< / span >
< span class = "c1" > # We create a destination that clients can connect to. We< / span >
< span class = "c1" > # want clients to create links to this destination, so we< / span >
< span class = "c1" > # need to create a " single" destination type.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "p" > (< / span >
< span class = "n" > server_identity< / span > < span class = "p" > ,< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "o" > .< / span > < span class = "n" > IN< / span > < span class = "p" > ,< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "o" > .< / span > < span class = "n" > SINGLE< / span > < span class = "p" > ,< / span >
< span class = "n" > APP_NAME< / span > < span class = "p" > ,< / span >
< span class = "s2" > " requestexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # We configure a function that will get called every time< / span >
< span class = "c1" > # a new client creates a link to this destination.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
< span class = "c1" > # We register a request handler for handling incoming< / span >
< span class = "c1" > # requests over any established links.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > register_request_handler< / span > < span class = "p" > (< / span >
< span class = "s2" > " /random/text" < / span > < span class = "p" > ,< / span >
< span class = "n" > response_generator< / span > < span class = "o" > =< / span > < span class = "n" > random_text_generator< / span > < span class = "p" > ,< / span >
< span class = "n" > allow< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "o" > .< / span > < span class = "n" > ALLOW_ALL< / span >
< span class = "p" > )< / span >
< span class = "c1" > # Everything' s ready!< / span >
< span class = "c1" > # Let' s Wait for client requests or user input< / span >
< span class = "n" > server_loop< / span > < span class = "p" > (< / span > < span class = "n" > server_destination< / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > server_loop< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "p" > ):< / span >
< span class = "c1" > # Let the user know that everything is ready< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span >
< span class = "s2" > " Request example " < / span > < span class = "o" > +< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > )< / span > < span class = "o" > +< / span >
< span class = "s2" > " running, waiting for a connection." < / span >
< span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Hit enter to manually send an announce (Ctrl-C to quit)" < / span > < span class = "p" > )< / span >
< span class = "c1" > # We enter a loop that runs until the users exits.< / span >
< span class = "c1" > # If the user hits enter, we will announce our server< / span >
< span class = "c1" > # destination on the network, which will let clients< / span >
< span class = "c1" > # know how to create messages directed towards it.< / span >
< span class = "k" > while< / span > < span class = "kc" > True< / span > < span class = "p" > :< / span >
< span class = "n" > entered< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > announce< / span > < span class = "p" > ()< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Sent announce from " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > destination< / span > < span class = "o" > .< / span > < span class = "n" > hash< / span > < span class = "p" > ))< / span >
< span class = "c1" > # When a client establishes a link to our server< / span >
< span class = "c1" > # destination, this function will be called with< / span >
< span class = "c1" > # a reference to the link.< / span >
< span class = "k" > def< / span > < span class = "nf" > client_connected< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > latest_client_link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client connected" < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "n" > latest_client_link< / span > < span class = "o" > =< / span > < span class = "n" > link< / span >
< span class = "k" > def< / span > < span class = "nf" > client_disconnected< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ):< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client disconnected" < / span > < span class = "p" > )< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Client Part #########################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # A reference to the server link< / span >
< span class = "n" > server_link< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "c1" > # This initialisation is executed when the users chooses< / span >
< span class = "c1" > # to run as a client< / span >
< span class = "k" > def< / span > < span class = "nf" > client< / span > < span class = "p" > (< / span > < span class = "n" > destination_hexhash< / span > < span class = "p" > ,< / span > < span class = "n" > configpath< / span > < span class = "p" > ):< / span >
< span class = "c1" > # We need a binary representation of the destination< / span >
< span class = "c1" > # hash that was entered on the command line< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
2022-07-01 19:15:15 +00:00
< span class = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
< span class = "p" > )< / span >
2021-08-20 21:29:06 +00:00
< span class = "n" > destination_hash< / span > < span class = "o" > =< / span > < span class = "nb" > bytes< / span > < span class = "o" > .< / span > < span class = "n" > fromhex< / span > < span class = "p" > (< / span > < span class = "n" > destination_hexhash< / span > < span class = "p" > )< / span >
< span class = "k" > except< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Invalid destination entered. Check your input!< / span > < span class = "se" > \n< / span > < span class = "s2" > " < / span > < span class = "p" > )< / span >
< span class = "n" > exit< / span > < span class = "p" > ()< / span >
< span class = "c1" > # We must first initialise Reticulum< / span >
< span class = "n" > reticulum< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Reticulum< / span > < span class = "p" > (< / span > < span class = "n" > configpath< / span > < span class = "p" > )< / span >
< span class = "c1" > # Check if we know a path to the destination< / span >
< span class = "k" > if< / span > < span class = "ow" > not< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Transport< / span > < span class = "o" > .< / span > < span class = "n" > has_path< / span > < span class = "p" > (< / span > < span class = "n" > destination_hash< / span > < span class = "p" > ):< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Destination is not yet known. Requesting path and waiting for announce to arrive..." < / span > < span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Transport< / span > < span class = "o" > .< / span > < span class = "n" > request_path< / span > < span class = "p" > (< / span > < span class = "n" > destination_hash< / span > < span class = "p" > )< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Transport< / span > < span class = "o" > .< / span > < span class = "n" > has_path< / span > < span class = "p" > (< / span > < span class = "n" > destination_hash< / span > < span class = "p" > ):< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.1< / span > < span class = "p" > )< / span >
< span class = "c1" > # Recall the server identity< / span >
< span class = "n" > server_identity< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Identity< / span > < span class = "o" > .< / span > < span class = "n" > recall< / span > < span class = "p" > (< / span > < span class = "n" > destination_hash< / span > < span class = "p" > )< / span >
< span class = "c1" > # Inform the user that we' ll begin connecting< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Establishing link with server..." < / span > < span class = "p" > )< / span >
< span class = "c1" > # When the server identity is known, we set< / span >
< span class = "c1" > # up a destination< / span >
< span class = "n" > server_destination< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "p" > (< / span >
< span class = "n" > server_identity< / span > < span class = "p" > ,< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "o" > .< / span > < span class = "n" > OUT< / span > < span class = "p" > ,< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Destination< / span > < span class = "o" > .< / span > < span class = "n" > SINGLE< / span > < span class = "p" > ,< / span >
< span class = "n" > APP_NAME< / span > < span class = "p" > ,< / span >
< span class = "s2" > " requestexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # And create a link< / span >
< span class = "n" > link< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "p" > (< / span > < span class = "n" > server_destination< / span > < span class = "p" > )< / span >
< span class = "c1" > # We' ll set up functions to inform the< / span >
< span class = "c1" > # user when the link is established or closed< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything is set up, so let' s enter a loop< / span >
< span class = "c1" > # for the user to interact with the example< / span >
< span class = "n" > client_loop< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > client_loop< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span >
< span class = "c1" > # Wait for the link to become active< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > server_link< / span > < span class = "p" > :< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.1< / span > < span class = "p" > )< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > should_quit< / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " > " < / span > < span class = "p" > ,< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > text< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Check if we should quit the example< / span >
< span class = "k" > if< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " quit" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " q" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " exit" < / span > < span class = "p" > :< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > request< / span > < span class = "p" > (< / span >
< span class = "s2" > " /random/text" < / span > < span class = "p" > ,< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ,< / span >
< span class = "n" > response_callback< / span > < span class = "o" > =< / span > < span class = "n" > got_response< / span > < span class = "p" > ,< / span >
< span class = "n" > failed_callback< / span > < span class = "o" > =< / span > < span class = "n" > request_failed< / span >
< span class = "p" > )< / span >
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while sending request over the link: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ))< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > got_response< / span > < span class = "p" > (< / span > < span class = "n" > request_receipt< / span > < span class = "p" > ):< / span >
< span class = "n" > request_id< / span > < span class = "o" > =< / span > < span class = "n" > request_receipt< / span > < span class = "o" > .< / span > < span class = "n" > request_id< / span >
< span class = "n" > response< / span > < span class = "o" > =< / span > < span class = "n" > request_receipt< / span > < span class = "o" > .< / span > < span class = "n" > response< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Got response for request " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > request_id< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " : " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > response< / span > < span class = "p" > ))< / span >
< span class = "k" > def< / span > < span class = "nf" > request_received< / span > < span class = "p" > (< / span > < span class = "n" > request_receipt< / span > < span class = "p" > ):< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " The request " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > request_receipt< / span > < span class = "o" > .< / span > < span class = "n" > request_id< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " was received by the remote peer." < / span > < span class = "p" > )< / span >
< span class = "k" > def< / span > < span class = "nf" > request_failed< / span > < span class = "p" > (< / span > < span class = "n" > request_receipt< / span > < span class = "p" > ):< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " The request " < / span > < span class = "o" > +< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > prettyhexrep< / span > < span class = "p" > (< / span > < span class = "n" > request_receipt< / span > < span class = "o" > .< / span > < span class = "n" > request_id< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " failed." < / span > < span class = "p" > )< / span >
< span class = "c1" > # This function is called when a link< / span >
< span class = "c1" > # has been established with the server< / span >
< span class = "k" > def< / span > < span class = "nf" > link_established< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ):< / span >
< span class = "c1" > # We store a reference to the link< / span >
< span class = "c1" > # instance for later use< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span >
< span class = "n" > server_link< / span > < span class = "o" > =< / span > < span class = "n" > link< / span >
< span class = "c1" > # Inform the user that the server is< / span >
< span class = "c1" > # connected< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Link established with server, hit enter to perform a request, or type in < / span > < span class = "se" > \" < / span > < span class = "s2" > quit< / span > < span class = "se" > \" < / span > < span class = "s2" > to quit" < / span > < span class = "p" > )< / span >
< span class = "c1" > # When a link is closed, we' ll inform the< / span >
< span class = "c1" > # user, and exit the program< / span >
< span class = "k" > def< / span > < span class = "nf" > link_closed< / span > < span class = "p" > (< / span > < span class = "n" > link< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown_reason< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "o" > .< / span > < span class = "n" > TIMEOUT< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " The link timed out, exiting now" < / span > < span class = "p" > )< / span >
< span class = "k" > elif< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > teardown_reason< / span > < span class = "o" > ==< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "o" > .< / span > < span class = "n" > DESTINATION_CLOSED< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " The link was closed by the server, exiting now" < / span > < span class = "p" > )< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Link closed, exiting now" < / span > < span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Reticulum< / span > < span class = "o" > .< / span > < span class = "n" > exit_handler< / span > < span class = "p" > ()< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 1.5< / span > < span class = "p" > )< / span >
< span class = "n" > os< / span > < span class = "o" > .< / span > < span class = "n" > _exit< / span > < span class = "p" > (< / span > < span class = "mi" > 0< / span > < span class = "p" > )< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > #### Program Startup #####################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This part of the program runs at startup,< / span >
< span class = "c1" > # and parses input of from the user, and then< / span >
< span class = "c1" > # starts up the desired program mode.< / span >
< span class = "k" > if< / span > < span class = "vm" > __name__< / span > < span class = "o" > ==< / span > < span class = "s2" > " __main__" < / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "n" > parser< / span > < span class = "o" > =< / span > < span class = "n" > argparse< / span > < span class = "o" > .< / span > < span class = "n" > ArgumentParser< / span > < span class = "p" > (< / span > < span class = "n" > description< / span > < span class = "o" > =< / span > < span class = "s2" > " Simple request/response example" < / span > < span class = "p" > )< / span >
< span class = "n" > parser< / span > < span class = "o" > .< / span > < span class = "n" > add_argument< / span > < span class = "p" > (< / span >
< span class = "s2" > " -s" < / span > < span class = "p" > ,< / span >
< span class = "s2" > " --server" < / span > < span class = "p" > ,< / span >
< span class = "n" > action< / span > < span class = "o" > =< / span > < span class = "s2" > " store_true" < / span > < span class = "p" > ,< / span >
< span class = "n" > help< / span > < span class = "o" > =< / span > < span class = "s2" > " wait for incoming requests from clients" < / span >
< span class = "p" > )< / span >
< span class = "n" > parser< / span > < span class = "o" > .< / span > < span class = "n" > add_argument< / span > < span class = "p" > (< / span >
< span class = "s2" > " --config" < / span > < span class = "p" > ,< / span >
< span class = "n" > action< / span > < span class = "o" > =< / span > < span class = "s2" > " store" < / span > < span class = "p" > ,< / span >
< span class = "n" > default< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ,< / span >
< span class = "n" > help< / span > < span class = "o" > =< / span > < span class = "s2" > " path to alternative Reticulum config directory" < / span > < span class = "p" > ,< / span >
< span class = "nb" > type< / span > < span class = "o" > =< / span > < span class = "nb" > str< / span >
< span class = "p" > )< / span >
< span class = "n" > parser< / span > < span class = "o" > .< / span > < span class = "n" > add_argument< / span > < span class = "p" > (< / span >
< span class = "s2" > " destination" < / span > < span class = "p" > ,< / span >
< span class = "n" > nargs< / span > < span class = "o" > =< / span > < span class = "s2" > " ?" < / span > < span class = "p" > ,< / span >
< span class = "n" > default< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ,< / span >
< span class = "n" > help< / span > < span class = "o" > =< / span > < span class = "s2" > " hexadecimal hash of the server destination" < / span > < span class = "p" > ,< / span >
< span class = "nb" > type< / span > < span class = "o" > =< / span > < span class = "nb" > str< / span >
< span class = "p" > )< / span >
< span class = "n" > args< / span > < span class = "o" > =< / span > < span class = "n" > parser< / span > < span class = "o" > .< / span > < span class = "n" > parse_args< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > config< / span > < span class = "p" > :< / span >
< span class = "n" > configarg< / span > < span class = "o" > =< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > config< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > configarg< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "k" > if< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > server< / span > < span class = "p" > :< / span >
< span class = "n" > server< / span > < span class = "p" > (< / span > < span class = "n" > configarg< / span > < span class = "p" > )< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > destination< / span > < span class = "o" > ==< / span > < span class = "kc" > None< / span > < span class = "p" > ):< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > parser< / span > < span class = "o" > .< / span > < span class = "n" > print_help< / span > < span class = "p" > ()< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > client< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "o" > .< / span > < span class = "n" > destination< / span > < span class = "p" > ,< / span > < span class = "n" > configarg< / span > < span class = "p" > )< / span >
< span class = "k" > except< / span > < span class = "ne" > KeyboardInterrupt< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > exit< / span > < span class = "p" > ()< / span >
< / pre > < / div >
< / div >
< p > This example can also be found at < a class = "reference external" href = "https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Request.py< / a > .< / p >
2022-09-29 22:02:15 +00:00
< / section >
2023-03-02 11:47:55 +00:00
< section id = "channel" >
< span id = "example-channel" > < / span > < h2 > Channel< a class = "headerlink" href = "#channel" title = "Permalink to this heading" > #< / a > < / h2 >
< p > The < em > Channel< / em > example explores using a < code class = "docutils literal notranslate" > < span class = "pre" > Channel< / span > < / code > to send structured
data between peers of a < code class = "docutils literal notranslate" > < span class = "pre" > Link< / span > < / code > .< / p >
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates how to set up a link to #< / span >
< span class = "c1" > # a destination, and pass structured messages over it #< / span >
< span class = "c1" > # using a channel. #< / 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" > from< / span > < span class = "nn" > datetime< / span > < span class = "kn" > import< / span > < span class = "n" > datetime< / span >
< span class = "kn" > import< / span > < span class = "nn" > RNS< / span >
< span class = "kn" > from< / span > < span class = "nn" > RNS.vendor< / span > < span class = "kn" > import< / span > < span class = "n" > 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" > ##########################################################< / span >
< span class = "c1" > #### Shared Objects ######################################< / span >
< span class = "c1" > ##########################################################< / span >
< span class = "c1" > # Channel data must be structured in a subclass of< / span >
< span class = "c1" > # MessageBase. This ensures that the channel will be able< / span >
< span class = "c1" > # to serialize and deserialize the object and multiplex it< / span >
< span class = "c1" > # with other objects. Both ends of a link will need the< / span >
< span class = "c1" > # same object definitions to be able to communicate over< / span >
< span class = "c1" > # a channel.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # Note: The objects we wish to use over the channel must< / span >
< span class = "c1" > # be registered with the channel, and each link has a< / span >
< span class = "c1" > # different channel instance. See the client_connected< / span >
< span class = "c1" > # and link_established functions in this example to see< / span >
< span class = "c1" > # how message types are registered.< / span >
< span class = "c1" > # Let' s make a simple message class called StringMessage< / span >
< span class = "c1" > # that will convey a string with a timestamp.< / span >
< span class = "k" > class< / span > < span class = "nc" > StringMessage< / span > < span class = "p" > (< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > MessageBase< / span > < span class = "p" > ):< / span >
< span class = "c1" > # The MSGTYPE class variable needs to be assigned a< / span >
< span class = "c1" > # 2 byte integer value. This identifier allows the< / span >
< span class = "c1" > # channel to look up your message' s constructor when a< / span >
< span class = "c1" > # message arrives over the channel.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # MSGTYPE must be unique across all message types we< / span >
< span class = "c1" > # register with the channel. MSGTYPEs > = 0xf000 are< / span >
< span class = "c1" > # reserved for the system.< / span >
< span class = "n" > MSGTYPE< / span > < span class = "o" > =< / span > < span class = "mh" > 0x0101< / span >
< span class = "c1" > # The constructor of our object must be callable with< / span >
< span class = "c1" > # no arguments. We can have parameters, but they must< / span >
< span class = "c1" > # have a default assignment.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # This is needed so the channel can create an empty< / span >
< span class = "c1" > # version of our message into which the incoming< / span >
< span class = "c1" > # message can be unpacked.< / 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" > data< / 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" > data< / span > < span class = "o" > =< / span > < span class = "n" > data< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > timestamp< / span > < span class = "o" > =< / span > < span class = "n" > datetime< / span > < span class = "o" > .< / span > < span class = "n" > now< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Finally, our message needs to implement functions< / span >
< span class = "c1" > # the channel can call to pack and unpack our message< / span >
< span class = "c1" > # to/from the raw packet payload. We' ll use the< / span >
< span class = "c1" > # umsgpack package bundled with RNS. We could also use< / span >
< span class = "c1" > # the struct package bundled with Python if we wanted< / span >
< span class = "c1" > # more control over the structure of the packed bytes.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # Also note that packed message objects must fit< / span >
< span class = "c1" > # entirely in one packet. The number of bytes< / span >
< span class = "c1" > # available for message payloads can be queried from< / span >
< span class = "c1" > # the channel using the Channel.MDU property. The< / span >
< span class = "c1" > # channel MDU is slightly less than the link MDU due< / span >
< span class = "c1" > # to encoding the message header.< / span >
< span class = "c1" > # The pack function encodes the message contents into< / span >
< span class = "c1" > # a byte stream.< / span >
< span class = "k" > def< / span > < span class = "nf" > pack< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > )< / span > < span class = "o" > -> < / span > < span class = "nb" > bytes< / span > < span class = "p" > :< / span >
< span class = "k" > return< / span > < span class = "n" > umsgpack< / span > < span class = "o" > .< / span > < span class = "n" > packb< / span > < span class = "p" > ((< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "p" > ,< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > timestamp< / span > < span class = "p" > ))< / span >
< span class = "c1" > # And the unpack function decodes a byte stream into< / span >
< span class = "c1" > # the message contents.< / span >
< span class = "k" > def< / span > < span class = "nf" > unpack< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ,< / span > < span class = "n" > raw< / span > < span class = "p" > ):< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "p" > ,< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > timestamp< / 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" > raw< / span > < span class = "p" > )< / 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" > " channelexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # We configure a function that will get called every time< / span >
< span class = "c1" > # a new client creates a link to this destination.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
< span class = "c1" > # 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" > latest_client_link< / span > < span class = "o" > =< / span > < span class = "n" > link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client connected" < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "c1" > # Register message types and add callback to channel< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span >
< span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > register_message_type< / span > < span class = "p" > (< / span > < span class = "n" > StringMessage< / span > < span class = "p" > )< / span >
< span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > add_message_handler< / span > < span class = "p" > (< / span > < span class = "n" > server_message_received< / 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" > server_message_received< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "p" > ):< / span >
2023-06-29 14:52:06 +00:00
< span class = "w" > < / span > < span class = "sd" > " " " < / span >
2023-03-02 11:47:55 +00:00
< span class = "sd" > A message handler< / span >
< span class = "sd" > @param message: An instance of a subclass of MessageBase< / span >
< span class = "sd" > @return: True if message was handled< / span >
< span class = "sd" > " " " < / span >
< span class = "k" > global< / span > < span class = "n" > latest_client_link< / span >
< span class = "c1" > # When a message is received over any active link,< / span >
< span class = "c1" > # the replies will all be directed to the last client< / span >
< span class = "c1" > # that connected.< / span >
< span class = "c1" > # In a message handler, any deserializable message< / span >
< span class = "c1" > # that arrives over the link' s channel will be passed< / span >
< span class = "c1" > # to all message handlers, unless a preceding handler indicates it< / span >
< span class = "c1" > # has handled the message.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > #< / span >
< span class = "k" > if< / span > < span class = "nb" > isinstance< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "p" > ,< / span > < span class = "n" > StringMessage< / 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" > message< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "o" > +< / span > < span class = "s2" > " (message created at " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "o" > .< / span > < span class = "n" > timestamp< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " )" < / span > < span class = "p" > )< / span >
< span class = "n" > reply_message< / span > < span class = "o" > =< / span > < span class = "n" > StringMessage< / span > < span class = "p" > (< / span > < span class = "s2" > " I received < / span > < span class = "se" > \" < / span > < span class = "s2" > " < / span > < span class = "o" > +< / span > < span class = "n" > message< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > over the link" < / span > < span class = "p" > )< / span >
< span class = "n" > latest_client_link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span > < span class = "o" > .< / span > < span class = "n" > send< / span > < span class = "p" > (< / span > < span class = "n" > reply_message< / span > < span class = "p" > )< / span >
< span class = "c1" > # Incoming messages are sent to each message< / span >
< span class = "c1" > # handler added to the channel, in the order they< / span >
< span class = "c1" > # were added.< / span >
< span class = "c1" > # If any message handler returns True, the message< / span >
< span class = "c1" > # is considered handled and any subsequent< / span >
< span class = "c1" > # handlers are skipped.< / span >
< span class = "k" > return< / span > < span class = "kc" > True< / 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 = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / 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" > " channelexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # And create a link< / span >
< span class = "n" > link< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "p" > (< / span > < span class = "n" > server_destination< / span > < span class = "p" > )< / span >
< span class = "c1" > # We' ll 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" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything is set up, so let' s enter a loop< / span >
< span class = "c1" > # for the user to interact with the example< / span >
< span class = "n" > client_loop< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > client_loop< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span >
< span class = "c1" > # Wait for the link to become active< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > server_link< / span > < span class = "p" > :< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.1< / span > < span class = "p" > )< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > should_quit< / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " > " < / span > < span class = "p" > ,< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > text< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Check if we should quit the example< / span >
< span class = "k" > if< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " quit" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " q" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " exit" < / span > < span class = "p" > :< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "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" > message< / span > < span class = "o" > =< / span > < span class = "n" > StringMessage< / span > < span class = "p" > (< / span > < span class = "n" > text< / span > < span class = "p" > )< / span >
< span class = "n" > packed_size< / span > < span class = "o" > =< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "o" > .< / span > < span class = "n" > pack< / span > < span class = "p" > ())< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > is_ready_to_send< / span > < span class = "p" > ():< / span >
< span class = "k" > if< / span > < span class = "n" > packed_size< / span > < span class = "o" > < =< / span > < span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > MDU< / span > < span class = "p" > :< / span >
< span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > send< / span > < span class = "p" > (< / span > < span class = "n" > message< / 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" > " Cannot send this packet, the data size of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > packed_size< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " bytes exceeds the link packet MDU of " < / span > < span class = "o" > +< / span >
< span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > MDU< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " bytes" < / 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 = "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" > " Channel is not ready to send, please wait for " < / span > < span class = "o" > +< / span >
< span class = "s2" > " pending messages to complete." < / 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 = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while sending data over the link: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ))< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "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" > # Register messages and add handler to channel< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span >
< span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > register_message_type< / span > < span class = "p" > (< / span > < span class = "n" > StringMessage< / span > < span class = "p" > )< / span >
< span class = "n" > channel< / span > < span class = "o" > .< / span > < span class = "n" > add_message_handler< / span > < span class = "p" > (< / span > < span class = "n" > client_message_received< / span > < span class = "p" > )< / 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 >
2023-03-03 21:16:13 +00:00
< span class = "c1" > # When a packet is received over the channel, we< / span >
2023-03-02 11:47:55 +00:00
< span class = "c1" > # simply print out the data.< / span >
< span class = "k" > def< / span > < span class = "nf" > client_message_received< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "nb" > isinstance< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "p" > ,< / span > < span class = "n" > StringMessage< / 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" > message< / span > < span class = "o" > .< / span > < span class = "n" > data< / span > < span class = "o" > +< / span > < span class = "s2" > " (message created at " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > message< / span > < span class = "o" > .< / span > < span class = "n" > timestamp< / span > < span class = "p" > )< / span > < span class = "o" > +< / 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 = "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 >
2023-03-03 21:16:13 +00:00
< 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 channel example" < / span > < span class = "p" > )< / span >
2023-03-02 11:47:55 +00:00
< 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/Channel.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Channel.py< / a > .< / p >
< / section >
2023-03-03 21:16:13 +00:00
< section id = "buffer" >
< h2 > Buffer< a class = "headerlink" href = "#buffer" title = "Permalink to this heading" > #< / a > < / h2 >
< p > The < em > Buffer< / em > example explores using buffered readers and writers to send
binary data between peers of a < code class = "docutils literal notranslate" > < span class = "pre" > Link< / span > < / code > .< / p >
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > ##########################################################< / span >
< span class = "c1" > # This RNS example demonstrates how to set up a link to #< / span >
< span class = "c1" > # a destination, and pass binary data over it using a #< / span >
2023-03-04 16:57:18 +00:00
< span class = "c1" > # channel buffer. #< / span >
2023-03-03 21:16:13 +00:00
< span class = "c1" > ##########################################################< / span >
< span class = "kn" > from< / span > < span class = "nn" > __future__< / span > < span class = "kn" > import< / span > < span class = "n" > annotations< / 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" > from< / span > < span class = "nn" > datetime< / span > < span class = "kn" > import< / span > < span class = "n" > datetime< / span >
< span class = "kn" > import< / span > < span class = "nn" > RNS< / span >
< span class = "kn" > from< / span > < span class = "nn" > RNS.vendor< / span > < span class = "kn" > import< / span > < span class = "n" > 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" > ##########################################################< / 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" > # A reference to the latest buffer object< / span >
< span class = "n" > latest_buffer< / 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 >
2023-03-04 16:57:18 +00:00
< span class = "c1" > # Randomly create a new identity for our example< / span >
2023-03-03 21:16:13 +00:00
< 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" > " bufferexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # We configure a function that will get called every time< / span >
< span class = "c1" > # a new client creates a link to this destination.< / span >
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
< span class = "c1" > # 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 >
2023-03-04 16:57:18 +00:00
< span class = "s2" > " Link buffer example " < / span > < span class = "o" > +< / span >
2023-03-03 21:16:13 +00:00
< 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 = "p" > ,< / span > < span class = "n" > latest_buffer< / span >
< span class = "n" > latest_client_link< / span > < span class = "o" > =< / span > < span class = "n" > link< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Client connected" < / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
< span class = "c1" > # If a new connection is received, the old reader< / span >
< span class = "c1" > # needs to be disconnected.< / span >
< span class = "k" > if< / span > < span class = "n" > latest_buffer< / span > < span class = "p" > :< / span >
< span class = "n" > latest_buffer< / span > < span class = "o" > .< / span > < span class = "n" > close< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Create buffer objects.< / span >
< span class = "c1" > # The stream_id parameter to these functions is< / span >
< span class = "c1" > # a bit like a file descriptor, except that it< / span >
< span class = "c1" > # is unique to the *receiver*.< / span >
< span class = "c1" > #< / span >
< span class = "c1" > # In this example, both the reader and the writer< / span >
< span class = "c1" > # use stream_id = 0, but there are actually two< / span >
< span class = "c1" > # separate unidirectional streams flowing in< / span >
< span class = "c1" > # opposite directions.< / span >
< span class = "c1" > #< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span >
< span class = "n" > latest_buffer< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Buffer< / span > < span class = "o" > .< / span > < span class = "n" > create_bidirectional_buffer< / span > < span class = "p" > (< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "n" > channel< / span > < span class = "p" > ,< / span > < span class = "n" > server_buffer_ready< / 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" > server_buffer_ready< / span > < span class = "p" > (< / span > < span class = "n" > ready_bytes< / span > < span class = "p" > :< / span > < span class = "nb" > int< / span > < span class = "p" > ):< / span >
2023-06-29 14:52:06 +00:00
< span class = "w" > < / span > < span class = "sd" > " " " < / span >
2023-03-03 21:16:13 +00:00
< span class = "sd" > Callback from buffer when buffer has data available< / span >
< span class = "sd" > :param ready_bytes: The number of bytes ready to read< / span >
< span class = "sd" > " " " < / span >
< span class = "k" > global< / span > < span class = "n" > latest_buffer< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > latest_buffer< / span > < span class = "o" > .< / span > < span class = "n" > read< / span > < span class = "p" > (< / span > < span class = "n" > ready_bytes< / span > < span class = "p" > )< / span >
< span class = "n" > 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 >
2023-03-04 16:57:18 +00:00
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Received data over the buffer: " < / span > < span class = "o" > +< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
2023-03-03 21:16:13 +00:00
< span class = "n" > reply_message< / 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" > data< / span > < span class = "o" > +< / span > < span class = "s2" > " < / span > < span class = "se" > \" < / span > < span class = "s2" > over the buffer" < / span >
< span class = "n" > reply_message< / span > < span class = "o" > =< / span > < span class = "n" > reply_message< / 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" > latest_buffer< / span > < span class = "o" > .< / span > < span class = "n" > write< / span > < span class = "p" > (< / span > < span class = "n" > reply_message< / span > < span class = "p" > )< / span >
< span class = "n" > latest_buffer< / span > < span class = "o" > .< / span > < span class = "n" > flush< / 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" > # A reference to the buffer object, needed to share the< / span >
< span class = "c1" > # object from the link connected callback to the client< / span >
< span class = "c1" > # loop.< / span >
< span class = "n" > buffer< / 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 = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / 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" > " bufferexample" < / span >
< span class = "p" > )< / span >
< span class = "c1" > # And create a link< / span >
< span class = "n" > link< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Link< / span > < span class = "p" > (< / span > < span class = "n" > server_destination< / span > < span class = "p" > )< / span >
< span class = "c1" > # We' ll 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" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
< span class = "c1" > # Everything is set up, so let' s enter a loop< / span >
< span class = "c1" > # for the user to interact with the example< / span >
< span class = "n" > client_loop< / span > < span class = "p" > ()< / span >
< span class = "k" > def< / span > < span class = "nf" > client_loop< / span > < span class = "p" > ():< / span >
< span class = "k" > global< / span > < span class = "n" > server_link< / span >
< span class = "c1" > # Wait for the link to become active< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > server_link< / span > < span class = "p" > :< / span >
< span class = "n" > time< / span > < span class = "o" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.1< / span > < span class = "p" > )< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "n" > should_quit< / span > < span class = "p" > :< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "nb" > print< / span > < span class = "p" > (< / span > < span class = "s2" > " > " < / span > < span class = "p" > ,< / span > < span class = "n" > end< / span > < span class = "o" > =< / span > < span class = "s2" > " " < / span > < span class = "p" > )< / span >
< span class = "n" > text< / span > < span class = "o" > =< / span > < span class = "nb" > input< / span > < span class = "p" > ()< / span >
< span class = "c1" > # Check if we should quit the example< / span >
< span class = "k" > if< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " quit" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " q" < / span > < span class = "ow" > or< / span > < span class = "n" > text< / span > < span class = "o" > ==< / span > < span class = "s2" > " exit" < / span > < span class = "p" > :< / span >
< span class = "n" > should_quit< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > server_link< / span > < span class = "o" > .< / span > < span class = "n" > teardown< / span > < span class = "p" > ()< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "c1" > # Otherwise, encode the text and write it to the buffer.< / span >
< span class = "n" > text< / 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" > buffer< / span > < span class = "o" > .< / span > < span class = "n" > write< / span > < span class = "p" > (< / span > < span class = "n" > text< / span > < span class = "p" > )< / span >
< span class = "c1" > # Flush the buffer to force the data to be sent.< / span >
< span class = "n" > buffer< / span > < span class = "o" > .< / span > < span class = "n" > flush< / 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 >
2023-03-04 16:57:18 +00:00
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while sending data over the link buffer: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ))< / span >
2023-03-03 21:16:13 +00:00
< 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 = "p" > ,< / span > < span class = "n" > buffer< / span >
< span class = "n" > server_link< / span > < span class = "o" > =< / span > < span class = "n" > link< / span >
< span class = "c1" > # Create buffer, see server_client_connected() for< / span >
< span class = "c1" > # more detail about setting up the buffer.< / span >
< span class = "n" > channel< / span > < span class = "o" > =< / span > < span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > get_channel< / span > < span class = "p" > ()< / span >
< span class = "n" > buffer< / span > < span class = "o" > =< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Buffer< / span > < span class = "o" > .< / span > < span class = "n" > create_bidirectional_buffer< / span > < span class = "p" > (< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span > < span class = "n" > channel< / span > < span class = "p" > ,< / span > < span class = "n" > client_buffer_ready< / span > < span class = "p" > )< / 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 the buffer has new data, read it and write it to the terminal.< / span >
< span class = "k" > def< / span > < span class = "nf" > client_buffer_ready< / span > < span class = "p" > (< / span > < span class = "n" > ready_bytes< / span > < span class = "p" > :< / span > < span class = "nb" > int< / span > < span class = "p" > ):< / span >
< span class = "k" > global< / span > < span class = "n" > buffer< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > buffer< / span > < span class = "o" > .< / span > < span class = "n" > read< / span > < span class = "p" > (< / span > < span class = "n" > ready_bytes< / span > < span class = "p" > )< / span >
2023-03-04 16:57:18 +00:00
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Received data over the link buffer: " < / 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 >
2023-03-03 21:16:13 +00:00
< 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 buffer 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/Buffer.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/Buffer.py< / a > .< / p >
< / section >
2022-09-29 22:02:15 +00:00
< section id = "filetransfer" >
2022-09-30 16:43:04 +00:00
< span id = "example-filetransfer" > < / span > < h2 > Filetransfer< a class = "headerlink" href = "#filetransfer" title = "Permalink to this heading" > #< / a > < / h2 >
2021-05-16 21:40:49 +00:00
< 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 12:10:47 +00: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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > server_destination< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_connected< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_disconnected< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > list_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_delivery_callback< / span > < span class = "p" > (< / span > < span class = "n" > list_delivered< / span > < span class = "p" > )< / span >
2021-05-20 20:35:10 +00:00
< span class = "n" > list_receipt< / span > < span class = "o" > .< / span > < span class = "n" > set_timeout_callback< / span > < span class = "p" > (< / span > < span class = "n" > list_timeout< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > client_request< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-08-20 21:29:06 +00:00
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "n" > filename< / span > < span class = "o" > =< / span > < span class = "n" > message< / span > < span class = "o" > .< / span > < span class = "n" > decode< / span > < span class = "p" > (< / span > < span class = "s2" > " utf-8" < / span > < span class = "p" > )< / span >
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > filename< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-07-01 19:15:15 +00:00
< span class = "n" > dest_len< / span > < span class = "o" > =< / 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" > TRUNCATED_HASHLENGTH< / span > < span class = "o" > //< / span > < span class = "mi" > 8< / span > < span class = "p" > )< / span > < span class = "o" > *< / span > < span class = "mi" > 2< / 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 = "n" > dest_len< / 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 < / span > < span class = "si" > {hex}< / span > < span class = "s2" > hexadecimal characters (< / span > < span class = "si" > {byte}< / span > < span class = "s2" > bytes)." < / span > < span class = "o" > .< / span > < span class = "n" > format< / span > < span class = "p" > (< / span > < span class = "nb" > hex< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "p" > ,< / span > < span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > dest_len< / span > < span class = "o" > //< / span > < span class = "mi" > 2< / span > < span class = "p" > )< / span >
< span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_packet_callback< / span > < span class = "p" > (< / span > < span class = "n" > filelist_received< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_established_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_established< / span > < span class = "p" > )< / span >
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_link_closed_callback< / span > < span class = "p" > (< / span > < span class = "n" > link_closed< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-20 13:31:58 +00:00
< span class = "n" > link< / span > < span class = "o" > .< / span > < span class = "n" > set_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" > set_resource_concluded_callback< / span > < span class = "p" > (< / span > < span class = "n" > download_concluded< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-09-02 18:35:42 +00:00
< 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" > get_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 >
2021-05-17 12:10:47 +00:00
< 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 >
2023-11-04 17:13:26 +00:00
< 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" > daemon< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span > < span class = "p" > )< / span >
2021-05-17 12:10:47 +00:00
< 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 >
2021-05-17 15:04:01 +00:00
< 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 >
2021-05-17 12:10:47 +00:00
< 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 >
2022-09-29 22:02:15 +00:00
< / section >
2024-11-22 13:16:53 +00:00
< section id = "custom-interfaces" >
< span id = "example-custominterface" > < / span > < h2 > Custom Interfaces< a class = "headerlink" href = "#custom-interfaces" title = "Permalink to this heading" > #< / a > < / h2 >
< p > The < em > ExampleInterface< / em > demonstrates creating custom interfaces for Reticulum.
Any number of custom interfaces can be loaded and utilised by Reticulum, and
will be fully on-par with natively included interfaces, including all supported
< a class = "reference internal" href = "interfaces.html#interfaces-modes" > < span class = "std std-ref" > interface modes< / span > < / a > and < a class = "reference internal" href = "interfaces.html#interfaces-options" > < span class = "std std-ref" > common configuration options< / span > < / a > .< / p >
< div class = "highlight-default notranslate" > < div class = "highlight" > < pre > < span > < / span > < span class = "c1" > # MIT License - Copyright (c) 2024 Mark Qvist / unsigned.io< / span >
< span class = "c1" > # This example illustrates creating a custom interface< / span >
< span class = "c1" > # definition, that can be loaded and used by Reticulum at< / span >
< span class = "c1" > # runtime. Any number of custom interfaces can be created< / span >
< span class = "c1" > # and loaded. To use the interface place it in the folder< / span >
< span class = "c1" > # ~/.reticulum/interfaces, and add an interface entry to< / span >
< span class = "c1" > # your Reticulum configuration file similar to this:< / span >
< span class = "c1" > # [[Example Custom Interface]]< / span >
< span class = "c1" > # type = ExampleInterface< / span >
< span class = "c1" > # enabled = no< / span >
< span class = "c1" > # mode = gateway< / span >
< span class = "c1" > # port = /dev/ttyUSB0< / span >
< span class = "c1" > # speed = 115200< / span >
< span class = "c1" > # databits = 8< / span >
< span class = "c1" > # parity = none< / span >
< span class = "c1" > # stopbits = 1< / span >
< span class = "kn" > from< / span > < span class = "nn" > time< / span > < span class = "kn" > import< / span > < span class = "n" > sleep< / span >
< span class = "kn" > import< / span > < span class = "nn" > sys< / span >
< span class = "kn" > import< / span > < span class = "nn" > threading< / span >
< span class = "kn" > import< / span > < span class = "nn" > time< / span >
< span class = "c1" > # This HDLC helper class is used by the interface< / span >
< span class = "c1" > # to delimit and packetize data over the physical< / span >
< span class = "c1" > # medium - in this case a serial connection.< / span >
< span class = "k" > class< / span > < span class = "nc" > HDLC< / span > < span class = "p" > ():< / span >
< span class = "c1" > # This example interface packetizes data using< / span >
< span class = "c1" > # simplified HDLC framing, similar to PPP< / span >
< span class = "n" > FLAG< / span > < span class = "o" > =< / span > < span class = "mh" > 0x7E< / span >
< span class = "n" > ESC< / span > < span class = "o" > =< / span > < span class = "mh" > 0x7D< / span >
< span class = "n" > ESC_MASK< / span > < span class = "o" > =< / span > < span class = "mh" > 0x20< / span >
< span class = "nd" > @staticmethod< / span >
< span class = "k" > def< / span > < span class = "nf" > escape< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > ):< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > data< / span > < span class = "o" > .< / span > < span class = "n" > replace< / span > < span class = "p" > (< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "p" > ]),< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "p" > ,< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "o" > ^< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC_MASK< / span > < span class = "p" > ]))< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "n" > data< / span > < span class = "o" > .< / span > < span class = "n" > replace< / span > < span class = "p" > (< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "p" > ]),< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "p" > ,< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "o" > ^< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC_MASK< / span > < span class = "p" > ]))< / span >
< span class = "k" > return< / span > < span class = "n" > data< / span >
< span class = "c1" > # Let' s define our custom interface class. It must< / span >
< span class = "c1" > # be a sub-class of the RNS " Interface" class.< / span >
< span class = "k" > class< / span > < span class = "nc" > ExampleInterface< / span > < span class = "p" > (< / span > < span class = "n" > Interface< / span > < span class = "p" > ):< / span >
< span class = "c1" > # All interface classes must define a default< / span >
< span class = "c1" > # IFAC size, used in IFAC setup when the user< / span >
< span class = "c1" > # has not specified a custom IFAC size. This< / span >
< span class = "c1" > # option is specified in bytes.< / span >
< span class = "n" > DEFAULT_IFAC_SIZE< / span > < span class = "o" > =< / span > < span class = "mi" > 8< / span >
< span class = "c1" > # The following properties are local to this< / span >
< span class = "c1" > # particular interface implementation.< / span >
< span class = "n" > owner< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > port< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > speed< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > databits< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > stopbits< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "n" > serial< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "c1" > # All Reticulum interfaces must have an __init__< / span >
< span class = "c1" > # method that takes 2 positional arguments:< / span >
< span class = "c1" > # The owner RNS Transport instance, and a dict< / span >
< span class = "c1" > # of configuration values.< / 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" > owner< / span > < span class = "p" > ,< / span > < span class = "n" > configuration< / span > < span class = "p" > ):< / span >
< span class = "c1" > # The following lines demonstrate handling< / span >
< span class = "c1" > # potential dependencies required for the< / span >
< span class = "c1" > # interface to function correctly.< / span >
< span class = "kn" > import< / span > < span class = "nn" > importlib< / span >
< span class = "k" > if< / span > < span class = "n" > importlib< / span > < span class = "o" > .< / span > < span class = "n" > util< / span > < span class = "o" > .< / span > < span class = "n" > find_spec< / span > < span class = "p" > (< / span > < span class = "s1" > ' serial' < / span > < span class = "p" > )< / span > < span class = "o" > !=< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "kn" > import< / span > < span class = "nn" > serial< / 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" > " Using this interface requires a serial communication module to be installed." < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_CRITICAL< / 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 can install one with the command: python3 -m pip install pyserial" < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_CRITICAL< / span > < span class = "p" > )< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > panic< / span > < span class = "p" > ()< / span >
< span class = "c1" > # We start out by initialising the super-class< / span >
< span class = "nb" > super< / span > < span class = "p" > ()< / span > < span class = "o" > .< / span > < span class = "fm" > __init__< / span > < span class = "p" > ()< / span >
< span class = "c1" > # To make sure the configuration data is in the< / span >
< span class = "c1" > # correct format, we parse it through the following< / span >
< span class = "c1" > # method on the generic Interface class. This step< / span >
< span class = "c1" > # is required to ensure compatibility on all the< / span >
< span class = "c1" > # platforms that Reticulum supports.< / span >
< span class = "n" > ifconf< / span > < span class = "o" > =< / span > < span class = "n" > Interface< / span > < span class = "o" > .< / span > < span class = "n" > get_config_obj< / span > < span class = "p" > (< / span > < span class = "n" > configuration< / span > < span class = "p" > )< / span >
< span class = "c1" > # Read the interface name from the configuration< / span >
< span class = "c1" > # and set it on our interface instance.< / span >
< span class = "n" > name< / span > < span class = "o" > =< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " name" < / span > < span class = "p" > ]< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > name< / span > < span class = "o" > =< / span > < span class = "n" > name< / span >
< span class = "c1" > # We read configuration parameters from the supplied< / span >
< span class = "c1" > # configuration data, and provide default values in< / span >
< span class = "c1" > # case any are missing.< / span >
< span class = "n" > port< / span > < span class = "o" > =< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " port" < / span > < span class = "p" > ]< / span > < span class = "k" > if< / span > < span class = "s2" > " port" < / span > < span class = "ow" > in< / span > < span class = "n" > ifconf< / span > < span class = "k" > else< / span > < span class = "kc" > None< / span >
< span class = "n" > speed< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " speed" < / span > < span class = "p" > ])< / span > < span class = "k" > if< / span > < span class = "s2" > " speed" < / span > < span class = "ow" > in< / span > < span class = "n" > ifconf< / span > < span class = "k" > else< / span > < span class = "mi" > 9600< / span >
< span class = "n" > databits< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " databits" < / span > < span class = "p" > ])< / span > < span class = "k" > if< / span > < span class = "s2" > " databits" < / span > < span class = "ow" > in< / span > < span class = "n" > ifconf< / span > < span class = "k" > else< / span > < span class = "mi" > 8< / span >
< span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " parity" < / span > < span class = "p" > ]< / span > < span class = "k" > if< / span > < span class = "s2" > " parity" < / span > < span class = "ow" > in< / span > < span class = "n" > ifconf< / span > < span class = "k" > else< / span > < span class = "s2" > " N" < / span >
< span class = "n" > stopbits< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / span > < span class = "n" > ifconf< / span > < span class = "p" > [< / span > < span class = "s2" > " stopbits" < / span > < span class = "p" > ])< / span > < span class = "k" > if< / span > < span class = "s2" > " stopbits" < / span > < span class = "ow" > in< / span > < span class = "n" > ifconf< / span > < span class = "k" > else< / span > < span class = "mi" > 1< / span >
< span class = "c1" > # In case no port is specified, we abort setup by< / span >
< span class = "c1" > # raising an exception.< / span >
< span class = "k" > if< / span > < span class = "n" > port< / span > < span class = "o" > ==< / span > < span class = "kc" > None< / span > < span class = "p" > :< / span >
< span class = "k" > raise< / span > < span class = "ne" > ValueError< / span > < span class = "p" > (< / span > < span class = "sa" > f< / span > < span class = "s2" > " No port specified for < / span > < span class = "si" > {< / span > < span class = "bp" > self< / span > < span class = "si" > }< / span > < span class = "s2" > " < / span > < span class = "p" > )< / span >
< span class = "c1" > # All interfaces must supply a hardware MTU value< / span >
< span class = "c1" > # to the RNS Transport instance. This value should< / span >
< span class = "c1" > # be the maximum data packet payload size that the< / span >
< span class = "c1" > # underlying medium is capable of handling in all< / span >
< span class = "c1" > # cases without any segmentation.< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > HW_MTU< / span > < span class = "o" > =< / span > < span class = "mi" > 564< / span >
< span class = "c1" > # We initially set the " online" property to false,< / span >
< span class = "c1" > # since the interface has not actually been fully< / span >
< span class = "c1" > # initialised and connected yet.< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "c1" > # In this case, we can also set the indicated bit-< / span >
< span class = "c1" > # rate of the interface to the serial port speed.< / span >
2024-11-22 13:39:58 +00:00
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > bitrate< / span > < span class = "o" > =< / span > < span class = "n" > speed< / span >
2024-11-22 13:16:53 +00:00
< span class = "c1" > # Configure internal properties on the interface< / span >
< span class = "c1" > # according to the supplied configuration.< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > pyserial< / span > < span class = "o" > =< / span > < span class = "n" > serial< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > owner< / span > < span class = "o" > =< / span > < span class = "n" > owner< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > port< / span > < span class = "o" > =< / span > < span class = "n" > port< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > speed< / span > < span class = "o" > =< / span > < span class = "n" > speed< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > databits< / span > < span class = "o" > =< / span > < span class = "n" > databits< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > PARITY_NONE< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > stopbits< / span > < span class = "o" > =< / span > < span class = "n" > stopbits< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > timeout< / span > < span class = "o" > =< / span > < span class = "mi" > 100< / span >
< span class = "k" > if< / span > < span class = "n" > parity< / span > < span class = "o" > .< / span > < span class = "n" > lower< / span > < span class = "p" > ()< / span > < span class = "o" > ==< / span > < span class = "s2" > " e" < / span > < span class = "ow" > or< / span > < span class = "n" > parity< / span > < span class = "o" > .< / span > < span class = "n" > lower< / span > < span class = "p" > ()< / span > < span class = "o" > ==< / span > < span class = "s2" > " even" < / span > < span class = "p" > :< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > PARITY_EVEN< / span >
< span class = "k" > if< / span > < span class = "n" > parity< / span > < span class = "o" > .< / span > < span class = "n" > lower< / span > < span class = "p" > ()< / span > < span class = "o" > ==< / span > < span class = "s2" > " o" < / span > < span class = "ow" > or< / span > < span class = "n" > parity< / span > < span class = "o" > .< / span > < span class = "n" > lower< / span > < span class = "p" > ()< / span > < span class = "o" > ==< / span > < span class = "s2" > " odd" < / span > < span class = "p" > :< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > PARITY_ODD< / span >
< span class = "c1" > # Since all required parameters are now configured,< / span >
< span class = "c1" > # we will try opening the serial port.< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > open_port< / span > < span class = "p" > ()< / span >
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Could not open serial port for interface " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "bp" > self< / 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 = "k" > raise< / span > < span class = "n" > e< / span >
< span class = "c1" > # If opening the port succeeded, run any post-open< / span >
< span class = "c1" > # configuration required.< / span >
< span class = "k" > if< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > is_open< / span > < span class = "p" > :< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > configure_device< / span > < span class = "p" > ()< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > raise< / span > < span class = "ne" > IOError< / span > < span class = "p" > (< / span > < span class = "s2" > " Could not open serial port" < / span > < span class = "p" > )< / span >
< span class = "c1" > # Open the serial port with supplied configuration< / span >
< span class = "c1" > # parameters and store a reference to the open port.< / span >
< span class = "k" > def< / span > < span class = "nf" > open_port< / span > < span class = "p" > (< / span > < span class = "bp" > self< / 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" > " Opening serial port " < / span > < span class = "o" > +< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > port< / span > < span class = "o" > +< / span > < span class = "s2" > " ..." < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_VERBOSE< / span > < span class = "p" > )< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > pyserial< / span > < span class = "o" > .< / span > < span class = "n" > Serial< / span > < span class = "p" > (< / span >
< span class = "n" > port< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > port< / span > < span class = "p" > ,< / span >
< span class = "n" > baudrate< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > speed< / span > < span class = "p" > ,< / span >
< span class = "n" > bytesize< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > databits< / span > < span class = "p" > ,< / span >
< span class = "n" > parity< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > parity< / span > < span class = "p" > ,< / span >
< span class = "n" > stopbits< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > stopbits< / span > < span class = "p" > ,< / span >
< span class = "n" > xonxoff< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span > < span class = "p" > ,< / span >
< span class = "n" > rtscts< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span > < span class = "p" > ,< / span >
< span class = "n" > timeout< / span > < span class = "o" > =< / span > < span class = "mi" > 0< / span > < span class = "p" > ,< / span >
< span class = "n" > inter_byte_timeout< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ,< / span >
< span class = "n" > write_timeout< / span > < span class = "o" > =< / span > < span class = "kc" > None< / span > < span class = "p" > ,< / span >
< span class = "n" > dsrdtr< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span > < span class = "p" > ,< / span >
< span class = "p" > )< / span >
< span class = "c1" > # The only thing required after opening the port< / span >
< span class = "c1" > # is to wait a small amount of time for the< / span >
< span class = "c1" > # hardware to initialise and then start a thread< / span >
< span class = "c1" > # that reads any incoming data from the device.< / span >
< span class = "k" > def< / span > < span class = "nf" > configure_device< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ):< / span >
< span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.5< / span > < span class = "p" > )< / 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 = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > read_loop< / span > < span class = "p" > )< / span >
< span class = "n" > thread< / span > < span class = "o" > .< / span > < span class = "n" > daemon< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > thread< / span > < span class = "o" > .< / span > < span class = "n" > start< / span > < span class = "p" > ()< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Serial port " < / span > < span class = "o" > +< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > port< / span > < span class = "o" > +< / span > < span class = "s2" > " is now open" < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_VERBOSE< / span > < span class = "p" > )< / span >
< span class = "c1" > # This method will be called from our read-loop< / span >
< span class = "c1" > # whenever a full packet has been received over< / span >
< span class = "c1" > # the underlying medium.< / span >
< span class = "k" > def< / span > < span class = "nf" > process_incoming< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > ):< / span >
< span class = "c1" > # Update our received bytes counter< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > rxb< / span > < span class = "o" > +=< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
< span class = "c1" > # And send the data packet to the Transport< / span >
< span class = "c1" > # instance for processing.< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > owner< / span > < span class = "o" > .< / span > < span class = "n" > inbound< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > ,< / span > < span class = "bp" > self< / span > < span class = "p" > )< / span >
< span class = "c1" > # The running Reticulum Transport instance will< / span >
< span class = "c1" > # call this method on the interface whenever the< / span >
< span class = "c1" > # interface must transmit a packet.< / span >
< span class = "k" > def< / span > < span class = "nf" > process_outgoing< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ,< / span > < span class = "n" > data< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "p" > :< / span >
< span class = "c1" > # First, escape and packetize the data< / span >
< span class = "c1" > # according to HDLC framing.< / span >
< span class = "n" > data< / span > < span class = "o" > =< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "p" > ])< / span > < span class = "o" > +< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > escape< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "p" > ])< / span >
< span class = "c1" > # Then write the framed data to the port< / span >
< span class = "n" > written< / span > < span class = "o" > =< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > write< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
< span class = "c1" > # Update the transmitted bytes counter< / span >
< span class = "c1" > # and ensure that all data was written< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > txb< / span > < span class = "o" > +=< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )< / span >
< span class = "k" > if< / span > < span class = "n" > written< / span > < span class = "o" > !=< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > ):< / span >
< span class = "k" > raise< / span > < span class = "ne" > IOError< / span > < span class = "p" > (< / span > < span class = "s2" > " Serial interface only wrote " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > written< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " bytes of " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data< / span > < span class = "p" > )))< / span >
< span class = "c1" > # This read loop runs in a thread and continously< / span >
< span class = "c1" > # receives bytes from the underlying serial port.< / span >
< span class = "c1" > # When a full packet has been received, it will< / span >
< span class = "c1" > # be sent to the process_incoming methed, which< / span >
< span class = "c1" > # will in turn pass it to the Transport instance.< / span >
< span class = "k" > def< / span > < span class = "nf" > read_loop< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ):< / span >
< span class = "k" > try< / span > < span class = "p" > :< / span >
< span class = "n" > in_frame< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > escape< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > data_buffer< / span > < span class = "o" > =< / span > < span class = "sa" > b< / span > < span class = "s2" > " " < / span >
< span class = "n" > last_read_ms< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / 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 = "mi" > 1000< / span > < span class = "p" > )< / span >
< span class = "k" > while< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > is_open< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > in_waiting< / span > < span class = "p" > :< / span >
< span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "nb" > ord< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > read< / span > < span class = "p" > (< / span > < span class = "mi" > 1< / span > < span class = "p" > ))< / span >
< span class = "n" > last_read_ms< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / 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 = "mi" > 1000< / span > < span class = "p" > )< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > in_frame< / span > < span class = "ow" > and< / span > < span class = "n" > byte< / span > < span class = "o" > ==< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "p" > ):< / span >
< span class = "n" > in_frame< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > process_incoming< / span > < span class = "p" > (< / span > < span class = "n" > data_buffer< / span > < span class = "p" > )< / span >
< span class = "k" > elif< / span > < span class = "p" > (< / span > < span class = "n" > byte< / span > < span class = "o" > ==< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "p" > ):< / span >
< span class = "n" > in_frame< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "n" > data_buffer< / span > < span class = "o" > =< / span > < span class = "sa" > b< / span > < span class = "s2" > " " < / span >
< span class = "k" > elif< / span > < span class = "p" > (< / span > < span class = "n" > in_frame< / span > < span class = "ow" > and< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data_buffer< / span > < span class = "p" > )< / span > < span class = "o" > < < / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > HW_MTU< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > byte< / span > < span class = "o" > ==< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "p" > ):< / span >
< span class = "n" > escape< / span > < span class = "o" > =< / span > < span class = "kc" > True< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > escape< / span > < span class = "p" > ):< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > byte< / span > < span class = "o" > ==< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span > < span class = "o" > ^< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC_MASK< / span > < span class = "p" > ):< / span >
< span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > FLAG< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > byte< / span > < span class = "o" > ==< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span > < span class = "o" > ^< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC_MASK< / span > < span class = "p" > ):< / span >
< span class = "n" > byte< / span > < span class = "o" > =< / span > < span class = "n" > HDLC< / span > < span class = "o" > .< / span > < span class = "n" > ESC< / span >
< span class = "n" > escape< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > data_buffer< / span > < span class = "o" > =< / span > < span class = "n" > data_buffer< / span > < span class = "o" > +< / span > < span class = "nb" > bytes< / span > < span class = "p" > ([< / span > < span class = "n" > byte< / span > < span class = "p" > ])< / span >
< span class = "k" > else< / span > < span class = "p" > :< / span >
< span class = "n" > time_since_last< / span > < span class = "o" > =< / span > < span class = "nb" > int< / span > < span class = "p" > (< / 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 = "mi" > 1000< / span > < span class = "p" > )< / span > < span class = "o" > -< / span > < span class = "n" > last_read_ms< / span >
< span class = "k" > if< / span > < span class = "nb" > len< / span > < span class = "p" > (< / span > < span class = "n" > data_buffer< / span > < span class = "p" > )< / span > < span class = "o" > > < / span > < span class = "mi" > 0< / span > < span class = "ow" > and< / span > < span class = "n" > time_since_last< / span > < span class = "o" > > < / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > timeout< / span > < span class = "p" > :< / span >
< span class = "n" > data_buffer< / span > < span class = "o" > =< / span > < span class = "sa" > b< / span > < span class = "s2" > " " < / span >
< span class = "n" > in_frame< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > escape< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "mf" > 0.08< / 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 = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " A serial port error occurred, the contained exception was: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ),< / span > < span class = "n" > 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" > " The interface " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " experienced an unrecoverable error and is now offline." < / 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 = "k" > if< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > Reticulum< / span > < span class = "o" > .< / span > < span class = "n" > panic_on_interface_error< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > panic< / 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" > " Reticulum will attempt to reconnect the interface periodically." < / 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 = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "o" > =< / span > < span class = "kc" > False< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > close< / span > < span class = "p" > ()< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > reconnect_port< / span > < span class = "p" > ()< / span >
< span class = "c1" > # This method handles serial port disconnects.< / span >
< span class = "k" > def< / span > < span class = "nf" > reconnect_port< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ):< / span >
< span class = "k" > while< / span > < span class = "ow" > not< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > online< / span > < span class = "p" > :< / span >
< span class = "k" > try< / 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" > 5< / 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" > " Attempting to reconnect serial port " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > port< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " for " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > )< / span > < span class = "o" > +< / span > < span class = "s2" > " ..." < / span > < span class = "p" > ,< / span > < span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > LOG_VERBOSE< / span > < span class = "p" > )< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > open_port< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > serial< / span > < span class = "o" > .< / span > < span class = "n" > is_open< / span > < span class = "p" > :< / span >
< span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > configure_device< / span > < span class = "p" > ()< / span >
< span class = "k" > except< / span > < span class = "ne" > Exception< / span > < span class = "k" > as< / span > < span class = "n" > e< / span > < span class = "p" > :< / span >
< span class = "n" > RNS< / span > < span class = "o" > .< / span > < span class = "n" > log< / span > < span class = "p" > (< / span > < span class = "s2" > " Error while reconnecting port, the contained exception was: " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "n" > e< / span > < span class = "p" > ),< / span > < span class = "n" > 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" > " Reconnected serial port for " < / span > < span class = "o" > +< / span > < span class = "nb" > str< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ))< / span >
< span class = "c1" > # Signal to Reticulum that this interface should< / span >
< span class = "c1" > # not perform any ingress limiting.< / span >
< span class = "k" > def< / span > < span class = "nf" > should_ingress_limit< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ):< / span >
< span class = "k" > return< / span > < span class = "kc" > False< / span >
< span class = "c1" > # We must provide a string representation of this< / span >
< span class = "c1" > # interface, that is used whenever the interface< / span >
< span class = "c1" > # is printed in logs or external programs.< / span >
< span class = "k" > def< / span > < span class = "fm" > __str__< / span > < span class = "p" > (< / span > < span class = "bp" > self< / span > < span class = "p" > ):< / span >
< span class = "k" > return< / span > < span class = "s2" > " ExampleInterface[" < / span > < span class = "o" > +< / span > < span class = "bp" > self< / span > < span class = "o" > .< / span > < span class = "n" > name< / span > < span class = "o" > +< / span > < span class = "s2" > " ]" < / span >
< span class = "c1" > # Finally, register the defined interface class as the< / span >
< span class = "c1" > # target class for Reticulum to use as an interface< / span >
< span class = "n" > interface_class< / span > < span class = "o" > =< / span > < span class = "n" > ExampleInterface< / 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/ExampleInterface.py" > https://github.com/markqvist/Reticulum/blob/master/Examples/ExampleInterface.py< / a > .< / p >
< / section >
2022-09-29 22:02:15 +00:00
< / section >
2021-05-16 21:40:49 +00:00
2022-09-30 16:43:04 +00:00
< / article >
< / div >
< footer >
< div class = "related-pages" >
< a class = "next-page" href = "support.html" >
< div class = "page-info" >
< div class = "context" >
< span > Next< / span >
< / div >
< div class = "title" > Support Reticulum< / div >
< / div >
< svg class = "furo-related-icon" > < use href = "#svg-arrow-right" > < / use > < / svg >
< / a >
< a class = "prev-page" href = "networks.html" >
< svg class = "furo-related-icon" > < use href = "#svg-arrow-right" > < / use > < / svg >
< div class = "page-info" >
< div class = "context" >
< span > Previous< / span >
< / div >
< div class = "title" > Building Networks< / div >
< / div >
< / a >
< / div >
< div class = "bottom-of-page" >
< div class = "left-details" >
< div class = "copyright" >
2023-02-23 16:25:38 +00:00
Copyright © 2023, Mark Qvist
2022-09-30 16:43:04 +00:00
< / div >
Generated with < a href = "https://www.sphinx-doc.org/" > Sphinx< / a > and
< a href = "https://github.com/pradyunsg/furo" > Furo< / a >
< / div >
< div class = "right-details" >
< div class = "icons" >
< / div >
2021-05-16 21:40:49 +00:00
< / div >
< / div >
2022-09-30 16:43:04 +00:00
< / footer >
< / div >
< aside class = "toc-drawer" >
< div class = "toc-sticky toc-scroll" >
< div class = "toc-title-container" >
< span class = "toc-title" >
On this page
< / span >
< / div >
< div class = "toc-tree-container" >
< div class = "toc-tree" >
< ul >
2021-09-25 21:22:33 +00:00
< li > < a class = "reference internal" href = "#" > Code Examples< / a > < ul >
2021-05-16 21:40:49 +00:00
< 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 >
2021-08-19 12:11:22 +00:00
< li > < a class = "reference internal" href = "#example-identify" > Identification< / a > < / li >
2021-08-20 21:29:06 +00:00
< li > < a class = "reference internal" href = "#requests-responses" > Requests & Responses< / a > < / li >
2023-03-02 11:47:55 +00:00
< li > < a class = "reference internal" href = "#channel" > Channel< / a > < / li >
2023-03-03 21:16:13 +00:00
< li > < a class = "reference internal" href = "#buffer" > Buffer< / a > < / li >
2021-05-16 21:40:49 +00:00
< li > < a class = "reference internal" href = "#filetransfer" > Filetransfer< / a > < / li >
2024-11-22 13:16:53 +00:00
< li > < a class = "reference internal" href = "#custom-interfaces" > Custom Interfaces< / a > < / li >
2021-05-16 21:40:49 +00:00
< / ul >
< / li >
< / ul >
2022-09-30 16:43:04 +00:00
< / div >
2021-05-16 21:40:49 +00:00
< / div >
< / div >
2022-09-30 16:43:04 +00:00
< / aside >
< / div >
2024-05-05 17:56:33 +00:00
< / div > < 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/_sphinx_javascript_frameworks_compat.js" > < / script >
< script src = "_static/doctools.js" > < / script >
< script src = "_static/sphinx_highlight.js" > < / script >
< script src = "_static/scripts/furo.js" > < / script >
< script src = "_static/clipboard.min.js" > < / script >
< script src = "_static/copybutton.js" > < / script >
2022-09-30 16:43:04 +00:00
< / body >
2023-10-01 10:09:49 +00:00
< / html >