Updated documentation

This commit is contained in:
Mark Qvist 2023-03-03 22:16:13 +01:00
parent e36312a3cb
commit 27861e96f8
8 changed files with 617 additions and 12 deletions

View File

@ -104,6 +104,16 @@ data between peers of a ``Link``.
This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Channel.py>`_.
Buffer
======
The *Buffer* example explores using buffered readers and writers to send
binary data between peers of a ``Link``.
.. literalinclude:: ../../Examples/Buffer.py
This example can also be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Buffer.py>`_.
.. _example-filetransfer:
Filetransfer

View File

@ -149,6 +149,48 @@ This chapter lists and explains all classes exposed by the Reticulum Network Sta
.. autoclass:: RNS.MessageBase()
:members:
.. _api-buffer:
.. only:: html
|start-h3| Buffer |end-h3|
.. only:: latex
Buffer
------
.. autoclass:: RNS.Buffer
:members:
.. _api-rawchannelreader:
.. only:: html
|start-h3| RawChannelReader |end-h3|
.. only:: latex
RawChannelReader
----------------
.. autoclass:: RNS.RawChannelReader
:members: __init__, add_ready_callback, remove_ready_callback
.. _api-rawchannelwriter:
.. only:: html
|start-h3| RawChannelWriter |end-h3|
.. only:: latex
RawChannelWriter
----------------
.. autoclass:: RNS.RawChannelWriter
:members: __init__
.. _api-transport:
.. only:: html

View File

