/ docs / manual / examples.html
examples.html
   1  <!doctype html>
   2  <html class="no-js" lang="en">
   3    <head><meta charset="utf-8"/>
   4      <meta name="viewport" content="width=device-width,initial-scale=1"/>
   5      <meta name="color-scheme" content="light dark"><meta name="viewport" content="width=device-width, initial-scale=1" />
   6  <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" />
   7  
   8      <meta name="generator" content="sphinx-5.3.0, furo 2022.09.29.dev1"/>
   9          <title>Code Examples - Reticulum Network Stack 1.0.0 documentation</title>
  10        <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
  11      <link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=189ec851f9bb375a2509b67be1f64f0cf212b702" />
  12      <link rel="stylesheet" type="text/css" href="_static/copybutton.css" />
  13      <link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
  14      <link rel="stylesheet" type="text/css" href="_static/custom.css" />
  15      
  16      
  17  
  18  
  19  <style>
  20    body {
  21      --color-code-background: #f8f8f8;
  22    --color-code-foreground: black;
  23    
  24    }
  25    @media not print {
  26      body[data-theme="dark"] {
  27        --color-code-background: #202020;
  28    --color-code-foreground: #d0d0d0;
  29    --color-background-primary: #202b38;
  30    --color-background-secondary: #161f27;
  31    --color-foreground-primary: #dbdbdb;
  32    --color-foreground-secondary: #a9b1ba;
  33    --color-brand-primary: #41adff;
  34    --color-background-hover: #161f27;
  35    --color-api-name: #ffbe85;
  36    --color-api-pre-name: #efae75;
  37    
  38      }
  39      @media (prefers-color-scheme: dark) {
  40        body:not([data-theme="light"]) {
  41          --color-code-background: #202020;
  42    --color-code-foreground: #d0d0d0;
  43    --color-background-primary: #202b38;
  44    --color-background-secondary: #161f27;
  45    --color-foreground-primary: #dbdbdb;
  46    --color-foreground-secondary: #a9b1ba;
  47    --color-brand-primary: #41adff;
  48    --color-background-hover: #161f27;
  49    --color-api-name: #ffbe85;
  50    --color-api-pre-name: #efae75;
  51    
  52        }
  53      }
  54    }
  55  </style></head>
  56    <body>
  57      
  58      <script>
  59        document.body.dataset.theme = localStorage.getItem("theme") || "auto";
  60      </script>
  61      
  62  
  63  <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  64    <symbol id="svg-toc" viewBox="0 0 24 24">
  65      <title>Contents</title>
  66      <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
  67        <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"/>
  68      </svg>
  69    </symbol>
  70    <symbol id="svg-menu" viewBox="0 0 24 24">
  71      <title>Menu</title>
  72      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
  73        stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
  74        <line x1="3" y1="12" x2="21" y2="12"></line>
  75        <line x1="3" y1="6" x2="21" y2="6"></line>
  76        <line x1="3" y1="18" x2="21" y2="18"></line>
  77      </svg>
  78    </symbol>
  79    <symbol id="svg-arrow-right" viewBox="0 0 24 24">
  80      <title>Expand</title>
  81      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
  82        stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
  83        <polyline points="9 18 15 12 9 6"></polyline>
  84      </svg>
  85    </symbol>
  86    <symbol id="svg-sun" viewBox="0 0 24 24">
  87      <title>Light mode</title>
  88      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
  89        stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
  90        <circle cx="12" cy="12" r="5"></circle>
  91        <line x1="12" y1="1" x2="12" y2="3"></line>
  92        <line x1="12" y1="21" x2="12" y2="23"></line>
  93        <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
  94        <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
  95        <line x1="1" y1="12" x2="3" y2="12"></line>
  96        <line x1="21" y1="12" x2="23" y2="12"></line>
  97        <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
  98        <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
  99      </svg>
 100    </symbol>
 101    <symbol id="svg-moon" viewBox="0 0 24 24">
 102      <title>Dark mode</title>
 103      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
 104        stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
 105        <path stroke="none" d="M0 0h24v24H0z" fill="none" />
 106        <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" />
 107      </svg>
 108    </symbol>
 109    <symbol id="svg-sun-half" viewBox="0 0 24 24">
 110      <title>Auto light/dark mode</title>
 111      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
 112        stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
 113        <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
 114        <circle cx="12" cy="12" r="9" />
 115        <path d="M13 12h5" />
 116        <path d="M13 15h4" />
 117        <path d="M13 18h1" />
 118        <path d="M13 9h4" />
 119        <path d="M13 6h1" />
 120      </svg>
 121    </symbol>
 122  </svg>
 123  
 124  <input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
 125  <input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
 126  <label class="overlay sidebar-overlay" for="__navigation">
 127    <div class="visually-hidden">Hide navigation sidebar</div>
 128  </label>
 129  <label class="overlay toc-overlay" for="__toc">
 130    <div class="visually-hidden">Hide table of contents sidebar</div>
 131  </label>
 132  
 133  
 134  
 135  <div class="page">
 136    <header class="mobile-header">
 137      <div class="header-left">
 138        <label class="nav-overlay-icon" for="__navigation">
 139          <div class="visually-hidden">Toggle site navigation sidebar</div>
 140          <i class="icon"><svg><use href="#svg-menu"></use></svg></i>
 141        </label>
 142      </div>
 143      <div class="header-center">
 144        <a href="index.html"><div class="brand">Reticulum Network Stack 1.0.0 documentation</div></a>
 145      </div>
 146      <div class="header-right">
 147        <div class="theme-toggle-container theme-toggle-header">
 148          <button class="theme-toggle">
 149            <div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
 150            <svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
 151            <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
 152            <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
 153          </button>
 154        </div>
 155        <label class="toc-overlay-icon toc-header-icon" for="__toc">
 156          <div class="visually-hidden">Toggle table of contents sidebar</div>
 157          <i class="icon"><svg><use href="#svg-toc"></use></svg></i>
 158        </label>
 159      </div>
 160    </header>
 161    <aside class="sidebar-drawer">
 162      <div class="sidebar-container">
 163        
 164        <div class="sidebar-sticky"><a class="sidebar-brand centered" href="index.html">
 165    
 166    <div class="sidebar-logo-container">
 167      <img class="sidebar-logo" src="_static/rns_logo_512.png" alt="Logo"/>
 168    </div>
 169    
 170    <span class="sidebar-brand-text">Reticulum Network Stack 1.0.0 documentation</span>
 171    
 172  </a><form class="sidebar-search-container" method="get" action="search.html" role="search">
 173    <input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
 174    <input type="hidden" name="check_keywords" value="yes">
 175    <input type="hidden" name="area" value="default">
 176  </form>
 177  <div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
 178    <ul class="current">
 179  <li class="toctree-l1"><a class="reference internal" href="whatis.html">What is Reticulum?</a></li>
 180  <li class="toctree-l1"><a class="reference internal" href="gettingstartedfast.html">Getting Started Fast</a></li>
 181  <li class="toctree-l1"><a class="reference internal" href="using.html">Using Reticulum on Your System</a></li>
 182  <li class="toctree-l1"><a class="reference internal" href="understanding.html">Understanding Reticulum</a></li>
 183  <li class="toctree-l1"><a class="reference internal" href="hardware.html">Communications Hardware</a></li>
 184  <li class="toctree-l1"><a class="reference internal" href="interfaces.html">Configuring Interfaces</a></li>
 185  <li class="toctree-l1"><a class="reference internal" href="networks.html">Building Networks</a></li>
 186  <li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Code Examples</a></li>
 187  <li class="toctree-l1"><a class="reference internal" href="support.html">Support Reticulum</a></li>
 188  </ul>
 189  <ul>
 190  <li class="toctree-l1"><a class="reference internal" href="reference.html">API Reference</a></li>
 191  </ul>
 192  
 193  </div>
 194  </div>
 195  
 196        </div>
 197        
 198      </div>
 199    </aside>
 200    <div class="main">
 201      <div class="content">
 202        <div class="article-container">
 203          <a href="#" class="back-to-top muted-link">
 204            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
 205              <path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
 206            </svg>
 207            <span>Back to top</span>
 208          </a>
 209          <div class="content-icon-container">
 210            <div class="theme-toggle-container theme-toggle-content">
 211              <button class="theme-toggle">
 212                <div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
 213                <svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
 214                <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
 215                <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
 216              </button>
 217            </div>
 218            <label class="toc-overlay-icon toc-content-icon" for="__toc">
 219              <div class="visually-hidden">Toggle table of contents sidebar</div>
 220              <i class="icon"><svg><use href="#svg-toc"></use></svg></i>
 221            </label>
 222          </div>
 223          <article role="main">
 224            <section id="code-examples">
 225  <span id="examples-main"></span><h1>Code Examples<a class="headerlink" href="#code-examples" title="Permalink to this heading">#</a></h1>
 226  <p>A number of examples are included in the source distribution of Reticulum.
 227  You can use these examples to learn how to write your own programs.</p>
 228  <section id="minimal">
 229  <span id="example-minimal"></span><h2>Minimal<a class="headerlink" href="#minimal" title="Permalink to this heading">#</a></h2>
 230  <p>The <em>Minimal</em> example demonstrates the bare-minimum setup required to connect to
 231  a Reticulum network from your program. In about five lines of code, you will
 232  have the Reticulum Network Stack initialised, and ready to pass traffic in your
 233  program.</p>
 234  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
 235  <span class="c1"># This RNS example demonstrates a minimal setup, that    #</span>
 236  <span class="c1"># will start up the Reticulum Network Stack, generate a  #</span>
 237  <span class="c1"># new destination, and let the user send an announce.    #</span>
 238  <span class="c1">##########################################################</span>
 239  
 240  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
 241  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
 242  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
 243  
 244  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
 245  <span class="c1"># destinations we create. Since this basic example</span>
 246  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
 247  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
 248  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
 249  
 250  <span class="c1"># This initialisation is executed when the program is started</span>
 251  <span class="k">def</span><span class="w"> </span><span class="nf">program_setup</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
 252      <span class="c1"># We must first initialise Reticulum</span>
 253      <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>
 254      
 255      <span class="c1"># Randomly create a new identity for our example</span>
 256      <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>
 257  
 258      <span class="c1"># Using the identity we just created, we create a destination.</span>
 259      <span class="c1"># Destinations are endpoints in Reticulum, that can be addressed</span>
 260      <span class="c1"># and communicated with. Destinations can also announce their</span>
 261      <span class="c1"># existence, which will let the network know they are reachable</span>
 262      <span class="c1"># and automatically create paths to them, from anywhere else</span>
 263      <span class="c1"># in the network.</span>
 264      <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>
 265          <span class="n">identity</span><span class="p">,</span>
 266          <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>
 267          <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>
 268          <span class="n">APP_NAME</span><span class="p">,</span>
 269          <span class="s2">&quot;minimalsample&quot;</span>
 270      <span class="p">)</span>
 271  
 272      <span class="c1"># We configure the destination to automatically prove all</span>
 273      <span class="c1"># packets addressed to it. By doing this, RNS will automatically</span>
 274      <span class="c1"># generate a proof for each incoming packet and transmit it</span>
 275      <span class="c1"># back to the sender of that packet. This will let anyone that</span>
 276      <span class="c1"># tries to communicate with the destination know whether their</span>
 277      <span class="c1"># communication was received correctly.</span>
 278      <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>
 279      
 280      <span class="c1"># Everything&#39;s ready!</span>
 281      <span class="c1"># Let&#39;s hand over control to the announce loop</span>
 282      <span class="n">announceLoop</span><span class="p">(</span><span class="n">destination</span><span class="p">)</span>
 283  
 284  
 285  <span class="k">def</span><span class="w"> </span><span class="nf">announceLoop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
 286      <span class="c1"># Let the user know that everything is ready</span>
 287      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 288          <span class="s2">&quot;Minimal example &quot;</span><span class="o">+</span>
 289          <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>
 290          <span class="s2">&quot; running, hit enter to manually send an announce (Ctrl-C to quit)&quot;</span>
 291      <span class="p">)</span>
 292  
 293      <span class="c1"># We enter a loop that runs until the users exits.</span>
 294      <span class="c1"># If the user hits enter, we will announce our server</span>
 295      <span class="c1"># destination on the network, which will let clients</span>
 296      <span class="c1"># know how to create messages directed towards it.</span>
 297      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
 298          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
 299          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
 300          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
 301  
 302  
 303  <span class="c1">##########################################################</span>
 304  <span class="c1">#### Program Startup #####################################</span>
 305  <span class="c1">##########################################################</span>
 306  
 307  <span class="c1"># This part of the program gets run at startup,</span>
 308  <span class="c1"># and parses input from the user, and then starts</span>
 309  <span class="c1"># the desired program mode.</span>
 310  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
 311      <span class="k">try</span><span class="p">:</span>
 312          <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>
 313              <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Minimal example to start Reticulum and create a destination&quot;</span>
 314          <span class="p">)</span>
 315  
 316          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 317              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
 318              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 319              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 320              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
 321              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 322          <span class="p">)</span>
 323  
 324          <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>
 325  
 326          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
 327              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
 328          <span class="k">else</span><span class="p">:</span>
 329              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
 330  
 331          <span class="n">program_setup</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
 332  
 333      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
 334          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 335          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
 336  </pre></div>
 337  </div>
 338  <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>
 339  </section>
 340  <section id="announce">
 341  <span id="example-announce"></span><h2>Announce<a class="headerlink" href="#announce" title="Permalink to this heading">#</a></h2>
 342  <p>The <em>Announce</em> example builds upon the previous example by exploring how to
 343  announce a destination on the network, and how to let your program receive
 344  notifications about announces from relevant destinations.</p>
 345  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
 346  <span class="c1"># This RNS example demonstrates setting up announce      #</span>
 347  <span class="c1"># callbacks, which will let an application receive a     #</span>
 348  <span class="c1"># notification when an announce relevant for it arrives  #</span>
 349  <span class="c1">##########################################################</span>
 350  
 351  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
 352  <span class="kn">import</span><span class="w"> </span><span class="nn">random</span>
 353  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
 354  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
 355  
 356  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
 357  <span class="c1"># destinations we create. Since this basic example</span>
 358  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
 359  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
 360  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
 361  
 362  <span class="c1"># We initialise two lists of strings to use as app_data</span>
 363  <span class="n">fruits</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;Peach&quot;</span><span class="p">,</span> <span class="s2">&quot;Quince&quot;</span><span class="p">,</span> <span class="s2">&quot;Date&quot;</span><span class="p">,</span> <span class="s2">&quot;Tangerine&quot;</span><span class="p">,</span> <span class="s2">&quot;Pomelo&quot;</span><span class="p">,</span> <span class="s2">&quot;Carambola&quot;</span><span class="p">,</span> <span class="s2">&quot;Grape&quot;</span><span class="p">]</span>
 364  <span class="n">noble_gases</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;Helium&quot;</span><span class="p">,</span> <span class="s2">&quot;Neon&quot;</span><span class="p">,</span> <span class="s2">&quot;Argon&quot;</span><span class="p">,</span> <span class="s2">&quot;Krypton&quot;</span><span class="p">,</span> <span class="s2">&quot;Xenon&quot;</span><span class="p">,</span> <span class="s2">&quot;Radon&quot;</span><span class="p">,</span> <span class="s2">&quot;Oganesson&quot;</span><span class="p">]</span>
 365  
 366  <span class="c1"># This initialisation is executed when the program is started</span>
 367  <span class="k">def</span><span class="w"> </span><span class="nf">program_setup</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
 368      <span class="c1"># We must first initialise Reticulum</span>
 369      <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>
 370      
 371      <span class="c1"># Randomly create a new identity for our example</span>
 372      <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>
 373  
 374      <span class="c1"># Using the identity we just created, we create two destinations</span>
 375      <span class="c1"># in the &quot;example_utilities.announcesample&quot; application space.</span>
 376      <span class="c1">#</span>
 377      <span class="c1"># Destinations are endpoints in Reticulum, that can be addressed</span>
 378      <span class="c1"># and communicated with. Destinations can also announce their</span>
 379      <span class="c1"># existence, which will let the network know they are reachable</span>
 380      <span class="c1"># and automatically create paths to them, from anywhere else</span>
 381      <span class="c1"># in the network.</span>
 382      <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>
 383          <span class="n">identity</span><span class="p">,</span>
 384          <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>
 385          <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>
 386          <span class="n">APP_NAME</span><span class="p">,</span>
 387          <span class="s2">&quot;announcesample&quot;</span><span class="p">,</span>
 388          <span class="s2">&quot;fruits&quot;</span>
 389      <span class="p">)</span>
 390  
 391      <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>
 392          <span class="n">identity</span><span class="p">,</span>
 393          <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>
 394          <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>
 395          <span class="n">APP_NAME</span><span class="p">,</span>
 396          <span class="s2">&quot;announcesample&quot;</span><span class="p">,</span>
 397          <span class="s2">&quot;noble_gases&quot;</span>
 398      <span class="p">)</span>
 399  
 400      <span class="c1"># We configure the destinations to automatically prove all</span>
 401      <span class="c1"># packets addressed to it. By doing this, RNS will automatically</span>
 402      <span class="c1"># generate a proof for each incoming packet and transmit it</span>
 403      <span class="c1"># back to the sender of that packet. This will let anyone that</span>
 404      <span class="c1"># tries to communicate with the destination know whether their</span>
 405      <span class="c1"># communication was received correctly.</span>
 406      <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>
 407      <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>
 408  
 409      <span class="c1"># We create an announce handler and configure it to only ask for</span>
 410      <span class="c1"># announces from &quot;example_utilities.announcesample.fruits&quot;.</span>
 411      <span class="c1"># Try changing the filter and see what happens.</span>
 412      <span class="n">announce_handler</span> <span class="o">=</span> <span class="n">ExampleAnnounceHandler</span><span class="p">(</span>
 413          <span class="n">aspect_filter</span><span class="o">=</span><span class="s2">&quot;example_utilities.announcesample.fruits&quot;</span>
 414      <span class="p">)</span>
 415  
 416      <span class="c1"># We register the announce handler with Reticulum</span>
 417      <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>
 418      
 419      <span class="c1"># Everything&#39;s ready!</span>
 420      <span class="c1"># Let&#39;s hand over control to the announce loop</span>
 421      <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>
 422  
 423  
 424  <span class="k">def</span><span class="w"> </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>
 425      <span class="c1"># Let the user know that everything is ready</span>
 426      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Announce example running, hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
 427  
 428      <span class="c1"># We enter a loop that runs until the users exits.</span>
 429      <span class="c1"># If the user hits enter, we will announce our server</span>
 430      <span class="c1"># destination on the network, which will let clients</span>
 431      <span class="c1"># know how to create messages directed towards it.</span>
 432      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
 433          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
 434          
 435          <span class="c1"># Randomly select a fruit</span>
 436          <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>
 437  
 438          <span class="c1"># Send the announce including the app data</span>
 439          <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">&quot;utf-8&quot;</span><span class="p">))</span>
 440          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 441              <span class="s2">&quot;Sent announce from &quot;</span><span class="o">+</span>
 442              <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>
 443              <span class="s2">&quot; (&quot;</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">&quot;)&quot;</span>
 444          <span class="p">)</span>
 445  
 446          <span class="c1"># Randomly select a noble gas</span>
 447          <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>
 448  
 449          <span class="c1"># Send the announce including the app data</span>
 450          <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">&quot;utf-8&quot;</span><span class="p">))</span>
 451          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 452              <span class="s2">&quot;Sent announce from &quot;</span><span class="o">+</span>
 453              <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>
 454              <span class="s2">&quot; (&quot;</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">&quot;)&quot;</span>
 455          <span class="p">)</span>
 456  
 457  <span class="c1"># We will need to define an announce handler class that</span>
 458  <span class="c1"># Reticulum can message when an announce arrives.</span>
 459  <span class="k">class</span><span class="w"> </span><span class="nc">ExampleAnnounceHandler</span><span class="p">:</span>
 460      <span class="c1"># The initialisation method takes the optional</span>
 461      <span class="c1"># aspect_filter argument. If aspect_filter is set to</span>
 462      <span class="c1"># None, all announces will be passed to the instance.</span>
 463      <span class="c1"># If only some announces are wanted, it can be set to</span>
 464      <span class="c1"># an aspect string.</span>
 465      <span class="k">def</span><span class="w"> </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>
 466          <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>
 467  
 468      <span class="c1"># This method will be called by Reticulums Transport</span>
 469      <span class="c1"># system when an announce arrives that matches the</span>
 470      <span class="c1"># configured aspect filter. Filters must be specific,</span>
 471      <span class="c1"># and cannot use wildcards.</span>
 472      <span class="k">def</span><span class="w"> </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>
 473          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 474              <span class="s2">&quot;Received an announce from &quot;</span><span class="o">+</span>
 475              <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>
 476          <span class="p">)</span>
 477  
 478          <span class="k">if</span> <span class="n">app_data</span><span class="p">:</span>
 479              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 480                  <span class="s2">&quot;The announce contained the following app data: &quot;</span><span class="o">+</span>
 481                  <span class="n">app_data</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span>
 482              <span class="p">)</span>
 483  
 484  <span class="c1">##########################################################</span>
 485  <span class="c1">#### Program Startup #####################################</span>
 486  <span class="c1">##########################################################</span>
 487  
 488  <span class="c1"># This part of the program gets run at startup,</span>
 489  <span class="c1"># and parses input from the user, and then starts</span>
 490  <span class="c1"># the desired program mode.</span>
 491  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
 492      <span class="k">try</span><span class="p">:</span>
 493          <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>
 494              <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Reticulum example that demonstrates announces and announce handlers&quot;</span>
 495          <span class="p">)</span>
 496  
 497          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 498              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
 499              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 500              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 501              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
 502              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 503          <span class="p">)</span>
 504  
 505          <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>
 506  
 507          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
 508              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
 509          <span class="k">else</span><span class="p">:</span>
 510              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
 511  
 512          <span class="n">program_setup</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
 513  
 514      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
 515          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 516          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
 517  </pre></div>
 518  </div>
 519  <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>
 520  </section>
 521  <section id="broadcast">
 522  <span id="example-broadcast"></span><h2>Broadcast<a class="headerlink" href="#broadcast" title="Permalink to this heading">#</a></h2>
 523  <p>The <em>Broadcast</em> example explores how to transmit plaintext broadcast messages
 524  over the network.</p>
 525  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
 526  <span class="c1"># This RNS example demonstrates broadcasting unencrypted #</span>
 527  <span class="c1"># information to any listening destinations.             #</span>
 528  <span class="c1">##########################################################</span>
 529  
 530  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
 531  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
 532  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
 533  
 534  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
 535  <span class="c1"># destinations we create. Since this basic example</span>
 536  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
 537  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
 538  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
 539  
 540  <span class="c1"># This initialisation is executed when the program is started</span>
 541  <span class="k">def</span><span class="w"> </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>
 542      <span class="c1"># We must first initialise Reticulum</span>
 543      <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>
 544      
 545      <span class="c1"># If the user did not select a &quot;channel&quot; we use</span>
 546      <span class="c1"># a default one called &quot;public_information&quot;.</span>
 547      <span class="c1"># This &quot;channel&quot; is added to the destination name-</span>
 548      <span class="c1"># space, so the user can select different broadcast</span>
 549      <span class="c1"># channels.</span>
 550      <span class="k">if</span> <span class="n">channel</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
 551          <span class="n">channel</span> <span class="o">=</span> <span class="s2">&quot;public_information&quot;</span>
 552  
 553      <span class="c1"># We create a PLAIN destination. This is an uncencrypted endpoint</span>
 554      <span class="c1"># that anyone can listen to and send information to.</span>
 555      <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>
 556          <span class="kc">None</span><span class="p">,</span>
 557          <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>
 558          <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>
 559          <span class="n">APP_NAME</span><span class="p">,</span>
 560          <span class="s2">&quot;broadcast&quot;</span><span class="p">,</span>
 561          <span class="n">channel</span>
 562      <span class="p">)</span>
 563  
 564      <span class="c1"># We specify a callback that will get called every time</span>
 565      <span class="c1"># the destination receives data.</span>
 566      <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>
 567      
 568      <span class="c1"># Everything&#39;s ready!</span>
 569      <span class="c1"># Let&#39;s hand over control to the main loop</span>
 570      <span class="n">broadcastLoop</span><span class="p">(</span><span class="n">broadcast_destination</span><span class="p">)</span>
 571  
 572  <span class="k">def</span><span class="w"> </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>
 573      <span class="c1"># Simply print out the received data</span>
 574      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 575      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Received data: &quot;</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">&quot;utf-8&quot;</span><span class="p">)</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\r\n</span><span class="s2">&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 576      <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>
 577  
 578  <span class="k">def</span><span class="w"> </span><span class="nf">broadcastLoop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
 579      <span class="c1"># Let the user know that everything is ready</span>
 580      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 581          <span class="s2">&quot;Broadcast example &quot;</span><span class="o">+</span>
 582          <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>
 583          <span class="s2">&quot; running, enter text and hit enter to broadcast (Ctrl-C to quit)&quot;</span>
 584      <span class="p">)</span>
 585  
 586      <span class="c1"># We enter a loop that runs until the users exits.</span>
 587      <span class="c1"># If the user hits enter, we will send the information</span>
 588      <span class="c1"># that the user entered into the prompt.</span>
 589      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
 590          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 591          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
 592  
 593          <span class="k">if</span> <span class="n">entered</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
 594              <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">&quot;utf-8&quot;</span><span class="p">)</span>
 595              <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>
 596              <span class="n">packet</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
 597  
 598  
 599  
 600  <span class="c1">##########################################################</span>
 601  <span class="c1">#### Program Startup #####################################</span>
 602  <span class="c1">##########################################################</span>
 603  
 604  <span class="c1"># This part of the program gets run at startup,</span>
 605  <span class="c1"># and parses input from the user, and then starts</span>
 606  <span class="c1"># the program.</span>
 607  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
 608      <span class="k">try</span><span class="p">:</span>
 609          <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>
 610              <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Reticulum example demonstrating sending and receiving broadcasts&quot;</span>
 611          <span class="p">)</span>
 612  
 613          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 614              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
 615              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 616              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 617              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
 618              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 619          <span class="p">)</span>
 620  
 621          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 622              <span class="s2">&quot;--channel&quot;</span><span class="p">,</span>
 623              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 624              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 625              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;broadcast channel name&quot;</span><span class="p">,</span>
 626              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 627          <span class="p">)</span>
 628  
 629          <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>
 630  
 631          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
 632              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
 633          <span class="k">else</span><span class="p">:</span>
 634              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
 635  
 636          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">channel</span><span class="p">:</span>
 637              <span class="n">channelarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">channel</span>
 638          <span class="k">else</span><span class="p">:</span>
 639              <span class="n">channelarg</span> <span class="o">=</span> <span class="kc">None</span>
 640  
 641          <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>
 642  
 643      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
 644          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 645          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
 646  </pre></div>
 647  </div>
 648  <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>
 649  </section>
 650  <section id="echo">
 651  <span id="example-echo"></span><h2>Echo<a class="headerlink" href="#echo" title="Permalink to this heading">#</a></h2>
 652  <p>The <em>Echo</em> example demonstrates communication between two destinations using
 653  the Packet interface.</p>
 654  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
 655  <span class="c1"># This RNS example demonstrates a simple client/server   #</span>
 656  <span class="c1"># echo utility. A client can send an echo request to the #</span>
 657  <span class="c1"># server, and the server will respond by proving receipt #</span>
 658  <span class="c1"># of the packet.                                         #</span>
 659  <span class="c1">##########################################################</span>
 660  
 661  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
 662  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
 663  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
 664  
 665  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
 666  <span class="c1"># destinations we create. Since this echo example</span>
 667  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
 668  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
 669  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
 670  
 671  
 672  <span class="c1">##########################################################</span>
 673  <span class="c1">#### Server Part #########################################</span>
 674  <span class="c1">##########################################################</span>
 675  
 676  <span class="c1"># This initialisation is executed when the users chooses</span>
 677  <span class="c1"># to run as a server</span>
 678  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
 679      <span class="k">global</span> <span class="n">reticulum</span>
 680  
 681      <span class="c1"># We must first initialise Reticulum</span>
 682      <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>
 683      
 684      <span class="c1"># Randomly create a new identity for our echo server</span>
 685      <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>
 686  
 687      <span class="c1"># We create a destination that clients can query. We want</span>
 688      <span class="c1"># to be able to verify echo replies to our clients, so we</span>
 689      <span class="c1"># create a &quot;single&quot; destination that can receive encrypted</span>
 690      <span class="c1"># messages. This way the client can send a request and be</span>
 691      <span class="c1"># certain that no-one else than this destination was able</span>
 692      <span class="c1"># to read it. </span>
 693      <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>
 694          <span class="n">server_identity</span><span class="p">,</span>
 695          <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>
 696          <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>
 697          <span class="n">APP_NAME</span><span class="p">,</span>
 698          <span class="s2">&quot;echo&quot;</span><span class="p">,</span>
 699          <span class="s2">&quot;request&quot;</span>
 700      <span class="p">)</span>
 701  
 702      <span class="c1"># We configure the destination to automatically prove all</span>
 703      <span class="c1"># packets addressed to it. By doing this, RNS will automatically</span>
 704      <span class="c1"># generate a proof for each incoming packet and transmit it</span>
 705      <span class="c1"># back to the sender of that packet.</span>
 706      <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>
 707      
 708      <span class="c1"># Tell the destination which function in our program to</span>
 709      <span class="c1"># run when a packet is received. We do this so we can</span>
 710      <span class="c1"># print a log message when the server receives a request</span>
 711      <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>
 712  
 713      <span class="c1"># Everything&#39;s ready!</span>
 714      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
 715      <span class="n">announceLoop</span><span class="p">(</span><span class="n">echo_destination</span><span class="p">)</span>
 716  
 717  
 718  <span class="k">def</span><span class="w"> </span><span class="nf">announceLoop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
 719      <span class="c1"># Let the user know that everything is ready</span>
 720      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 721          <span class="s2">&quot;Echo server &quot;</span><span class="o">+</span>
 722          <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>
 723          <span class="s2">&quot; running, hit enter to manually send an announce (Ctrl-C to quit)&quot;</span>
 724      <span class="p">)</span>
 725  
 726      <span class="c1"># We enter a loop that runs until the users exits.</span>
 727      <span class="c1"># If the user hits enter, we will announce our server</span>
 728      <span class="c1"># destination on the network, which will let clients</span>
 729      <span class="c1"># know how to create messages directed towards it.</span>
 730      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
 731          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
 732          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
 733          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
 734  
 735  
 736  <span class="k">def</span><span class="w"> </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>
 737      <span class="k">global</span> <span class="n">reticulum</span>
 738      
 739      <span class="c1"># Tell the user that we received an echo request, and</span>
 740      <span class="c1"># that we are going to send a reply to the requester.</span>
 741      <span class="c1"># Sending the proof is handled automatically, since we</span>
 742      <span class="c1"># set up the destination to prove all incoming packets.</span>
 743  
 744      <span class="n">reception_stats</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
 745      <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>
 746          <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>
 747          <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>
 748  
 749          <span class="k">if</span> <span class="n">reception_rssi</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
 750              <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [RSSI &quot;</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">&quot; dBm]&quot;</span>
 751          
 752          <span class="k">if</span> <span class="n">reception_snr</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
 753              <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [SNR &quot;</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">&quot; dBm]&quot;</span>
 754  
 755      <span class="k">else</span><span class="p">:</span>
 756          <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>
 757              <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [RSSI &quot;</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">&quot; dBm]&quot;</span>
 758          
 759          <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>
 760              <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [SNR &quot;</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">&quot; dB]&quot;</span>
 761  
 762      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received packet from echo client, proof sent&quot;</span><span class="o">+</span><span class="n">reception_stats</span><span class="p">)</span>
 763  
 764  
 765  <span class="c1">##########################################################</span>
 766  <span class="c1">#### Client Part #########################################</span>
 767  <span class="c1">##########################################################</span>
 768  
 769  <span class="c1"># This initialisation is executed when the users chooses</span>
 770  <span class="c1"># to run as a client</span>
 771  <span class="k">def</span><span class="w"> </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>
 772      <span class="k">global</span> <span class="n">reticulum</span>
 773      
 774      <span class="c1"># We need a binary representation of the destination</span>
 775      <span class="c1"># hash that was entered on the command line</span>
 776      <span class="k">try</span><span class="p">:</span>
 777          <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>
 778          <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>
 779              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
 780                  <span class="s2">&quot;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).&quot;</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>
 781              <span class="p">)</span>
 782  
 783          <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>
 784      <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
 785          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!&quot;</span><span class="p">)</span>
 786          <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">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
 787          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
 788  
 789      <span class="c1"># We must first initialise Reticulum</span>
 790      <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>
 791  
 792      <span class="c1"># We override the loglevel to provide feedback when</span>
 793      <span class="c1"># an announce is received</span>
 794      <span class="k">if</span> <span class="n">RNS</span><span class="o">.</span><span class="n">loglevel</span> <span class="o">&lt;</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_INFO</span><span class="p">:</span>
 795          <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>
 796  
 797      <span class="c1"># Tell the user that the client is ready!</span>
 798      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 799          <span class="s2">&quot;Echo client ready, hit enter to send echo request to &quot;</span><span class="o">+</span>
 800          <span class="n">destination_hexhash</span><span class="o">+</span>
 801          <span class="s2">&quot; (Ctrl-C to quit)&quot;</span>
 802      <span class="p">)</span>
 803  
 804      <span class="c1"># We enter a loop that runs until the user exits.</span>
 805      <span class="c1"># If the user hits enter, we will try to send an</span>
 806      <span class="c1"># echo request to the destination specified on the</span>
 807      <span class="c1"># command line.</span>
 808      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
 809          <span class="nb">input</span><span class="p">()</span>
 810          
 811          <span class="c1"># Let&#39;s first check if RNS knows a path to the destination.</span>
 812          <span class="c1"># If it does, we&#39;ll load the server identity and create a packet</span>
 813          <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>
 814  
 815              <span class="c1"># To address the server, we need to know it&#39;s public</span>
 816              <span class="c1"># key, so we check if Reticulum knows this destination.</span>
 817              <span class="c1"># This is done by calling the &quot;recall&quot; method of the</span>
 818              <span class="c1"># Identity module. If the destination is known, it will</span>
 819              <span class="c1"># return an Identity instance that can be used in</span>
 820              <span class="c1"># outgoing destinations.</span>
 821              <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>
 822  
 823              <span class="c1"># We got the correct identity instance from the</span>
 824              <span class="c1"># recall method, so let&#39;s create an outgoing</span>
 825              <span class="c1"># destination. We use the naming convention:</span>
 826              <span class="c1"># example_utilities.echo.request</span>
 827              <span class="c1"># This matches the naming we specified in the</span>
 828              <span class="c1"># server part of the code.</span>
 829              <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>
 830                  <span class="n">server_identity</span><span class="p">,</span>
 831                  <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>
 832                  <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>
 833                  <span class="n">APP_NAME</span><span class="p">,</span>
 834                  <span class="s2">&quot;echo&quot;</span><span class="p">,</span>
 835                  <span class="s2">&quot;request&quot;</span>
 836              <span class="p">)</span>
 837  
 838              <span class="c1"># The destination is ready, so let&#39;s create a packet.</span>
 839              <span class="c1"># We set the destination to the request_destination</span>
 840              <span class="c1"># that was just created, and the only data we add</span>
 841              <span class="c1"># is a random hash.</span>
 842              <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>
 843  
 844              <span class="c1"># Send the packet! If the packet is successfully</span>
 845              <span class="c1"># sent, it will return a PacketReceipt instance.</span>
 846              <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>
 847  
 848              <span class="c1"># If the user specified a timeout, we set this</span>
 849              <span class="c1"># timeout on the packet receipt, and configure</span>
 850              <span class="c1"># a callback function, that will get called if</span>
 851              <span class="c1"># the packet times out.</span>
 852              <span class="k">if</span> <span class="n">timeout</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
 853                  <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>
 854                  <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>
 855  
 856              <span class="c1"># We can then set a delivery callback on the receipt.</span>
 857              <span class="c1"># This will get automatically called when a proof for</span>
 858              <span class="c1"># this specific packet is received from the destination.</span>
 859              <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>
 860  
 861              <span class="c1"># Tell the user that the echo request was sent</span>
 862              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent echo request to &quot;</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>
 863          <span class="k">else</span><span class="p">:</span>
 864              <span class="c1"># If we do not know this destination, tell the</span>
 865              <span class="c1"># user to wait for an announce to arrive.</span>
 866              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path...&quot;</span><span class="p">)</span>
 867              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually retry once an announce is received.&quot;</span><span class="p">)</span>
 868              <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>
 869  
 870  <span class="c1"># This function is called when our reply destination</span>
 871  <span class="c1"># receives a proof packet.</span>
 872  <span class="k">def</span><span class="w"> </span><span class="nf">packet_delivered</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
 873      <span class="k">global</span> <span class="n">reticulum</span>
 874  
 875      <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>
 876          <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>
 877          <span class="k">if</span> <span class="p">(</span><span class="n">rtt</span> <span class="o">&gt;=</span> <span class="mi">1</span><span class="p">):</span>
 878              <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>
 879              <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">&quot; seconds&quot;</span>
 880          <span class="k">else</span><span class="p">:</span>
 881              <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>
 882              <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">&quot; milliseconds&quot;</span>
 883  
 884          <span class="n">reception_stats</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
 885          <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>
 886              <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>
 887              <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>
 888  
 889              <span class="k">if</span> <span class="n">reception_rssi</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
 890                  <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [RSSI &quot;</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">&quot; dBm]&quot;</span>
 891              
 892              <span class="k">if</span> <span class="n">reception_snr</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
 893                  <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [SNR &quot;</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">&quot; dB]&quot;</span>
 894  
 895          <span class="k">else</span><span class="p">:</span>
 896              <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>
 897                  <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>
 898                      <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [RSSI &quot;</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">&quot; dBm]&quot;</span>
 899                  
 900                  <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>
 901                      <span class="n">reception_stats</span> <span class="o">+=</span> <span class="s2">&quot; [SNR &quot;</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">&quot; dB]&quot;</span>
 902  
 903          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
 904              <span class="s2">&quot;Valid reply received from &quot;</span><span class="o">+</span>
 905              <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>
 906              <span class="s2">&quot;, round-trip time is &quot;</span><span class="o">+</span><span class="n">rttstring</span><span class="o">+</span>
 907              <span class="n">reception_stats</span>
 908          <span class="p">)</span>
 909  
 910  <span class="c1"># This function is called if a packet times out.</span>
 911  <span class="k">def</span><span class="w"> </span><span class="nf">packet_timed_out</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
 912      <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>
 913          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Packet &quot;</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">&quot; timed out&quot;</span><span class="p">)</span>
 914  
 915  
 916  <span class="c1">##########################################################</span>
 917  <span class="c1">#### Program Startup #####################################</span>
 918  <span class="c1">##########################################################</span>
 919  
 920  <span class="c1"># This part of the program gets run at startup,</span>
 921  <span class="c1"># and parses input from the user, and then starts</span>
 922  <span class="c1"># the desired program mode.</span>
 923  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
 924      <span class="k">try</span><span class="p">:</span>
 925          <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">&quot;Simple echo server and client utility&quot;</span><span class="p">)</span>
 926  
 927          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 928              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
 929              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
 930              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
 931              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming packets from clients&quot;</span>
 932          <span class="p">)</span>
 933  
 934          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 935              <span class="s2">&quot;-t&quot;</span><span class="p">,</span>
 936              <span class="s2">&quot;--timeout&quot;</span><span class="p">,</span>
 937              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 938              <span class="n">metavar</span><span class="o">=</span><span class="s2">&quot;s&quot;</span><span class="p">,</span>
 939              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 940              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;set a reply timeout in seconds&quot;</span><span class="p">,</span>
 941              <span class="nb">type</span><span class="o">=</span><span class="nb">float</span>
 942          <span class="p">)</span>
 943  
 944          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s2">&quot;--config&quot;</span><span class="p">,</span>
 945              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
 946              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 947              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
 948              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 949          <span class="p">)</span>
 950  
 951          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
 952              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
 953              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
 954              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
 955              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
 956              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
 957          <span class="p">)</span>
 958  
 959          <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>
 960  
 961          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
 962              <span class="n">configarg</span><span class="o">=</span><span class="kc">None</span>
 963              <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
 964                  <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
 965              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
 966          <span class="k">else</span><span class="p">:</span>
 967              <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
 968                  <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
 969              <span class="k">else</span><span class="p">:</span>
 970                  <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
 971  
 972              <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">timeout</span><span class="p">:</span>
 973                  <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>
 974              <span class="k">else</span><span class="p">:</span>
 975                  <span class="n">timeoutarg</span> <span class="o">=</span> <span class="kc">None</span>
 976  
 977              <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>
 978                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 979                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
 980                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 981              <span class="k">else</span><span class="p">:</span>
 982                  <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>
 983      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
 984          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
 985          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
 986  </pre></div>
 987  </div>
 988  <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>
 989  </section>
 990  <section id="link">
 991  <span id="example-link"></span><h2>Link<a class="headerlink" href="#link" title="Permalink to this heading">#</a></h2>
 992  <p>The <em>Link</em> example explores establishing an encrypted link to a remote
 993  destination, and passing traffic back and forth over the link.</p>
 994  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
 995  <span class="c1"># This RNS example demonstrates how to set up a link to  #</span>
 996  <span class="c1"># a destination, and pass data back and forth over it.   #</span>
 997  <span class="c1">##########################################################</span>
 998  
 999  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