@ -2148,11 +2148,6 @@ data between peers of a <code class="docutils literal notranslate"><span class="
<span class="c1"># And create a link</span>
<span class="n">link</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
<span class="c1"># We set a callback that will get executed</span>
<span class="c1"># every time a packet is received over the</span>
<span class="c1"># link</span>
<span class="n">link</span><span class="o">.</span><span class="n">set_packet_callback</span><span class="p">(</span><span class="n">client_message_received</span><span class="p">)</span>
<span class="c1"># We&#39;ll also set up functions to inform the</span>
<span class="c1"># user when the link is established or closed</span>
<span class="n">link</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
@ -2235,7 +2230,7 @@ data between peers of a <code class="docutils literal notranslate"><span class="
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># When a packet is received over the link, we</span>
<span class="c1"># When a packet is received over the channel, we</span>
<span class="c1"># simply print out the data.</span>
<span class="k">def</span> <span class="nf">client_message_received</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">StringMessage</span><span class="p">):</span>
@ -2253,7 +2248,7 @@ data between peers of a <code class="docutils literal notranslate"><span class="
<span class="c1"># starts up the desired program mode.</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;Simple link example&quot;</span><span class="p">)</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;Simple channel example&quot;</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">&quot;-s&quot;</span><span class="p">,</span>
@ -2302,6 +2297,337 @@ data between peers of a <code class="docutils literal notranslate"><span class="
</div>
<p>This example can also be found at <a class="reference external" href="https://github.com/markqvist/Reticulum/blob/master/Examples/Channel.py">https://github.com/markqvist/Reticulum/blob/master/Examples/Channel.py</a>.</p>
</section>
<section id="buffer">
<h2>Buffer<a class="headerlink" href="#buffer" title="Permalink to this heading">#</a></h2>
<p>The <em>Buffer</em> example explores using buffered readers and writers to send
binary data between peers of a <code class="docutils literal notranslate"><span class="pre">Link</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1">##########################################################</span>
<span class="c1"># This RNS example demonstrates how to set up a link to #</span>
<span class="c1"># a destination, and pass binary data over it using a #</span>
<span class="c1"># using a channel buffer. #</span>
<span class="c1">##########################################################</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">argparse</span>
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
<span class="kn">import</span> <span class="nn">RNS</span>
<span class="kn">from</span> <span class="nn">RNS.vendor</span> <span class="kn">import</span> <span class="n">umsgpack</span>
<span class="c1"># Let&#39;s define an app name. We&#39;ll use this for all</span>
<span class="c1"># destinations we create. Since this echo example</span>
<span class="c1"># is part of a range of example utilities, we&#39;ll put</span>
<span class="c1"># them all within the app namespace &quot;example_utilities&quot;</span>
<span class="n">APP_NAME</span> <span class="o">=</span> <span class="s2">&quot;example_utilities&quot;</span>
<span class="c1">##########################################################</span>
<span class="c1">#### Server Part #########################################</span>
<span class="c1">##########################################################</span>
<span class="c1"># A reference to the latest client link that connected</span>
<span class="n">latest_client_link</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># A reference to the latest buffer object</span>
<span class="n">latest_buffer</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># This initialisation is executed when the users chooses</span>
<span class="c1"># to run as a server</span>
<span class="k">def</span> <span class="nf">server</span><span class="p">(</span><span class="n">configpath</span><span class="p">):</span>
<span class="c1"># We must first initialise Reticulum</span>
<span class="n">reticulum</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="p">(</span><span class="n">configpath</span><span class="p">)</span>
<span class="c1"># Randomly create a new identity for our link example</span>
<span class="n">server_identity</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Identity</span><span class="p">()</span>
<span class="c1"># We create a destination that clients can connect to. We</span>
<span class="c1"># want clients to create links to this destination, so we</span>
<span class="c1"># need to create a &quot;single&quot; destination type.</span>
<span class="n">server_destination</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="p">(</span>
<span class="n">server_identity</span><span class="p">,</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">IN</span><span class="p">,</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">SINGLE</span><span class="p">,</span>
<span class="n">APP_NAME</span><span class="p">,</span>
<span class="s2">&quot;bufferexample&quot;</span>
<span class="p">)</span>
<span class="c1"># We configure a function that will get called every time</span>
<span class="c1"># a new client creates a link to this destination.</span>
<span class="n">server_destination</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">client_connected</span><span class="p">)</span>
<span class="c1"># Everything&#39;s ready!</span>
<span class="c1"># Let&#39;s Wait for client requests or user input</span>
<span class="n">server_loop</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">server_loop</span><span class="p">(</span><span class="n">destination</span><span class="p">):</span>
<span class="c1"># Let the user know that everything is ready</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span>
<span class="s2">&quot;Link example &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, waiting for a connection.&quot;</span>
<span class="p">)</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Hit enter to manually send an announce (Ctrl-C to quit)&quot;</span><span class="p">)</span>
<span class="c1"># We enter a loop that runs until the users exits.</span>
<span class="c1"># If the user hits enter, we will announce our server</span>
<span class="c1"># destination on the network, which will let clients</span>
<span class="c1"># know how to create messages directed towards it.</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">entered</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
<span class="n">destination</span><span class="o">.</span><span class="n">announce</span><span class="p">()</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&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>
<span class="c1"># When a client establishes a link to our server</span>
<span class="c1"># destination, this function will be called with</span>
<span class="c1"># a reference to the link.</span>
<span class="k">def</span> <span class="nf">client_connected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
<span class="k">global</span> <span class="n">latest_client_link</span><span class="p">,</span> <span class="n">latest_buffer</span>
<span class="n">latest_client_link</span> <span class="o">=</span> <span class="n">link</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client connected&quot;</span><span class="p">)</span>
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">client_disconnected</span><span class="p">)</span>
<span class="c1"># If a new connection is received, the old reader</span>
<span class="c1"># needs to be disconnected.</span>
<span class="k">if</span> <span class="n">latest_buffer</span><span class="p">:</span>
<span class="n">latest_buffer</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="c1"># Create buffer objects.</span>
<span class="c1"># The stream_id parameter to these functions is</span>
<span class="c1"># a bit like a file descriptor, except that it</span>
<span class="c1"># is unique to the *receiver*.</span>
<span class="c1">#</span>
<span class="c1"># In this example, both the reader and the writer</span>
<span class="c1"># use stream_id = 0, but there are actually two</span>
<span class="c1"># separate unidirectional streams flowing in</span>
<span class="c1"># opposite directions.</span>
<span class="c1">#</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">link</span><span class="o">.</span><span class="n">get_channel</span><span class="p">()</span>
<span class="n">latest_buffer</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Buffer</span><span class="o">.</span><span class="n">create_bidirectional_buffer</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">channel</span><span class="p">,</span> <span class="n">server_buffer_ready</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">client_disconnected</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Client disconnected&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">server_buffer_ready</span><span class="p">(</span><span class="n">ready_bytes</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Callback from buffer when buffer has data available</span>
<span class="sd"> :param ready_bytes: The number of bytes ready to read</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">global</span> <span class="n">latest_buffer</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">latest_buffer</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">ready_bytes</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Received data on the link: &quot;</span> <span class="o">+</span> <span class="n">data</span><span class="p">)</span>
<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>
<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>
<span class="n">latest_buffer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">reply_message</span><span class="p">)</span>
<span class="n">latest_buffer</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="c1">##########################################################</span>
<span class="c1">#### Client Part #########################################</span>
<span class="c1">##########################################################</span>
<span class="c1"># A reference to the server link</span>
<span class="n">server_link</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># A reference to the buffer object, needed to share the</span>
<span class="c1"># object from the link connected callback to the client</span>
<span class="c1"># loop.</span>
<span class="n">buffer</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># This initialisation is executed when the users chooses</span>
<span class="c1"># to run as a client</span>
<span class="k">def</span> <span class="nf">client</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">,</span> <span class="n">configpath</span><span class="p">):</span>
<span class="c1"># We need a binary representation of the destination</span>
<span class="c1"># hash that was entered on the command line</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">dest_len</span> <span class="o">=</span> <span class="p">(</span><span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">TRUNCATED_HASHLENGTH</span><span class="o">//</span><span class="mi">8</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">)</span> <span class="o">!=</span> <span class="n">dest_len</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s2">&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>
<span class="p">)</span>
<span class="n">destination_hash</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">destination_hexhash</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Invalid destination entered. Check your input!</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">exit</span><span class="p">()</span>
<span class="c1"># We must first initialise Reticulum</span>
<span class="n">reticulum</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="p">(</span><span class="n">configpath</span><span class="p">)</span>
<span class="c1"># Check if we know a path to the destination</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">has_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">):</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Destination is not yet known. Requesting path and waiting for announce to arrive...&quot;</span><span class="p">)</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">request_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Transport</span><span class="o">.</span><span class="n">has_path</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">):</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="c1"># Recall the server identity</span>
<span class="n">server_identity</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Identity</span><span class="o">.</span><span class="n">recall</span><span class="p">(</span><span class="n">destination_hash</span><span class="p">)</span>
<span class="c1"># Inform the user that we&#39;ll begin connecting</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Establishing link with server...&quot;</span><span class="p">)</span>
<span class="c1"># When the server identity is known, we set</span>
<span class="c1"># up a destination</span>
<span class="n">server_destination</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="p">(</span>
<span class="n">server_identity</span><span class="p">,</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">OUT</span><span class="p">,</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Destination</span><span class="o">.</span><span class="n">SINGLE</span><span class="p">,</span>
<span class="n">APP_NAME</span><span class="p">,</span>
<span class="s2">&quot;bufferexample&quot;</span>
<span class="p">)</span>
<span class="c1"># And create a link</span>
<span class="n">link</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="p">(</span><span class="n">server_destination</span><span class="p">)</span>
<span class="c1"># We&#39;ll also set up functions to inform the</span>
<span class="c1"># user when the link is established or closed</span>
<span class="n">link</span><span class="o">.</span><span class="n">set_link_established_callback</span><span class="p">(</span><span class="n">link_established</span><span class="p">)</span>
<span class="n">link</span><span class="o">.</span><span class="n">set_link_closed_callback</span><span class="p">(</span><span class="n">link_closed</span><span class="p">)</span>
<span class="c1"># Everything is set up, so let&#39;s enter a loop</span>
<span class="c1"># for the user to interact with the example</span>
<span class="n">client_loop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">client_loop</span><span class="p">():</span>
<span class="k">global</span> <span class="n">server_link</span>
<span class="c1"># Wait for the link to become active</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">server_link</span><span class="p">:</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="n">should_quit</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">should_quit</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&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>
<span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
<span class="c1"># Check if we should quit the example</span>
<span class="k">if</span> <span class="n">text</span> <span class="o">==</span> <span class="s2">&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>
<span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Otherwise, encode the text and write it to the buffer.</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s2">&quot;utf-8&quot;</span><span class="p">)</span>
<span class="n">buffer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="c1"># Flush the buffer to force the data to be sent.</span>
<span class="n">buffer</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<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>
<span class="n">should_quit</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">server_link</span><span class="o">.</span><span class="n">teardown</span><span class="p">()</span>
<span class="c1"># This function is called when a link</span>
<span class="c1"># has been established with the server</span>
<span class="k">def</span> <span class="nf">link_established</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
<span class="c1"># We store a reference to the link</span>
<span class="c1"># instance for later use</span>
<span class="k">global</span> <span class="n">server_link</span><span class="p">,</span> <span class="n">buffer</span>
<span class="n">server_link</span> <span class="o">=</span> <span class="n">link</span>
<span class="c1"># Create buffer, see server_client_connected() for</span>
<span class="c1"># more detail about setting up the buffer.</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">link</span><span class="o">.</span><span class="n">get_channel</span><span class="p">()</span>
<span class="n">buffer</span> <span class="o">=</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Buffer</span><span class="o">.</span><span class="n">create_bidirectional_buffer</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">channel</span><span class="p">,</span> <span class="n">client_buffer_ready</span><span class="p">)</span>
<span class="c1"># Inform the user that the server is</span>
<span class="c1"># connected</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&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>
<span class="c1"># When a link is closed, we&#39;ll inform the</span>
<span class="c1"># user, and exit the program</span>
<span class="k">def</span> <span class="nf">link_closed</span><span class="p">(</span><span class="n">link</span><span class="p">):</span>
<span class="k">if</span> <span class="n">link</span><span class="o">.</span><span class="n">teardown_reason</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">TIMEOUT</span><span class="p">:</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link timed out, exiting now&quot;</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">link</span><span class="o">.</span><span class="n">teardown_reason</span> <span class="o">==</span> <span class="n">RNS</span><span class="o">.</span><span class="n">Link</span><span class="o">.</span><span class="n">DESTINATION_CLOSED</span><span class="p">:</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;The link was closed by the server, exiting now&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="s2">&quot;Link closed, exiting now&quot;</span><span class="p">)</span>
<span class="n">RNS</span><span class="o">.</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">exit_handler</span><span class="p">()</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">1.5</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># When the buffer has new data, read it and write it to the terminal.</span>
<span class="k">def</span> <span class="nf">client_buffer_ready</span><span class="p">(</span><span class="n">ready_bytes</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
<span class="k">global</span> <span class="n">buffer</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">buffer</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">ready_bytes</span><span class="p">)</span>
<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">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="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>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
<span class="c1">##########################################################</span>
<span class="c1">#### Program Startup #####################################</span>
<span class="c1">##########################################################</span>
<span class="c1"># This part of the program runs at startup,</span>
<span class="c1"># and parses input of from the user, and then</span>
<span class="c1"># starts up the desired program mode.</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;Simple buffer example&quot;</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">&quot;-s&quot;</span><span class="p">,</span>
<span class="s2">&quot;--server&quot;</span><span class="p">,</span>
<span class="n">action</span><span class="o">=</span><span class="s2">&quot;store_true&quot;</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s2">&quot;wait for incoming link requests from clients&quot;</span>
<span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">&quot;--config&quot;</span><span class="p">,</span>
<span class="n">action</span><span class="o">=</span><span class="s2">&quot;store&quot;</span><span class="p">,</span>
<span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s2">&quot;path to alternative Reticulum config directory&quot;</span><span class="p">,</span>
<span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
<span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span>
<span class="s2">&quot;destination&quot;</span><span class="p">,</span>
<span class="n">nargs</span><span class="o">=</span><span class="s2">&quot;?&quot;</span><span class="p">,</span>
<span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s2">&quot;hexadecimal hash of the server destination&quot;</span><span class="p">,</span>
<span class="nb">type</span><span class="o">=</span><span class="nb">str</span>
<span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
<span class="n">configarg</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">config</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">configarg</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">server</span><span class="p">:</span>
<span class="n">server</span><span class="p">(</span><span class="n">configarg</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">destination</span> <span class="o">==</span> <span class="kc">None</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">client</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">destination</span><span class="p">,</span> <span class="n">configarg</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="n">exit</span><span class="p">()</span>
</pre></div>
</div>
<p>This example can also be found at <a class="reference external" href="https://github.com/markqvist/Reticulum/blob/master/Examples/Buffer.py">https://github.com/markqvist/Reticulum/blob/master/Examples/Buffer.py</a>.</p>
</section>
<section id="filetransfer">
<span id="example-filetransfer"></span><h2>Filetransfer<a class="headerlink" href="#filetransfer" title="Permalink to this heading">#</a></h2>
<p>The <em>Filetransfer</em> example implements a basic file-server program that
@ -2983,6 +3309,7 @@ interface to efficiently pass files of any size over a Reticulum <a class="refer
<li><a class="reference internal" href="#example-identify">Identification</a></li>
<li><a class="reference internal" href="#requests-responses">Requests &amp; Responses</a></li>
<li><a class="reference internal" href="#channel">Channel</a></li>
<li><a class="reference internal" href="#buffer">Buffer</a></li>
<li><a class="reference internal" href="#filetransfer">Filetransfer</a></li>
</ul>
</li>

View File

@ -222,8 +222,22 @@
<section class="genindex-section">
<h1 id="index">Index</h1>
<div class="genindex-jumpbox"><a href="#A"><strong>A</strong></a> | <a href="#C"><strong>C</strong></a> | <a href="#D"><strong>D</strong></a> | <a href="#E"><strong>E</strong></a> | <a href="#F"><strong>F</strong></a> | <a href="#G"><strong>G</strong></a> | <a href="#H"><strong>H</strong></a> | <a href="#I"><strong>I</strong></a> | <a href="#K"><strong>K</strong></a> | <a href="#L"><strong>L</strong></a> | <a href="#M"><strong>M</strong></a> | <a href="#N"><strong>N</strong></a> | <a href="#P"><strong>P</strong></a> | <a href="#R"><strong>R</strong></a> | <a href="#S"><strong>S</strong></a> | <a href="#T"><strong>T</strong></a> | <a href="#U"><strong>U</strong></a> | <a href="#V"><strong>V</strong></a></div>
<div class="genindex-jumpbox"><a href="#_"><strong>_</strong></a> | <a href="#A"><strong>A</strong></a> | <a href="#B"><strong>B</strong></a> | <a href="#C"><strong>C</strong></a> | <a href="#D"><strong>D</strong></a> | <a href="#E"><strong>E</strong></a> | <a href="#F"><strong>F</strong></a> | <a href="#G"><strong>G</strong></a> | <a href="#H"><strong>H</strong></a> | <a href="#I"><strong>I</strong></a> | <a href="#K"><strong>K</strong></a> | <a href="#L"><strong>L</strong></a> | <a href="#M"><strong>M</strong></a> | <a href="#N"><strong>N</strong></a> | <a href="#P"><strong>P</strong></a> | <a href="#R"><strong>R</strong></a> | <a href="#S"><strong>S</strong></a> | <a href="#T"><strong>T</strong></a> | <a href="#U"><strong>U</strong></a> | <a href="#V"><strong>V</strong></a></div>
</section>
<section id="_" class="genindex-section">
<h2>_</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.RawChannelReader.__init__">__init__() (RNS.RawChannelReader method)</a>
<ul>
<li><a href="reference.html#RNS.RawChannelWriter.__init__">(RNS.RawChannelWriter method)</a>
</li>
</ul></li>
</ul></td>
</tr></table>
</section>
<section id="A" class="genindex-section">
<h2>A</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
@ -232,10 +246,12 @@
</li>
<li><a href="reference.html#RNS.Channel.Channel.add_message_handler">add_message_handler() (RNS.Channel.Channel method)</a>
</li>
<li><a href="reference.html#RNS.Resource.advertise">advertise() (RNS.Resource method)</a>
<li><a href="reference.html#RNS.RawChannelReader.add_ready_callback">add_ready_callback() (RNS.RawChannelReader method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Resource.advertise">advertise() (RNS.Resource method)</a>
</li>
<li><a href="reference.html#RNS.Destination.announce">announce() (RNS.Destination method)</a>
</li>
<li><a href="reference.html#RNS.Reticulum.ANNOUNCE_CAP">ANNOUNCE_CAP (RNS.Reticulum attribute)</a>
@ -246,6 +262,16 @@
</tr></table>
</section>
<section id="B" class="genindex-section">
<h2>B</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Buffer">Buffer (class in RNS)</a>
</li>
</ul></td>
</tr></table>
</section>
<section id="C" class="genindex-section">
<h2>C</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
@ -255,10 +281,16 @@
<li><a href="reference.html#RNS.Channel.Channel">Channel (class in RNS.Channel)</a>
</li>
<li><a href="reference.html#RNS.Destination.clear_default_app_data">clear_default_app_data() (RNS.Destination method)</a>
</li>
<li><a href="reference.html#RNS.Buffer.create_bidirectional_buffer">create_bidirectional_buffer() (RNS.Buffer static method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Destination.create_keys">create_keys() (RNS.Destination method)</a>
</li>
<li><a href="reference.html#RNS.Buffer.create_reader">create_reader() (RNS.Buffer static method)</a>
</li>
<li><a href="reference.html#RNS.Buffer.create_writer">create_writer() (RNS.Buffer static method)</a>
</li>
<li><a href="reference.html#RNS.Identity.CURVE">CURVE (RNS.Identity attribute)</a>
@ -520,6 +552,10 @@
<h2>R</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.RawChannelReader">RawChannelReader (class in RNS)</a>
</li>
<li><a href="reference.html#RNS.RawChannelWriter">RawChannelWriter (class in RNS)</a>
</li>
<li><a href="reference.html#RNS.Identity.recall">recall() (RNS.Identity static method)</a>
</li>
<li><a href="reference.html#RNS.Identity.recall_app_data">recall_app_data() (RNS.Identity static method)</a>
@ -529,11 +565,13 @@
<li><a href="reference.html#RNS.Channel.Channel.register_message_type">register_message_type() (RNS.Channel.Channel method)</a>
</li>
<li><a href="reference.html#RNS.Destination.register_request_handler">register_request_handler() (RNS.Destination method)</a>
</li>
<li><a href="reference.html#RNS.Channel.Channel.remove_message_handler">remove_message_handler() (RNS.Channel.Channel method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="reference.html#RNS.Channel.Channel.remove_message_handler">remove_message_handler() (RNS.Channel.Channel method)</a>
</li>
<li><a href="reference.html#RNS.RawChannelReader.remove_ready_callback">remove_ready_callback() (RNS.RawChannelReader method)</a>
</li>
<li><a href="reference.html#RNS.Link.request">request() (RNS.Link method)</a>
</li>
<li><a href="reference.html#RNS.Transport.request_path">request_path() (RNS.Transport static method)</a>

View File

@ -356,6 +356,7 @@ to participate in the development of Reticulum itself.</p>
<li class="toctree-l2"><a class="reference internal" href="examples.html#example-identify">Identification</a></li>
<li class="toctree-l2"><a class="reference internal" href="examples.html#requests-responses">Requests &amp; Responses</a></li>
<li class="toctree-l2"><a class="reference internal" href="examples.html#channel">Channel</a></li>
<li class="toctree-l2"><a class="reference internal" href="examples.html#buffer">Buffer</a></li>
<li class="toctree-l2"><a class="reference internal" href="examples.html#filetransfer">Filetransfer</a></li>
</ul>
</li>
@ -380,6 +381,9 @@ to participate in the development of Reticulum itself.</p>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.Resource"><code class="docutils literal notranslate"><span class="pre">Resource</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.Channel.Channel"><code class="docutils literal notranslate"><span class="pre">Channel</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.MessageBase"><code class="docutils literal notranslate"><span class="pre">MessageBase</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.Buffer"><code class="docutils literal notranslate"><span class="pre">Buffer</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.RawChannelReader"><code class="docutils literal notranslate"><span class="pre">RawChannelReader</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.RawChannelWriter"><code class="docutils literal notranslate"><span class="pre">RawChannelWriter</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="reference.html#RNS.Transport"><code class="docutils literal notranslate"><span class="pre">Transport</span></code></a></li>
</ul>
</li>

Binary file not shown.

View File

@ -1525,6 +1525,174 @@ the <code class="docutils literal notranslate"><span class="pre">MSGTYPE</span><
</dd></dl>
<p id="api-buffer"><h3> Buffer </h3></p>
<dl class="py class">
<dt class="sig sig-object py" id="RNS.Buffer">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">Buffer</span></span><a class="headerlink" href="#RNS.Buffer" title="Permalink to this definition">#</a></dt>
<dd><p>Static functions for creating buffered streams that send
and receive over a <code class="docutils literal notranslate"><span class="pre">Channel</span></code>.</p>
<p>These functions use <code class="docutils literal notranslate"><span class="pre">BufferedReader</span></code>, <code class="docutils literal notranslate"><span class="pre">BufferedWriter</span></code>,
and <code class="docutils literal notranslate"><span class="pre">BufferedRWPair</span></code> to add buffering to
<code class="docutils literal notranslate"><span class="pre">RawChannelReader</span></code> and <code class="docutils literal notranslate"><span class="pre">RawChannelWriter</span></code>.</p>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Buffer.create_reader">
<em class="property"><span class="pre">static</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">create_reader</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">ready_callback</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">None</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">BufferedReader</span></span></span><a class="headerlink" href="#RNS.Buffer.create_reader" title="Permalink to this definition">#</a></dt>
<dd><p>Create a buffered reader that reads binary data sent
over a <code class="docutils literal notranslate"><span class="pre">Channel</span></code>, with an optional callback when
new data is available.</p>
<p>Callback signature: <code class="docutils literal notranslate"><span class="pre">(ready_bytes:</span> <span class="pre">int)</span> <span class="pre">-&gt;</span> <span class="pre">None</span></code></p>
<p>For more information on the reader-specific functions
of this object, see the Python documentation for
<code class="docutils literal notranslate"><span class="pre">BufferedReader</span></code></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>stream_id</strong> the local stream id to receive from</p></li>
<li><p><strong>channel</strong> the channel to receive on</p></li>
<li><p><strong>ready_callback</strong> function to call when new data is available</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>a BufferedReader object</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Buffer.create_writer">
<em class="property"><span class="pre">static</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">create_writer</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">BufferedWriter</span></span></span><a class="headerlink" href="#RNS.Buffer.create_writer" title="Permalink to this definition">#</a></dt>
<dd><p>Create a buffered writer that writes binary data over
a <code class="docutils literal notranslate"><span class="pre">Channel</span></code>.</p>
<p>For more information on the writer-specific functions
of this object, see the Python documentation for
<code class="docutils literal notranslate"><span class="pre">BufferedWriter</span></code></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>stream_id</strong> the remote stream id to send to</p></li>
<li><p><strong>channel</strong> the channel to send on</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>a BufferedWriter object</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.Buffer.create_bidirectional_buffer">
<em class="property"><span class="pre">static</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">create_bidirectional_buffer</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">receive_stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">send_stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em>, <em class="sig-param"><span class="n"><span class="pre">ready_callback</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">None</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">BufferedRWPair</span></span></span><a class="headerlink" href="#RNS.Buffer.create_bidirectional_buffer" title="Permalink to this definition">#</a></dt>
<dd><p>Create a buffered reader/writer pair that reads and
writes binary data over a <code class="docutils literal notranslate"><span class="pre">Channel</span></code>, with an
optional callback when new data is available.</p>
<p>Callback signature: <code class="docutils literal notranslate"><span class="pre">(ready_bytes:</span> <span class="pre">int)</span> <span class="pre">-&gt;</span> <span class="pre">None</span></code></p>
<p>For more information on the reader-specific functions
of this object, see the Python documentation for
<code class="docutils literal notranslate"><span class="pre">BufferedRWPair</span></code></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>receive_stream_id</strong> the local stream id to receive at</p></li>
<li><p><strong>send_stream_id</strong> the remote stream id to send to</p></li>
<li><p><strong>channel</strong> the channel to send and receive on</p></li>
<li><p><strong>ready_callback</strong> function to call when new data is available</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>a BufferedRWPair object</p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<p id="api-rawchannelreader"><h3> RawChannelReader </h3></p>
<dl class="py class">
<dt class="sig sig-object py" id="RNS.RawChannelReader">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">RawChannelReader</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelReader" title="Permalink to this definition">#</a></dt>
<dd><p>An implementation of RawIOBase that receives
binary stream data sent over a <code class="docutils literal notranslate"><span class="pre">Channel</span></code>.</p>
<blockquote>
<div><p>This class generally need not be instantiated directly.
Use <a class="reference internal" href="#RNS.Buffer.create_reader" title="RNS.Buffer.create_reader"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_reader()</span></code></a>,
<a class="reference internal" href="#RNS.Buffer.create_writer" title="RNS.Buffer.create_writer"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_writer()</span></code></a>, and
<a class="reference internal" href="#RNS.Buffer.create_bidirectional_buffer" title="RNS.Buffer.create_bidirectional_buffer"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_bidirectional_buffer()</span></code></a> functions
to create buffered streams with optional callbacks.</p>
<p>For additional information on the API of this
object, see the Python documentation for
<code class="docutils literal notranslate"><span class="pre">RawIOBase</span></code>.</p>
</div></blockquote>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.RawChannelReader.__init__">
<span class="sig-name descname"><span class="pre">__init__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelReader.__init__" title="Permalink to this definition">#</a></dt>
<dd><p>Create a raw channel reader.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>stream_id</strong> local stream id to receive at</p></li>
<li><p><strong>channel</strong> <code class="docutils literal notranslate"><span class="pre">Channel</span></code> object to receive from</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.RawChannelReader.add_ready_callback">
<span class="sig-name descname"><span class="pre">add_ready_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cb</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">None</span><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelReader.add_ready_callback" title="Permalink to this definition">#</a></dt>
<dd><p>Add a function to be called when new data is available.
The function should have the signature <code class="docutils literal notranslate"><span class="pre">(ready_bytes:</span> <span class="pre">int)</span> <span class="pre">-&gt;</span> <span class="pre">None</span></code></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>cb</strong> function to call</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.RawChannelReader.remove_ready_callback">
<span class="sig-name descname"><span class="pre">remove_ready_callback</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">cb</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">None</span><span class="p"><span class="pre">]</span></span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelReader.remove_ready_callback" title="Permalink to this definition">#</a></dt>
<dd><p>Remove a function added with <a class="reference internal" href="#RNS.RawChannelReader.add_ready_callback" title="RNS.RawChannelReader.add_ready_callback"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.RawChannelReader.add_ready_callback()</span></code></a></p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>cb</strong> function to remove</p>
</dd>
</dl>
</dd></dl>
</dd></dl>
<p id="api-rawchannelwriter"><h3> RawChannelWriter </h3></p>
<dl class="py class">
<dt class="sig sig-object py" id="RNS.RawChannelWriter">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">RNS.</span></span><span class="sig-name descname"><span class="pre">RawChannelWriter</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelWriter" title="Permalink to this definition">#</a></dt>
<dd><p>An implementation of RawIOBase that receives
binary stream data sent over a channel.</p>
<blockquote>
<div><p>This class generally need not be instantiated directly.
Use <a class="reference internal" href="#RNS.Buffer.create_reader" title="RNS.Buffer.create_reader"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_reader()</span></code></a>,
<a class="reference internal" href="#RNS.Buffer.create_writer" title="RNS.Buffer.create_writer"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_writer()</span></code></a>, and
<a class="reference internal" href="#RNS.Buffer.create_bidirectional_buffer" title="RNS.Buffer.create_bidirectional_buffer"><code class="xref py py-func docutils literal notranslate"><span class="pre">RNS.Buffer.create_bidirectional_buffer()</span></code></a> functions
to create buffered streams with optional callbacks.</p>
<p>For additional information on the API of this
object, see the Python documentation for
<code class="docutils literal notranslate"><span class="pre">RawIOBase</span></code>.</p>
</div></blockquote>
<dl class="py method">
<dt class="sig sig-object py" id="RNS.RawChannelWriter.__init__">
<span class="sig-name descname"><span class="pre">__init__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stream_id</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">int</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">channel</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference internal" href="#RNS.Channel.Channel" title="RNS.Channel.Channel"><span class="pre">Channel</span></a></span></em><span class="sig-paren">)</span><a class="headerlink" href="#RNS.RawChannelWriter.__init__" title="Permalink to this definition">#</a></dt>
<dd><p>Create a raw channel writer.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>stream_id</strong> remote stream id to sent do</p></li>
<li><p><strong>channel</strong> <code class="docutils literal notranslate"><span class="pre">Channel</span></code> object to send on</p></li>
</ul>
</dd>
</dl>
</dd></dl>
</dd></dl>
<p id="api-transport"><h3> Transport </h3></p>
<dl class="py class">
<dt class="sig sig-object py" id="RNS.Transport">
@ -1807,6 +1975,22 @@ will announce it.</p>
<li><a class="reference internal" href="#RNS.MessageBase.unpack"><code class="docutils literal notranslate"><span class="pre">unpack()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#RNS.Buffer"><code class="docutils literal notranslate"><span class="pre">Buffer</span></code></a><ul>
<li><a class="reference internal" href="#RNS.Buffer.create_reader"><code class="docutils literal notranslate"><span class="pre">create_reader()</span></code></a></li>
<li><a class="reference internal" href="#RNS.Buffer.create_writer"><code class="docutils literal notranslate"><span class="pre">create_writer()</span></code></a></li>
<li><a class="reference internal" href="#RNS.Buffer.create_bidirectional_buffer"><code class="docutils literal notranslate"><span class="pre">create_bidirectional_buffer()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#RNS.RawChannelReader"><code class="docutils literal notranslate"><span class="pre">RawChannelReader</span></code></a><ul>
<li><a class="reference internal" href="#RNS.RawChannelReader.__init__"><code class="docutils literal notranslate"><span class="pre">__init__()</span></code></a></li>
<li><a class="reference internal" href="#RNS.RawChannelReader.add_ready_callback"><code class="docutils literal notranslate"><span class="pre">add_ready_callback()</span></code></a></li>
<li><a class="reference internal" href="#RNS.RawChannelReader.remove_ready_callback"><code class="docutils literal notranslate"><span class="pre">remove_ready_callback()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#RNS.RawChannelWriter"><code class="docutils literal notranslate"><span class="pre">RawChannelWriter</span></code></a><ul>
<li><a class="reference internal" href="#RNS.RawChannelWriter.__init__"><code class="docutils literal notranslate"><span class="pre">__init__()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#RNS.Transport"><code class="docutils literal notranslate"><span class="pre">Transport</span></code></a><ul>
<li><a class="reference internal" href="#RNS.Transport.PATHFINDER_M"><code class="docutils literal notranslate"><span class="pre">PATHFINDER_M</span></code></a></li>
<li><a class="reference internal" href="#RNS.Transport.register_announce_handler"><code class="docutils literal notranslate"><span class="pre">register_announce_handler()</span></code></a></li>

File diff suppressed because one or more lines are too long