1000  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
1001  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
1002  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
1003  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
1004  
1005  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
1006  <span class="c1"># destinations we create. Since this echo example</span>
1007  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
1008  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
1009  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
1010  
1011  <span class="c1">##########################################################</span>
1012  <span class="c1">#### Server Part #########################################</span>
1013  <span class="c1">##########################################################</span>
1014  
1015  <span class="c1"># A reference to the latest client link that connected</span>
1016  <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
1017  
1018  <span class="c1"># This initialisation is executed when the users chooses</span>
1019  <span class="c1"># to run as a server</span>
1020  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
1021      <span class="c1"># We must first initialise Reticulum</span>
1022      <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>
1023      
1024      <span class="c1"># Randomly create a new identity for our link example</span>
1025      <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>
1026  
1027      <span class="c1"># We create a destination that clients can connect to. We</span>
1028      <span class="c1"># want clients to create links to this destination, so we</span>
1029      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
1030      <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>
1031          <span class="n">server_identity</span><span class="p">,</span>
1032          <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>
1033          <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>
1034          <span class="n">APP_NAME</span><span class="p">,</span>
1035          <span class="s2">&quot;linkexample&quot;</span>
1036      <span class="p">)</span>
1037  
1038      <span class="c1"># We configure a function that will get called every time</span>
1039      <span class="c1"># a new client creates a link to this destination.</span>
1040      <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>
1041  
1042      <span class="c1"># Everything&#39;s ready!</span>
1043      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
1044      <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
1045  
1046  <span class="k">def</span><span class="w"> </span><span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
1047      <span class="c1"># Let the user know that everything is ready</span>
1048      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1049          <span class="s2">&quot;Link example &quot;</span><span class="o">+</span>
1050          <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>
1051          <span class="s2">&quot; running, waiting for a connection.&quot;</span>
1052      <span class="p">)</span>
1053  
1054      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
1055  
1056      <span class="c1"># We enter a loop that runs until the users exits.</span>
1057      <span class="c1"># If the user hits enter, we will announce our server</span>
1058      <span class="c1"># destination on the network, which will let clients</span>
1059      <span class="c1"># know how to create messages directed towards it.</span>
1060      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
1061          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1062          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
1063          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
1064  
1065  <span class="c1"># When a client establishes a link to our server</span>
1066  <span class="c1"># destination, this function will be called with</span>
1067  <span class="c1"># a reference to the link.</span>
1068  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1069      <span class="k">global</span> <span class="n">latest_client_link</span>
1070  
1071      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
1072      <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>
1073      <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>
1074      <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
1075  
1076  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1077      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
1078  
1079  <span class="k">def</span><span class="w"> </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>
1080      <span class="k">global</span> <span class="n">latest_client_link</span>
1081  
1082      <span class="c1"># When data is received over any active link,</span>
1083      <span class="c1"># it will all be directed to the last client</span>
1084      <span class="c1"># that connected.</span>
1085      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1086      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</span><span class="o">+</span><span class="n">text</span><span class="p">)</span>
1087      
1088      <span class="n">reply_text</span> <span class="o">=</span> <span class="s2">&quot;I received </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">text</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> over the link&quot;</span>
1089      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1090      <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>
1091  
1092  
1093  <span class="c1">##########################################################</span>
1094  <span class="c1">#### Client Part #########################################</span>
1095  <span class="c1">##########################################################</span>
1096  
1097  <span class="c1"># A reference to the server link</span>
1098  <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
1099  
1100  <span class="c1"># This initialisation is executed when the users chooses</span>
1101  <span class="c1"># to run as a client</span>
1102  <span class="k">def</span><span class="w"> </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>
1103      <span class="c1"># We need a binary representation of the destination</span>
1104      <span class="c1"># hash that was entered on the command line</span>
1105      <span class="k">try</span><span class="p">:</span>
1106          <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>
1107          <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>
1108              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
1109                  <span class="s2">&quot;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).&quot;</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>
1110              <span class="p">)</span>
1111              
1112          <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>
1113      <span class="k">except</span><span class="p">:</span>
1114          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
1115          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1116  
1117      <span class="c1"># We must first initialise Reticulum</span>
1118      <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>
1119  
1120      <span class="c1"># Check if we know a path to the destination</span>
1121      <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>
1122          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
1123          <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>
1124          <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>
1125              <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>
1126  
1127      <span class="c1"># Recall the server identity</span>
1128      <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>
1129  
1130      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
1131      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
1132  
1133      <span class="c1"># When the server identity is known, we set</span>
1134      <span class="c1"># up a destination</span>
1135      <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>
1136          <span class="n">server_identity</span><span class="p">,</span>
1137          <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>
1138          <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>
1139          <span class="n">APP_NAME</span><span class="p">,</span>
1140          <span class="s2">&quot;linkexample&quot;</span>
1141      <span class="p">)</span>
1142  
1143      <span class="c1"># And create a link</span>
1144      <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>
1145  
1146      <span class="c1"># We set a callback that will get executed</span>
1147      <span class="c1"># every time a packet is received over the</span>
1148      <span class="c1"># link</span>
1149      <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>
1150  
1151      <span class="c1"># We&#39;ll also set up functions to inform the</span>
1152      <span class="c1"># user when the link is established or closed</span>
1153      <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>
1154      <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>
1155  
1156      <span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
1157      <span class="c1"># for the user to interact with the example</span>
1158      <span class="n">client_loop</span><span class="p">()</span>
1159  
1160  <span class="k">def</span><span class="w"> </span><span class="nf">client_loop</span><span class="p">():</span>
1161      <span class="k">global</span> <span class="n">server_link</span>
1162  
1163      <span class="c1"># Wait for the link to become active</span>
1164      <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
1165          <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>
1166  
1167      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
1168      <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
1169          <span class="k">try</span><span class="p">:</span>
1170              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
1171              <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1172  
1173              <span class="c1"># Check if we should quit the example</span>
1174              <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
1175                  <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1176                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1177  
1178              <span class="c1"># If not, send the entered text over the link</span>
1179              <span class="k">if</span> <span class="n">text</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
1180                  <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">&quot;utf-8&quot;</span><span class="p">)</span>
1181                  <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">&lt;=</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>
1182                      <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>
1183                  <span class="k">else</span><span class="p">:</span>
1184                      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1185                          <span class="s2">&quot;Cannot send this packet, the data size of &quot;</span><span class="o">+</span>
1186                          <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">&quot; bytes exceeds the link packet MDU of &quot;</span><span class="o">+</span>
1187                          <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">&quot; bytes&quot;</span><span class="p">,</span>
1188                          <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span>
1189                      <span class="p">)</span>
1190  
1191          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1192              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while sending data over the link: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
1193              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1194              <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1195  
1196  <span class="c1"># This function is called when a link</span>
1197  <span class="c1"># has been established with the server</span>
1198  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1199      <span class="c1"># We store a reference to the link</span>
1200      <span class="c1"># instance for later use</span>
1201      <span class="k">global</span> <span class="n">server_link</span>
1202      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
1203  
1204      <span class="c1"># Inform the user that the server is</span>
1205      <span class="c1"># connected</span>
1206      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server, enter some text to send, or </span><span class="se">\&quot;</span><span class="s2">quit</span><span class="se">\&quot;</span><span class="s2"> to quit&quot;</span><span class="p">)</span>
1207  
1208  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
1209  <span class="c1"># user, and exit the program</span>
1210  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1211      <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>
1212          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
1213      <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>
1214          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
1215      <span class="k">else</span><span class="p">:</span>
1216          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
1217      
1218      <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>
1219      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1220  
1221  <span class="c1"># When a packet is received over the link, we</span>
1222  <span class="c1"># simply print out the data.</span>
1223  <span class="k">def</span><span class="w"> </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>
1224      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1225      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</span><span class="o">+</span><span class="n">text</span><span class="p">)</span>
1226      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
1227      <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>
1228  
1229  
1230  <span class="c1">##########################################################</span>
1231  <span class="c1">#### Program Startup #####################################</span>
1232  <span class="c1">##########################################################</span>
1233  
1234  <span class="c1"># This part of the program runs at startup,</span>
1235  <span class="c1"># and parses input of from the user, and then</span>
1236  <span class="c1"># starts up the desired program mode.</span>
1237  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
1238      <span class="k">try</span><span class="p">:</span>
1239          <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">&quot;Simple link example&quot;</span><span class="p">)</span>
1240  
1241          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1242              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
1243              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
1244              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
1245              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming link requests from clients&quot;</span>
1246          <span class="p">)</span>
1247  
1248          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1249              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
1250              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
1251              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1252              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
1253              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1254          <span class="p">)</span>
1255  
1256          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1257              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
1258              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
1259              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1260              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
1261              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1262          <span class="p">)</span>
1263  
1264          <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>
1265  
1266          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
1267              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
1268          <span class="k">else</span><span class="p">:</span>
1269              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
1270  
1271          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
1272              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
1273          <span class="k">else</span><span class="p">:</span>
1274              <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>
1275                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1276                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
1277                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1278              <span class="k">else</span><span class="p">:</span>
1279                  <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>
1280  
1281      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
1282          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1283          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1284  </pre></div>
1285  </div>
1286  <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>
1287  </section>
1288  <section id="example-identify">
1289  <span id="identification"></span><h2>Identification<a class="headerlink" href="#example-identify" title="Permalink to this heading">#</a></h2>
1290  <p>The <em>Identify</em> example explores identifying an intiator of a link, once
1291  the link has been established.</p>
1292  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
1293  <span class="c1"># This RNS example demonstrates how to set up a link to  #</span>
1294  <span class="c1"># a destination, and identify the initiator to it&#39;s peer #</span>
1295  <span class="c1">##########################################################</span>
1296  
1297  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
1298  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
1299  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
1300  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
1301  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
1302  
1303  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
1304  <span class="c1"># destinations we create. Since this echo example</span>
1305  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
1306  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
1307  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
1308  
1309  <span class="c1">##########################################################</span>
1310  <span class="c1">#### Server Part #########################################</span>
1311  <span class="c1">##########################################################</span>
1312  
1313  <span class="c1"># A reference to the latest client link that connected</span>
1314  <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
1315  
1316  <span class="c1"># This initialisation is executed when the users chooses</span>
1317  <span class="c1"># to run as a server</span>
1318  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
1319      <span class="c1"># We must first initialise Reticulum</span>
1320      <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>
1321      
1322      <span class="c1"># Randomly create a new identity for our link example</span>
1323      <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>
1324  
1325      <span class="c1"># We create a destination that clients can connect to. We</span>
1326      <span class="c1"># want clients to create links to this destination, so we</span>
1327      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
1328      <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>
1329          <span class="n">server_identity</span><span class="p">,</span>
1330          <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>
1331          <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>
1332          <span class="n">APP_NAME</span><span class="p">,</span>
1333          <span class="s2">&quot;identifyexample&quot;</span>
1334      <span class="p">)</span>
1335  
1336      <span class="c1"># We configure a function that will get called every time</span>
1337      <span class="c1"># a new client creates a link to this destination.</span>
1338      <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>
1339  
1340      <span class="c1"># Everything&#39;s ready!</span>
1341      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
1342      <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
1343  
1344  <span class="k">def</span><span class="w"> </span><span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
1345      <span class="c1"># Let the user know that everything is ready</span>
1346      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1347          <span class="s2">&quot;Link identification example &quot;</span><span class="o">+</span>
1348          <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>
1349          <span class="s2">&quot; running, waiting for a connection.&quot;</span>
1350      <span class="p">)</span>
1351  
1352      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
1353  
1354      <span class="c1"># We enter a loop that runs until the users exits.</span>
1355      <span class="c1"># If the user hits enter, we will announce our server</span>
1356      <span class="c1"># destination on the network, which will let clients</span>
1357      <span class="c1"># know how to create messages directed towards it.</span>
1358      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
1359          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1360          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
1361          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
1362  
1363  <span class="c1"># When a client establishes a link to our server</span>
1364  <span class="c1"># destination, this function will be called with</span>
1365  <span class="c1"># a reference to the link.</span>
1366  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1367      <span class="k">global</span> <span class="n">latest_client_link</span>
1368  
1369      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
1370      <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>
1371      <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>
1372      <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>
1373      <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
1374  
1375  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1376      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
1377  
1378  <span class="k">def</span><span class="w"> </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>
1379      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Remote identified as: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">identity</span><span class="p">))</span>
1380  
1381  <span class="k">def</span><span class="w"> </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>
1382      <span class="k">global</span> <span class="n">latest_client_link</span>
1383  
1384      <span class="c1"># Get the originating identity for display</span>
1385      <span class="n">remote_peer</span> <span class="o">=</span>  <span class="s2">&quot;unidentified peer&quot;</span>
1386      <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>
1387          <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>
1388  
1389      <span class="c1"># When data is received over any active link,</span>
1390      <span class="c1"># it will all be directed to the last client</span>
1391      <span class="c1"># that connected.</span>
1392      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1393  
1394      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data from &quot;</span><span class="o">+</span><span class="n">remote_peer</span><span class="o">+</span><span class="s2">&quot;: &quot;</span><span class="o">+</span><span class="n">text</span><span class="p">)</span>
1395      
1396      <span class="n">reply_text</span> <span class="o">=</span> <span class="s2">&quot;I received </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">text</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> over the link from &quot;</span><span class="o">+</span><span class="n">remote_peer</span>
1397      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1398      <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>
1399  
1400  
1401  <span class="c1">##########################################################</span>
1402  <span class="c1">#### Client Part #########################################</span>
1403  <span class="c1">##########################################################</span>
1404  
1405  <span class="c1"># A reference to the server link</span>
1406  <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
1407  
1408  <span class="c1"># A reference to the client identity</span>
1409  <span class="n">client_identity</span> <span class="o">=</span> <span class="kc">None</span>
1410  
1411  <span class="c1"># This initialisation is executed when the users chooses</span>
1412  <span class="c1"># to run as a client</span>
1413  <span class="k">def</span><span class="w"> </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>
1414      <span class="k">global</span> <span class="n">client_identity</span>
1415      <span class="c1"># We need a binary representation of the destination</span>
1416      <span class="c1"># hash that was entered on the command line</span>
1417      <span class="k">try</span><span class="p">:</span>
1418          <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>
1419          <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>
1420              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
1421                  <span class="s2">&quot;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).&quot;</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>
1422              <span class="p">)</span>
1423  
1424          <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>
1425      <span class="k">except</span><span class="p">:</span>
1426          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
1427          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1428  
1429      <span class="c1"># We must first initialise Reticulum</span>
1430      <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>
1431  
1432      <span class="c1"># Create a new client identity</span>
1433      <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>
1434      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1435          <span class="s2">&quot;Client created new identity &quot;</span><span class="o">+</span>
1436          <span class="nb">str</span><span class="p">(</span><span class="n">client_identity</span><span class="p">)</span>
1437      <span class="p">)</span>
1438  
1439      <span class="c1"># Check if we know a path to the destination</span>
1440      <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>
1441          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
1442          <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>
1443          <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>
1444              <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>
1445  
1446      <span class="c1"># Recall the server identity</span>
1447      <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>
1448  
1449      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
1450      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
1451  
1452      <span class="c1"># When the server identity is known, we set</span>
1453      <span class="c1"># up a destination</span>
1454      <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>
1455          <span class="n">server_identity</span><span class="p">,</span>
1456          <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>
1457          <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>
1458          <span class="n">APP_NAME</span><span class="p">,</span>
1459          <span class="s2">&quot;identifyexample&quot;</span>
1460      <span class="p">)</span>
1461  
1462      <span class="c1"># And create a link</span>
1463      <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>
1464  
1465      <span class="c1"># We set a callback that will get executed</span>
1466      <span class="c1"># every time a packet is received over the</span>
1467      <span class="c1"># link</span>
1468      <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>
1469  
1470      <span class="c1"># We&#39;ll also set up functions to inform the</span>
1471      <span class="c1"># user when the link is established or closed</span>
1472      <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>
1473      <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>
1474  
1475      <span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
1476      <span class="c1"># for the user to interact with the example</span>
1477      <span class="n">client_loop</span><span class="p">()</span>
1478  
1479  <span class="k">def</span><span class="w"> </span><span class="nf">client_loop</span><span class="p">():</span>
1480      <span class="k">global</span> <span class="n">server_link</span>
1481  
1482      <span class="c1"># Wait for the link to become active</span>
1483      <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
1484          <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>
1485  
1486      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
1487      <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
1488          <span class="k">try</span><span class="p">:</span>
1489              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
1490              <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1491  
1492              <span class="c1"># Check if we should quit the example</span>
1493              <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
1494                  <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1495                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1496  
1497              <span class="c1"># If not, send the entered text over the link</span>
1498              <span class="k">if</span> <span class="n">text</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
1499                  <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">&quot;utf-8&quot;</span><span class="p">)</span>
1500                  <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">&lt;=</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>
1501                      <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>
1502                  <span class="k">else</span><span class="p">:</span>
1503                      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1504                          <span class="s2">&quot;Cannot send this packet, the data size of &quot;</span><span class="o">+</span>
1505                          <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">&quot; bytes exceeds the link packet MDU of &quot;</span><span class="o">+</span>
1506                          <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">&quot; bytes&quot;</span><span class="p">,</span>
1507                          <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span>
1508                      <span class="p">)</span>
1509  
1510          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1511              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while sending data over the link: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
1512              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1513              <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1514  
1515  <span class="c1"># This function is called when a link</span>
1516  <span class="c1"># has been established with the server</span>
1517  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1518      <span class="c1"># We store a reference to the link</span>
1519      <span class="c1"># instance for later use</span>
1520      <span class="k">global</span> <span class="n">server_link</span><span class="p">,</span> <span class="n">client_identity</span>
1521      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
1522  
1523      <span class="c1"># Inform the user that the server is</span>
1524      <span class="c1"># connected</span>
1525      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server, identifying to remote peer...&quot;</span><span class="p">)</span>
1526  
1527      <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>
1528  
1529  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
1530  <span class="c1"># user, and exit the program</span>
1531  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1532      <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>
1533          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
1534      <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>
1535          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
1536      <span class="k">else</span><span class="p">:</span>
1537          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
1538      
1539      <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>
1540      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1541  
1542  <span class="c1"># When a packet is received over the link, we</span>
1543  <span class="c1"># simply print out the data.</span>
1544  <span class="k">def</span><span class="w"> </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>
1545      <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">&quot;utf-8&quot;</span><span class="p">)</span>
1546      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</span><span class="o">+</span><span class="n">text</span><span class="p">)</span>
1547      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
1548      <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>
1549  
1550  
1551  <span class="c1">##########################################################</span>
1552  <span class="c1">#### Program Startup #####################################</span>
1553  <span class="c1">##########################################################</span>
1554  
1555  <span class="c1"># This part of the program runs at startup,</span>
1556  <span class="c1"># and parses input of from the user, and then</span>
1557  <span class="c1"># starts up the desired program mode.</span>
1558  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
1559      <span class="k">try</span><span class="p">:</span>
1560          <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">&quot;Simple link example&quot;</span><span class="p">)</span>
1561  
1562          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1563              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
1564              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
1565              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
1566              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming link requests from clients&quot;</span>
1567          <span class="p">)</span>
1568  
1569          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1570              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
1571              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
1572              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1573              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
1574              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1575          <span class="p">)</span>
1576  
1577          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1578              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
1579              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
1580              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1581              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
1582              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1583          <span class="p">)</span>
1584  
1585          <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>
1586  
1587          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
1588              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
1589          <span class="k">else</span><span class="p">:</span>
1590              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
1591  
1592          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
1593              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
1594          <span class="k">else</span><span class="p">:</span>
1595              <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>
1596                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1597                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
1598                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1599              <span class="k">else</span><span class="p">:</span>
1600                  <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>
1601  
1602      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
1603          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1604          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1605  </pre></div>
1606  </div>
1607  <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>
1608  </section>
1609  <section id="requests-responses">
1610  <span id="example-request"></span><h2>Requests &amp; Responses<a class="headerlink" href="#requests-responses" title="Permalink to this heading">#</a></h2>
1611  <p>The <em>Request</em> example explores sending requests and receiving responses.</p>
1612  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
1613  <span class="c1"># This RNS example demonstrates how to perform requests  #</span>
1614  <span class="c1"># and receive responses over a link.                     #</span>
1615  <span class="c1">##########################################################</span>
1616  
1617  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
1618  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
1619  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
1620  <span class="kn">import</span><span class="w"> </span><span class="nn">random</span>
1621  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
1622  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
1623  
1624  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
1625  <span class="c1"># destinations we create. Since this echo example</span>
1626  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
1627  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
1628  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
1629  
1630  <span class="c1">##########################################################</span>
1631  <span class="c1">#### Server Part #########################################</span>
1632  <span class="c1">##########################################################</span>
1633  
1634  <span class="c1"># A reference to the latest client link that connected</span>
1635  <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
1636  
1637  <span class="k">def</span><span class="w"> </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>
1638      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Generating response to request &quot;</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">&quot; on link &quot;</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>
1639      <span class="n">texts</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;They looked up&quot;</span><span class="p">,</span> <span class="s2">&quot;On each full moon&quot;</span><span class="p">,</span> <span class="s2">&quot;Becky was upset&quot;</span><span class="p">,</span> <span class="s2">&quot;I’ll stay away from it&quot;</span><span class="p">,</span> <span class="s2">&quot;The pet shop stocks everything&quot;</span><span class="p">]</span>
1640      <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>
1641  
1642  <span class="c1"># This initialisation is executed when the users chooses</span>
1643  <span class="c1"># to run as a server</span>
1644  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
1645      <span class="c1"># We must first initialise Reticulum</span>
1646      <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>
1647      
1648      <span class="c1"># Randomly create a new identity for our link example</span>
1649      <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>
1650  
1651      <span class="c1"># We create a destination that clients can connect to. We</span>
1652      <span class="c1"># want clients to create links to this destination, so we</span>
1653      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
1654      <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>
1655          <span class="n">server_identity</span><span class="p">,</span>
1656          <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>
1657          <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>
1658          <span class="n">APP_NAME</span><span class="p">,</span>
1659          <span class="s2">&quot;requestexample&quot;</span>
1660      <span class="p">)</span>
1661  
1662      <span class="c1"># We configure a function that will get called every time</span>
1663      <span class="c1"># a new client creates a link to this destination.</span>
1664      <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>
1665  
1666      <span class="c1"># We register a request handler for handling incoming</span>
1667      <span class="c1"># requests over any established links.</span>
1668      <span class="n">server_destination</span><span class="o">.</span><span class="n">register_request_handler</span><span class="p">(</span>
1669          <span class="s2">&quot;/random/text&quot;</span><span class="p">,</span>
1670          <span class="n">response_generator</span> <span class="o">=</span> <span class="n">random_text_generator</span><span class="p">,</span>
1671          <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>
1672      <span class="p">)</span>
1673  
1674      <span class="c1"># Everything&#39;s ready!</span>
1675      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
1676      <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
1677  
1678  <span class="k">def</span><span class="w"> </span><span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
1679      <span class="c1"># Let the user know that everything is ready</span>
1680      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
1681          <span class="s2">&quot;Request example &quot;</span><span class="o">+</span>
1682          <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>
1683          <span class="s2">&quot; running, waiting for a connection.&quot;</span>
1684      <span class="p">)</span>
1685  
1686      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
1687  
1688      <span class="c1"># We enter a loop that runs until the users exits.</span>
1689      <span class="c1"># If the user hits enter, we will announce our server</span>
1690      <span class="c1"># destination on the network, which will let clients</span>
1691      <span class="c1"># know how to create messages directed towards it.</span>
1692      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
1693          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1694          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
1695          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
1696  
1697  <span class="c1"># When a client establishes a link to our server</span>
1698  <span class="c1"># destination, this function will be called with</span>
1699  <span class="c1"># a reference to the link.</span>
1700  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1701      <span class="k">global</span> <span class="n">latest_client_link</span>
1702  
1703      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
1704      <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>
1705      <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
1706  
1707  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1708      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
1709  
1710  
1711  <span class="c1">##########################################################</span>
1712  <span class="c1">#### Client Part #########################################</span>
1713  <span class="c1">##########################################################</span>
1714  
1715  <span class="c1"># A reference to the server link</span>
1716  <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
1717  
1718  <span class="c1"># This initialisation is executed when the users chooses</span>
1719  <span class="c1"># to run as a client</span>
1720  <span class="k">def</span><span class="w"> </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>
1721      <span class="c1"># We need a binary representation of the destination</span>
1722      <span class="c1"># hash that was entered on the command line</span>
1723      <span class="k">try</span><span class="p">:</span>
1724          <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>
1725          <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>
1726              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
1727                  <span class="s2">&quot;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).&quot;</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>
1728              <span class="p">)</span>
1729              
1730          <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>
1731      <span class="k">except</span><span class="p">:</span>
1732          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
1733          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1734  
1735      <span class="c1"># We must first initialise Reticulum</span>
1736      <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>
1737  
1738      <span class="c1"># Check if we know a path to the destination</span>
1739      <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>
1740          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
1741          <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>
1742          <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>
1743              <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>
1744  
1745      <span class="c1"># Recall the server identity</span>
1746      <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>
1747  
1748      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
1749      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
1750  
1751      <span class="c1"># When the server identity is known, we set</span>
1752      <span class="c1"># up a destination</span>
1753      <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>
1754          <span class="n">server_identity</span><span class="p">,</span>
1755          <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>
1756          <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>
1757          <span class="n">APP_NAME</span><span class="p">,</span>
1758          <span class="s2">&quot;requestexample&quot;</span>
1759      <span class="p">)</span>
1760  
1761      <span class="c1"># And create a link</span>
1762      <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>
1763  
1764      <span class="c1"># We&#39;ll set up functions to inform the</span>
1765      <span class="c1"># user when the link is established or closed</span>
1766      <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>
1767      <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>
1768  
1769      <span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
1770      <span class="c1"># for the user to interact with the example</span>
1771      <span class="n">client_loop</span><span class="p">()</span>
1772  
1773  <span class="k">def</span><span class="w"> </span><span class="nf">client_loop</span><span class="p">():</span>
1774      <span class="k">global</span> <span class="n">server_link</span>
1775  
1776      <span class="c1"># Wait for the link to become active</span>
1777      <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
1778          <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>
1779  
1780      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
1781      <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
1782          <span class="k">try</span><span class="p">:</span>
1783              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
1784              <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
1785  
1786              <span class="c1"># Check if we should quit the example</span>
1787              <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
1788                  <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1789                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1790  
1791              <span class="k">else</span><span class="p">:</span>
1792                  <span class="n">server_link</span><span class="o">.</span><span class="n">request</span><span class="p">(</span>
1793                      <span class="s2">&quot;/random/text&quot;</span><span class="p">,</span>
1794                      <span class="n">data</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1795                      <span class="n">response_callback</span> <span class="o">=</span> <span class="n">got_response</span><span class="p">,</span>
1796                      <span class="n">failed_callback</span> <span class="o">=</span> <span class="n">request_failed</span>
1797                  <span class="p">)</span>
1798  
1799  
1800          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1801              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while sending request over the link: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
1802              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
1803              <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
1804  
1805  <span class="k">def</span><span class="w"> </span><span class="nf">got_response</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span>
1806      <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>
1807      <span class="n">response</span> <span class="o">=</span> <span class="n">request_receipt</span><span class="o">.</span><span class="n">response</span>
1808  
1809      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Got response for request &quot;</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">&quot;: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
1810  
1811  <span class="k">def</span><span class="w"> </span><span class="nf">request_received</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span>
1812      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The request &quot;</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">&quot; was received by the remote peer.&quot;</span><span class="p">)</span>
1813  
1814  <span class="k">def</span><span class="w"> </span><span class="nf">request_failed</span><span class="p">(</span><span class="n">request_receipt</span><span class="p">):</span>
1815      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The request &quot;</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">&quot; failed.&quot;</span><span class="p">)</span>
1816  
1817  
1818  <span class="c1"># This function is called when a link</span>
1819  <span class="c1"># has been established with the server</span>
1820  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1821      <span class="c1"># We store a reference to the link</span>
1822      <span class="c1"># instance for later use</span>
1823      <span class="k">global</span> <span class="n">server_link</span>
1824      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
1825  
1826      <span class="c1"># Inform the user that the server is</span>
1827      <span class="c1"># connected</span>
1828      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server, hit enter to perform a request, or type in </span><span class="se">\&quot;</span><span class="s2">quit</span><span class="se">\&quot;</span><span class="s2"> to quit&quot;</span><span class="p">)</span>
1829  
1830  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
1831  <span class="c1"># user, and exit the program</span>
1832  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
1833      <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>
1834          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
1835      <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>
1836          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
1837      <span class="k">else</span><span class="p">:</span>
1838          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
1839      
1840      <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>
1841      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1842  
1843  
1844  <span class="c1">##########################################################</span>
1845  <span class="c1">#### Program Startup #####################################</span>
1846  <span class="c1">##########################################################</span>
1847  
1848  <span class="c1"># This part of the program runs at startup,</span>
1849  <span class="c1"># and parses input of from the user, and then</span>
1850  <span class="c1"># starts up the desired program mode.</span>
1851  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
1852      <span class="k">try</span><span class="p">:</span>
1853          <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">&quot;Simple request/response example&quot;</span><span class="p">)</span>
1854  
1855          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1856              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
1857              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
1858              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
1859              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming requests from clients&quot;</span>
1860          <span class="p">)</span>
1861  
1862          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1863              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
1864              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
1865              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1866              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
1867              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1868          <span class="p">)</span>
1869  
1870          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
1871              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
1872              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
1873              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
1874              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
1875              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
1876          <span class="p">)</span>
1877  
1878          <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>
1879  
1880          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
1881              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
1882          <span class="k">else</span><span class="p">:</span>
1883              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
1884  
1885          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
1886              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
1887          <span class="k">else</span><span class="p">:</span>
1888              <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>
1889                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1890                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
1891                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1892              <span class="k">else</span><span class="p">:</span>
1893                  <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>
1894  
1895      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
1896          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
1897          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
1898  </pre></div>
1899  </div>
1900  <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>
1901  </section>
1902  <section id="channel">
1903  <span id="example-channel"></span><h2>Channel<a class="headerlink" href="#channel" title="Permalink to this heading">#</a></h2>
1904  <p>The <em>Channel</em> example explores using a <code class="docutils literal notranslate"><span class="pre">Channel</span></code> to send structured
1905  data between peers of a <code class="docutils literal notranslate"><span class="pre">Link</span></code>.</p>
1906  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
1907  <span class="c1"># This RNS example demonstrates how to set up a link to  #</span>
1908  <span class="c1"># a destination, and pass structured messages over it    #</span>
1909  <span class="c1"># using a channel.                                       #</span>
1910  <span class="c1">##########################################################</span>
1911  
1912  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
1913  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
1914  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
1915  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
1916  <span class="kn">from</span><span class="w"> </span><span class="nn">datetime</span><span class="w"> </span><span class="kn">import</span> <span class="n">datetime</span>
1917  
1918  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
1919  <span class="kn">from</span><span class="w"> </span><span class="nn">RNS.vendor</span><span class="w"> </span><span class="kn">import</span> <span class="n">umsgpack</span>
1920  
1921  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
1922  <span class="c1"># destinations we create. Since this echo example</span>
1923  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
1924  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
1925  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
1926  
1927  <span class="c1">##########################################################</span>
1928  <span class="c1">#### Shared Objects ######################################</span>
1929  <span class="c1">##########################################################</span>
1930  
1931  <span class="c1"># Channel data must be structured in a subclass of</span>
1932  <span class="c1"># MessageBase. This ensures that the channel will be able</span>
1933  <span class="c1"># to serialize and deserialize the object and multiplex it</span>
1934  <span class="c1"># with other objects. Both ends of a link will need the</span>
1935  <span class="c1"># same object definitions to be able to communicate over</span>
1936  <span class="c1"># a channel.</span>
1937  <span class="c1">#</span>
1938  <span class="c1"># Note: The objects we wish to use over the channel must</span>
1939  <span class="c1"># be registered with the channel, and each link has a</span>
1940  <span class="c1"># different channel instance. See the client_connected</span>
1941  <span class="c1"># and link_established functions in this example to see</span>
1942  <span class="c1"># how message types are registered.</span>
1943  
1944  <span class="c1"># Let&#39;s make a simple message class called StringMessage</span>
1945  <span class="c1"># that will convey a string with a timestamp.</span>
1946  
1947  <span class="k">class</span><span class="w"> </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>
1948      <span class="c1"># The MSGTYPE class variable needs to be assigned a</span>
1949      <span class="c1"># 2 byte integer value. This identifier allows the</span>
1950      <span class="c1"># channel to look up your message&#39;s constructor when a</span>
1951      <span class="c1"># message arrives over the channel.</span>
1952      <span class="c1">#</span>
1953      <span class="c1"># MSGTYPE must be unique across all message types we</span>
1954      <span class="c1"># register with the channel. MSGTYPEs &gt;= 0xf000 are</span>
1955      <span class="c1"># reserved for the system.</span>
1956      <span class="n">MSGTYPE</span> <span class="o">=</span> <span class="mh">0x0101</span>
1957  
1958      <span class="c1"># The constructor of our object must be callable with</span>
1959      <span class="c1"># no arguments. We can have parameters, but they must</span>
1960      <span class="c1"># have a default assignment.</span>
1961      <span class="c1">#</span>
1962      <span class="c1"># This is needed so the channel can create an empty</span>
1963      <span class="c1"># version of our message into which the incoming</span>
1964      <span class="c1"># message can be unpacked.</span>
1965      <span class="k">def</span><span class="w"> </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>
1966          <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">data</span>
1967          <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>
1968  
1969      <span class="c1"># Finally, our message needs to implement functions</span>
1970      <span class="c1"># the channel can call to pack and unpack our message</span>
1971      <span class="c1"># to/from the raw packet payload. We&#39;ll use the</span>
1972      <span class="c1"># umsgpack package bundled with RNS. We could also use</span>
1973      <span class="c1"># the struct package bundled with Python if we wanted</span>
1974      <span class="c1"># more control over the structure of the packed bytes.</span>
1975      <span class="c1">#</span>
1976      <span class="c1"># Also note that packed message objects must fit</span>
1977      <span class="c1"># entirely in one packet. The number of bytes</span>
1978      <span class="c1"># available for message payloads can be queried from</span>
1979      <span class="c1"># the channel using the Channel.MDU property. The</span>
1980      <span class="c1"># channel MDU is slightly less than the link MDU due</span>
1981      <span class="c1"># to encoding the message header.</span>
1982  
1983      <span class="c1"># The pack function encodes the message contents into</span>
1984      <span class="c1"># a byte stream.</span>
1985      <span class="k">def</span><span class="w"> </span><span class="nf">pack</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bytes</span><span class="p">:</span>
1986          <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>
1987  
1988      <span class="c1"># And the unpack function decodes a byte stream into</span>
1989      <span class="c1"># the message contents.</span>
1990      <span class="k">def</span><span class="w"> </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>
1991          <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>
1992  
1993  
1994  <span class="c1">##########################################################</span>
1995  <span class="c1">#### Server Part #########################################</span>
1996  <span class="c1">##########################################################</span>
1997  
1998  <span class="c1"># A reference to the latest client link that connected</span>
1999  <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
2000  
2001  <span class="c1"># This initialisation is executed when the users chooses</span>
2002  <span class="c1"># to run as a server</span>
2003  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
2004      <span class="c1"># We must first initialise Reticulum</span>
2005      <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>
2006      
2007      <span class="c1"># Randomly create a new identity for our link example</span>
2008      <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>
2009  
2010      <span class="c1"># We create a destination that clients can connect to. We</span>
2011      <span class="c1"># want clients to create links to this destination, so we</span>
2012      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
2013      <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>
2014          <span class="n">server_identity</span><span class="p">,</span>
2015          <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>
2016          <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>
2017          <span class="n">APP_NAME</span><span class="p">,</span>
2018          <span class="s2">&quot;channelexample&quot;</span>
2019      <span class="p">)</span>
2020  
2021      <span class="c1"># We configure a function that will get called every time</span>
2022      <span class="c1"># a new client creates a link to this destination.</span>
2023      <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>
2024  
2025      <span class="c1"># Everything&#39;s ready!</span>
2026      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
2027      <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
2028  
2029  <span class="k">def</span><span class="w"> </span><span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
2030      <span class="c1"># Let the user know that everything is ready</span>
2031      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
2032          <span class="s2">&quot;Channel example &quot;</span><span class="o">+</span>
2033          <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>
2034          <span class="s2">&quot; running, waiting for a connection.&quot;</span>
2035      <span class="p">)</span>
2036  
2037      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
2038  
2039      <span class="c1"># We enter a loop that runs until the users exits.</span>
2040      <span class="c1"># If the user hits enter, we will announce our server</span>
2041      <span class="c1"># destination on the network, which will let clients</span>
2042      <span class="c1"># know how to create messages directed towards it.</span>
2043      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
2044          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2045          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
2046          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
2047  
2048  <span class="c1"># When a client establishes a link to our server</span>
2049  <span class="c1"># destination, this function will be called with</span>
2050  <span class="c1"># a reference to the link.</span>
2051  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2052      <span class="k">global</span> <span class="n">latest_client_link</span>
2053      <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
2054  
2055      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
2056      <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>
2057  
2058      <span class="c1"># Register message types and add callback to channel</span>
2059      <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>
2060      <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>
2061      <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>
2062  
2063  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2064      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
2065  
2066  <span class="k">def</span><span class="w"> </span><span class="nf">server_message_received</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
2067  <span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
2068  <span class="sd">    A message handler</span>
2069  <span class="sd">    @param message: An instance of a subclass of MessageBase</span>
2070  <span class="sd">    @return: True if message was handled</span>
2071  <span class="sd">    &quot;&quot;&quot;</span>
2072      <span class="k">global</span> <span class="n">latest_client_link</span>
2073      <span class="c1"># When a message is received over any active link,</span>
2074      <span class="c1"># the replies will all be directed to the last client</span>
2075      <span class="c1"># that connected.</span>
2076  
2077      <span class="c1"># In a message handler, any deserializable message</span>
2078      <span class="c1"># that arrives over the link&#39;s channel will be passed</span>
2079      <span class="c1"># to all message handlers, unless a preceding handler indicates it</span>
2080      <span class="c1"># has handled the message.</span>
2081      <span class="c1">#</span>
2082      <span class="c1">#</span>
2083      <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>
2084          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</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">&quot; (message created at &quot;</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">&quot;)&quot;</span><span class="p">)</span>
2085  
2086          <span class="n">reply_message</span> <span class="o">=</span> <span class="n">StringMessage</span><span class="p">(</span><span class="s2">&quot;I received </span><span class="se">\&quot;</span><span class="s2">&quot;</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">&quot;</span><span class="se">\&quot;</span><span class="s2"> over the link&quot;</span><span class="p">)</span>
2087          <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>
2088  
2089          <span class="c1"># Incoming messages are sent to each message</span>
2090          <span class="c1"># handler added to the channel, in the order they</span>
2091          <span class="c1"># were added.</span>
2092          <span class="c1"># If any message handler returns True, the message</span>
2093          <span class="c1"># is considered handled and any subsequent</span>
2094          <span class="c1"># handlers are skipped.</span>
2095          <span class="k">return</span> <span class="kc">True</span>
2096  
2097  
2098  <span class="c1">##########################################################</span>
2099  <span class="c1">#### Client Part #########################################</span>
2100  <span class="c1">##########################################################</span>
2101  
2102  <span class="c1"># A reference to the server link</span>
2103  <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
2104  
2105  <span class="c1"># This initialisation is executed when the users chooses</span>
2106  <span class="c1"># to run as a client</span>
2107  <span class="k">def</span><span class="w"> </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>
2108      <span class="c1"># We need a binary representation of the destination</span>
2109      <span class="c1"># hash that was entered on the command line</span>
2110      <span class="k">try</span><span class="p">:</span>
2111          <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>
2112          <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>
2113              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
2114                  <span class="s2">&quot;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).&quot;</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>
2115              <span class="p">)</span>
2116              
2117          <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>
2118      <span class="k">except</span><span class="p">:</span>
2119          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
2120          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2121  
2122      <span class="c1"># We must first initialise Reticulum</span>
2123      <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>
2124  
2125      <span class="c1"># Check if we know a path to the destination</span>
2126      <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>
2127          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
2128          <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>
2129          <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>
2130              <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>
2131  
2132      <span class="c1"># Recall the server identity</span>
2133      <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>
2134  
2135      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
2136      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
2137  
2138      <span class="c1"># When the server identity is known, we set</span>
2139      <span class="c1"># up a destination</span>
2140      <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>
2141          <span class="n">server_identity</span><span class="p">,</span>
2142          <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>
2143          <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>
2144          <span class="n">APP_NAME</span><span class="p">,</span>
2145          <span class="s2">&quot;channelexample&quot;</span>
2146      <span class="p">)</span>
2147  
2148      <span class="c1"># And create a link</span>
2149      <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>
2150  
2151      <span class="c1"># We&#39;ll also set up functions to inform the</span>
2152      <span class="c1"># user when the link is established or closed</span>
2153      <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>
2154      <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>
2155  
2156      <span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
2157      <span class="c1"># for the user to interact with the example</span>
2158      <span class="n">client_loop</span><span class="p">()</span>
2159  
2160  <span class="k">def</span><span class="w"> </span><span class="nf">client_loop</span><span class="p">():</span>
2161      <span class="k">global</span> <span class="n">server_link</span>
2162  
2163      <span class="c1"># Wait for the link to become active</span>
2164      <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
2165          <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>
2166  
2167      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
2168      <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
2169          <span class="k">try</span><span class="p">:</span>
2170              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
2171              <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2172  
2173              <span class="c1"># Check if we should quit the example</span>
2174              <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
2175                  <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
2176                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2177  
2178              <span class="c1"># If not, send the entered text over the link</span>
2179              <span class="k">if</span> <span class="n">text</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
2180                  <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>
2181                  <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>
2182                  <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>
2183                  <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>
2184                      <span class="k">if</span> <span class="n">packed_size</span> <span class="o">&lt;=</span> <span class="n">channel</span><span class="o">.</span><span class="n">mdu</span><span class="p">:</span>
2185                          <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>
2186                      <span class="k">else</span><span class="p">:</span>
2187                          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
2188                              <span class="s2">&quot;Cannot send this packet, the data size of &quot;</span><span class="o">+</span>
2189                              <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">&quot; bytes exceeds the link packet MDU of &quot;</span><span class="o">+</span>
2190                              <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">&quot; bytes&quot;</span><span class="p">,</span>
2191                              <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span>
2192                          <span class="p">)</span>
2193                  <span class="k">else</span><span class="p">:</span>
2194                      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Channel is not ready to send, please wait for &quot;</span> <span class="o">+</span>
2195                              <span class="s2">&quot;pending messages to complete.&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2196  
2197          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
2198              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while sending data over the link: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
2199              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
2200              <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2201  
2202  <span class="c1"># This function is called when a link</span>
2203  <span class="c1"># has been established with the server</span>
2204  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2205      <span class="c1"># We store a reference to the link</span>
2206      <span class="c1"># instance for later use</span>
2207      <span class="k">global</span> <span class="n">server_link</span>
2208      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
2209  
2210      <span class="c1"># Register messages and add handler to channel</span>
2211      <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>
2212      <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>
2213      <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>
2214  
2215      <span class="c1"># Inform the user that the server is</span>
2216      <span class="c1"># connected</span>
2217      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server, enter some text to send, or </span><span class="se">\&quot;</span><span class="s2">quit</span><span class="se">\&quot;</span><span class="s2"> to quit&quot;</span><span class="p">)</span>
2218  
2219  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
2220  <span class="c1"># user, and exit the program</span>
2221  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2222      <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>
2223          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
2224      <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>
2225          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
2226      <span class="k">else</span><span class="p">:</span>
2227          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
2228      
2229      <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>
2230      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2231  
2232  <span class="c1"># When a packet is received over the channel, we</span>
2233  <span class="c1"># simply print out the data.</span>
2234  <span class="k">def</span><span class="w"> </span><span class="nf">client_message_received</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
2235      <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>
2236          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</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">&quot; (message created at &quot;</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">&quot;)&quot;</span><span class="p">)</span>
2237          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
2238          <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>
2239  
2240  
2241  <span class="c1">##########################################################</span>
2242  <span class="c1">#### Program Startup #####################################</span>
2243  <span class="c1">##########################################################</span>
2244  
2245  <span class="c1"># This part of the program runs at startup,</span>
2246  <span class="c1"># and parses input of from the user, and then</span>
2247  <span class="c1"># starts up the desired program mode.</span>
2248  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
2249      <span class="k">try</span><span class="p">:</span>
2250          <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">&quot;Simple channel example&quot;</span><span class="p">)</span>
2251  
2252          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2253              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
2254              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
2255              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
2256              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming link requests from clients&quot;</span>
2257          <span class="p">)</span>
2258  
2259          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2260              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
2261              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
2262              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
2263              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
2264              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
2265          <span class="p">)</span>
2266  
2267          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2268              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
2269              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
2270              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
2271              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
2272              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
2273          <span class="p">)</span>
2274  
2275          <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>
2276  
2277          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
2278              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
2279          <span class="k">else</span><span class="p">:</span>
2280              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
2281  
2282          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
2283              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
2284          <span class="k">else</span><span class="p">:</span>
2285              <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>
2286                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2287                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
2288                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2289              <span class="k">else</span><span class="p">:</span>
2290                  <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>
2291  
2292      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
2293          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2294          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2295  </pre></div>
2296  </div>
2297  <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>
2298  </section>
2299  <section id="buffer">
2300  <h2>Buffer<a class="headerlink" href="#buffer" title="Permalink to this heading">#</a></h2>
2301  <p>The <em>Buffer</em> example explores using buffered readers and writers to send
2302  binary data between peers of a <code class="docutils literal notranslate"><span class="pre">Link</span></code>.</p>
2303  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
2304  <span class="c1"># This RNS example demonstrates how to set up a link to  #</span>
2305  <span class="c1"># a destination, and pass binary data over it using a    #</span>
2306  <span class="c1"># channel buffer.                                        #</span>
2307  <span class="c1">##########################################################</span>
2308  <span class="kn">from</span><span class="w"> </span><span class="nn">__future__</span><span class="w"> </span><span class="kn">import</span> <span class="n">annotations</span>
2309  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
2310  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
2311  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
2312  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
2313  <span class="kn">from</span><span class="w"> </span><span class="nn">datetime</span><span class="w"> </span><span class="kn">import</span> <span class="n">datetime</span>
2314  
2315  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
2316  <span class="kn">from</span><span class="w"> </span><span class="nn">RNS.vendor</span><span class="w"> </span><span class="kn">import</span> <span class="n">umsgpack</span>
2317  
2318  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
2319  <span class="c1"># destinations we create. Since this echo example</span>
2320  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
2321  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
2322  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
2323  
2324  
2325  <span class="c1">##########################################################</span>
2326  <span class="c1">#### Server Part #########################################</span>
2327  <span class="c1">##########################################################</span>
2328  
2329  <span class="c1"># A reference to the latest client link that connected</span>
2330  <span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
2331  
2332  <span class="c1"># A reference to the latest buffer object</span>
2333  <span class="n">latest_buffer</span> <span class="o">=</span> <span class="kc">None</span>
2334  
2335  <span class="c1"># This initialisation is executed when the users chooses</span>
2336  <span class="c1"># to run as a server</span>
2337  <span class="k">def</span><span class="w"> </span><span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
2338      <span class="c1"># We must first initialise Reticulum</span>
2339      <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>
2340      
2341      <span class="c1"># Randomly create a new identity for our example</span>
2342      <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>
2343  
2344      <span class="c1"># We create a destination that clients can connect to. We</span>
2345      <span class="c1"># want clients to create links to this destination, so we</span>
2346      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
2347      <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>
2348          <span class="n">server_identity</span><span class="p">,</span>
2349          <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>
2350          <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>
2351          <span class="n">APP_NAME</span><span class="p">,</span>
2352          <span class="s2">&quot;bufferexample&quot;</span>
2353      <span class="p">)</span>
2354  
2355      <span class="c1"># We configure a function that will get called every time</span>
2356      <span class="c1"># a new client creates a link to this destination.</span>
2357      <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>
2358  
2359      <span class="c1"># Everything&#39;s ready!</span>
2360      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
2361      <span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
2362  
2363  <span class="k">def</span><span class="w"> </span><span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
2364      <span class="c1"># Let the user know that everything is ready</span>
2365      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
2366          <span class="s2">&quot;Link buffer example &quot;</span><span class="o">+</span>
2367          <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>
2368          <span class="s2">&quot; running, waiting for a connection.&quot;</span>
2369      <span class="p">)</span>
2370  
2371      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
2372  
2373      <span class="c1"># We enter a loop that runs until the users exits.</span>
2374      <span class="c1"># If the user hits enter, we will announce our server</span>
2375      <span class="c1"># destination on the network, which will let clients</span>
2376      <span class="c1"># know how to create messages directed towards it.</span>
2377      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
2378          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2379          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
2380          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
2381  
2382  <span class="c1"># When a client establishes a link to our server</span>
2383  <span class="c1"># destination, this function will be called with</span>
2384  <span class="c1"># a reference to the link.</span>
2385  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2386      <span class="k">global</span> <span class="n">latest_client_link</span><span class="p">,</span> <span class="n">latest_buffer</span>
2387      <span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
2388  
2389      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
2390      <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>
2391  
2392      <span class="c1"># If a new connection is received, the old reader</span>
2393      <span class="c1"># needs to be disconnected.</span>
2394      <span class="k">if</span> <span class="n">latest_buffer</span><span class="p">:</span>
2395          <span class="n">latest_buffer</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
2396  
2397  
2398      <span class="c1"># Create buffer objects.</span>
2399      <span class="c1">#   The stream_id parameter to these functions is</span>
2400      <span class="c1">#   a bit like a file descriptor, except that it</span>
2401      <span class="c1">#   is unique to the *receiver*.</span>
2402      <span class="c1">#</span>
2403      <span class="c1">#   In this example, both the reader and the writer</span>
2404      <span class="c1">#   use stream_id = 0, but there are actually two</span>
2405      <span class="c1">#   separate unidirectional streams flowing in</span>
2406      <span class="c1">#   opposite directions.</span>
2407      <span class="c1">#</span>
2408      <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>
2409      <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>
2410  
2411  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2412      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
2413  
2414  <span class="k">def</span><span class="w"> </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>
2415  <span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
2416  <span class="sd">    Callback from buffer when buffer has data available</span>
2417  
2418  <span class="sd">    :param ready_bytes: The number of bytes ready to read</span>
2419  <span class="sd">    &quot;&quot;&quot;</span>
2420      <span class="k">global</span> <span class="n">latest_buffer</span>
2421  
2422      <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>
2423      <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">&quot;utf-8&quot;</span><span class="p">)</span>
2424  
2425      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data over the buffer: &quot;</span> <span class="o">+</span> <span class="n">data</span><span class="p">)</span>
2426  
2427      <span class="n">reply_message</span> <span class="o">=</span> <span class="s2">&quot;I received </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">data</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> over the buffer&quot;</span>
2428      <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">&quot;utf-8&quot;</span><span class="p">)</span>
2429      <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>
2430      <span class="n">latest_buffer</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
2431  
2432  
2433  
2434  
2435  <span class="c1">##########################################################</span>
2436  <span class="c1">#### Client Part #########################################</span>
2437  <span class="c1">##########################################################</span>
2438  
2439  <span class="c1"># A reference to the server link</span>
2440  <span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
2441  
2442  <span class="c1"># A reference to the buffer object, needed to share the</span>
2443  <span class="c1"># object from the link connected callback to the client</span>
2444  <span class="c1"># loop.</span>
2445  <span class="n">buffer</span> <span class="o">=</span> <span class="kc">None</span>
2446  
2447  <span class="c1"># This initialisation is executed when the users chooses</span>
2448  <span class="c1"># to run as a client</span>
2449  <span class="k">def</span><span class="w"> </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>
2450      <span class="c1"># We need a binary representation of the destination</span>
2451      <span class="c1"># hash that was entered on the command line</span>
2452      <span class="k">try</span><span class="p">:</span>
2453          <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>
2454          <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>
2455              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
2456                  <span class="s2">&quot;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).&quot;</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>
2457              <span class="p">)</span>
2458              
2459          <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>
2460      <span class="k">except</span><span class="p">:</span>
2461          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
2462          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2463  
2464      <span class="c1"># We must first initialise Reticulum</span>
2465      <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>
2466  
2467      <span class="c1"># Check if we know a path to the destination</span>
2468      <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>
2469          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
2470          <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>
2471          <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>
2472              <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>
2473  
2474      <span class="c1"># Recall the server identity</span>
2475      <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>
2476  
2477      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
2478      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
2479  
2480      <span class="c1"># When the server identity is known, we set</span>
2481      <span class="c1"># up a destination</span>
2482      <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>
2483          <span class="n">server_identity</span><span class="p">,</span>
2484          <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>
2485          <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>
2486          <span class="n">APP_NAME</span><span class="p">,</span>
2487          <span class="s2">&quot;bufferexample&quot;</span>
2488      <span class="p">)</span>
2489  
2490      <span class="c1"># And create a link</span>
2491      <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>
2492  
2493      <span class="c1"># We&#39;ll also set up functions to inform the</span>
2494      <span class="c1"># user when the link is established or closed</span>
2495      <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>
2496      <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>
2497  
2498      <span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
2499      <span class="c1"># for the user to interact with the example</span>
2500      <span class="n">client_loop</span><span class="p">()</span>
2501  
2502  <span class="k">def</span><span class="w"> </span><span class="nf">client_loop</span><span class="p">():</span>
2503      <span class="k">global</span> <span class="n">server_link</span>
2504  
2505      <span class="c1"># Wait for the link to become active</span>
2506      <span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
2507          <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>
2508  
2509      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
2510      <span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
2511          <span class="k">try</span><span class="p">:</span>
2512              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
2513              <span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2514  
2515              <span class="c1"># Check if we should quit the example</span>
2516              <span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
2517                  <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
2518                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2519              <span class="k">else</span><span class="p">:</span>
2520                  <span class="c1"># Otherwise, encode the text and write it to the buffer.</span>
2521                  <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">&quot;utf-8&quot;</span><span class="p">)</span>
2522                  <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>
2523                  <span class="c1"># Flush the buffer to force the data to be sent.</span>
2524                  <span class="n">buffer</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
2525  
2526  
2527          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
2528              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while sending data over the link buffer: &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
2529              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
2530              <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2531  
2532  <span class="c1"># This function is called when a link</span>
2533  <span class="c1"># has been established with the server</span>
2534  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2535      <span class="c1"># We store a reference to the link</span>
2536      <span class="c1"># instance for later use</span>
2537      <span class="k">global</span> <span class="n">server_link</span><span class="p">,</span> <span class="n">buffer</span>
2538      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
2539  
2540      <span class="c1"># Create buffer, see server_client_connected() for</span>
2541      <span class="c1"># more detail about setting up the buffer.</span>
2542      <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>
2543      <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>
2544  
2545      <span class="c1"># Inform the user that the server is</span>
2546      <span class="c1"># connected</span>
2547      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server, enter some text to send, or </span><span class="se">\&quot;</span><span class="s2">quit</span><span class="se">\&quot;</span><span class="s2"> to quit&quot;</span><span class="p">)</span>
2548  
2549  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
2550  <span class="c1"># user, and exit the program</span>
2551  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2552      <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>
2553          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
2554      <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>
2555          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
2556      <span class="k">else</span><span class="p">:</span>
2557          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
2558      
2559      <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>
2560      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2561  
2562  <span class="c1"># When the buffer has new data, read it and write it to the terminal.</span>
2563  <span class="k">def</span><span class="w"> </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>
2564      <span class="k">global</span> <span class="n">buffer</span>
2565      <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>
2566      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data over the link buffer: &quot;</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">&quot;utf-8&quot;</span><span class="p">))</span>
2567      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&gt; &quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&quot; &quot;</span><span class="p">)</span>
2568      <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>
2569  
2570  
2571  <span class="c1">##########################################################</span>
2572  <span class="c1">#### Program Startup #####################################</span>
2573  <span class="c1">##########################################################</span>
2574  
2575  <span class="c1"># This part of the program runs at startup,</span>
2576  <span class="c1"># and parses input of from the user, and then</span>
2577  <span class="c1"># starts up the desired program mode.</span>
2578  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
2579      <span class="k">try</span><span class="p">:</span>
2580          <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">&quot;Simple buffer example&quot;</span><span class="p">)</span>
2581  
2582          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2583              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
2584              <span class="s2">&quot;--server&quot;</span><span class="p">,</span>
2585              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
2586              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming link requests from clients&quot;</span>
2587          <span class="p">)</span>
2588  
2589          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2590              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
2591              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
2592              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
2593              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
2594              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
2595          <span class="p">)</span>
2596  
2597          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
2598              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
2599              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
2600              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
2601              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
2602              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
2603          <span class="p">)</span>
2604  
2605          <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>
2606  
2607          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
2608              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
2609          <span class="k">else</span><span class="p">:</span>
2610              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
2611  
2612          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
2613              <span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
2614          <span class="k">else</span><span class="p">:</span>
2615              <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>
2616                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2617                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
2618                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2619              <span class="k">else</span><span class="p">:</span>
2620                  <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>
2621  
2622      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
2623          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2624          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2625  </pre></div>
2626  </div>
2627  <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>
2628  </section>
2629  <section id="filetransfer">
2630  <span id="example-filetransfer"></span><h2>Filetransfer<a class="headerlink" href="#filetransfer" title="Permalink to this heading">#</a></h2>
2631  <p>The <em>Filetransfer</em> example implements a basic file-server program that
2632  allow clients to connect and download files. The program uses the Resource
2633  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>
2634  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
2635  <span class="c1"># This RNS example demonstrates a simple filetransfer    #</span>
2636  <span class="c1"># server and client program. The server will serve a     #</span>
2637  <span class="c1"># directory of files, and the clients can list and       #</span>
2638  <span class="c1"># download files from the server.                        #</span>
2639  <span class="c1">#                                                        #</span>
2640  <span class="c1"># Please note that using RNS Resources for large file    #</span>
2641  <span class="c1"># transfers is not recommended, since compression,       #</span>
2642  <span class="c1"># encryption and hashmap sequencing can take a long time #</span>
2643  <span class="c1"># on systems with slow CPUs, which will probably result  #</span>
2644  <span class="c1"># in the client timing out before the resource sender    #</span>
2645  <span class="c1"># can complete preparing the resource.                   #</span>
2646  <span class="c1">#                                                        #</span>
2647  <span class="c1"># If you need to transfer large files, use the Bundle    #</span>
2648  <span class="c1"># class instead, which will automatically slice the data #</span>
2649  <span class="c1"># into chunks suitable for packing as a Resource.        #</span>
2650  <span class="c1">##########################################################</span>
2651  
2652  <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
2653  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
2654  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
2655  <span class="kn">import</span><span class="w"> </span><span class="nn">threading</span>
2656  <span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span>
2657  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS</span>
2658  <span class="kn">import</span><span class="w"> </span><span class="nn">RNS.vendor.umsgpack</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">umsgpack</span>
2659  
2660  <span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
2661  <span class="c1"># destinations we create. Since this echo example</span>
2662  <span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
2663  <span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
2664  <span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
2665  
2666  <span class="c1"># We&#39;ll also define a default timeout, in seconds</span>
2667  <span class="n">APP_TIMEOUT</span> <span class="o">=</span> <span class="mf">45.0</span>
2668  
2669  <span class="c1">##########################################################</span>
2670  <span class="c1">#### Server Part #########################################</span>
2671  <span class="c1">##########################################################</span>
2672  
2673  <span class="n">serve_path</span> <span class="o">=</span> <span class="kc">None</span>
2674  
2675  <span class="c1"># This initialisation is executed when the users chooses</span>
2676  <span class="c1"># to run as a server</span>
2677  <span class="k">def</span><span class="w"> </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>
2678      <span class="c1"># We must first initialise Reticulum</span>
2679      <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>
2680      
2681      <span class="c1"># Randomly create a new identity for our file server</span>
2682      <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>
2683  
2684      <span class="k">global</span> <span class="n">serve_path</span>
2685      <span class="n">serve_path</span> <span class="o">=</span> <span class="n">path</span>
2686  
2687      <span class="c1"># We create a destination that clients can connect to. We</span>
2688      <span class="c1"># want clients to create links to this destination, so we</span>
2689      <span class="c1"># need to create a &quot;single&quot; destination type.</span>
2690      <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>
2691          <span class="n">server_identity</span><span class="p">,</span>
2692          <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>
2693          <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>
2694          <span class="n">APP_NAME</span><span class="p">,</span>
2695          <span class="s2">&quot;filetransfer&quot;</span><span class="p">,</span>
2696          <span class="s2">&quot;server&quot;</span>
2697      <span class="p">)</span>
2698  
2699      <span class="c1"># We configure a function that will get called every time</span>
2700      <span class="c1"># a new client creates a link to this destination.</span>
2701      <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>
2702  
2703      <span class="c1"># Everything&#39;s ready!</span>
2704      <span class="c1"># Let&#39;s Wait for client requests or user input</span>
2705      <span class="n">announceLoop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
2706  
2707  <span class="k">def</span><span class="w"> </span><span class="nf">announceLoop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
2708      <span class="c1"># Let the user know that everything is ready</span>
2709      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;File server &quot;</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">&quot; running&quot;</span><span class="p">)</span>
2710      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
2711  
2712      <span class="c1"># We enter a loop that runs until the users exits.</span>
2713      <span class="c1"># If the user hits enter, we will announce our server</span>
2714      <span class="c1"># destination on the network, which will let clients</span>
2715      <span class="c1"># know how to create messages directed towards it.</span>
2716      <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
2717          <span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2718          <span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
2719          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sent announce from &quot;</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>
2720  
2721  <span class="c1"># Here&#39;s a convenience function for listing all files</span>
2722  <span class="c1"># in our served directory</span>
2723  <span class="k">def</span><span class="w"> </span><span class="nf">list_files</span><span class="p">():</span>
2724      <span class="c1"># We add all entries from the directory that are</span>
2725      <span class="c1"># actual files, and does not start with &quot;.&quot;</span>
2726      <span class="k">global</span> <span class="n">serve_path</span>
2727      <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">&quot;.&quot;</span><span class="p">]</span>
2728  
2729  <span class="c1"># When a client establishes a link to our server</span>
2730  <span class="c1"># destination, this function will be called with</span>
2731  <span class="c1"># a reference to the link. We then send the client</span>
2732  <span class="c1"># a list of files hosted on the server.</span>
2733  <span class="k">def</span><span class="w"> </span><span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2734      <span class="c1"># Check if the served directory still exists</span>
2735      <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>
2736          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected, sending file list...&quot;</span><span class="p">)</span>
2737  
2738          <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>
2739  
2740          <span class="c1"># We pack a list of files for sending in a packet</span>
2741          <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>
2742  
2743          <span class="c1"># Check the size of the packed data</span>
2744          <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">&lt;=</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>
2745              <span class="c1"># If it fits in one packet, we will just</span>
2746              <span class="c1"># send it as a single packet over the link.</span>
2747              <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>
2748              <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>
2749              <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>
2750              <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>
2751              <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>
2752          <span class="k">else</span><span class="p">:</span>
2753              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Too many files in served directory!&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2754              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;You should implement a function to split the filelist over multiple packets.&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2755              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hint: The client already supports it :)&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2756              
2757          <span class="c1"># After this, we&#39;re just going to keep the link</span>
2758          <span class="c1"># open until the client requests a file. We&#39;ll</span>
2759          <span class="c1"># configure a function that get&#39;s called when</span>
2760          <span class="c1"># the client sends a packet with a file request.</span>
2761          <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>
2762      <span class="k">else</span><span class="p">:</span>
2763          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected, but served path no longer exists!&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2764          <span class="n">link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2765  
2766  <span class="k">def</span><span class="w"> </span><span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
2767      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
2768  
2769  <span class="k">def</span><span class="w"> </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>
2770      <span class="k">global</span> <span class="n">serve_path</span>
2771  
2772      <span class="k">try</span><span class="p">:</span>
2773          <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">&quot;utf-8&quot;</span><span class="p">)</span>
2774      <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
2775          <span class="n">filename</span> <span class="o">=</span> <span class="kc">None</span>
2776  
2777      <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>
2778          <span class="k">try</span><span class="p">:</span>
2779              <span class="c1"># If we have the requested file, we&#39;ll</span>
2780              <span class="c1"># read it and pack it as a resource</span>
2781              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client requested </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">filename</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="p">)</span>
2782              <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">&quot;rb&quot;</span><span class="p">)</span>
2783              
2784              <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>
2785                  <span class="n">file</span><span class="p">,</span>
2786                  <span class="n">packet</span><span class="o">.</span><span class="n">link</span><span class="p">,</span>
2787                  <span class="n">callback</span><span class="o">=</span><span class="n">resource_sending_concluded</span>
2788              <span class="p">)</span>
2789  
2790              <span class="n">file_resource</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">filename</span>
2791          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
2792              <span class="c1"># If somethign went wrong, we close</span>
2793              <span class="c1"># the link</span>
2794              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while reading file </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">filename</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
2795              <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>
2796              <span class="k">raise</span> <span class="n">e</span>
2797      <span class="k">else</span><span class="p">:</span>
2798          <span class="c1"># If we don&#39;t have it, we close the link</span>
2799          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client requested an unknown file&quot;</span><span class="p">)</span>
2800          <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>
2801  
2802  <span class="c1"># This function is called on the server when a</span>
2803  <span class="c1"># resource transfer concludes.</span>
2804  <span class="k">def</span><span class="w"> </span><span class="nf">resource_sending_concluded</span><span class="p">(</span><span class="n">resource</span><span class="p">):</span>
2805      <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">&quot;filename&quot;</span><span class="p">):</span>
2806          <span class="n">name</span> <span class="o">=</span> <span class="n">resource</span><span class="o">.</span><span class="n">filename</span>
2807      <span class="k">else</span><span class="p">:</span>
2808          <span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;resource&quot;</span>
2809  
2810      <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>
2811          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Done sending </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">name</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> to client&quot;</span><span class="p">)</span>
2812      <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>
2813          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sending </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">name</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> to client failed&quot;</span><span class="p">)</span>
2814  
2815  <span class="k">def</span><span class="w"> </span><span class="nf">list_delivered</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
2816      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The file list was received by the client&quot;</span><span class="p">)</span>
2817  
2818  <span class="k">def</span><span class="w"> </span><span class="nf">list_timeout</span><span class="p">(</span><span class="n">receipt</span><span class="p">):</span>
2819      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Sending list to client timed out, closing this link&quot;</span><span class="p">)</span>
2820      <span class="n">link</span> <span class="o">=</span> <span class="n">receipt</span><span class="o">.</span><span class="n">destination</span>
2821      <span class="n">link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2822  
2823  <span class="c1">##########################################################</span>
2824  <span class="c1">#### Client Part #########################################</span>
2825  <span class="c1">##########################################################</span>
2826  
2827  <span class="c1"># We store a global list of files available on the server</span>
2828  <span class="n">server_files</span>      <span class="o">=</span> <span class="p">[]</span>
2829  
2830  <span class="c1"># A reference to the server link</span>
2831  <span class="n">server_link</span>       <span class="o">=</span> <span class="kc">None</span>
2832  
2833  <span class="c1"># And a reference to the current download</span>
2834  <span class="n">current_download</span>  <span class="o">=</span> <span class="kc">None</span>
2835  <span class="n">current_filename</span>  <span class="o">=</span> <span class="kc">None</span>
2836  
2837  <span class="c1"># Variables to store download statistics</span>
2838  <span class="n">download_started</span>  <span class="o">=</span> <span class="mi">0</span>
2839  <span class="n">download_finished</span> <span class="o">=</span> <span class="mi">0</span>
2840  <span class="n">download_time</span>     <span class="o">=</span> <span class="mi">0</span>
2841  <span class="n">transfer_size</span>     <span class="o">=</span> <span class="mi">0</span>
2842  <span class="n">file_size</span>         <span class="o">=</span> <span class="mi">0</span>
2843  
2844  
2845  <span class="c1"># This initialisation is executed when the users chooses</span>
2846  <span class="c1"># to run as a client</span>
2847  <span class="k">def</span><span class="w"> </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>
2848      <span class="c1"># We need a binary representation of the destination</span>
2849      <span class="c1"># hash that was entered on the command line</span>
2850      <span class="k">try</span><span class="p">:</span>
2851          <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>
2852          <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>
2853              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
2854                  <span class="s2">&quot;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).&quot;</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>
2855              <span class="p">)</span>
2856              
2857          <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>
2858      <span class="k">except</span><span class="p">:</span>
2859          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
2860          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
2861  
2862      <span class="c1"># We must first initialise Reticulum</span>
2863      <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>
2864  
2865  
2866      <span class="c1"># Check if we know a path to the destination</span>
2867      <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>
2868          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
2869          <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>
2870          <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>
2871              <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>
2872  
2873      <span class="c1"># Recall the server identity</span>
2874      <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>
2875  
2876      <span class="c1"># Inform the user that we&#39;ll begin connecting</span>
2877      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
2878  
2879      <span class="c1"># When the server identity is known, we set</span>
2880      <span class="c1"># up a destination</span>
2881      <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>
2882          <span class="n">server_identity</span><span class="p">,</span>
2883          <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>
2884          <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>
2885          <span class="n">APP_NAME</span><span class="p">,</span>
2886          <span class="s2">&quot;filetransfer&quot;</span><span class="p">,</span>
2887          <span class="s2">&quot;server&quot;</span>
2888      <span class="p">)</span>
2889  
2890      <span class="c1"># We also want to automatically prove incoming packets</span>
2891      <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>
2892  
2893      <span class="c1"># And create a link</span>
2894      <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>
2895  
2896      <span class="c1"># We expect any normal data packets on the link</span>
2897      <span class="c1"># to contain a list of served files, so we set</span>
2898      <span class="c1"># a callback accordingly</span>
2899      <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>
2900  
2901      <span class="c1"># We&#39;ll also set up functions to inform the</span>
2902      <span class="c1"># user when the link is established or closed</span>
2903      <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>
2904      <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>
2905  
2906      <span class="c1"># And set the link to automatically begin</span>
2907      <span class="c1"># downloading advertised resources</span>
2908      <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>
2909      <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>
2910      <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>
2911  
2912      <span class="n">menu</span><span class="p">()</span>
2913  
2914  <span class="c1"># Requests the specified file from the server</span>
2915  <span class="k">def</span><span class="w"> </span><span class="nf">download</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
2916      <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>
2917      <span class="n">current_filename</span> <span class="o">=</span> <span class="n">filename</span>
2918      <span class="n">download_started</span> <span class="o">=</span> <span class="mi">0</span>
2919      <span class="n">transfer_size</span>    <span class="o">=</span> <span class="mi">0</span>
2920  
2921      <span class="c1"># We just create a packet containing the</span>
2922      <span class="c1"># requested filename, and send it down the</span>
2923      <span class="c1"># link. We also specify we don&#39;t need a</span>
2924      <span class="c1"># packet receipt.</span>
2925      <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">&quot;utf-8&quot;</span><span class="p">),</span> <span class="n">create_receipt</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
2926      <span class="n">request_packet</span><span class="o">.</span><span class="n">send</span><span class="p">()</span>
2927      
2928      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2929      <span class="nb">print</span><span class="p">((</span><span class="s2">&quot;Requested </span><span class="se">\&quot;</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">filename</span><span class="o">+</span><span class="s2">&quot;</span><span class="se">\&quot;</span><span class="s2"> from server, waiting for download to begin...&quot;</span><span class="p">))</span>
2930      <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;download_started&quot;</span>
2931  
2932  <span class="c1"># This function runs a simple menu for the user</span>
2933  <span class="c1"># to select which files to download, or quit</span>
2934  <span class="n">menu_mode</span> <span class="o">=</span> <span class="kc">None</span>
2935  <span class="k">def</span><span class="w"> </span><span class="nf">menu</span><span class="p">():</span>
2936      <span class="k">global</span> <span class="n">server_files</span><span class="p">,</span> <span class="n">server_link</span>
2937      <span class="c1"># Wait until we have a filelist</span>
2938      <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>
2939          <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>
2940      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Ready!&quot;</span><span class="p">)</span>
2941      <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>
2942  
2943      <span class="k">global</span> <span class="n">menu_mode</span>
2944      <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;main&quot;</span>
2945      <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
2946      <span class="k">while</span> <span class="p">(</span><span class="ow">not</span> <span class="n">should_quit</span><span class="p">):</span>
2947          <span class="n">print_menu</span><span class="p">()</span>
2948  
2949          <span class="k">while</span> <span class="ow">not</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;main&quot;</span><span class="p">:</span>
2950              <span class="c1"># Wait</span>
2951              <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>
2952  
2953          <span class="n">user_input</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
2954          <span class="k">if</span> <span class="n">user_input</span> <span class="o">==</span> <span class="s2">&quot;q&quot;</span> <span class="ow">or</span> <span class="n">user_input</span> <span class="o">==</span> <span class="s2">&quot;quit&quot;</span> <span class="ow">or</span> <span class="n">user_input</span> <span class="o">==</span> <span class="s2">&quot;exit&quot;</span><span class="p">:</span>
2955              <span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
2956              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2957          <span class="k">else</span><span class="p">:</span>
2958              <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>
2959                  <span class="n">download</span><span class="p">(</span><span class="n">user_input</span><span class="p">)</span>
2960              <span class="k">else</span><span class="p">:</span>
2961                  <span class="k">try</span><span class="p">:</span>
2962                      <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="nb">int</span><span class="p">(</span><span class="n">user_input</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">server_files</span><span class="p">):</span>
2963                          <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>
2964                  <span class="k">except</span><span class="p">:</span>
2965                      <span class="k">pass</span>
2966  
2967      <span class="k">if</span> <span class="n">should_quit</span><span class="p">:</span>
2968          <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2969  
2970  <span class="c1"># Prints out menus or screens for the</span>
2971  <span class="c1"># various states of the client program.</span>
2972  <span class="c1"># It&#39;s simple and quite uninteresting.</span>
2973  <span class="c1"># I won&#39;t go into detail here. Just</span>
2974  <span class="c1"># strings basically.</span>
2975  <span class="k">def</span><span class="w"> </span><span class="nf">print_menu</span><span class="p">():</span>
2976      <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>
2977  
2978      <span class="k">if</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;main&quot;</span><span class="p">:</span>
2979          <span class="n">clear_screen</span><span class="p">()</span>
2980          <span class="n">print_filelist</span><span class="p">()</span>
2981          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2982          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Select a file to download by entering name or number, or q to quit&quot;</span><span class="p">)</span>
2983          <span class="nb">print</span><span class="p">((</span><span class="s2">&quot;&gt; &quot;</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
2984      <span class="k">elif</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;download_started&quot;</span><span class="p">:</span>
2985          <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>
2986          <span class="k">while</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;download_started&quot;</span><span class="p">:</span>
2987              <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>
2988              <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">&gt;</span> <span class="n">download_began</span><span class="o">+</span><span class="n">APP_TIMEOUT</span><span class="p">:</span>
2989                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;The download timed out&quot;</span><span class="p">)</span>
2990                  <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>
2991                  <span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
2992  
2993      <span class="k">if</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;downloading&quot;</span><span class="p">:</span>
2994          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Download started&quot;</span><span class="p">)</span>
2995          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
2996          <span class="k">while</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;downloading&quot;</span><span class="p">:</span>
2997              <span class="k">global</span> <span class="n">current_download</span>
2998              <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>
2999              <span class="nb">print</span><span class="p">((</span><span class="s2">&quot;</span><span class="se">\r</span><span class="s2">Progress: &quot;</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">&quot; %   &quot;</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
3000              <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>
3001              <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>
3002  
3003      <span class="k">if</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;save_error&quot;</span><span class="p">:</span>
3004          <span class="nb">print</span><span class="p">((</span><span class="s2">&quot;</span><span class="se">\r</span><span class="s2">Progress: 100.0 %&quot;</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
3005          <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>
3006          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3007          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Could not write downloaded file to disk&quot;</span><span class="p">)</span>
3008          <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>
3009          <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;download_concluded&quot;</span>
3010  
3011      <span class="k">if</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;download_concluded&quot;</span><span class="p">:</span>
3012          <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>
3013              <span class="nb">print</span><span class="p">((</span><span class="s2">&quot;</span><span class="se">\r</span><span class="s2">Progress: 100.0 %&quot;</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
3014              <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>
3015  
3016              <span class="c1"># Print statistics</span>
3017              <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>
3018              <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>
3019              <span class="n">timestring</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{:0&gt;2}</span><span class="s2">:</span><span class="si">{:0&gt;2}</span><span class="s2">:</span><span class="si">{:05.2f}</span><span class="s2">&quot;</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>
3020              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3021              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3022              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;--- Statistics -----&quot;</span><span class="p">)</span>
3023              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">Time taken       : &quot;</span><span class="o">+</span><span class="n">timestring</span><span class="p">)</span>
3024              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">File size        : &quot;</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>
3025              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">Data transferred : &quot;</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>
3026              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">Effective rate   : &quot;</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">&#39;b&#39;</span><span class="p">)</span><span class="o">+</span><span class="s2">&quot;/s&quot;</span><span class="p">)</span>
3027              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">Transfer rate    : &quot;</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">&#39;b&#39;</span><span class="p">)</span><span class="o">+</span><span class="s2">&quot;/s&quot;</span><span class="p">)</span>
3028              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3029              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;The download completed! Press enter to return to the menu.&quot;</span><span class="p">)</span>
3030              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3031              <span class="nb">input</span><span class="p">()</span>
3032  
3033          <span class="k">else</span><span class="p">:</span>
3034              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3035              <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;The download failed! Press enter to return to the menu.&quot;</span><span class="p">)</span>
3036              <span class="nb">input</span><span class="p">()</span>
3037  
3038          <span class="n">current_download</span> <span class="o">=</span> <span class="kc">None</span>
3039          <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;main&quot;</span>
3040          <span class="n">print_menu</span><span class="p">()</span>
3041  
3042  <span class="c1"># This function prints out a list of files</span>
3043  <span class="c1"># on the connected server.</span>
3044  <span class="k">def</span><span class="w"> </span><span class="nf">print_filelist</span><span class="p">():</span>
3045      <span class="k">global</span> <span class="n">server_files</span>
3046      <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Files on server:&quot;</span><span class="p">)</span>
3047      <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>
3048          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\t</span><span class="s2">(&quot;</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">&quot;)</span><span class="se">\t</span><span class="s2">&quot;</span><span class="o">+</span><span class="n">file</span><span class="p">)</span>
3049  
3050  <span class="k">def</span><span class="w"> </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>
3051      <span class="k">global</span> <span class="n">server_files</span><span class="p">,</span> <span class="n">menu_mode</span>
3052      <span class="k">try</span><span class="p">:</span>
3053          <span class="c1"># Unpack the list and extend our</span>
3054          <span class="c1"># local list of available files</span>
3055          <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>
3056          <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">filelist</span><span class="p">:</span>
3057              <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>
3058                  <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>
3059  
3060          <span class="c1"># If the menu is already visible,</span>
3061          <span class="c1"># we&#39;ll update it with what was</span>
3062          <span class="c1"># just received</span>
3063          <span class="k">if</span> <span class="n">menu_mode</span> <span class="o">==</span> <span class="s2">&quot;main&quot;</span><span class="p">:</span>
3064              <span class="n">print_menu</span><span class="p">()</span>
3065      <span class="k">except</span><span class="p">:</span>
3066          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid file list data received, closing link&quot;</span><span class="p">)</span>
3067          <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>
3068  
3069  <span class="c1"># This function is called when a link</span>
3070  <span class="c1"># has been established with the server</span>
3071  <span class="k">def</span><span class="w"> </span><span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
3072      <span class="c1"># We store a reference to the link</span>
3073      <span class="c1"># instance for later use</span>
3074      <span class="k">global</span> <span class="n">server_link</span>
3075      <span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
3076  
3077      <span class="c1"># Inform the user that the server is</span>
3078      <span class="c1"># connected</span>
3079      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link established with server&quot;</span><span class="p">)</span>
3080      <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Waiting for filelist...&quot;</span><span class="p">)</span>
3081  
3082      <span class="c1"># And set up a small job to check for</span>
3083      <span class="c1"># a potential timeout in receiving the</span>
3084      <span class="c1"># file list</span>
3085      <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>
3086      <span class="n">thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
3087  
3088  <span class="c1"># This job just sleeps for the specified</span>
3089  <span class="c1"># time, and then checks if the file list</span>
3090  <span class="c1"># was received. If not, the program will</span>
3091  <span class="c1"># exit.</span>
3092  <span class="k">def</span><span class="w"> </span><span class="nf">filelist_timeout_job</span><span class="p">():</span>
3093      <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>
3094  
3095      <span class="k">global</span> <span class="n">server_files</span>
3096      <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>
3097          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Timed out waiting for filelist, exiting&quot;</span><span class="p">)</span>
3098          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
3099  
3100  
3101  <span class="c1"># When a link is closed, we&#39;ll inform the</span>
3102  <span class="c1"># user, and exit the program</span>
3103  <span class="k">def</span><span class="w"> </span><span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
3104      <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>
3105          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
3106      <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>
3107          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
3108      <span class="k">else</span><span class="p">:</span>
3109          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
3110      
3111      <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>
3112      <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
3113  
3114  <span class="c1"># When RNS detects that the download has</span>
3115  <span class="c1"># started, we&#39;ll update our menu state</span>
3116  <span class="c1"># so the user can be shown a progress of</span>
3117  <span class="c1"># the download.</span>
3118  <span class="k">def</span><span class="w"> </span><span class="nf">download_began</span><span class="p">(</span><span class="n">resource</span><span class="p">):</span>
3119      <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>
3120      <span class="n">current_download</span> <span class="o">=</span> <span class="n">resource</span>
3121      
3122      <span class="k">if</span> <span class="n">download_started</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
3123          <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>
3124      
3125      <span class="n">transfer_size</span> <span class="o">+=</span> <span class="n">resource</span><span class="o">.</span><span class="n">size</span>
3126      <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>
3127      
3128      <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;downloading&quot;</span>
3129  
3130  <span class="c1"># When the download concludes, successfully</span>
3131  <span class="c1"># or not, we&#39;ll update our menu state and </span>
3132  <span class="c1"># inform the user about how it all went.</span>
3133  <span class="k">def</span><span class="w"> </span><span class="nf">download_concluded</span><span class="p">(</span><span class="n">resource</span><span class="p">):</span>
3134      <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>
3135      <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>
3136      <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>
3137  
3138      <span class="n">saved_filename</span> <span class="o">=</span> <span class="n">current_filename</span>
3139  
3140      <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>
3141          <span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
3142          <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>
3143              <span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span>
3144              <span class="n">saved_filename</span> <span class="o">=</span> <span class="n">current_filename</span><span class="o">+</span><span class="s2">&quot;.&quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span>
3145  
3146          <span class="k">try</span><span class="p">:</span>
3147              <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">&quot;wb&quot;</span><span class="p">)</span>
3148              <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>
3149              <span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
3150              <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;download_concluded&quot;</span>
3151          <span class="k">except</span><span class="p">:</span>
3152              <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;save_error&quot;</span>
3153      <span class="k">else</span><span class="p">:</span>
3154          <span class="n">menu_mode</span> <span class="o">=</span> <span class="s2">&quot;download_concluded&quot;</span>
3155  
3156  <span class="c1"># A convenience function for printing a human-</span>
3157  <span class="c1"># readable file size</span>
3158  <span class="k">def</span><span class="w"> </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">&#39;B&#39;</span><span class="p">):</span>
3159      <span class="n">units</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;&#39;</span><span class="p">,</span><span class="s1">&#39;Ki&#39;</span><span class="p">,</span><span class="s1">&#39;Mi&#39;</span><span class="p">,</span><span class="s1">&#39;Gi&#39;</span><span class="p">,</span><span class="s1">&#39;Ti&#39;</span><span class="p">,</span><span class="s1">&#39;Pi&#39;</span><span class="p">,</span><span class="s1">&#39;Ei&#39;</span><span class="p">,</span><span class="s1">&#39;Zi&#39;</span><span class="p">]</span>
3160      <span class="n">last_unit</span> <span class="o">=</span> <span class="s1">&#39;Yi&#39;</span>
3161  
3162      <span class="k">if</span> <span class="n">suffix</span> <span class="o">==</span> <span class="s1">&#39;b&#39;</span><span class="p">:</span>
3163          <span class="n">num</span> <span class="o">*=</span> <span class="mi">8</span>
3164          <span class="n">units</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;&#39;</span><span class="p">,</span><span class="s1">&#39;K&#39;</span><span class="p">,</span><span class="s1">&#39;M&#39;</span><span class="p">,</span><span class="s1">&#39;G&#39;</span><span class="p">,</span><span class="s1">&#39;T&#39;</span><span class="p">,</span><span class="s1">&#39;P&#39;</span><span class="p">,</span><span class="s1">&#39;E&#39;</span><span class="p">,</span><span class="s1">&#39;Z&#39;</span><span class="p">]</span>
3165          <span class="n">last_unit</span> <span class="o">=</span> <span class="s1">&#39;Y&#39;</span>
3166  
3167      <span class="k">for</span> <span class="n">unit</span> <span class="ow">in</span> <span class="n">units</span><span class="p">:</span>
3168          <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">&lt;</span> <span class="mf">1024.0</span><span class="p">:</span>
3169              <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%3.2f</span><span class="s2"> </span><span class="si">%s%s</span><span class="s2">&quot;</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>
3170          <span class="n">num</span> <span class="o">/=</span> <span class="mf">1024.0</span>
3171      <span class="k">return</span> <span class="s2">&quot;</span><span class="si">%.2f</span><span class="s2"> </span><span class="si">%s%s</span><span class="s2">&quot;</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>
3172  
3173  <span class="c1"># A convenience function for clearing the screen</span>
3174  <span class="k">def</span><span class="w"> </span><span class="nf">clear_screen</span><span class="p">():</span>
3175      <span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#39;cls&#39;</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">&#39;nt&#39;</span> <span class="k">else</span> <span class="s1">&#39;clear&#39;</span><span class="p">)</span>
3176  
3177  <span class="c1">##########################################################</span>
3178  <span class="c1">#### Program Startup #####################################</span>
3179  <span class="c1">##########################################################</span>
3180  
3181  <span class="c1"># This part of the program runs at startup,</span>
3182  <span class="c1"># and parses input of from the user, and then</span>
3183  <span class="c1"># starts up the desired program mode.</span>
3184  <span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
3185      <span class="k">try</span><span class="p">:</span>
3186          <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>
3187              <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Simple file transfer server and client utility&quot;</span>
3188          <span class="p">)</span>
3189  
3190          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
3191              <span class="s2">&quot;-s&quot;</span><span class="p">,</span>
3192              <span class="s2">&quot;--serve&quot;</span><span class="p">,</span>
3193              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
3194              <span class="n">metavar</span><span class="o">=</span><span class="s2">&quot;dir&quot;</span><span class="p">,</span>
3195              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;serve a directory of files to clients&quot;</span>
3196          <span class="p">)</span>
3197  
3198          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
3199              <span class="s2">&quot;--config&quot;</span><span class="p">,</span>
3200              <span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
3201              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
3202              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
3203              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
3204          <span class="p">)</span>
3205  
3206          <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
3207              <span class="s2">&quot;destination&quot;</span><span class="p">,</span>
3208              <span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
3209              <span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
3210              <span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
3211              <span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
3212          <span class="p">)</span>
3213  
3214          <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>
3215  
3216          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
3217              <span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
3218          <span class="k">else</span><span class="p">:</span>
3219              <span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
3220  
3221          <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">serve</span><span class="p">:</span>
3222              <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>
3223                  <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>
3224              <span class="k">else</span><span class="p">:</span>
3225                  <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The specified directory does not exist&quot;</span><span class="p">)</span>
3226          <span class="k">else</span><span class="p">:</span>
3227              <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>
3228                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3229                  <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
3230                  <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3231              <span class="k">else</span><span class="p">:</span>
3232                  <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>
3233  
3234      <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
3235          <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
3236          <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
3237  </pre></div>
3238  </div>
3239  <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>
3240  </section>
3241  <section id="custom-interfaces">
3242  <span id="example-custominterface"></span><h2>Custom Interfaces<a class="headerlink" href="#custom-interfaces" title="Permalink to this heading">#</a></h2>
3243  <p>The <em>ExampleInterface</em> demonstrates creating custom interfaces for Reticulum.
3244  Any number of custom interfaces can be loaded and utilised by Reticulum, and
3245  will be fully on-par with natively included interfaces, including all supported
3246  <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>
3247  <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># This example illustrates creating a custom interface</span>
3248  <span class="c1"># definition, that can be loaded and used by Reticulum at</span>
3249  <span class="c1"># runtime. Any number of custom interfaces can be created</span>
3250  <span class="c1"># and loaded. To use the interface place it in the folder</span>
3251  <span class="c1"># ~/.reticulum/interfaces, and add an interface entry to</span>
3252  <span class="c1"># your Reticulum configuration file similar to this:</span>
3253  
3254  <span class="c1">#  [[Example Custom Interface]]</span>
3255  <span class="c1">#    type = ExampleInterface</span>
3256  <span class="c1">#    enabled = no</span>
3257  <span class="c1">#    mode = gateway</span>
3258  <span class="c1">#    port = /dev/ttyUSB0</span>
3259  <span class="c1">#    speed = 115200</span>
3260  <span class="c1">#    databits = 8</span>
3261  <span class="c1">#    parity = none</span>
3262  <span class="c1">#    stopbits = 1</span>
3263  
3264  <span class="kn">from</span><span class="w"> </span><span class="nn">time</span><span class="w"> </span><span class="kn">import</span> <span class="n">sleep</span>
3265  <span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
3266  <span class="kn">import</span><span class="w"> </span><span class="nn">threading</span>
3267  <span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
3268  
3269  <span class="c1"># This HDLC helper class is used by the interface</span>
3270  <span class="c1"># to delimit and packetize data over the physical</span>
3271  <span class="c1"># medium - in this case a serial connection.</span>
3272  <span class="k">class</span><span class="w"> </span><span class="nc">HDLC</span><span class="p">():</span>
3273      <span class="c1"># This example interface packetizes data using</span>
3274      <span class="c1"># simplified HDLC framing, similar to PPP</span>
3275      <span class="n">FLAG</span>     <span class="o">=</span> <span class="mh">0x7E</span>
3276      <span class="n">ESC</span>      <span class="o">=</span> <span class="mh">0x7D</span>
3277      <span class="n">ESC_MASK</span> <span class="o">=</span> <span class="mh">0x20</span>
3278  
3279      <span class="nd">@staticmethod</span>
3280      <span class="k">def</span><span class="w"> </span><span class="nf">escape</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
3281          <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>
3282          <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>
3283          <span class="k">return</span> <span class="n">data</span>
3284  
3285  <span class="c1"># Let&#39;s define our custom interface class. It must</span>
3286  <span class="c1"># be a sub-class of the RNS &quot;Interface&quot; class.</span>
3287  <span class="k">class</span><span class="w"> </span><span class="nc">ExampleInterface</span><span class="p">(</span><span class="n">Interface</span><span class="p">):</span>
3288      <span class="c1"># All interface classes must define a default</span>
3289      <span class="c1"># IFAC size, used in IFAC setup when the user</span>
3290      <span class="c1"># has not specified a custom IFAC size. This</span>
3291      <span class="c1"># option is specified in bytes.</span>
3292      <span class="n">DEFAULT_IFAC_SIZE</span> <span class="o">=</span> <span class="mi">8</span>
3293  
3294      <span class="c1"># The following properties are local to this</span>
3295      <span class="c1"># particular interface implementation.</span>
3296      <span class="n">owner</span>    <span class="o">=</span> <span class="kc">None</span>
3297      <span class="n">port</span>     <span class="o">=</span> <span class="kc">None</span>
3298      <span class="n">speed</span>    <span class="o">=</span> <span class="kc">None</span>
3299      <span class="n">databits</span> <span class="o">=</span> <span class="kc">None</span>
3300      <span class="n">parity</span>   <span class="o">=</span> <span class="kc">None</span>
3301      <span class="n">stopbits</span> <span class="o">=</span> <span class="kc">None</span>
3302      <span class="n">serial</span>   <span class="o">=</span> <span class="kc">None</span>
3303  
3304      <span class="c1"># All Reticulum interfaces must have an __init__</span>
3305      <span class="c1"># method that takes 2 positional arguments:</span>
3306      <span class="c1"># The owner RNS Transport instance, and a dict</span>
3307      <span class="c1"># of configuration values.</span>
3308      <span class="k">def</span><span class="w"> </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>
3309  
3310          <span class="c1"># The following lines demonstrate handling</span>
3311          <span class="c1"># potential dependencies required for the</span>
3312          <span class="c1"># interface to function correctly.</span>
3313          <span class="kn">import</span><span class="w"> </span><span class="nn">importlib</span>
3314          <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">&#39;serial&#39;</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">None</span><span class="p">:</span>
3315              <span class="kn">import</span><span class="w"> </span><span class="nn">serial</span>
3316          <span class="k">else</span><span class="p">:</span>
3317              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Using this interface requires a serial communication module to be installed.&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_CRITICAL</span><span class="p">)</span>
3318              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;You can install one with the command: python3 -m pip install pyserial&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_CRITICAL</span><span class="p">)</span>
3319              <span class="n">RNS</span><span class="o">.</span><span class="n">panic</span><span class="p">()</span>
3320  
3321          <span class="c1"># We start out by initialising the super-class</span>
3322          <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
3323  
3324          <span class="c1"># To make sure the configuration data is in the</span>
3325          <span class="c1"># correct format, we parse it through the following</span>
3326          <span class="c1"># method on the generic Interface class. This step</span>
3327          <span class="c1"># is required to ensure compatibility on all the</span>
3328          <span class="c1"># platforms that Reticulum supports.</span>
3329          <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>
3330  
3331          <span class="c1"># Read the interface name from the configuration</span>
3332          <span class="c1"># and set it on our interface instance.</span>
3333          <span class="n">name</span>      <span class="o">=</span> <span class="n">ifconf</span><span class="p">[</span><span class="s2">&quot;name&quot;</span><span class="p">]</span>
3334          <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
3335  
3336          <span class="c1"># We read configuration parameters from the supplied</span>
3337          <span class="c1"># configuration data, and provide default values in</span>
3338          <span class="c1"># case any are missing.</span>
3339          <span class="n">port</span>      <span class="o">=</span> <span class="n">ifconf</span><span class="p">[</span><span class="s2">&quot;port&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="s2">&quot;port&quot;</span> <span class="ow">in</span> <span class="n">ifconf</span> <span class="k">else</span> <span class="kc">None</span>
3340          <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">&quot;speed&quot;</span><span class="p">])</span> <span class="k">if</span> <span class="s2">&quot;speed&quot;</span> <span class="ow">in</span> <span class="n">ifconf</span> <span class="k">else</span> <span class="mi">9600</span>
3341          <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">&quot;databits&quot;</span><span class="p">])</span> <span class="k">if</span> <span class="s2">&quot;databits&quot;</span> <span class="ow">in</span> <span class="n">ifconf</span> <span class="k">else</span> <span class="mi">8</span>
3342          <span class="n">parity</span>    <span class="o">=</span> <span class="n">ifconf</span><span class="p">[</span><span class="s2">&quot;parity&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="s2">&quot;parity&quot;</span> <span class="ow">in</span> <span class="n">ifconf</span> <span class="k">else</span> <span class="s2">&quot;N&quot;</span>
3343          <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">&quot;stopbits&quot;</span><span class="p">])</span> <span class="k">if</span> <span class="s2">&quot;stopbits&quot;</span> <span class="ow">in</span> <span class="n">ifconf</span> <span class="k">else</span> <span class="mi">1</span>
3344  
3345          <span class="c1"># In case no port is specified, we abort setup by</span>
3346          <span class="c1"># raising an exception.</span>
3347          <span class="k">if</span> <span class="n">port</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
3348              <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;No port specified for </span><span class="si">{</span><span class="bp">self</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
3349  
3350          <span class="c1"># All interfaces must supply a hardware MTU value</span>
3351          <span class="c1"># to the RNS Transport instance. This value should</span>
3352          <span class="c1"># be the maximum data packet payload size that the</span>
3353          <span class="c1"># underlying medium is capable of handling in all</span>
3354          <span class="c1"># cases without any segmentation.</span>
3355          <span class="bp">self</span><span class="o">.</span><span class="n">HW_MTU</span> <span class="o">=</span> <span class="mi">564</span>
3356  
3357          <span class="c1"># We initially set the &quot;online&quot; property to false,</span>
3358          <span class="c1"># since the interface has not actually been fully</span>
3359          <span class="c1"># initialised and connected yet.</span>
3360          <span class="bp">self</span><span class="o">.</span><span class="n">online</span>   <span class="o">=</span> <span class="kc">False</span>
3361  
3362          <span class="c1"># In this case, we can also set the indicated bit-</span>
3363          <span class="c1"># rate of the interface to the serial port speed.</span>
3364          <span class="bp">self</span><span class="o">.</span><span class="n">bitrate</span>  <span class="o">=</span> <span class="n">speed</span>
3365          
3366          <span class="c1"># Configure internal properties on the interface</span>
3367          <span class="c1"># according to the supplied configuration.</span>
3368          <span class="bp">self</span><span class="o">.</span><span class="n">pyserial</span> <span class="o">=</span> <span class="n">serial</span>
3369          <span class="bp">self</span><span class="o">.</span><span class="n">serial</span>   <span class="o">=</span> <span class="kc">None</span>
3370          <span class="bp">self</span><span class="o">.</span><span class="n">owner</span>    <span class="o">=</span> <span class="n">owner</span>
3371          <span class="bp">self</span><span class="o">.</span><span class="n">port</span>     <span class="o">=</span> <span class="n">port</span>
3372          <span class="bp">self</span><span class="o">.</span><span class="n">speed</span>    <span class="o">=</span> <span class="n">speed</span>
3373          <span class="bp">self</span><span class="o">.</span><span class="n">databits</span> <span class="o">=</span> <span class="n">databits</span>
3374          <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>
3375          <span class="bp">self</span><span class="o">.</span><span class="n">stopbits</span> <span class="o">=</span> <span class="n">stopbits</span>
3376          <span class="bp">self</span><span class="o">.</span><span class="n">timeout</span>  <span class="o">=</span> <span class="mi">100</span>
3377  
3378          <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">&quot;e&quot;</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">&quot;even&quot;</span><span class="p">:</span>
3379              <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>
3380  
3381          <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">&quot;o&quot;</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">&quot;odd&quot;</span><span class="p">:</span>
3382              <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>
3383  
3384          <span class="c1"># Since all required parameters are now configured,</span>
3385          <span class="c1"># we will try opening the serial port.</span>
3386          <span class="k">try</span><span class="p">:</span>
3387              <span class="bp">self</span><span class="o">.</span><span class="n">open_port</span><span class="p">()</span>
3388          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
3389              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Could not open serial port for interface &quot;</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>
3390              <span class="k">raise</span> <span class="n">e</span>
3391  
3392          <span class="c1"># If opening the port succeeded, run any post-open</span>
3393          <span class="c1"># configuration required.</span>
3394          <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>
3395              <span class="bp">self</span><span class="o">.</span><span class="n">configure_device</span><span class="p">()</span>
3396          <span class="k">else</span><span class="p">:</span>
3397              <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s2">&quot;Could not open serial port&quot;</span><span class="p">)</span>
3398  
3399      <span class="c1"># Open the serial port with supplied configuration</span>
3400      <span class="c1"># parameters and store a reference to the open port.</span>
3401      <span class="k">def</span><span class="w"> </span><span class="nf">open_port</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3402          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Opening serial port &quot;</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">&quot;...&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_VERBOSE</span><span class="p">)</span>
3403          <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>
3404              <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>
3405              <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>
3406              <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>
3407              <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>
3408              <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>
3409              <span class="n">xonxoff</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
3410              <span class="n">rtscts</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
3411              <span class="n">timeout</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
3412              <span class="n">inter_byte_timeout</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
3413              <span class="n">write_timeout</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
3414              <span class="n">dsrdtr</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
3415          <span class="p">)</span>
3416  
3417      <span class="c1"># The only thing required after opening the port</span>
3418      <span class="c1"># is to wait a small amount of time for the</span>
3419      <span class="c1"># hardware to initialise and then start a thread</span>
3420      <span class="c1"># that reads any incoming data from the device.</span>
3421      <span class="k">def</span><span class="w"> </span><span class="nf">configure_device</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3422          <span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
3423          <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>
3424          <span class="n">thread</span><span class="o">.</span><span class="n">daemon</span> <span class="o">=</span> <span class="kc">True</span>
3425          <span class="n">thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
3426          <span class="bp">self</span><span class="o">.</span><span class="n">online</span> <span class="o">=</span> <span class="kc">True</span>
3427          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Serial port &quot;</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">&quot; is now open&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_VERBOSE</span><span class="p">)</span>
3428  
3429  
3430      <span class="c1"># This method will be called from our read-loop</span>
3431      <span class="c1"># whenever a full packet has been received over</span>
3432      <span class="c1"># the underlying medium.</span>
3433      <span class="k">def</span><span class="w"> </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>
3434          <span class="c1"># Update our received bytes counter</span>
3435          <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>            
3436  
3437          <span class="c1"># And send the data packet to the Transport</span>
3438          <span class="c1"># instance for processing.</span>
3439          <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>
3440  
3441      <span class="c1"># The running Reticulum Transport instance will</span>
3442      <span class="c1"># call this method on the interface whenever the</span>
3443      <span class="c1"># interface must transmit a packet.</span>
3444      <span class="k">def</span><span class="w"> </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>
3445          <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">online</span><span class="p">:</span>
3446              <span class="c1"># First, escape and packetize the data</span>
3447              <span class="c1"># according to HDLC framing.</span>
3448              <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>
3449  
3450              <span class="c1"># Then write the framed data to the port</span>
3451              <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>
3452  
3453              <span class="c1"># Update the transmitted bytes counter</span>
3454              <span class="c1"># and ensure that all data was written</span>
3455              <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>            
3456              <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>
3457                  <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s2">&quot;Serial interface only wrote &quot;</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">&quot; bytes of &quot;</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>
3458  
3459      <span class="c1"># This read loop runs in a thread and continously</span>
3460      <span class="c1"># receives bytes from the underlying serial port.</span>
3461      <span class="c1"># When a full packet has been received, it will</span>
3462      <span class="c1"># be sent to the process_incoming methed, which</span>
3463      <span class="c1"># will in turn pass it to the Transport instance.</span>
3464      <span class="k">def</span><span class="w"> </span><span class="nf">read_loop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3465          <span class="k">try</span><span class="p">:</span>
3466              <span class="n">in_frame</span> <span class="o">=</span> <span class="kc">False</span>
3467              <span class="n">escape</span> <span class="o">=</span> <span class="kc">False</span>
3468              <span class="n">data_buffer</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&quot;&quot;</span>
3469              <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>
3470  
3471              <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>
3472                  <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>
3473                      <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>
3474                      <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>
3475  
3476                      <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>
3477                          <span class="n">in_frame</span> <span class="o">=</span> <span class="kc">False</span>
3478                          <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>
3479                      <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>
3480                          <span class="n">in_frame</span> <span class="o">=</span> <span class="kc">True</span>
3481                          <span class="n">data_buffer</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&quot;&quot;</span>
3482                      <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">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">HW_MTU</span><span class="p">):</span>
3483                          <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>
3484                              <span class="n">escape</span> <span class="o">=</span> <span class="kc">True</span>
3485                          <span class="k">else</span><span class="p">:</span>
3486                              <span class="k">if</span> <span class="p">(</span><span class="n">escape</span><span class="p">):</span>
3487                                  <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>
3488                                      <span class="n">byte</span> <span class="o">=</span> <span class="n">HDLC</span><span class="o">.</span><span class="n">FLAG</span>
3489                                  <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>
3490                                      <span class="n">byte</span> <span class="o">=</span> <span class="n">HDLC</span><span class="o">.</span><span class="n">ESC</span>
3491                                  <span class="n">escape</span> <span class="o">=</span> <span class="kc">False</span>
3492                              <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>
3493                          
3494                  <span class="k">else</span><span class="p">:</span>
3495                      <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>
3496                      <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">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">time_since_last</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">timeout</span><span class="p">:</span>
3497                          <span class="n">data_buffer</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&quot;&quot;</span>
3498                          <span class="n">in_frame</span> <span class="o">=</span> <span class="kc">False</span>
3499                          <span class="n">escape</span> <span class="o">=</span> <span class="kc">False</span>
3500                      <span class="n">sleep</span><span class="p">(</span><span class="mf">0.08</span><span class="p">)</span>
3501                      
3502          <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
3503              <span class="bp">self</span><span class="o">.</span><span class="n">online</span> <span class="o">=</span> <span class="kc">False</span>
3504              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;A serial port error occurred, the contained exception was: &quot;</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>
3505              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The interface &quot;</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">&quot; experienced an unrecoverable error and is now offline.&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
3506              
3507              <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>
3508                  <span class="n">RNS</span><span class="o">.</span><span class="n">panic</span><span class="p">()</span>
3509  
3510              <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Reticulum will attempt to reconnect the interface periodically.&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
3511  
3512          <span class="bp">self</span><span class="o">.</span><span class="n">online</span> <span class="o">=</span> <span class="kc">False</span>
3513          <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>
3514          <span class="bp">self</span><span class="o">.</span><span class="n">reconnect_port</span><span class="p">()</span>
3515  
3516      <span class="c1"># This method handles serial port disconnects.</span>
3517      <span class="k">def</span><span class="w"> </span><span class="nf">reconnect_port</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3518          <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>
3519              <span class="k">try</span><span class="p">:</span>
3520                  <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>
3521                  <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Attempting to reconnect serial port &quot;</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">&quot; for &quot;</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">&quot;...&quot;</span><span class="p">,</span> <span class="n">RNS</span><span class="o">.</span><span class="n">LOG_VERBOSE</span><span class="p">)</span>
3522                  <span class="bp">self</span><span class="o">.</span><span class="n">open_port</span><span class="p">()</span>
3523                  <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>
3524                      <span class="bp">self</span><span class="o">.</span><span class="n">configure_device</span><span class="p">()</span>
3525              <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
3526                  <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Error while reconnecting port, the contained exception was: &quot;</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>
3527  
3528          <span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Reconnected serial port for &quot;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
3529  
3530      <span class="c1"># Signal to Reticulum that this interface should</span>
3531      <span class="c1"># not perform any ingress limiting.</span>
3532      <span class="k">def</span><span class="w"> </span><span class="nf">should_ingress_limit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3533          <span class="k">return</span> <span class="kc">False</span>
3534  
3535      <span class="c1"># We must provide a string representation of this</span>
3536      <span class="c1"># interface, that is used whenever the interface</span>
3537      <span class="c1"># is printed in logs or external programs.</span>
3538      <span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3539          <span class="k">return</span> <span class="s2">&quot;ExampleInterface[&quot;</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">&quot;]&quot;</span>
3540  
3541  <span class="c1"># Finally, register the defined interface class as the</span>
3542  <span class="c1"># target class for Reticulum to use as an interface</span>
3543  <span class="n">interface_class</span> <span class="o">=</span> <span class="n">ExampleInterface</span>
3544  </pre></div>
3545  </div>
3546  <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>
3547  </section>
3548  </section>
3549  
3550          </article>
3551        </div>
3552        <footer>
3553          
3554          <div class="related-pages">
3555            <a class="next-page" href="support.html">
3556                <div class="page-info">
3557                  <div class="context">
3558                    <span>Next</span>
3559                  </div>
3560                  <div class="title">Support Reticulum</div>
3561                </div>
3562                <svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
3563              </a>
3564            <a class="prev-page" href="networks.html">
3565                <svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
3566                <div class="page-info">
3567                  <div class="context">
3568                    <span>Previous</span>
3569                  </div>
3570                  
3571                  <div class="title">Building Networks</div>
3572                  
3573                </div>
3574              </a>
3575          </div>
3576          <div class="bottom-of-page">
3577            <div class="left-details">
3578              <div class="copyright">
3579                  Copyright &#169; 2023, Mark Qvist
3580              </div>
3581              Generated with <a href="https://www.sphinx-doc.org/">Sphinx</a> and 
3582              <a href="https://github.com/pradyunsg/furo">Furo</a>
3583              
3584            </div>
3585            <div class="right-details">
3586              <div class="icons">
3587                
3588              </div>
3589            </div>
3590          </div>
3591          
3592        </footer>
3593      </div>
3594      <aside class="toc-drawer">
3595        
3596        
3597        <div class="toc-sticky toc-scroll">
3598          <div class="toc-title-container">
3599            <span class="toc-title">
3600              On this page
3601            </span>
3602          </div>
3603          <div class="toc-tree-container">
3604            <div class="toc-tree">
3605              <ul>
3606  <li><a class="reference internal" href="#">Code Examples</a><ul>
3607  <li><a class="reference internal" href="#minimal">Minimal</a></li>
3608  <li><a class="reference internal" href="#announce">Announce</a></li>
3609  <li><a class="reference internal" href="#broadcast">Broadcast</a></li>
3610  <li><a class="reference internal" href="#echo">Echo</a></li>
3611  <li><a class="reference internal" href="#link">Link</a></li>
3612  <li><a class="reference internal" href="#example-identify">Identification</a></li>
3613  <li><a class="reference internal" href="#requests-responses">Requests &amp; Responses</a></li>
3614  <li><a class="reference internal" href="#channel">Channel</a></li>
3615  <li><a class="reference internal" href="#buffer">Buffer</a></li>
3616  <li><a class="reference internal" href="#filetransfer">Filetransfer</a></li>
3617  <li><a class="reference internal" href="#custom-interfaces">Custom Interfaces</a></li>
3618  </ul>
3619  </li>
3620  </ul>
3621  
3622            </div>
3623          </div>
3624        </div>
3625        
3626        
3627      </aside>
3628    </div>
3629  </div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
3630      <script src="_static/jquery.js"></script>
3631      <script src="_static/underscore.js"></script>
3632      <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
3633      <script src="_static/doctools.js"></script>
3634      <script src="_static/sphinx_highlight.js"></script>
3635      <script src="_static/scripts/furo.js"></script>
3636      <script src="_static/clipboard.min.js"></script>
3637      <script src="_static/copybutton.js"></script>
3638      </body>
3639  </html>