mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-15 10:20:15 +00:00
Added HTML documentation
This commit is contained in:
parent
b7e8128e06
commit
84a55f89b4
65
Documentation/html/_sources/examples.rst.txt
Normal file
65
Documentation/html/_sources/examples.rst.txt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
.. _examples-main:
|
||||||
|
|
||||||
|
********
|
||||||
|
Examples
|
||||||
|
********
|
||||||
|
A number of examples are included in the source distribution of Reticulum.
|
||||||
|
You can use these examples to learn how to write your own programs.
|
||||||
|
|
||||||
|
.. _example-minimal:
|
||||||
|
|
||||||
|
Minimal
|
||||||
|
=======
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Minimal.py>`_.
|
||||||
|
|
||||||
|
The *Minimal* example demonstrates the bare-minimum setup required to connect to
|
||||||
|
a Reticulum network from your program. In about five lines of code, you will
|
||||||
|
have the Reticulum Network Stack initialised, and ready to pass traffic in your
|
||||||
|
program.
|
||||||
|
|
||||||
|
.. _example-announce:
|
||||||
|
|
||||||
|
Announce
|
||||||
|
========
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Announce.py>`_.
|
||||||
|
|
||||||
|
The *Announce* example builds upon the previous example by exploring how to
|
||||||
|
announce a destination on the network, and how to let your program receive
|
||||||
|
notifications about announces from relevant destinations.
|
||||||
|
|
||||||
|
.. _example-broadcast:
|
||||||
|
|
||||||
|
Broadcast
|
||||||
|
=========
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Broadcast.py>`_.
|
||||||
|
|
||||||
|
The *Broadcast* example explores how to transmit plaintext broadcast messages
|
||||||
|
over the network.
|
||||||
|
|
||||||
|
.. _example-echo:
|
||||||
|
|
||||||
|
Echo
|
||||||
|
====
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Echo.py>`_.
|
||||||
|
|
||||||
|
The *Echo* example demonstrates communication between two destinations using
|
||||||
|
the Packet interface.
|
||||||
|
|
||||||
|
.. _example-link:
|
||||||
|
|
||||||
|
Link
|
||||||
|
====
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Link.py>`_.
|
||||||
|
|
||||||
|
The *Link* example explores establishing an encrypted link to a remote
|
||||||
|
destination, and passing traffic back and forth over the link.
|
||||||
|
|
||||||
|
.. _example-filetransfer:
|
||||||
|
|
||||||
|
Filetransfer
|
||||||
|
============
|
||||||
|
This example can be found at `<https://github.com/markqvist/Reticulum/blob/master/Examples/Filetransfer.py>`_.
|
||||||
|
|
||||||
|
The *Filetransfer* example implements a basic file-server program that
|
||||||
|
allow clients to connect and download files. The program uses the Resource
|
||||||
|
interface to efficiently pass files of any size over a Reticulum :ref:`Link<api-link>`.
|
72
Documentation/html/_sources/gettingstartedfast.rst.txt
Normal file
72
Documentation/html/_sources/gettingstartedfast.rst.txt
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
********************
|
||||||
|
Getting Started Fast
|
||||||
|
********************
|
||||||
|
What do we want to do? Something! When do want to do it? Right now!
|
||||||
|
|
||||||
|
The best way to get started with the Reticulum Network Stack depends on what
|
||||||
|
you want to do. This guide will outline sensible starting paths for different
|
||||||
|
scenarios.
|
||||||
|
|
||||||
|
Try Using a Reticulum-based Program
|
||||||
|
=============================================
|
||||||
|
If you simply want to try using a program built with Reticulum, you can take
|
||||||
|
a look at `Nomad Network <https://github.com/markqvist/nomadnet>`_, which
|
||||||
|
provides a basic encrypted communications suite built completely on Reticulum.
|
||||||
|
|
||||||
|
Develop a Program with Reticulum
|
||||||
|
===========================================
|
||||||
|
If you want to develop programs that use Reticulum, the easiest way to get
|
||||||
|
started is to install Reticulum via pip:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
pip3 install rns
|
||||||
|
|
||||||
|
The above command will install Reticulum and dependencies, and you will be
|
||||||
|
ready to import and use RNS in your own programs. The next step will most
|
||||||
|
likely be to look at some :ref:`Example Programs<examples-main>`.
|
||||||
|
|
||||||
|
Further information can be found in the :ref:`API Reference<api-main>`.
|
||||||
|
|
||||||
|
|
||||||
|
Participate in Reticulum Development
|
||||||
|
==============================================
|
||||||
|
If you want to participate in the development of Reticulum and associated
|
||||||
|
utilities, you'll want to get the latest source from GitHub. In that case,
|
||||||
|
don't use pip, but try this recipe:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip3 install cryptography pyserial
|
||||||
|
|
||||||
|
# Clone repository
|
||||||
|
git clone https://github.com/markqvist/Reticulum.git
|
||||||
|
|
||||||
|
# Move into Reticulum folder and symlink library to examples folder
|
||||||
|
cd Reticulum
|
||||||
|
ln -s ../RNS ./Examples/
|
||||||
|
|
||||||
|
# Run an example
|
||||||
|
python3 Examples/Echo.py -s
|
||||||
|
|
||||||
|
# Unless you've manually created a config file, Reticulum will do so now,
|
||||||
|
# and immediately exit. Make any necessary changes to the file:
|
||||||
|
nano ~/.reticulum/config
|
||||||
|
|
||||||
|
# ... and launch the example again.
|
||||||
|
python3 Examples/Echo.py -s
|
||||||
|
|
||||||
|
# You can now repeat the process on another computer,
|
||||||
|
# and run the same example with -h to get command line options.
|
||||||
|
python3 Examples/Echo.py -h
|
||||||
|
|
||||||
|
# Run the example in client mode to "ping" the server.
|
||||||
|
# Replace the hash below with the actual destination hash of your server.
|
||||||
|
python3 Examples/Echo.py 3e12fc71692f8ec47bc5
|
||||||
|
|
||||||
|
# Have a look at another example
|
||||||
|
python3 Examples/Filetransfer.py -h
|
||||||
|
|
||||||
|
When you have experimented with the basic examples, it's time to go read the
|
||||||
|
:ref:`Understanding Reticulum<understanding-main>` chapter.
|
35
Documentation/html/_sources/index.rst.txt
Normal file
35
Documentation/html/_sources/index.rst.txt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
*************************************
|
||||||
|
Reticulum Network Stack Documentation
|
||||||
|
*************************************
|
||||||
|
Welcome to the documentation for Reticulum. This document aims to provide you
|
||||||
|
with all the information you need to understand Reticulum, develop programs
|
||||||
|
using it, or to participate in the development of Reticulum itself.
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
=================
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 3
|
||||||
|
|
||||||
|
whatis
|
||||||
|
gettingstartedfast
|
||||||
|
examples
|
||||||
|
reference
|
||||||
|
understanding
|
||||||
|
|
||||||
|
|
||||||
|
Current Status
|
||||||
|
==============
|
||||||
|
Reticulum should currently be considered beta software. All core protocol features are implemented and functioning, but additions will probably occur as real-world use is explored. The API and wire-format can be considered relatively stable at the moment, but could change if warranted.
|
||||||
|
|
||||||
|
|
||||||
|
Caveat Emptor
|
||||||
|
=============
|
||||||
|
Reticulum is experimental software, and should be considered as such. While it has been built with cryptography best-practices very foremost in mind, it has not been externally security audited, and there could very well be privacy-breaking bugs. To be considered secure, Reticulum needs a very thourough security review by independt cryptographers and security researchers. If you want to help out, or help sponsor an audit, please do get in touch.
|
||||||
|
|
||||||
|
|
||||||
|
Indices and Tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
75
Documentation/html/_sources/reference.rst.txt
Normal file
75
Documentation/html/_sources/reference.rst.txt
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
.. _api-main:
|
||||||
|
|
||||||
|
*************
|
||||||
|
API Reference
|
||||||
|
*************
|
||||||
|
This reference guide lists and explains all classes exposed by the RNS API.
|
||||||
|
|
||||||
|
Classes
|
||||||
|
=========================
|
||||||
|
Communication over a Reticulum network is achieved using a set of classes exposed by RNS.
|
||||||
|
|
||||||
|
.. _api-reticulum:
|
||||||
|
|
||||||
|
Reticulum
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Reticulum
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
.. _api-identity:
|
||||||
|
|
||||||
|
Identity
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Identity
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-destination:
|
||||||
|
|
||||||
|
Destination
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Destination
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-packet:
|
||||||
|
|
||||||
|
Packet
|
||||||
|
------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Packet
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-packetreceipt:
|
||||||
|
|
||||||
|
Packet Receipt
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.PacketReceipt
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-link:
|
||||||
|
|
||||||
|
Link
|
||||||
|
----
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Link
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-resource:
|
||||||
|
|
||||||
|
Resource
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Resource
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. _api-transport:
|
||||||
|
|
||||||
|
Transport
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. autoclass:: RNS.Transport
|
||||||
|
:members:
|
503
Documentation/html/_sources/understanding.rst.txt
Normal file
503
Documentation/html/_sources/understanding.rst.txt
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
.. _understanding-main:
|
||||||
|
|
||||||
|
***********************
|
||||||
|
Understanding Reticulum
|
||||||
|
***********************
|
||||||
|
This chapter will briefly describe the overall purpose and operating principles of Reticulum, a
|
||||||
|
networking stack designed for reliable and secure communication over high-latency, low-bandwidth
|
||||||
|
links. It should give you an overview of how the stack works, and an understanding of how to
|
||||||
|
develop networked applications using Reticulum.
|
||||||
|
|
||||||
|
This document is not an exhaustive source of information on Reticulum, at least not yet. Currently,
|
||||||
|
the best place to go for such information is the Python reference implementation of Reticulum, along
|
||||||
|
with the API reference.
|
||||||
|
|
||||||
|
After reading this document, you should be well-equipped to understand how a Reticulum network
|
||||||
|
operates, what it can achieve, and how you can use it yourself. If you want to help out with the
|
||||||
|
development, this is also the place to start, since it will also provide a pretty clear overview of the
|
||||||
|
sentiments and the philosophy behind Reticulum.
|
||||||
|
|
||||||
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
|
The primary motivation for designing and implementing Reticulum has been the current lack of
|
||||||
|
reliable, functional and secure minimal-infrastructure modes of digital communication. It is my
|
||||||
|
belief that it is highly desirable to create a cheap and reliable way to set up a wide-range digital
|
||||||
|
communication network that can securely allow exchange of information between people and
|
||||||
|
machines, with no central point of authority, control, censorship or barrier to entry.
|
||||||
|
|
||||||
|
Almost all of the various networking stacks in wide use today share a common limitation, namely
|
||||||
|
that they require large amounts of coordination and trust to work. You can’t just plug in a bunch of
|
||||||
|
ethernet cables to the same switch, or turn on a number of WiFi radios, and expect such a setup to
|
||||||
|
provide a reliable platform for communication.
|
||||||
|
|
||||||
|
This need for coordination and trust inevitably leads to an environment of control, where it's very
|
||||||
|
easy for infrastructure operators or governments to control or alter traffic.
|
||||||
|
|
||||||
|
Reticulum aims to require as little coordination and trust as possible. In fact, the only
|
||||||
|
“coordination” required is to know how to get connected to a Reticulum network. Since Reticulum
|
||||||
|
is medium agnostic, this could be whatever is best suited to the situation. In some cases, this might
|
||||||
|
be 1200 baud packet radio links over VHF frequencies, in other cases it might be a microwave
|
||||||
|
network using off-the-shelf radios. At the time of release of this document, the recommended setup
|
||||||
|
is using cheap LoRa radio modules with an open source firmware (see the chapter *Reference System
|
||||||
|
Setup* ), connected to a small computer like a Raspberry Pi. As an example, the default reference
|
||||||
|
setup provides a channel capacity of 5.4 Kbps, and a usable direct node-to-node range of around 15
|
||||||
|
kilometers (indefinitely extendable by using multiple hops).
|
||||||
|
|
||||||
|
Goals
|
||||||
|
=====
|
||||||
|
|
||||||
|
To be as widely usable and easy to implement as possible, the following goals have been used to
|
||||||
|
guide the design of Reticulum:
|
||||||
|
|
||||||
|
|
||||||
|
* **Fully useable as open source software stack**
|
||||||
|
Reticulum must be implemented, and be able to run using only open source software. This is
|
||||||
|
critical to ensuring availability, security and transparency of the system.
|
||||||
|
* **Hardware layer agnosticism**
|
||||||
|
Reticulum shall be fully hardware agnostic, and should be useable over a wide range
|
||||||
|
physical networking layers, such as data radios, serial lines, modems, handheld transceivers,
|
||||||
|
wired ethernet, wifi, or anything else that can carry a digital data stream. Hardware made for
|
||||||
|
dedicated Reticulum use shall be as cheap as possible and use off-the-shelf components, so
|
||||||
|
it can be easily replicated.
|
||||||
|
* **Very low bandwidth requirements**
|
||||||
|
Reticulum should be able to function reliably over links with a data capacity as low as *1,*
|
||||||
|
*bps*.
|
||||||
|
* **Encryption by default**
|
||||||
|
Reticulum must use encryption by default where possible and applicable.
|
||||||
|
* **Unlicensed use**
|
||||||
|
Reticulum shall be functional over physical communication mediums that do not require any
|
||||||
|
form of license to use. Reticulum must be designed in a way, so it is usable over ISM radio
|
||||||
|
frequency bands, and can provide functional long distance links in such conditions.
|
||||||
|
* **Supplied software**
|
||||||
|
Apart from the core networking stack and API, that allows any developer to build
|
||||||
|
applications with Reticulum, a basic communication suite using Reticulum must be
|
||||||
|
implemented and released at the same time as Reticulum itself. This shall serve both as a
|
||||||
|
functional communication suite, and as an example and learning resource to others wishing
|
||||||
|
to build applications with Reticulum.
|
||||||
|
* **Ease of use**
|
||||||
|
The reference implementation of Reticulum is written in Python, to make it very easy to use
|
||||||
|
and understand. Any programmer with only basic experience should be able to use
|
||||||
|
Reticulum in their own applications.
|
||||||
|
* **Low cost**
|
||||||
|
It shall be as cheap as possible to deploy a communication system based on Reticulum. This
|
||||||
|
should be achieved by using cheap off-the-shelf hardware that potential users might already
|
||||||
|
own. The cost of setting up a functioning node should be less than $100 even if all parts
|
||||||
|
needs to be purchased.
|
||||||
|
|
||||||
|
Introduction & Basic Functionality
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Reticulum is a networking stack suited for high-latency, low-bandwidth links. Reticulum is at it’s
|
||||||
|
core *message oriented* , but can provide connection oriented sessions. It is suited for both local
|
||||||
|
point-to-point or point-to-multipoint scenarios where alle nodes are within range of each other, as
|
||||||
|
well as scenarios where packets need to be transported over multiple hops to reach the recipient.
|
||||||
|
|
||||||
|
Reticulum does away with the idea of addresses and ports known from IP, TCP and UDP. Instead
|
||||||
|
Reticulum uses the singular concept of *destinations*. Any application using Reticulum as it’s
|
||||||
|
networking stack will need to create one or more destinations to receive data, and know the
|
||||||
|
destinations it needs to send data to.
|
||||||
|
|
||||||
|
Reticulum encrypts all data by default using public-key cryptography. Any message sent to a
|
||||||
|
destination is encrypted with that destinations public key. Reticulum also offers symmetric key
|
||||||
|
encryption for group-oriented communications, as well as unencrypted packets for broadcast
|
||||||
|
purposes, or situations where you need the communication to be in plain text. The multi-hop
|
||||||
|
transport, coordination, verification and reliability layers are fully autonomous and based on public
|
||||||
|
key cryptography.
|
||||||
|
|
||||||
|
Reticulum can connect to a variety of interfaces such as radio modems, data radios and serial ports,
|
||||||
|
and offers the possibility to easily tunnel Reticulum traffic over IP links such as the Internet or
|
||||||
|
private IP networks.
|
||||||
|
|
||||||
|
Destinations
|
||||||
|
------------
|
||||||
|
|
||||||
|
To receive and send data with the Reticulum stack, an application needs to create one or more
|
||||||
|
destinations. Reticulum uses three different basic destination types, and one special:
|
||||||
|
|
||||||
|
|
||||||
|
* **Single**
|
||||||
|
The *single* destination type defines a public-key encrypted destination. Any data sent to this
|
||||||
|
destination will be encrypted with the destination’s public key, and will only be readable by
|
||||||
|
the creator of the destination.
|
||||||
|
* **Group**
|
||||||
|
The *group* destination type defines a symmetrically encrypted destination. Data sent to this
|
||||||
|
destination will be encrypted with a symmetric key, and will be readable by anyone in
|
||||||
|
possession of the key. The *group* destination can be used just as well by only two peers, as it
|
||||||
|
can by many.
|
||||||
|
* **Plain**
|
||||||
|
A *plain* destination type is unencrypted, and suited for traffic that should be broadcast to a
|
||||||
|
number of users, or should be readable by anyone.
|
||||||
|
* **Link**
|
||||||
|
A *link* is a special destination type, that serves as an abstract channel between two *single*
|
||||||
|
destinations, directly connected or over multiple hops. The *link* also offers reliability and
|
||||||
|
more efficient encryption, and as such is useful even when nodes are directly connected.
|
||||||
|
|
||||||
|
Destination Naming
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Destinations are created and named in an easy to understand dotted notation of *aspects* , and
|
||||||
|
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
||||||
|
top level aspect should always be the a unique identifier for the application using the destination.
|
||||||
|
The next levels of aspects can be defined in any way by the creator of the application. For example,
|
||||||
|
a destination for a messaging application could be made up of the application name and a username,
|
||||||
|
and look like this:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
name: simplemessenger.someuser hash: 2a7ddfab5213f916dea
|
||||||
|
|
||||||
|
For the *single* destination, Reticulum will automatically append the associated public key as a
|
||||||
|
destination aspect before hashing. This is done to ensure only the correct destination is reached,
|
||||||
|
since anyone can listen to any destination name. Appending the public key ensures that a given
|
||||||
|
packet is only directed at the destination that holds the corresponding private key to decrypt the
|
||||||
|
packet. It is important to understand that anyone can use the destination name
|
||||||
|
*simplemessenger.myusername* , but each person that does so will still have a different destination
|
||||||
|
hash, because their public keys will differ. In actual use of *single* destination naming, it is advisable
|
||||||
|
not to use any uniquely identifying features in aspect naming, though. In the simple messenger
|
||||||
|
example, when using *single* destinations, we would instead use a destination naming scheme such
|
||||||
|
as *simplemessenger.user* where appending the public key expands the destination into a uniquely
|
||||||
|
identifying one.
|
||||||
|
|
||||||
|
To recap, the destination types should be used in the following situations:
|
||||||
|
|
||||||
|
|
||||||
|
* **Single**
|
||||||
|
When private communication between two endpoints is needed. Supports routing.
|
||||||
|
* **Group**
|
||||||
|
When private communication between two or more endpoints is needed. More efficient in
|
||||||
|
data usage than *single* destinations. Supports routing indirectly, but must first be established
|
||||||
|
through a *single* destination.
|
||||||
|
* **Plain**
|
||||||
|
When plain-text communication is desirable, for example when broadcasting information.
|
||||||
|
|
||||||
|
To communicate with a *single* destination, you need to know it’s public key. Any method for
|
||||||
|
obtaining the public key is valid, but Reticulum includes a simple mechanism for making other
|
||||||
|
nodes aware of your destinations public key, called the *announce*.
|
||||||
|
|
||||||
|
Note that this information could be shared and verified in many other ways, and that it is therefore
|
||||||
|
not required to use the announce functionality, although it is by far the easiest, and should probably
|
||||||
|
be used if you are not confident in how to verify public keys and signatures manually.
|
||||||
|
|
||||||
|
Public Key Announcements
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
An *announce* will send a special packet over any configured interfaces, containing all needed
|
||||||
|
information about the destination hash and public key, and can also contain some additional,
|
||||||
|
application specific data. The entire packet is signed by the sender to ensure authenticity. It is not
|
||||||
|
required to use the announce functionality, but in many cases it will be the simplest way to share
|
||||||
|
public keys on the network. As an example, an announce in a simple messenger application might
|
||||||
|
contain the following information:
|
||||||
|
|
||||||
|
|
||||||
|
* The announcers destination hash
|
||||||
|
* The announcers public key
|
||||||
|
* Application specific data, in this case the users nickname and availability status
|
||||||
|
* A random blob, making each new announce unique
|
||||||
|
* A signature of the above information, verifying authenticity
|
||||||
|
|
||||||
|
With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
||||||
|
destination to securely communicate with that destination. You might have noticed that there is one
|
||||||
|
piece of information lacking to reconstruct full knowledge of the announced destination, and that is
|
||||||
|
the aspect names of the destination. These are intentionally left out to save bandwidth, since they
|
||||||
|
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
||||||
|
included in the application specific data part that will allow the receiver to infer the naming.
|
||||||
|
|
||||||
|
It is important to note that announcements will be forwarded throughout the network according to a
|
||||||
|
certain pattern. This will be detailed later. Seeing how *single* destinations are always tied to a
|
||||||
|
private/public key pair leads us to the next topic.
|
||||||
|
|
||||||
|
Identities
|
||||||
|
----------
|
||||||
|
|
||||||
|
In Reticulum, an *identity* does not necessarily represent a personal identity, but is an abstraction that
|
||||||
|
can represent any kind of *verified entity*. This could very well be a person, but it could also be the
|
||||||
|
control interface of a machine, a program, robot, computer, sensor or something else entirely. In
|
||||||
|
general, any kind of agent that can act, or be acted upon, or store or manipulate information, can be
|
||||||
|
represented as an identity.
|
||||||
|
|
||||||
|
As we have seen, a *single* destination will always have an *identity* tied to it, but not *plain* or *group*
|
||||||
|
destinations. Destinations and identities share a multilateral connection. You can create a
|
||||||
|
destination, and if it is not connected to an identity upon creation, it will just create a new one to use
|
||||||
|
automatically. This may be desirable in some situations, but often you will probably want to create
|
||||||
|
the identity first, and then link it to created destinations.
|
||||||
|
|
||||||
|
Building upon the simple messenger example, we could use an identity to represent the user of the
|
||||||
|
application. Destinations created will then be linked to this identity to allow communication to
|
||||||
|
reach the user. In such a case it is of great importance to store the user’s identity securely and
|
||||||
|
privately.
|
||||||
|
|
||||||
|
Getting Further
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The above functions and principles form the core of Reticulum, and would suffice to create
|
||||||
|
functional networked applications in local clusters, for example over radio links where all interested
|
||||||
|
nodes can hear each other. But to be truly useful, we need a way to go further. In the next chapter,
|
||||||
|
two concepts that allow this will be introduced, *paths* and *resources*.
|
||||||
|
|
||||||
|
Reticulum Transport
|
||||||
|
===================
|
||||||
|
|
||||||
|
I have purposefully avoided the term routing until now, and will continue to do so, because the
|
||||||
|
current methods of routing used in IP based networks are fundamentally incompatible for the link
|
||||||
|
types that Reticulum was designed to handle. These routing methodologies assume trust at the
|
||||||
|
physical layer. Since Reticulum is designed to run over open radio spectrum, no such trust exists.
|
||||||
|
Furthermore, existing routing protocols like BGP or OSPF carry too much overhead to be
|
||||||
|
practically useable over bandwidth-limited, high-latency links.
|
||||||
|
|
||||||
|
To overcome such challenges, Reticulum’s *Transport* system uses public-key cryptography to
|
||||||
|
implement the concept of *paths* that allow discovery of how to get information to a certain
|
||||||
|
destination, and *resources* that help alleviate congestion and make reliable communication more
|
||||||
|
efficient and less bandwidth-hungry.
|
||||||
|
|
||||||
|
Threading a Path
|
||||||
|
----------------
|
||||||
|
|
||||||
|
In networks with changing topology and trustless connectivity, nodes need a way to establish
|
||||||
|
*verified connectivity* with each other. To do this, the following process is employed:
|
||||||
|
|
||||||
|
|
||||||
|
* First, the node that wishes to establish connectivity will send out a special packet, that
|
||||||
|
traverses the network and locates the desired destination. Along the way, the nodes that
|
||||||
|
forward the packet will take note of this *link request*.
|
||||||
|
* Second, if the destination accepts the *link request* , it will send back a packet that proves the
|
||||||
|
authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
||||||
|
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
||||||
|
accept the validity of the *link* throughout the network.
|
||||||
|
* When the validity of the *link* has been accepted by forwarding nodes, these nodes will
|
||||||
|
remember the *link* , and it can subsequently be used by referring to a hash representing it.
|
||||||
|
* As a part of the *link request* , a Diffie-Hellman key exchange takes place, that sets up an
|
||||||
|
efficient symmetrically encrypted tunnel between the two nodes, using elliptic curve
|
||||||
|
cryptography. As such, this mode of communication is preferred, even for situations when
|
||||||
|
nodes can directly communicate, when the amount of data to be exchanged numbers in the
|
||||||
|
tens of packets.
|
||||||
|
* When a *link* has been set up, it automatically provides message receipt functionality, so the
|
||||||
|
sending node can obtain verified confirmation that the information reached the intended
|
||||||
|
recipient.
|
||||||
|
|
||||||
|
In a moment, we will discuss the specifics of how this methodology is implemented, but let’s first
|
||||||
|
recap what purposes this serves. We first ensure that the node answering our request is actually the
|
||||||
|
one we want to communicate with, and not a malicious actor pretending to be so. At the same time
|
||||||
|
we establish an efficient encrypted channel. The setup of this is relatively cheap in terms of
|
||||||
|
bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will also
|
||||||
|
|
||||||
|
rotate encryption keys (keys can also be rotated over an existing path), but the link can also be kept
|
||||||
|
alive for longer periods of time, if this is more suitable to the application. The amount of bandwidth
|
||||||
|
used on keeping a link open is practically negligible. The procedure also inserts the *link id* , a hash
|
||||||
|
calculated from the link request packet, into the memory of forwarding nodes, which means that the
|
||||||
|
communicating nodes can thereafter reach each other simply by referring to this *link id*.
|
||||||
|
|
||||||
|
**Step 1, pathfinding**
|
||||||
|
|
||||||
|
The pathfinding method builds on the *announce* functionality discussed earlier. When an announce
|
||||||
|
is sent out by a node, it will be forwarded by any node receiving it, but according to some specific
|
||||||
|
rules:
|
||||||
|
|
||||||
|
|
||||||
|
* If this announce has already been received before, ignore it.
|
||||||
|
* Record into a table which node the announce was received from, and how many times in
|
||||||
|
total it has been retransmitted to get here.
|
||||||
|
* If the announce has been retransmitted *m+1* times, it will not be forwarded. By default, *m* is
|
||||||
|
set to 18.
|
||||||
|
* The announce will be assigned a delay *d* = *ch* seconds, where *c* is a decay constant, by
|
||||||
|
default 2, and *h* is the amount of times this packet has already been forwarded.
|
||||||
|
* The packet will be given a priority *p = 1/d*.
|
||||||
|
* If at least *d* seconds has passed since the announce was received, and no other packets with a
|
||||||
|
priority higher than *p* are waiting in the queue (see Packet Prioritisation), and the channel is
|
||||||
|
not utilized by other traffic, the announce will be forwarded.
|
||||||
|
* If no other nodes are heard retransmitting the announce with a greater hop count than when
|
||||||
|
it left this node, transmitting it will be retried *r* times. By default, *r* is set to 2. Retries follow
|
||||||
|
same rules as above, with the exception that it must wait for at least *d = ch+1 + t* seconds, ie.,
|
||||||
|
the amount of time it would take the next node to retransmit the packet. By default, *t* is set to
|
||||||
|
10.
|
||||||
|
* If a newer announce from the same destination arrives, while an identical one is already in
|
||||||
|
the queue, the newest announce is discarded. If the newest announce contains different
|
||||||
|
application specific data, it will replace the old announce, but will use *d* and *p* of the old
|
||||||
|
announce.
|
||||||
|
|
||||||
|
Once an announce has reached a node in the network, any other node in direct contact with that
|
||||||
|
node will be able to reach the destination the announce originated from, simply by sending a packet
|
||||||
|
addressed to that destination. Any node with knowledge of the announce will be able to direct the
|
||||||
|
packet towards the destination by looking up the next node with the shortest amount of hops to the
|
||||||
|
destination. The specifics of this process is detailed in *Path Calculation*.
|
||||||
|
|
||||||
|
According to these rules and default constants, an announce will propagate throughout the network
|
||||||
|
in a predictable way. In an example network utilising the default constants, and with an average link
|
||||||
|
|
||||||
|
distance of *Lavg =* 15 kilometers, an announce will be able to propagate outwards to a radius of 180
|
||||||
|
kilometers in 34 minutes, and a *maximum announce radius* of 270 kilometers in approximately 3
|
||||||
|
days. Methods for overcoming the distance limitation of *m * Lavg* will be introduced later in this
|
||||||
|
chapter.
|
||||||
|
|
||||||
|
**Step 2, link establishment**
|
||||||
|
|
||||||
|
After seeing how the conditions for finding a path through the network are created, we will now
|
||||||
|
explore how two nodes can establish reliable communications over multiple hops. The *link* in
|
||||||
|
Reticulum terminology should not be viewed as a direct node-to-node link on the physical layer, but
|
||||||
|
as an abstract channel, that can be open for any amount of time, and can span an arbitrary number
|
||||||
|
of hops, where information will be exchanged between two nodes.
|
||||||
|
|
||||||
|
|
||||||
|
* When a node in the network wants to establish verified connectivity with another node, it
|
||||||
|
will create a *link request* packet, and broadcast it.
|
||||||
|
* The *link request* packet contains the destination hash *Hd* , and an asymmetrically encrypted
|
||||||
|
part containing the following data: The source hash *Hs* , a symmetric key *Lk* , a truncated
|
||||||
|
hash of a random number *Hr* , and a signature *S* of the plaintext values of *Hd* , *Hs* , *Lk* and *Hr*.
|
||||||
|
* The broadcasted packet will be directed through the network according to the rules laid out
|
||||||
|
previously.
|
||||||
|
* Any node that forwards the link request will store a *link id* in it’s *link table* , along with the
|
||||||
|
amount of hops the packet had taken when received. The link id is a hash of the entire link
|
||||||
|
request packet. If the path is not *proven* within some set amount of time, the entry will be
|
||||||
|
dropped from the table again.
|
||||||
|
* When the destination receives the link request packet, it will decide whether to accept the
|
||||||
|
request. If it is accepted, it will create a special packet called a *proof*. A *proof* is a simple
|
||||||
|
construct, consisting of a truncated hash of the message that needs to be proven, and a
|
||||||
|
signature (made by the destination’s private key) of this hash. This *proof* effectively verifies
|
||||||
|
that the intended recipient got the packet, and also serves to verify the discovered path
|
||||||
|
through the network. Since the *proof* hash matches the *path id* in the intermediary nodes’
|
||||||
|
*path tables* , the intermediary nodes can forward the proof all the way back to the source.
|
||||||
|
* When the source receives the *proof* , it will know unequivocally that a verified path has been
|
||||||
|
established to the destination, and that information can now be exchanged reliably and
|
||||||
|
securely.
|
||||||
|
|
||||||
|
It’s important to note that this methodology ensures that the source of the request does not need to
|
||||||
|
reveal any identifying information. Only the intended destination will know “who called”, so to
|
||||||
|
speak. This is a huge improvement to protocols like IP, where by design, you have to reveal your
|
||||||
|
own address to communicate with anyone, unless you jump through a lot of hoops to hide it.
|
||||||
|
Reticulum offers initiator anonymity by design.
|
||||||
|
|
||||||
|
When using *links* , Reticulum will automatically verify anything sent over the link, and also
|
||||||
|
automates retransmissions if parts of a message was lost along the way. Due to the caching features
|
||||||
|
of Reticulum, such a retransmission does not need to travel the entire length of an established path.
|
||||||
|
If a packet is lost on the 8th hop of a 12 hop path, it can be fetched from the last hop that received it
|
||||||
|
reliably.
|
||||||
|
|
||||||
|
Crossing Continents
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
When a packet needs to travel farther than local network topology knowledge stretches, a system of
|
||||||
|
geographical or topological hinting is used to direct the packet towards a network segment with
|
||||||
|
direct knowledge of the intended destination. This functionality is currently left out of the protocol
|
||||||
|
for simplicity of testing other parts, but will be activated in a future release. For more information
|
||||||
|
on when, refer to the roadmap on the website.
|
||||||
|
|
||||||
|
Resourceful Memory
|
||||||
|
------------------
|
||||||
|
|
||||||
|
In traditional networks, large amounts of data is rapidly exchanged with very low latency. Links of
|
||||||
|
several thousand kilometers will often only have round-trip latency in the tens of milliseconds, and
|
||||||
|
as such, traditional protocols are often designed to not store any transmitted data at intermediary
|
||||||
|
hops. If a transmission error occurs, the sending node will simply notice the lack of a packet
|
||||||
|
acknowledgement, and retransmit the packet all the way, until it hears back from the receiver that it
|
||||||
|
got the intended data.
|
||||||
|
|
||||||
|
In bandwidth-limited and high-latency conditions, such behaviour quickly causes congestion on the
|
||||||
|
network, and communications that span many hops become exceedingly expensive in terms of
|
||||||
|
bandwidth usage, due to the higher risk of some packets failing.
|
||||||
|
|
||||||
|
Reticulum alleviates this in part with it’s *path* discovery methodology, and in part by implementing
|
||||||
|
*resource* caching at all nodes that can support it. Network operation can be made much more
|
||||||
|
efficient by caching everything for a period of time, and given the availability of cheap memory and
|
||||||
|
storage, this is a very welcome tradeoff. A gigabyte of memory can store millions of Reticulum
|
||||||
|
packets, and since everything is encrypted by default, the storing poses very little privacy risk.
|
||||||
|
|
||||||
|
In a Reticulum network, any node that is able to do so, should cache as many packets as it’s
|
||||||
|
memory will allow for. When a packet is received, a timestamp and a hash of the packet is stored
|
||||||
|
along with the full packet itself, and it will be kept in storage until the allocated cache storage is
|
||||||
|
full, whereupon the packet that was last accessed in the cache will be deleted. If a packet is accessed
|
||||||
|
from the cache, it’s timestamp will be updated to the current time, to ensure that packets that are
|
||||||
|
used stay in the cache, and packets that are not used are dropped from memory.
|
||||||
|
|
||||||
|
Some packet types are stored in separate caching tables, that allow easier lookup for other nodes.
|
||||||
|
For example, an announce is stored in a way, that allows other nodes to request the public key for a
|
||||||
|
certain destination, and as such the network as a whole operates as a distributed key ledger.
|
||||||
|
|
||||||
|
For more details on how the caching works and is used, see the reference implementation source
|
||||||
|
code.
|
||||||
|
|
||||||
|
Reference System Setup
|
||||||
|
======================
|
||||||
|
|
||||||
|
This section will detail the recommended *Reference System Setup* for Reticulum. It is important to
|
||||||
|
note that Reticulum is designed to be usable over more or less any medium that allows you to send
|
||||||
|
and receive data in a digital form, and satisfies some very low minimum requirements. The
|
||||||
|
communication channel must support at least half-duplex operation, and provide an average
|
||||||
|
throughput of around 1000 bits per second, and supports a physical layer MTU of 500 bytes. The
|
||||||
|
Reticulum software should be able to run on more or less any hardware that can provide a Python 3.x
|
||||||
|
runtime environment.
|
||||||
|
|
||||||
|
That being said, the reference setup has been outlined to provide a common platform for anyone
|
||||||
|
who wants to help in the development of Reticulum, and for everyone who wants to know a
|
||||||
|
recommended setup to get started. A reference system consists of three parts:
|
||||||
|
|
||||||
|
* **A channel access device**
|
||||||
|
Or *CAD* , in short, provides access to the physical medium whereupon the communication
|
||||||
|
takes place, for example a radio with an integrated modem. A setup with a separate modem
|
||||||
|
connected to a radio would also be termed a “channel access device”.
|
||||||
|
* **A host device**
|
||||||
|
Some sort of computing device that can run the necessary software, communicates with the
|
||||||
|
channel access device, and provides user interaction.
|
||||||
|
* **A software stack**
|
||||||
|
The software implementing the Reticulum protocol and applications using it.
|
||||||
|
|
||||||
|
The reference setup can be considered a relatively stable platform to develop on, and also to start
|
||||||
|
building networks on. While details of the implementation might change at the current stage of
|
||||||
|
development, it is the goal to maintain hardware compatibility for as long as entirely possible, and
|
||||||
|
the current reference setup has been determined to provide a functional platform for many years
|
||||||
|
into the future. The current Reference System Setup is as follows:
|
||||||
|
|
||||||
|
|
||||||
|
* **Channel Access Device**
|
||||||
|
A data radio consisting of a LoRa radio module, and a microcontroller with open source
|
||||||
|
firmware, that can connect to host devices via USB. It operates in either the 430, 868 or 900
|
||||||
|
MHz frequency bands. More details on the exact parts and how to get/make one can be
|
||||||
|
found on the website.
|
||||||
|
* **Host device**
|
||||||
|
Any computer device running Linux and Python. A Raspberry Pi with Raspbian is
|
||||||
|
recommended.
|
||||||
|
* **Software stack**
|
||||||
|
The current Reference Implementation Release of Reticulum, running on a Debian based
|
||||||
|
operating system.
|
||||||
|
|
||||||
|
It is very important to note, that the reference channel access device **does not** use the LoRaWAN
|
||||||
|
standard, but uses a custom MAC layer on top of the plain LoRa modulation! As such, you will
|
||||||
|
need a plain LoRa radio module connected to an MCU with the correct Reticulum firmware. Full
|
||||||
|
details on how to get or make such a device is available on the website.
|
||||||
|
|
||||||
|
With the current reference setup, it should be possible to get on a Reticulum network for around 70$
|
||||||
|
even if you have none of the hardware already.
|
||||||
|
|
||||||
|
Protocol Specifics
|
||||||
|
==================
|
||||||
|
|
||||||
|
This chapter will detail protocol specific information that is essential to the implementation of
|
||||||
|
Reticulum, but non critical in understanding how the protocol works on a general level. It should be
|
||||||
|
treated more as a reference than as essential reading.
|
||||||
|
|
||||||
|
Node Types
|
||||||
|
----------
|
||||||
|
|
||||||
|
Currently Reticulum defines two node types, the *Station* and the *Peer*. A node is a *station* if it fixed
|
||||||
|
in one place, and if it is intended to be kept online at all times. Otherwise the node is a *peer*. This
|
||||||
|
distinction is made by the user configuring the node, and is used to determine what nodes on the
|
||||||
|
network will help forward traffic, and what nodes rely on other nodes for connectivity.
|
||||||
|
|
||||||
|
Packet Prioritisation
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
*The packet prioritisation algorithms are subject to rapid change at the moment, and for now, they
|
||||||
|
are not documented here. See the reference implementation for more info on how this functionality
|
||||||
|
works.*
|
||||||
|
|
||||||
|
Path Calculation
|
||||||
|
----------------
|
||||||
|
|
||||||
|
*The path calculation algorithms are subject to rapid change at the moment, and for now, they are
|
||||||
|
not documented here. See the reference implementation for more info on how this functionality
|
||||||
|
works.*
|
||||||
|
|
||||||
|
Binary Packet Format
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
*The binary packet format is subject to rapid change at the moment, and for now, it is not
|
||||||
|
documented here. See the reference implementation for the specific details on this topic.*
|
84
Documentation/html/_sources/whatis.rst.txt
Normal file
84
Documentation/html/_sources/whatis.rst.txt
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
******************
|
||||||
|
What is Reticulum?
|
||||||
|
******************
|
||||||
|
|
||||||
|
Reticulum is a cryptography-based networking stack for wide-area networks built on readily available hardware, and can operate even with very high latency and extremely low bandwidth. Reticulum allows you to build very wide-area networks with off-the-shelf tools, and offers end-to-end encryption, autoconfiguring cryptographically backed multi-hop transport, efficient addressing, unforgeable packet acknowledgements and more.
|
||||||
|
|
||||||
|
Reticulum is a complete networking stack, and does not use IP or higher layers, although it is easy to utilise IP (with TCP or UDP) as the underlying carrier for Reticulum. It is therefore trivial to tunnel Reticulum over the Internet or private IP networks. Reticulum is built directly on cryptographic principles, allowing resilience and stable functionality in open and trustless networks.
|
||||||
|
|
||||||
|
No kernel modules or drivers are required. Reticulum runs completely in userland, and can run on practically any system that runs Python 3.
|
||||||
|
|
||||||
|
|
||||||
|
What does Reticulum Offer?
|
||||||
|
==========================
|
||||||
|
* Coordination-less globally unique adressing and identification
|
||||||
|
|
||||||
|
* Fully self-configuring multi-hop routing
|
||||||
|
|
||||||
|
* Asymmetric RSA encryption and signatures as basis for all communication
|
||||||
|
|
||||||
|
* Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on the SECP256R1 curve)
|
||||||
|
|
||||||
|
* Reticulum uses the Fernet specification for encryption on links and to group destinations
|
||||||
|
|
||||||
|
* AES-128 in CBC mode with PKCS7 padding
|
||||||
|
|
||||||
|
* HMAC using SHA256 for authentication
|
||||||
|
|
||||||
|
* IVs are generated through os.urandom()
|
||||||
|
|
||||||
|
* Unforgeable packet delivery confirmations
|
||||||
|
|
||||||
|
* A variety of supported interface types
|
||||||
|
|
||||||
|
* An intuitive and easy-to-use API
|
||||||
|
|
||||||
|
* Reliable and efficient transfer of arbritrary amounts of data
|
||||||
|
|
||||||
|
* Reticulum can handle a few bytes of data or files of many gigabytes
|
||||||
|
|
||||||
|
* Sequencing, transfer coordination and checksumming is automatic
|
||||||
|
|
||||||
|
* The API is very easy to use, and provides transfer progress
|
||||||
|
|
||||||
|
|
||||||
|
Where can Reticulum be Used?
|
||||||
|
============================
|
||||||
|
On practically any hardware that can support at least a half-duplex channel
|
||||||
|
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
||||||
|
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
||||||
|
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
||||||
|
of the types of interfaces Reticulum was designed for.
|
||||||
|
|
||||||
|
An open-source LoRa-based interface called RNode has been designed
|
||||||
|
specifically for use with Reticulum. It is possible to build yourself, or it
|
||||||
|
can be purchased as a complete transceiver that just needs a USB connection
|
||||||
|
to the host.
|
||||||
|
|
||||||
|
Reticulum can also be encapsulated over existing IP networks, so there's
|
||||||
|
nothing stopping you from using it over wired ethernet or your local WiFi
|
||||||
|
network, where it'll work just as well. In fact, one of the strengths of
|
||||||
|
Reticulum is how easily it allows you to connect different mediums into a
|
||||||
|
self-configuring, resilient and encrypted mesh.
|
||||||
|
|
||||||
|
As an example, it's possible to set up a Raspberry Pi connected to both a
|
||||||
|
LoRa radio, a packet radio TNC and a WiFi network. Once the interfaces are
|
||||||
|
configured, Reticulum will take care of the rest, and any device on the WiFi
|
||||||
|
network can communicate with nodes on the LoRa and packet radio sides of the
|
||||||
|
network, and vice versa.
|
||||||
|
|
||||||
|
Supported Interface Types and Devices
|
||||||
|
=====================================
|
||||||
|
Reticulum implements a range of generalised interface types that covers most of the communications hardware that Reticulum can run over. If your hardware is not supported, it's relatively simple to implement an interface class. Currently, the following interfaces are supported:
|
||||||
|
|
||||||
|
* Any ethernet device
|
||||||
|
|
||||||
|
* LoRa using `RNode <https://unsigned.io/rnode>`_
|
||||||
|
|
||||||
|
* Packet Radio TNCs, such as `OpenModem <https://unsigned.io/openmodem>`_
|
||||||
|
|
||||||
|
* Any device with a serial port
|
||||||
|
|
||||||
|
* TCP over IP networks
|
||||||
|
|
||||||
|
* UDP over IP networks
|
904
Documentation/html/_static/basic.css
Normal file
904
Documentation/html/_static/basic.css
Normal file
@ -0,0 +1,904 @@
|
|||||||
|
/*
|
||||||
|
* basic.css
|
||||||
|
* ~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- basic theme.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -- main layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.clearer {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section::after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- relbar ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related h3 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li.right {
|
||||||
|
float: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebar --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 10px 5px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
float: left;
|
||||||
|
width: 230px;
|
||||||
|
margin-left: -100%;
|
||||||
|
font-size: 90%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap : break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul,
|
||||||
|
div.sphinxsidebar ul.want-points {
|
||||||
|
margin-left: 20px;
|
||||||
|
list-style: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar form {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #98dbcc;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox form.search {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="text"] {
|
||||||
|
float: left;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
border-left: none;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- search page ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
ul.search {
|
||||||
|
margin: 10px 0 0 20px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li {
|
||||||
|
padding: 5px 0 5px 20px;
|
||||||
|
background-image: url(file.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li p.context {
|
||||||
|
color: #888;
|
||||||
|
margin: 2px 0 0 30px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.keywordmatches li.goodmatch a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- index page ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
table.contentstable {
|
||||||
|
width: 90%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.contentstable p.biglink {
|
||||||
|
line-height: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.biglink {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.linkdescr {
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general index --------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.indextable {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable td {
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable > tbody > tr > td > ul {
|
||||||
|
padding-left: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.pcap {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.cap {
|
||||||
|
margin-top: 10px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.toggler {
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.modindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.genindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- domain module index --------------------------------------------------- */
|
||||||
|
|
||||||
|
table.modindextable td {
|
||||||
|
padding: 2px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general body styles --------------------------------------------------- */
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
min-width: 450px;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.brackets:before,
|
||||||
|
span.brackets > a:before{
|
||||||
|
content: "[";
|
||||||
|
}
|
||||||
|
|
||||||
|
a.brackets:after,
|
||||||
|
span.brackets > a:after {
|
||||||
|
content: "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover > a.headerlink,
|
||||||
|
h2:hover > a.headerlink,
|
||||||
|
h3:hover > a.headerlink,
|
||||||
|
h4:hover > a.headerlink,
|
||||||
|
h5:hover > a.headerlink,
|
||||||
|
h6:hover > a.headerlink,
|
||||||
|
dt:hover > a.headerlink,
|
||||||
|
caption:hover > a.headerlink,
|
||||||
|
p.caption:hover > a.headerlink,
|
||||||
|
div.code-block-caption:hover > a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.caption {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rubric {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||||
|
clear: left;
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-default, figure.align-default, .figure.align-default {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-default {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebars -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar,
|
||||||
|
aside.sidebar {
|
||||||
|
margin: 0 0 0.5em 1em;
|
||||||
|
border: 1px solid #ddb;
|
||||||
|
padding: 7px;
|
||||||
|
background-color: #ffe;
|
||||||
|
width: 40%;
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition, div.topic, blockquote {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- topics ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 7px;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- admonitions ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
margin: 0px 10px 5px 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.centered {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar > :last-child,
|
||||||
|
aside.sidebar > :last-child,
|
||||||
|
div.topic > :last-child,
|
||||||
|
div.admonition > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sidebar::after,
|
||||||
|
aside.sidebar::after,
|
||||||
|
div.topic::after,
|
||||||
|
div.admonition::after,
|
||||||
|
blockquote::after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- tables ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.align-center {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.align-default {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils td, table.docutils th {
|
||||||
|
padding: 1px 8px 1px 5px;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote td, table.footnote th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
th > :first-child,
|
||||||
|
td > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th > :last-child,
|
||||||
|
td > :last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- figures --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.figure, figure {
|
||||||
|
margin: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption, figcaption {
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-number,
|
||||||
|
figcaption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-text,
|
||||||
|
figcaption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- field list styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
table.field-list td, table.field-list th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-name {
|
||||||
|
-moz-hyphens: manual;
|
||||||
|
-ms-hyphens: manual;
|
||||||
|
-webkit-hyphens: manual;
|
||||||
|
hyphens: manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- hlist styles ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.hlist {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.hlist td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- object description styles --------------------------------------------- */
|
||||||
|
|
||||||
|
.sig {
|
||||||
|
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-name, code.descname {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-name {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.descname {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-prename, code.descclassname {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optional {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-paren {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-param.n {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* C++ specific styling */
|
||||||
|
|
||||||
|
.sig-inline.c-texpr,
|
||||||
|
.sig-inline.cpp-texpr {
|
||||||
|
font-family: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .k, .sig.c .kt,
|
||||||
|
.sig.cpp .k, .sig.cpp .kt {
|
||||||
|
color: #0033B3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .m,
|
||||||
|
.sig.cpp .m {
|
||||||
|
color: #1750EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .s, .sig.c .sc,
|
||||||
|
.sig.cpp .s, .sig.cpp .sc {
|
||||||
|
color: #067D17;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -- other body styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(li) > ol > li:first-child > :first-child,
|
||||||
|
:not(li) > ul > li:first-child > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(li) > ol > li:last-child > :last-child,
|
||||||
|
:not(li) > ul > li:last-child > :last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple ol p,
|
||||||
|
ol.simple ul p,
|
||||||
|
ul.simple ol p,
|
||||||
|
ul.simple ul p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple > li:not(:first-child) > p,
|
||||||
|
ul.simple > li:not(:first-child) > p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple p,
|
||||||
|
ul.simple p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dt,
|
||||||
|
dl.citation > dt {
|
||||||
|
float: left;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dd,
|
||||||
|
dl.citation > dd {
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.footnote > dd:after,
|
||||||
|
dl.citation > dd:after {
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: fit-content(30%) auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dt {
|
||||||
|
font-weight: bold;
|
||||||
|
word-break: break-word;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dt:after {
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dd {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
margin-top: 0em;
|
||||||
|
margin-left: 0em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd ul, dd table {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl > dd:last-child,
|
||||||
|
dl > dd:last-child > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, span.highlighted {
|
||||||
|
background-color: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.highlighted {
|
||||||
|
fill: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.glossary dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionmodified {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-message {
|
||||||
|
background-color: #fda;
|
||||||
|
padding: 5px;
|
||||||
|
border: 3px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footnote:target {
|
||||||
|
background-color: #ffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block .line-block {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guilabel, .menuselection {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accelerator {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier {
|
||||||
|
font-style: oblique;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier:before {
|
||||||
|
font-style: normal;
|
||||||
|
margin: 0.5em;
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr, acronym {
|
||||||
|
border-bottom: dotted 1px;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- code displays --------------------------------------------------------- */
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, div[class*="highlight-"] {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class*="highlight-"] {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.linenos pre {
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable tbody {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.linenos {
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.code {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .hll {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.highlight pre,
|
||||||
|
table.highlighttable pre {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption + div {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption {
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 2px 5px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.linenos,
|
||||||
|
span.linenos,
|
||||||
|
div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: text; /* Safari fallback only */
|
||||||
|
-webkit-user-select: none; /* Chrome/Safari */
|
||||||
|
-moz-user-select: none; /* Firefox */
|
||||||
|
-ms-user-select: none; /* IE10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-number {
|
||||||
|
padding: 0.1em 0.3em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
div.literal-block-wrapper {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.xref, a code {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-link {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
float: right;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
margin: -1px -10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- math display ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
img.math {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body div.math p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno a.headerlink {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.math:hover a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- printout stylesheet --------------------------------------------------- */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
div.document,
|
||||||
|
div.documentwrapper,
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar,
|
||||||
|
div.related,
|
||||||
|
div.footer,
|
||||||
|
#top-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
266
Documentation/html/_static/classic.css
Normal file
266
Documentation/html/_static/classic.css
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* classic.css_t
|
||||||
|
* ~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- classic theme.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url("basic.css");
|
||||||
|
|
||||||
|
/* -- page layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
html {
|
||||||
|
/* CSS hack for macOS's scrollbar (see #1125) */
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 100%;
|
||||||
|
background-color: #11303d;
|
||||||
|
color: #000;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.document {
|
||||||
|
background-color: #1c4e63;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.documentwrapper {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 0 0 230px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
padding: 0 20px 30px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
color: #ffffff;
|
||||||
|
width: 100%;
|
||||||
|
padding: 9px 0 9px 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer a {
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
background-color: #133f52;
|
||||||
|
line-height: 30px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related a {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3 {
|
||||||
|
font-family: 'Trebuchet MS', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3 a {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h4 {
|
||||||
|
font-family: 'Trebuchet MS', sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 5px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar p {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar p.topless {
|
||||||
|
margin: 5px 10px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
margin: 10px;
|
||||||
|
padding: 0;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar a {
|
||||||
|
color: #98dbcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #98dbcc;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* -- hyperlink styles ------------------------------------------------------ */
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #355f7c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #355f7c;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* -- body styles ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.body h1,
|
||||||
|
div.body h2,
|
||||||
|
div.body h3,
|
||||||
|
div.body h4,
|
||||||
|
div.body h5,
|
||||||
|
div.body h6 {
|
||||||
|
font-family: 'Trebuchet MS', sans-serif;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #20435c;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin: 20px -20px 10px -20px;
|
||||||
|
padding: 3px 0 3px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||||
|
div.body h2 { font-size: 160%; }
|
||||||
|
div.body h3 { font-size: 140%; }
|
||||||
|
div.body h4 { font-size: 120%; }
|
||||||
|
div.body h5 { font-size: 110%; }
|
||||||
|
div.body h6 { font-size: 100%; }
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
color: #c60f0f;
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding: 0 4px 0 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink:hover {
|
||||||
|
background-color: #c60f0f;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||||
|
text-align: justify;
|
||||||
|
line-height: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p.admonition-title + p {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition pre {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition ul, div.admonition ol {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.note {
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.seealso {
|
||||||
|
background-color: #ffc;
|
||||||
|
border: 1px solid #ff6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.warning {
|
||||||
|
background-color: #ffe4e4;
|
||||||
|
border: 1px solid #f66;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title:after {
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 5px;
|
||||||
|
background-color: unset;
|
||||||
|
color: unset;
|
||||||
|
line-height: 120%;
|
||||||
|
border: 1px solid #ac9;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: #ecf0f3;
|
||||||
|
padding: 0 1px 0 1px;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, dl.field-list > dt {
|
||||||
|
background-color: #ede;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning code {
|
||||||
|
background: #efc2c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note code {
|
||||||
|
background: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
background-color: #f4debf;
|
||||||
|
border-top: 1px solid #ac9;
|
||||||
|
border-bottom: 1px solid #ac9;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption {
|
||||||
|
color: #efefef;
|
||||||
|
background-color: #1c4e63;
|
||||||
|
}
|
321
Documentation/html/_static/doctools.js
Normal file
321
Documentation/html/_static/doctools.js
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
* doctools.js
|
||||||
|
* ~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx JavaScript utilities for all documentation.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select a different prefix for underscore
|
||||||
|
*/
|
||||||
|
$u = _.noConflict();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make the code below compatible with browsers without
|
||||||
|
* an installed firebug like debugger
|
||||||
|
if (!window.console || !console.firebug) {
|
||||||
|
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||||
|
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||||
|
"profile", "profileEnd"];
|
||||||
|
window.console = {};
|
||||||
|
for (var i = 0; i < names.length; ++i)
|
||||||
|
window.console[names[i]] = function() {};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* small helper function to urldecode strings
|
||||||
|
*
|
||||||
|
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
|
||||||
|
*/
|
||||||
|
jQuery.urldecode = function(x) {
|
||||||
|
if (!x) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return decodeURIComponent(x.replace(/\+/g, ' '));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* small helper function to urlencode strings
|
||||||
|
*/
|
||||||
|
jQuery.urlencode = encodeURIComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the parsed url parameters of the
|
||||||
|
* current request. Multiple values per key are supported,
|
||||||
|
* it will always return arrays of strings for the value parts.
|
||||||
|
*/
|
||||||
|
jQuery.getQueryParameters = function(s) {
|
||||||
|
if (typeof s === 'undefined')
|
||||||
|
s = document.location.search;
|
||||||
|
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||||
|
var result = {};
|
||||||
|
for (var i = 0; i < parts.length; i++) {
|
||||||
|
var tmp = parts[i].split('=', 2);
|
||||||
|
var key = jQuery.urldecode(tmp[0]);
|
||||||
|
var value = jQuery.urldecode(tmp[1]);
|
||||||
|
if (key in result)
|
||||||
|
result[key].push(value);
|
||||||
|
else
|
||||||
|
result[key] = [value];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight a given string on a jquery object by wrapping it in
|
||||||
|
* span elements with the given class name.
|
||||||
|
*/
|
||||||
|
jQuery.fn.highlightText = function(text, className) {
|
||||||
|
function highlight(node, addItems) {
|
||||||
|
if (node.nodeType === 3) {
|
||||||
|
var val = node.nodeValue;
|
||||||
|
var pos = val.toLowerCase().indexOf(text);
|
||||||
|
if (pos >= 0 &&
|
||||||
|
!jQuery(node.parentNode).hasClass(className) &&
|
||||||
|
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||||
|
var span;
|
||||||
|
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||||
|
if (isInSVG) {
|
||||||
|
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||||
|
} else {
|
||||||
|
span = document.createElement("span");
|
||||||
|
span.className = className;
|
||||||
|
}
|
||||||
|
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||||
|
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||||
|
document.createTextNode(val.substr(pos + text.length)),
|
||||||
|
node.nextSibling));
|
||||||
|
node.nodeValue = val.substr(0, pos);
|
||||||
|
if (isInSVG) {
|
||||||
|
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||||
|
var bbox = node.parentElement.getBBox();
|
||||||
|
rect.x.baseVal.value = bbox.x;
|
||||||
|
rect.y.baseVal.value = bbox.y;
|
||||||
|
rect.width.baseVal.value = bbox.width;
|
||||||
|
rect.height.baseVal.value = bbox.height;
|
||||||
|
rect.setAttribute('class', className);
|
||||||
|
addItems.push({
|
||||||
|
"parent": node.parentNode,
|
||||||
|
"target": rect});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!jQuery(node).is("button, select, textarea")) {
|
||||||
|
jQuery.each(node.childNodes, function() {
|
||||||
|
highlight(this, addItems);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var addItems = [];
|
||||||
|
var result = this.each(function() {
|
||||||
|
highlight(this, addItems);
|
||||||
|
});
|
||||||
|
for (var i = 0; i < addItems.length; ++i) {
|
||||||
|
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* backward compatibility for jQuery.browser
|
||||||
|
* This will be supported until firefox bug is fixed.
|
||||||
|
*/
|
||||||
|
if (!jQuery.browser) {
|
||||||
|
jQuery.uaMatch = function(ua) {
|
||||||
|
ua = ua.toLowerCase();
|
||||||
|
|
||||||
|
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||||
|
/(msie) ([\w.]+)/.exec(ua) ||
|
||||||
|
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
return {
|
||||||
|
browser: match[ 1 ] || "",
|
||||||
|
version: match[ 2 ] || "0"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
jQuery.browser = {};
|
||||||
|
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small JavaScript module for the documentation.
|
||||||
|
*/
|
||||||
|
var Documentation = {
|
||||||
|
|
||||||
|
init : function() {
|
||||||
|
this.fixFirefoxAnchorBug();
|
||||||
|
this.highlightSearchWords();
|
||||||
|
this.initIndexTable();
|
||||||
|
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
|
||||||
|
this.initOnKeyListeners();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18n support
|
||||||
|
*/
|
||||||
|
TRANSLATIONS : {},
|
||||||
|
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
|
||||||
|
LOCALE : 'unknown',
|
||||||
|
|
||||||
|
// gettext and ngettext don't access this so that the functions
|
||||||
|
// can safely bound to a different name (_ = Documentation.gettext)
|
||||||
|
gettext : function(string) {
|
||||||
|
var translated = Documentation.TRANSLATIONS[string];
|
||||||
|
if (typeof translated === 'undefined')
|
||||||
|
return string;
|
||||||
|
return (typeof translated === 'string') ? translated : translated[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
ngettext : function(singular, plural, n) {
|
||||||
|
var translated = Documentation.TRANSLATIONS[singular];
|
||||||
|
if (typeof translated === 'undefined')
|
||||||
|
return (n == 1) ? singular : plural;
|
||||||
|
return translated[Documentation.PLURALEXPR(n)];
|
||||||
|
},
|
||||||
|
|
||||||
|
addTranslations : function(catalog) {
|
||||||
|
for (var key in catalog.messages)
|
||||||
|
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||||
|
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||||
|
this.LOCALE = catalog.locale;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add context elements like header anchor links
|
||||||
|
*/
|
||||||
|
addContextElements : function() {
|
||||||
|
$('div[id] > :header:first').each(function() {
|
||||||
|
$('<a class="headerlink">\u00B6</a>').
|
||||||
|
attr('href', '#' + this.id).
|
||||||
|
attr('title', _('Permalink to this headline')).
|
||||||
|
appendTo(this);
|
||||||
|
});
|
||||||
|
$('dt[id]').each(function() {
|
||||||
|
$('<a class="headerlink">\u00B6</a>').
|
||||||
|
attr('href', '#' + this.id).
|
||||||
|
attr('title', _('Permalink to this definition')).
|
||||||
|
appendTo(this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* workaround a firefox stupidity
|
||||||
|
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
|
||||||
|
*/
|
||||||
|
fixFirefoxAnchorBug : function() {
|
||||||
|
if (document.location.hash && $.browser.mozilla)
|
||||||
|
window.setTimeout(function() {
|
||||||
|
document.location.href += '';
|
||||||
|
}, 10);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight the search words provided in the url in the text
|
||||||
|
*/
|
||||||
|
highlightSearchWords : function() {
|
||||||
|
var params = $.getQueryParameters();
|
||||||
|
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||||
|
if (terms.length) {
|
||||||
|
var body = $('div.body');
|
||||||
|
if (!body.length) {
|
||||||
|
body = $('body');
|
||||||
|
}
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$.each(terms, function() {
|
||||||
|
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||||
|
});
|
||||||
|
}, 10);
|
||||||
|
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||||
|
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||||
|
.appendTo($('#searchbox'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init the domain index toggle buttons
|
||||||
|
*/
|
||||||
|
initIndexTable : function() {
|
||||||
|
var togglers = $('img.toggler').click(function() {
|
||||||
|
var src = $(this).attr('src');
|
||||||
|
var idnum = $(this).attr('id').substr(7);
|
||||||
|
$('tr.cg-' + idnum).toggle();
|
||||||
|
if (src.substr(-9) === 'minus.png')
|
||||||
|
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||||
|
else
|
||||||
|
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||||
|
}).css('display', '');
|
||||||
|
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||||
|
togglers.click();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to hide the search marks again
|
||||||
|
*/
|
||||||
|
hideSearchWords : function() {
|
||||||
|
$('#searchbox .highlight-link').fadeOut(300);
|
||||||
|
$('span.highlighted').removeClass('highlighted');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* make the url absolute
|
||||||
|
*/
|
||||||
|
makeURL : function(relativeURL) {
|
||||||
|
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the current relative url
|
||||||
|
*/
|
||||||
|
getCurrentURL : function() {
|
||||||
|
var path = document.location.pathname;
|
||||||
|
var parts = path.split(/\//);
|
||||||
|
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||||
|
if (this === '..')
|
||||||
|
parts.pop();
|
||||||
|
});
|
||||||
|
var url = parts.join('/');
|
||||||
|
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
initOnKeyListeners: function() {
|
||||||
|
$(document).keydown(function(event) {
|
||||||
|
var activeElementType = document.activeElement.tagName;
|
||||||
|
// don't navigate when in search box, textarea, dropdown or button
|
||||||
|
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
|
||||||
|
&& activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
|
||||||
|
&& !event.shiftKey) {
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 37: // left
|
||||||
|
var prevHref = $('link[rel="prev"]').prop('href');
|
||||||
|
if (prevHref) {
|
||||||
|
window.location.href = prevHref;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 39: // right
|
||||||
|
var nextHref = $('link[rel="next"]').prop('href');
|
||||||
|
if (nextHref) {
|
||||||
|
window.location.href = nextHref;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// quick alias for translations
|
||||||
|
_ = Documentation.gettext;
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
Documentation.init();
|
||||||
|
});
|
12
Documentation/html/_static/documentation_options.js
Normal file
12
Documentation/html/_static/documentation_options.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
var DOCUMENTATION_OPTIONS = {
|
||||||
|
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||||
|
VERSION: '0.2.0 beta',
|
||||||
|
LANGUAGE: 'None',
|
||||||
|
COLLAPSE_INDEX: false,
|
||||||
|
BUILDER: 'html',
|
||||||
|
FILE_SUFFIX: '.html',
|
||||||
|
LINK_SUFFIX: '.html',
|
||||||
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: '.txt',
|
||||||
|
NAVIGATION_WITH_KEYS: false
|
||||||
|
};
|
BIN
Documentation/html/_static/file.png
Normal file
BIN
Documentation/html/_static/file.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 286 B |
10872
Documentation/html/_static/jquery-3.5.1.js
vendored
Normal file
10872
Documentation/html/_static/jquery-3.5.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
Documentation/html/_static/jquery.js
vendored
Normal file
2
Documentation/html/_static/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
297
Documentation/html/_static/language_data.js
Normal file
297
Documentation/html/_static/language_data.js
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* language_data.js
|
||||||
|
* ~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This script contains the language-specific data used by searchtools.js,
|
||||||
|
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||||
|
|
||||||
|
|
||||||
|
/* Non-minified version is copied as a separate JS file, is available */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Porter Stemmer
|
||||||
|
*/
|
||||||
|
var Stemmer = function() {
|
||||||
|
|
||||||
|
var step2list = {
|
||||||
|
ational: 'ate',
|
||||||
|
tional: 'tion',
|
||||||
|
enci: 'ence',
|
||||||
|
anci: 'ance',
|
||||||
|
izer: 'ize',
|
||||||
|
bli: 'ble',
|
||||||
|
alli: 'al',
|
||||||
|
entli: 'ent',
|
||||||
|
eli: 'e',
|
||||||
|
ousli: 'ous',
|
||||||
|
ization: 'ize',
|
||||||
|
ation: 'ate',
|
||||||
|
ator: 'ate',
|
||||||
|
alism: 'al',
|
||||||
|
iveness: 'ive',
|
||||||
|
fulness: 'ful',
|
||||||
|
ousness: 'ous',
|
||||||
|
aliti: 'al',
|
||||||
|
iviti: 'ive',
|
||||||
|
biliti: 'ble',
|
||||||
|
logi: 'log'
|
||||||
|
};
|
||||||
|
|
||||||
|
var step3list = {
|
||||||
|
icate: 'ic',
|
||||||
|
ative: '',
|
||||||
|
alize: 'al',
|
||||||
|
iciti: 'ic',
|
||||||
|
ical: 'ic',
|
||||||
|
ful: '',
|
||||||
|
ness: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
var c = "[^aeiou]"; // consonant
|
||||||
|
var v = "[aeiouy]"; // vowel
|
||||||
|
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||||
|
var V = v + "[aeiou]*"; // vowel sequence
|
||||||
|
|
||||||
|
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||||
|
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||||
|
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||||
|
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||||
|
|
||||||
|
this.stemWord = function (w) {
|
||||||
|
var stem;
|
||||||
|
var suffix;
|
||||||
|
var firstch;
|
||||||
|
var origword = w;
|
||||||
|
|
||||||
|
if (w.length < 3)
|
||||||
|
return w;
|
||||||
|
|
||||||
|
var re;
|
||||||
|
var re2;
|
||||||
|
var re3;
|
||||||
|
var re4;
|
||||||
|
|
||||||
|
firstch = w.substr(0,1);
|
||||||
|
if (firstch == "y")
|
||||||
|
w = firstch.toUpperCase() + w.substr(1);
|
||||||
|
|
||||||
|
// Step 1a
|
||||||
|
re = /^(.+?)(ss|i)es$/;
|
||||||
|
re2 = /^(.+?)([^s])s$/;
|
||||||
|
|
||||||
|
if (re.test(w))
|
||||||
|
w = w.replace(re,"$1$2");
|
||||||
|
else if (re2.test(w))
|
||||||
|
w = w.replace(re2,"$1$2");
|
||||||
|
|
||||||
|
// Step 1b
|
||||||
|
re = /^(.+?)eed$/;
|
||||||
|
re2 = /^(.+?)(ed|ing)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(fp[1])) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (re2.test(w)) {
|
||||||
|
var fp = re2.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re2 = new RegExp(s_v);
|
||||||
|
if (re2.test(stem)) {
|
||||||
|
w = stem;
|
||||||
|
re2 = /(at|bl|iz)$/;
|
||||||
|
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||||
|
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||||
|
if (re2.test(w))
|
||||||
|
w = w + "e";
|
||||||
|
else if (re3.test(w)) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
else if (re4.test(w))
|
||||||
|
w = w + "e";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1c
|
||||||
|
re = /^(.+?)y$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(s_v);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + "i";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
suffix = fp[2];
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + step2list[suffix];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
suffix = fp[2];
|
||||||
|
re = new RegExp(mgr0);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem + step3list[suffix];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||||
|
re2 = /^(.+?)(s|t)(ion)$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(mgr1);
|
||||||
|
if (re.test(stem))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
else if (re2.test(w)) {
|
||||||
|
var fp = re2.exec(w);
|
||||||
|
stem = fp[1] + fp[2];
|
||||||
|
re2 = new RegExp(mgr1);
|
||||||
|
if (re2.test(stem))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
re = /^(.+?)e$/;
|
||||||
|
if (re.test(w)) {
|
||||||
|
var fp = re.exec(w);
|
||||||
|
stem = fp[1];
|
||||||
|
re = new RegExp(mgr1);
|
||||||
|
re2 = new RegExp(meq1);
|
||||||
|
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||||
|
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||||
|
w = stem;
|
||||||
|
}
|
||||||
|
re = /ll$/;
|
||||||
|
re2 = new RegExp(mgr1);
|
||||||
|
if (re.test(w) && re2.test(w)) {
|
||||||
|
re = /.$/;
|
||||||
|
w = w.replace(re,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// and turn initial Y back to y
|
||||||
|
if (firstch == "y")
|
||||||
|
w = firstch.toLowerCase() + w.substr(1);
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var splitChars = (function() {
|
||||||
|
var result = {};
|
||||||
|
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
|
||||||
|
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
|
||||||
|
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
|
||||||
|
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
|
||||||
|
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
|
||||||
|
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
|
||||||
|
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
|
||||||
|
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
|
||||||
|
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
|
||||||
|
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
|
||||||
|
var i, j, start, end;
|
||||||
|
for (i = 0; i < singles.length; i++) {
|
||||||
|
result[singles[i]] = true;
|
||||||
|
}
|
||||||
|
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
|
||||||
|
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
|
||||||
|
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
|
||||||
|
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
|
||||||
|
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
|
||||||
|
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
|
||||||
|
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
|
||||||
|
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
|
||||||
|
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
|
||||||
|
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
|
||||||
|
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
|
||||||
|
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
|
||||||
|
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
|
||||||
|
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
|
||||||
|
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
|
||||||
|
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
|
||||||
|
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
|
||||||
|
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
|
||||||
|
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
|
||||||
|
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
|
||||||
|
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
|
||||||
|
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
|
||||||
|
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
|
||||||
|
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
|
||||||
|
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
|
||||||
|
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
|
||||||
|
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
|
||||||
|
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
|
||||||
|
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
|
||||||
|
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
|
||||||
|
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
|
||||||
|
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
|
||||||
|
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
|
||||||
|
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
|
||||||
|
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
|
||||||
|
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
|
||||||
|
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
|
||||||
|
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
|
||||||
|
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
|
||||||
|
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
|
||||||
|
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
|
||||||
|
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
|
||||||
|
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
|
||||||
|
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
|
||||||
|
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
|
||||||
|
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
|
||||||
|
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
|
||||||
|
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
|
||||||
|
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
|
||||||
|
for (i = 0; i < ranges.length; i++) {
|
||||||
|
start = ranges[i][0];
|
||||||
|
end = ranges[i][1];
|
||||||
|
for (j = start; j <= end; j++) {
|
||||||
|
result[j] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function splitQuery(query) {
|
||||||
|
var result = [];
|
||||||
|
var start = -1;
|
||||||
|
for (var i = 0; i < query.length; i++) {
|
||||||
|
if (splitChars[query.charCodeAt(i)]) {
|
||||||
|
if (start !== -1) {
|
||||||
|
result.push(query.slice(start, i));
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
} else if (start === -1) {
|
||||||
|
start = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start !== -1) {
|
||||||
|
result.push(query.slice(start));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
BIN
Documentation/html/_static/minus.png
Normal file
BIN
Documentation/html/_static/minus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 B |
BIN
Documentation/html/_static/plus.png
Normal file
BIN
Documentation/html/_static/plus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 B |
74
Documentation/html/_static/pygments.css
Normal file
74
Documentation/html/_static/pygments.css
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
pre { line-height: 125%; }
|
||||||
|
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||||
|
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||||
|
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||||
|
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||||
|
.highlight .hll { background-color: #ffffcc }
|
||||||
|
.highlight { background: #eeffcc; }
|
||||||
|
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||||
|
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { color: #666666 } /* Operator */
|
||||||
|
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||||
|
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||||
|
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||||
|
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||||
|
.highlight .go { color: #333333 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||||
|
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #208050 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||||
|
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||||
|
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||||
|
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #06287e } /* Name.Function */
|
||||||
|
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||||
|
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||||
|
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
|
||||||
|
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||||
|
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||||
|
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||||
|
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||||
|
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||||
|
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||||
|
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
522
Documentation/html/_static/searchtools.js
Normal file
522
Documentation/html/_static/searchtools.js
Normal file
@ -0,0 +1,522 @@
|
|||||||
|
/*
|
||||||
|
* searchtools.js
|
||||||
|
* ~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx JavaScript utilities for the full-text search.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!Scorer) {
|
||||||
|
/**
|
||||||
|
* Simple result scoring code.
|
||||||
|
*/
|
||||||
|
var Scorer = {
|
||||||
|
// Implement the following function to further tweak the score for each result
|
||||||
|
// The function takes a result array [filename, title, anchor, descr, score]
|
||||||
|
// and returns the new score.
|
||||||
|
/*
|
||||||
|
score: function(result) {
|
||||||
|
return result[4];
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
// query matches the full name of an object
|
||||||
|
objNameMatch: 11,
|
||||||
|
// or matches in the last dotted part of the object name
|
||||||
|
objPartialMatch: 6,
|
||||||
|
// Additive scores depending on the priority of the object
|
||||||
|
objPrio: {0: 15, // used to be importantResults
|
||||||
|
1: 5, // used to be objectResults
|
||||||
|
2: -5}, // used to be unimportantResults
|
||||||
|
// Used when the priority is not in the mapping.
|
||||||
|
objPrioDefault: 0,
|
||||||
|
|
||||||
|
// query found in title
|
||||||
|
title: 15,
|
||||||
|
partialTitle: 7,
|
||||||
|
// query found in terms
|
||||||
|
term: 5,
|
||||||
|
partialTerm: 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!splitQuery) {
|
||||||
|
function splitQuery(query) {
|
||||||
|
return query.split(/\s+/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search Module
|
||||||
|
*/
|
||||||
|
var Search = {
|
||||||
|
|
||||||
|
_index : null,
|
||||||
|
_queued_query : null,
|
||||||
|
_pulse_status : -1,
|
||||||
|
|
||||||
|
htmlToText : function(htmlString) {
|
||||||
|
var virtualDocument = document.implementation.createHTMLDocument('virtual');
|
||||||
|
var htmlElement = $(htmlString, virtualDocument);
|
||||||
|
htmlElement.find('.headerlink').remove();
|
||||||
|
docContent = htmlElement.find('[role=main]')[0];
|
||||||
|
if(docContent === undefined) {
|
||||||
|
console.warn("Content block not found. Sphinx search tries to obtain it " +
|
||||||
|
"via '[role=main]'. Could you check your theme or template.");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return docContent.textContent || docContent.innerText;
|
||||||
|
},
|
||||||
|
|
||||||
|
init : function() {
|
||||||
|
var params = $.getQueryParameters();
|
||||||
|
if (params.q) {
|
||||||
|
var query = params.q[0];
|
||||||
|
$('input[name="q"]')[0].value = query;
|
||||||
|
this.performSearch(query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadIndex : function(url) {
|
||||||
|
$.ajax({type: "GET", url: url, data: null,
|
||||||
|
dataType: "script", cache: true,
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
if (textstatus != "success") {
|
||||||
|
document.getElementById("searchindexloader").src = url;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
|
||||||
|
setIndex : function(index) {
|
||||||
|
var q;
|
||||||
|
this._index = index;
|
||||||
|
if ((q = this._queued_query) !== null) {
|
||||||
|
this._queued_query = null;
|
||||||
|
Search.query(q);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hasIndex : function() {
|
||||||
|
return this._index !== null;
|
||||||
|
},
|
||||||
|
|
||||||
|
deferQuery : function(query) {
|
||||||
|
this._queued_query = query;
|
||||||
|
},
|
||||||
|
|
||||||
|
stopPulse : function() {
|
||||||
|
this._pulse_status = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
startPulse : function() {
|
||||||
|
if (this._pulse_status >= 0)
|
||||||
|
return;
|
||||||
|
function pulse() {
|
||||||
|
var i;
|
||||||
|
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||||
|
var dotString = '';
|
||||||
|
for (i = 0; i < Search._pulse_status; i++)
|
||||||
|
dotString += '.';
|
||||||
|
Search.dots.text(dotString);
|
||||||
|
if (Search._pulse_status > -1)
|
||||||
|
window.setTimeout(pulse, 500);
|
||||||
|
}
|
||||||
|
pulse();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* perform a search for something (or wait until index is loaded)
|
||||||
|
*/
|
||||||
|
performSearch : function(query) {
|
||||||
|
// create the required interface elements
|
||||||
|
this.out = $('#search-results');
|
||||||
|
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||||
|
this.dots = $('<span></span>').appendTo(this.title);
|
||||||
|
this.status = $('<p class="search-summary"> </p>').appendTo(this.out);
|
||||||
|
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||||
|
|
||||||
|
$('#search-progress').text(_('Preparing search...'));
|
||||||
|
this.startPulse();
|
||||||
|
|
||||||
|
// index already loaded, the browser was quick!
|
||||||
|
if (this.hasIndex())
|
||||||
|
this.query(query);
|
||||||
|
else
|
||||||
|
this.deferQuery(query);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute search (requires search index to be loaded)
|
||||||
|
*/
|
||||||
|
query : function(query) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// stem the searchterms and add them to the correct list
|
||||||
|
var stemmer = new Stemmer();
|
||||||
|
var searchterms = [];
|
||||||
|
var excluded = [];
|
||||||
|
var hlterms = [];
|
||||||
|
var tmp = splitQuery(query);
|
||||||
|
var objectterms = [];
|
||||||
|
for (i = 0; i < tmp.length; i++) {
|
||||||
|
if (tmp[i] !== "") {
|
||||||
|
objectterms.push(tmp[i].toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i] === "") {
|
||||||
|
// skip this "word"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// stem the word
|
||||||
|
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||||
|
// prevent stemmer from cutting word smaller than two chars
|
||||||
|
if(word.length < 3 && tmp[i].length >= 3) {
|
||||||
|
word = tmp[i];
|
||||||
|
}
|
||||||
|
var toAppend;
|
||||||
|
// select the correct list
|
||||||
|
if (word[0] == '-') {
|
||||||
|
toAppend = excluded;
|
||||||
|
word = word.substr(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toAppend = searchterms;
|
||||||
|
hlterms.push(tmp[i].toLowerCase());
|
||||||
|
}
|
||||||
|
// only add if not already in the list
|
||||||
|
if (!$u.contains(toAppend, word))
|
||||||
|
toAppend.push(word);
|
||||||
|
}
|
||||||
|
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||||
|
|
||||||
|
// console.debug('SEARCH: searching for:');
|
||||||
|
// console.info('required: ', searchterms);
|
||||||
|
// console.info('excluded: ', excluded);
|
||||||
|
|
||||||
|
// prepare search
|
||||||
|
var terms = this._index.terms;
|
||||||
|
var titleterms = this._index.titleterms;
|
||||||
|
|
||||||
|
// array of [filename, title, anchor, descr, score]
|
||||||
|
var results = [];
|
||||||
|
$('#search-progress').empty();
|
||||||
|
|
||||||
|
// lookup as object
|
||||||
|
for (i = 0; i < objectterms.length; i++) {
|
||||||
|
var others = [].concat(objectterms.slice(0, i),
|
||||||
|
objectterms.slice(i+1, objectterms.length));
|
||||||
|
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup as search terms in fulltext
|
||||||
|
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||||
|
|
||||||
|
// let the scorer override scores with a custom scoring function
|
||||||
|
if (Scorer.score) {
|
||||||
|
for (i = 0; i < results.length; i++)
|
||||||
|
results[i][4] = Scorer.score(results[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now sort the results by score (in opposite order of appearance, since the
|
||||||
|
// display function below uses pop() to retrieve items) and then
|
||||||
|
// alphabetically
|
||||||
|
results.sort(function(a, b) {
|
||||||
|
var left = a[4];
|
||||||
|
var right = b[4];
|
||||||
|
if (left > right) {
|
||||||
|
return 1;
|
||||||
|
} else if (left < right) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
// same score: sort alphabetically
|
||||||
|
left = a[1].toLowerCase();
|
||||||
|
right = b[1].toLowerCase();
|
||||||
|
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Search.lastresults = results.slice(); // a copy
|
||||||
|
//console.info('search results:', Search.lastresults);
|
||||||
|
|
||||||
|
// print the results
|
||||||
|
var resultCount = results.length;
|
||||||
|
function displayNextItem() {
|
||||||
|
// results left, load the summary and display it
|
||||||
|
if (results.length) {
|
||||||
|
var item = results.pop();
|
||||||
|
var listItem = $('<li></li>');
|
||||||
|
var requestUrl = "";
|
||||||
|
var linkUrl = "";
|
||||||
|
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
|
||||||
|
// dirhtml builder
|
||||||
|
var dirname = item[0] + '/';
|
||||||
|
if (dirname.match(/\/index\/$/)) {
|
||||||
|
dirname = dirname.substring(0, dirname.length-6);
|
||||||
|
} else if (dirname == 'index/') {
|
||||||
|
dirname = '';
|
||||||
|
}
|
||||||
|
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
|
||||||
|
linkUrl = requestUrl;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// normal html builders
|
||||||
|
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||||
|
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||||
|
}
|
||||||
|
listItem.append($('<a/>').attr('href',
|
||||||
|
linkUrl +
|
||||||
|
highlightstring + item[2]).html(item[1]));
|
||||||
|
if (item[3]) {
|
||||||
|
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||||
|
Search.output.append(listItem);
|
||||||
|
setTimeout(function() {
|
||||||
|
displayNextItem();
|
||||||
|
}, 5);
|
||||||
|
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||||
|
$.ajax({url: requestUrl,
|
||||||
|
dataType: "text",
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
var data = jqxhr.responseText;
|
||||||
|
if (data !== '' && data !== undefined) {
|
||||||
|
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
|
||||||
|
}
|
||||||
|
Search.output.append(listItem);
|
||||||
|
setTimeout(function() {
|
||||||
|
displayNextItem();
|
||||||
|
}, 5);
|
||||||
|
}});
|
||||||
|
} else {
|
||||||
|
// no source available, just display title
|
||||||
|
Search.output.append(listItem);
|
||||||
|
setTimeout(function() {
|
||||||
|
displayNextItem();
|
||||||
|
}, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// search finished, update title and status message
|
||||||
|
else {
|
||||||
|
Search.stopPulse();
|
||||||
|
Search.title.text(_('Search Results'));
|
||||||
|
if (!resultCount)
|
||||||
|
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||||
|
else
|
||||||
|
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||||
|
Search.status.fadeIn(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayNextItem();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for object names
|
||||||
|
*/
|
||||||
|
performObjectSearch : function(object, otherterms) {
|
||||||
|
var filenames = this._index.filenames;
|
||||||
|
var docnames = this._index.docnames;
|
||||||
|
var objects = this._index.objects;
|
||||||
|
var objnames = this._index.objnames;
|
||||||
|
var titles = this._index.titles;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
for (var prefix in objects) {
|
||||||
|
for (var name in objects[prefix]) {
|
||||||
|
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||||
|
var fullnameLower = fullname.toLowerCase()
|
||||||
|
if (fullnameLower.indexOf(object) > -1) {
|
||||||
|
var score = 0;
|
||||||
|
var parts = fullnameLower.split('.');
|
||||||
|
// check for different match types: exact matches of full name or
|
||||||
|
// "last name" (i.e. last dotted part)
|
||||||
|
if (fullnameLower == object || parts[parts.length - 1] == object) {
|
||||||
|
score += Scorer.objNameMatch;
|
||||||
|
// matches in last name
|
||||||
|
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||||
|
score += Scorer.objPartialMatch;
|
||||||
|
}
|
||||||
|
var match = objects[prefix][name];
|
||||||
|
var objname = objnames[match[1]][2];
|
||||||
|
var title = titles[match[0]];
|
||||||
|
// If more than one term searched for, we require other words to be
|
||||||
|
// found in the name/title/description
|
||||||
|
if (otherterms.length > 0) {
|
||||||
|
var haystack = (prefix + ' ' + name + ' ' +
|
||||||
|
objname + ' ' + title).toLowerCase();
|
||||||
|
var allfound = true;
|
||||||
|
for (i = 0; i < otherterms.length; i++) {
|
||||||
|
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||||
|
allfound = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allfound) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var descr = objname + _(', in ') + title;
|
||||||
|
|
||||||
|
var anchor = match[3];
|
||||||
|
if (anchor === '')
|
||||||
|
anchor = fullname;
|
||||||
|
else if (anchor == '-')
|
||||||
|
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||||
|
// add custom score for some objects according to scorer
|
||||||
|
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||||
|
score += Scorer.objPrio[match[2]];
|
||||||
|
} else {
|
||||||
|
score += Scorer.objPrioDefault;
|
||||||
|
}
|
||||||
|
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||||
|
*/
|
||||||
|
escapeRegExp : function(string) {
|
||||||
|
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for full-text terms in the index
|
||||||
|
*/
|
||||||
|
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||||
|
var docnames = this._index.docnames;
|
||||||
|
var filenames = this._index.filenames;
|
||||||
|
var titles = this._index.titles;
|
||||||
|
|
||||||
|
var i, j, file;
|
||||||
|
var fileMap = {};
|
||||||
|
var scoreMap = {};
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
// perform the search on the required terms
|
||||||
|
for (i = 0; i < searchterms.length; i++) {
|
||||||
|
var word = searchterms[i];
|
||||||
|
var files = [];
|
||||||
|
var _o = [
|
||||||
|
{files: terms[word], score: Scorer.term},
|
||||||
|
{files: titleterms[word], score: Scorer.title}
|
||||||
|
];
|
||||||
|
// add support for partial matches
|
||||||
|
if (word.length > 2) {
|
||||||
|
var word_regex = this.escapeRegExp(word);
|
||||||
|
for (var w in terms) {
|
||||||
|
if (w.match(word_regex) && !terms[word]) {
|
||||||
|
_o.push({files: terms[w], score: Scorer.partialTerm})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var w in titleterms) {
|
||||||
|
if (w.match(word_regex) && !titleterms[word]) {
|
||||||
|
_o.push({files: titleterms[w], score: Scorer.partialTitle})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no match but word was a required one
|
||||||
|
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// found search word in contents
|
||||||
|
$u.each(_o, function(o) {
|
||||||
|
var _files = o.files;
|
||||||
|
if (_files === undefined)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (_files.length === undefined)
|
||||||
|
_files = [_files];
|
||||||
|
files = files.concat(_files);
|
||||||
|
|
||||||
|
// set score for the word in each file to Scorer.term
|
||||||
|
for (j = 0; j < _files.length; j++) {
|
||||||
|
file = _files[j];
|
||||||
|
if (!(file in scoreMap))
|
||||||
|
scoreMap[file] = {};
|
||||||
|
scoreMap[file][word] = o.score;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// create the mapping
|
||||||
|
for (j = 0; j < files.length; j++) {
|
||||||
|
file = files[j];
|
||||||
|
if (file in fileMap && fileMap[file].indexOf(word) === -1)
|
||||||
|
fileMap[file].push(word);
|
||||||
|
else
|
||||||
|
fileMap[file] = [word];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check if the files don't contain excluded terms
|
||||||
|
for (file in fileMap) {
|
||||||
|
var valid = true;
|
||||||
|
|
||||||
|
// check if all requirements are matched
|
||||||
|
var filteredTermCount = // as search terms with length < 3 are discarded: ignore
|
||||||
|
searchterms.filter(function(term){return term.length > 2}).length
|
||||||
|
if (
|
||||||
|
fileMap[file].length != searchterms.length &&
|
||||||
|
fileMap[file].length != filteredTermCount
|
||||||
|
) continue;
|
||||||
|
|
||||||
|
// ensure that none of the excluded terms is in the search result
|
||||||
|
for (i = 0; i < excluded.length; i++) {
|
||||||
|
if (terms[excluded[i]] == file ||
|
||||||
|
titleterms[excluded[i]] == file ||
|
||||||
|
$u.contains(terms[excluded[i]] || [], file) ||
|
||||||
|
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have still a valid result we can add it to the result list
|
||||||
|
if (valid) {
|
||||||
|
// select one (max) score for the file.
|
||||||
|
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||||
|
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||||
|
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to return a node containing the
|
||||||
|
* search summary for a given text. keywords is a list
|
||||||
|
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||||
|
* words. the first one is used to find the occurrence, the
|
||||||
|
* latter for highlighting it.
|
||||||
|
*/
|
||||||
|
makeSearchSummary : function(htmlText, keywords, hlwords) {
|
||||||
|
var text = Search.htmlToText(htmlText);
|
||||||
|
var textLower = text.toLowerCase();
|
||||||
|
var start = 0;
|
||||||
|
$.each(keywords, function() {
|
||||||
|
var i = textLower.indexOf(this.toLowerCase());
|
||||||
|
if (i > -1)
|
||||||
|
start = i;
|
||||||
|
});
|
||||||
|
start = Math.max(start - 120, 0);
|
||||||
|
var excerpt = ((start > 0) ? '...' : '') +
|
||||||
|
$.trim(text.substr(start, 240)) +
|
||||||
|
((start + 240 - text.length) ? '...' : '');
|
||||||
|
var rv = $('<p class="context"></p>').text(excerpt);
|
||||||
|
$.each(hlwords, function() {
|
||||||
|
rv = rv.highlightText(this, 'highlighted');
|
||||||
|
});
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
Search.init();
|
||||||
|
});
|
159
Documentation/html/_static/sidebar.js
Normal file
159
Documentation/html/_static/sidebar.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* sidebar.js
|
||||||
|
* ~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This script makes the Sphinx sidebar collapsible.
|
||||||
|
*
|
||||||
|
* .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
|
||||||
|
* in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
|
||||||
|
* used to collapse and expand the sidebar.
|
||||||
|
*
|
||||||
|
* When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
|
||||||
|
* and the width of the sidebar and the margin-left of the document
|
||||||
|
* are decreased. When the sidebar is expanded the opposite happens.
|
||||||
|
* This script saves a per-browser/per-session cookie used to
|
||||||
|
* remember the position of the sidebar among the pages.
|
||||||
|
* Once the browser is closed the cookie is deleted and the position
|
||||||
|
* reset to the default (expanded).
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// global elements used by the functions.
|
||||||
|
// the 'sidebarbutton' element is defined as global after its
|
||||||
|
// creation, in the add_sidebar_button function
|
||||||
|
var bodywrapper = $('.bodywrapper');
|
||||||
|
var sidebar = $('.sphinxsidebar');
|
||||||
|
var sidebarwrapper = $('.sphinxsidebarwrapper');
|
||||||
|
|
||||||
|
// for some reason, the document has no sidebar; do not run into errors
|
||||||
|
if (!sidebar.length) return;
|
||||||
|
|
||||||
|
// original margin-left of the bodywrapper and width of the sidebar
|
||||||
|
// with the sidebar expanded
|
||||||
|
var bw_margin_expanded = bodywrapper.css('margin-left');
|
||||||
|
var ssb_width_expanded = sidebar.width();
|
||||||
|
|
||||||
|
// margin-left of the bodywrapper and width of the sidebar
|
||||||
|
// with the sidebar collapsed
|
||||||
|
var bw_margin_collapsed = '.8em';
|
||||||
|
var ssb_width_collapsed = '.8em';
|
||||||
|
|
||||||
|
// colors used by the current theme
|
||||||
|
var dark_color = $('.related').css('background-color');
|
||||||
|
var light_color = $('.document').css('background-color');
|
||||||
|
|
||||||
|
function sidebar_is_collapsed() {
|
||||||
|
return sidebarwrapper.is(':not(:visible)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle_sidebar() {
|
||||||
|
if (sidebar_is_collapsed())
|
||||||
|
expand_sidebar();
|
||||||
|
else
|
||||||
|
collapse_sidebar();
|
||||||
|
}
|
||||||
|
|
||||||
|
function collapse_sidebar() {
|
||||||
|
sidebarwrapper.hide();
|
||||||
|
sidebar.css('width', ssb_width_collapsed);
|
||||||
|
bodywrapper.css('margin-left', bw_margin_collapsed);
|
||||||
|
sidebarbutton.css({
|
||||||
|
'margin-left': '0',
|
||||||
|
'height': bodywrapper.height()
|
||||||
|
});
|
||||||
|
sidebarbutton.find('span').text('»');
|
||||||
|
sidebarbutton.attr('title', _('Expand sidebar'));
|
||||||
|
document.cookie = 'sidebar=collapsed';
|
||||||
|
}
|
||||||
|
|
||||||
|
function expand_sidebar() {
|
||||||
|
bodywrapper.css('margin-left', bw_margin_expanded);
|
||||||
|
sidebar.css('width', ssb_width_expanded);
|
||||||
|
sidebarwrapper.show();
|
||||||
|
sidebarbutton.css({
|
||||||
|
'margin-left': ssb_width_expanded-12,
|
||||||
|
'height': bodywrapper.height()
|
||||||
|
});
|
||||||
|
sidebarbutton.find('span').text('«');
|
||||||
|
sidebarbutton.attr('title', _('Collapse sidebar'));
|
||||||
|
document.cookie = 'sidebar=expanded';
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_sidebar_button() {
|
||||||
|
sidebarwrapper.css({
|
||||||
|
'float': 'left',
|
||||||
|
'margin-right': '0',
|
||||||
|
'width': ssb_width_expanded - 28
|
||||||
|
});
|
||||||
|
// create the button
|
||||||
|
sidebar.append(
|
||||||
|
'<div id="sidebarbutton"><span>«</span></div>'
|
||||||
|
);
|
||||||
|
var sidebarbutton = $('#sidebarbutton');
|
||||||
|
light_color = sidebarbutton.css('background-color');
|
||||||
|
// find the height of the viewport to center the '<<' in the page
|
||||||
|
var viewport_height;
|
||||||
|
if (window.innerHeight)
|
||||||
|
viewport_height = window.innerHeight;
|
||||||
|
else
|
||||||
|
viewport_height = $(window).height();
|
||||||
|
sidebarbutton.find('span').css({
|
||||||
|
'display': 'block',
|
||||||
|
'margin-top': (viewport_height - sidebar.position().top - 20) / 2
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebarbutton.click(toggle_sidebar);
|
||||||
|
sidebarbutton.attr('title', _('Collapse sidebar'));
|
||||||
|
sidebarbutton.css({
|
||||||
|
'color': '#FFFFFF',
|
||||||
|
'border-left': '1px solid ' + dark_color,
|
||||||
|
'font-size': '1.2em',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'height': bodywrapper.height(),
|
||||||
|
'padding-top': '1px',
|
||||||
|
'margin-left': ssb_width_expanded - 12
|
||||||
|
});
|
||||||
|
|
||||||
|
sidebarbutton.hover(
|
||||||
|
function () {
|
||||||
|
$(this).css('background-color', dark_color);
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
$(this).css('background-color', light_color);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_position_from_cookie() {
|
||||||
|
if (!document.cookie)
|
||||||
|
return;
|
||||||
|
var items = document.cookie.split(';');
|
||||||
|
for(var k=0; k<items.length; k++) {
|
||||||
|
var key_val = items[k].split('=');
|
||||||
|
var key = key_val[0].replace(/ /, ""); // strip leading spaces
|
||||||
|
if (key == 'sidebar') {
|
||||||
|
var value = key_val[1];
|
||||||
|
if ((value == 'collapsed') && (!sidebar_is_collapsed()))
|
||||||
|
collapse_sidebar();
|
||||||
|
else if ((value == 'expanded') && (sidebar_is_collapsed()))
|
||||||
|
expand_sidebar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_sidebar_button();
|
||||||
|
var sidebarbutton = $('#sidebarbutton');
|
||||||
|
set_position_from_cookie();
|
||||||
|
});
|
2027
Documentation/html/_static/underscore-1.12.0.js
Normal file
2027
Documentation/html/_static/underscore-1.12.0.js
Normal file
File diff suppressed because it is too large
Load Diff
6
Documentation/html/_static/underscore.js
Normal file
6
Documentation/html/_static/underscore.js
Normal file
File diff suppressed because one or more lines are too long
158
Documentation/html/examples.html
Normal file
158
Documentation/html/examples.html
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Examples — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="API Reference" href="reference.html" />
|
||||||
|
<link rel="prev" title="Getting Started Fast" href="gettingstartedfast.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="reference.html" title="API Reference"
|
||||||
|
accesskey="N">next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
|
accesskey="P">previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<div class="section" id="examples">
|
||||||
|
<span id="examples-main"></span><h1>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>A number of examples are included in the source distribution of Reticulum.
|
||||||
|
You can use these examples to learn how to write your own programs.</p>
|
||||||
|
<div class="section" id="minimal">
|
||||||
|
<span id="example-minimal"></span><h2>Minimal<a class="headerlink" href="#minimal" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Minimal</em> example demonstrates the bare-minimum setup required to connect to
|
||||||
|
a Reticulum network from your program. In about five lines of code, you will
|
||||||
|
have the Reticulum Network Stack initialised, and ready to pass traffic in your
|
||||||
|
program.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="announce">
|
||||||
|
<span id="example-announce"></span><h2>Announce<a class="headerlink" href="#announce" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Announce</em> example builds upon the previous example by exploring how to
|
||||||
|
announce a destination on the network, and how to let your program receive
|
||||||
|
notifications about announces from relevant destinations.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="broadcast">
|
||||||
|
<span id="example-broadcast"></span><h2>Broadcast<a class="headerlink" href="#broadcast" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Broadcast</em> example explores how to transmit plaintext broadcast messages
|
||||||
|
over the network.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="echo">
|
||||||
|
<span id="example-echo"></span><h2>Echo<a class="headerlink" href="#echo" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Echo</em> example demonstrates communication between two destinations using
|
||||||
|
the Packet interface.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="link">
|
||||||
|
<span id="example-link"></span><h2>Link<a class="headerlink" href="#link" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Link</em> example explores establishing an encrypted link to a remote
|
||||||
|
destination, and passing traffic back and forth over the link.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="filetransfer">
|
||||||
|
<span id="example-filetransfer"></span><h2>Filetransfer<a class="headerlink" href="#filetransfer" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This example can 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>
|
||||||
|
<p>The <em>Filetransfer</em> example implements a basic file-server program that
|
||||||
|
allow clients to connect and download files. The program uses the Resource
|
||||||
|
interface to efficiently pass files of any size over a Reticulum <a class="reference internal" href="reference.html#api-link"><span class="std std-ref">Link</span></a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h3><a href="index.html">Table of Contents</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li><a class="reference internal" href="#">Examples</a><ul>
|
||||||
|
<li><a class="reference internal" href="#minimal">Minimal</a></li>
|
||||||
|
<li><a class="reference internal" href="#announce">Announce</a></li>
|
||||||
|
<li><a class="reference internal" href="#broadcast">Broadcast</a></li>
|
||||||
|
<li><a class="reference internal" href="#echo">Echo</a></li>
|
||||||
|
<li><a class="reference internal" href="#link">Link</a></li>
|
||||||
|
<li><a class="reference internal" href="#filetransfer">Filetransfer</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Previous topic</h4>
|
||||||
|
<p class="topless"><a href="gettingstartedfast.html"
|
||||||
|
title="previous chapter">Getting Started Fast</a></p>
|
||||||
|
<h4>Next topic</h4>
|
||||||
|
<p class="topless"><a href="reference.html"
|
||||||
|
title="next chapter">API Reference</a></p>
|
||||||
|
<div role="note" aria-label="source link">
|
||||||
|
<h3>This Page</h3>
|
||||||
|
<ul class="this-page-menu">
|
||||||
|
<li><a href="_sources/examples.rst.txt"
|
||||||
|
rel="nofollow">Show Source</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="reference.html" title="API Reference"
|
||||||
|
>next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
|
>previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Examples</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
384
Documentation/html/genindex.html
Normal file
384
Documentation/html/genindex.html
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Index — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="#" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="#" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
|
||||||
|
<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="#V"><strong>V</strong></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<h2 id="A">A</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Resource.advertise">advertise() (RNS.Resource method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.announce">announce() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.app_and_aspects_from_name">app_and_aspects_from_name() (RNS.Destination static method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="C">C</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Resource.cancel">cancel() (RNS.Resource method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.clear_default_app_data">clear_default_app_data() (RNS.Destination 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.Link.CURVE">CURVE (RNS.Link attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="D">D</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.decrypt">decrypt() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.decrypt">(RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="reference.html#RNS.Link.DEFAULT_TIMEOUT">DEFAULT_TIMEOUT (RNS.Link attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.delivery_callback">delivery_callback() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Transport.deregister_announce_handler">deregister_announce_handler() (RNS.Transport static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination">Destination (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.disable_encryption">disable_encryption() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="E">E</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.encrypt">encrypt() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.encrypt">(RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="F">F</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.from_file">from_file() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.full_hash">full_hash() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.full_name">full_name() (RNS.Destination static method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="G">G</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.get_private_key">get_private_key() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.get_private_key">(RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.get_public_key">get_public_key() (RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Identity.get_random_hash">get_random_hash() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.get_status">get_status() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="H">H</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Transport.has_path">has_path() (RNS.Transport static method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.hash">hash() (RNS.Destination static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.hash_from_name_and_identity">hash_from_name_and_identity() (RNS.Destination static method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="I">I</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity">Identity (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.inactive_for">inactive_for() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="K">K</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.KEEPALIVE">KEEPALIVE (RNS.Link attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.KEYSIZE">KEYSIZE (RNS.Identity attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="L">L</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link">Link (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.link_established_callback">link_established_callback() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Destination.load_private_key">load_private_key() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.load_private_key">(RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
<li><a href="reference.html#RNS.Identity.load_public_key">load_public_key() (RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="M">M</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Resource.MAX_EFFICIENT_SIZE">MAX_EFFICIENT_SIZE (RNS.Resource attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="N">N</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.no_inbound_for">no_inbound_for() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.no_outbound_for">no_outbound_for() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="P">P</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Packet">Packet (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.packet_callback">packet_callback() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.packet_callback">(RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt">PacketReceipt (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Resource.progress">progress() (RNS.Resource method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.proof_requested_callback">proof_requested_callback() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="R">R</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<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>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Transport.register_announce_handler">register_announce_handler() (RNS.Transport static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Transport.request_path">request_path() (RNS.Transport static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Packet.resend">resend() (RNS.Packet method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Resource">Resource (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.resource_callback">resource_callback() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.resource_concluded_callback">resource_concluded_callback() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.resource_started_callback">resource_started_callback() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Reticulum">Reticulum (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.rtt">rtt() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="S">S</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Packet.send">send() (RNS.Packet method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.set_default_app_data">set_default_app_data() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.set_proof_strategy">set_proof_strategy() (RNS.Destination method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Link.set_resource_strategy">set_resource_strategy() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.set_timeout">set_timeout() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Reticulum.should_allow_unencrypted">should_allow_unencrypted() (RNS.Reticulum static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Reticulum.should_use_implicit_proof">should_use_implicit_proof() (RNS.Reticulum static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Destination.sign">sign() (RNS.Destination method)</a>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.sign">(RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="T">T</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Link.teardown">teardown() (RNS.Link method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.PacketReceipt.timeout_callback">timeout_callback() (RNS.PacketReceipt method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Identity.to_file">to_file() (RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Transport">Transport (class in RNS)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Reticulum.transport_enabled">transport_enabled() (RNS.Reticulum static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Identity.truncated_hash">truncated_hash() (RNS.Identity static method)</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="reference.html#RNS.Identity.TRUNCATED_HASHLENGTH">TRUNCATED_HASHLENGTH (RNS.Identity attribute)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
<h2 id="V">V</h2>
|
||||||
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
|
<li><a href="reference.html#RNS.Identity.validate">validate() (RNS.Identity method)</a>
|
||||||
|
</li>
|
||||||
|
</ul></td>
|
||||||
|
</tr></table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="#" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Index</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
175
Documentation/html/gettingstartedfast.html
Normal file
175
Documentation/html/gettingstartedfast.html
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Getting Started Fast — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="Examples" href="examples.html" />
|
||||||
|
<link rel="prev" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="examples.html" title="Examples"
|
||||||
|
accesskey="N">next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
|
accesskey="P">previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<div class="section" id="getting-started-fast">
|
||||||
|
<h1>Getting Started Fast<a class="headerlink" href="#getting-started-fast" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>What do we want to do? Something! When do want to do it? Right now!</p>
|
||||||
|
<p>The best way to get started with the Reticulum Network Stack depends on what
|
||||||
|
you want to do. This guide will outline sensible starting paths for different
|
||||||
|
scenarios.</p>
|
||||||
|
<div class="section" id="try-using-a-reticulum-based-program">
|
||||||
|
<h2>Try Using a Reticulum-based Program<a class="headerlink" href="#try-using-a-reticulum-based-program" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>If you simply want to try using a program built with Reticulum, you can take
|
||||||
|
a look at <a class="reference external" href="https://github.com/markqvist/nomadnet">Nomad Network</a>, which
|
||||||
|
provides a basic encrypted communications suite built completely on Reticulum.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="develop-a-program-with-reticulum">
|
||||||
|
<h2>Develop a Program with Reticulum<a class="headerlink" href="#develop-a-program-with-reticulum" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>If you want to develop programs that use Reticulum, the easiest way to get
|
||||||
|
started is to install Reticulum via pip:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip3</span> <span class="n">install</span> <span class="n">rns</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>The above command will install Reticulum and dependencies, and you will be
|
||||||
|
ready to import and use RNS in your own programs. The next step will most
|
||||||
|
likely be to look at some <a class="reference internal" href="examples.html#examples-main"><span class="std std-ref">Example Programs</span></a>.</p>
|
||||||
|
<p>Further information can be found in the <a class="reference internal" href="reference.html#api-main"><span class="std std-ref">API Reference</span></a>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="participate-in-reticulum-development">
|
||||||
|
<h2>Participate in Reticulum Development<a class="headerlink" href="#participate-in-reticulum-development" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>If you want to participate in the development of Reticulum and associated
|
||||||
|
utilities, you’ll want to get the latest source from GitHub. In that case,
|
||||||
|
don’t use pip, but try this recipe:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># Install dependencies</span>
|
||||||
|
<span class="n">pip3</span> <span class="n">install</span> <span class="n">cryptography</span> <span class="n">pyserial</span>
|
||||||
|
|
||||||
|
<span class="c1"># Clone repository</span>
|
||||||
|
<span class="n">git</span> <span class="n">clone</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">github</span><span class="o">.</span><span class="n">com</span><span class="o">/</span><span class="n">markqvist</span><span class="o">/</span><span class="n">Reticulum</span><span class="o">.</span><span class="n">git</span>
|
||||||
|
|
||||||
|
<span class="c1"># Move into Reticulum folder and symlink library to examples folder</span>
|
||||||
|
<span class="n">cd</span> <span class="n">Reticulum</span>
|
||||||
|
<span class="n">ln</span> <span class="o">-</span><span class="n">s</span> <span class="o">../</span><span class="n">RNS</span> <span class="o">./</span><span class="n">Examples</span><span class="o">/</span>
|
||||||
|
|
||||||
|
<span class="c1"># Run an example</span>
|
||||||
|
<span class="n">python3</span> <span class="n">Examples</span><span class="o">/</span><span class="n">Echo</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">s</span>
|
||||||
|
|
||||||
|
<span class="c1"># Unless you've manually created a config file, Reticulum will do so now,</span>
|
||||||
|
<span class="c1"># and immediately exit. Make any necessary changes to the file:</span>
|
||||||
|
<span class="n">nano</span> <span class="o">~/.</span><span class="n">reticulum</span><span class="o">/</span><span class="n">config</span>
|
||||||
|
|
||||||
|
<span class="c1"># ... and launch the example again.</span>
|
||||||
|
<span class="n">python3</span> <span class="n">Examples</span><span class="o">/</span><span class="n">Echo</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">s</span>
|
||||||
|
|
||||||
|
<span class="c1"># You can now repeat the process on another computer,</span>
|
||||||
|
<span class="c1"># and run the same example with -h to get command line options.</span>
|
||||||
|
<span class="n">python3</span> <span class="n">Examples</span><span class="o">/</span><span class="n">Echo</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">h</span>
|
||||||
|
|
||||||
|
<span class="c1"># Run the example in client mode to "ping" the server.</span>
|
||||||
|
<span class="c1"># Replace the hash below with the actual destination hash of your server.</span>
|
||||||
|
<span class="n">python3</span> <span class="n">Examples</span><span class="o">/</span><span class="n">Echo</span><span class="o">.</span><span class="n">py</span> <span class="mf">3e12</span><span class="n">fc71692f8ec47bc5</span>
|
||||||
|
|
||||||
|
<span class="c1"># Have a look at another example</span>
|
||||||
|
<span class="n">python3</span> <span class="n">Examples</span><span class="o">/</span><span class="n">Filetransfer</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">h</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>When you have experimented with the basic examples, it’s time to go read the
|
||||||
|
<a class="reference internal" href="understanding.html#understanding-main"><span class="std std-ref">Understanding Reticulum</span></a> chapter.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h3><a href="index.html">Table of Contents</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li><a class="reference internal" href="#">Getting Started Fast</a><ul>
|
||||||
|
<li><a class="reference internal" href="#try-using-a-reticulum-based-program">Try Using a Reticulum-based Program</a></li>
|
||||||
|
<li><a class="reference internal" href="#develop-a-program-with-reticulum">Develop a Program with Reticulum</a></li>
|
||||||
|
<li><a class="reference internal" href="#participate-in-reticulum-development">Participate in Reticulum Development</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Previous topic</h4>
|
||||||
|
<p class="topless"><a href="whatis.html"
|
||||||
|
title="previous chapter">What is Reticulum?</a></p>
|
||||||
|
<h4>Next topic</h4>
|
||||||
|
<p class="topless"><a href="examples.html"
|
||||||
|
title="next chapter">Examples</a></p>
|
||||||
|
<div role="note" aria-label="source link">
|
||||||
|
<h3>This Page</h3>
|
||||||
|
<ul class="this-page-menu">
|
||||||
|
<li><a href="_sources/gettingstartedfast.rst.txt"
|
||||||
|
rel="nofollow">Show Source</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="examples.html" title="Examples"
|
||||||
|
>next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
|
>previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Getting Started Fast</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
191
Documentation/html/index.html
Normal file
191
Documentation/html/index.html
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Reticulum Network Stack Documentation — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="What is Reticulum?" href="whatis.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
|
accesskey="N">next</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Documentation</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<div class="section" id="reticulum-network-stack-documentation">
|
||||||
|
<h1>Reticulum Network Stack Documentation<a class="headerlink" href="#reticulum-network-stack-documentation" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Welcome to the documentation for Reticulum. This document aims to provide you
|
||||||
|
with all the information you need to understand Reticulum, develop programs
|
||||||
|
using it, or to participate in the development of Reticulum itself.</p>
|
||||||
|
<div class="section" id="table-of-contents">
|
||||||
|
<h2>Table of Contents<a class="headerlink" href="#table-of-contents" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<div class="toctree-wrapper compound">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="whatis.html">What is Reticulum?</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="whatis.html#what-does-reticulum-offer">What does Reticulum Offer?</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="whatis.html#where-can-reticulum-be-used">Where can Reticulum be Used?</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="whatis.html#supported-interface-types-and-devices">Supported Interface Types and Devices</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="gettingstartedfast.html">Getting Started Fast</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="gettingstartedfast.html#try-using-a-reticulum-based-program">Try Using a Reticulum-based Program</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="gettingstartedfast.html#develop-a-program-with-reticulum">Develop a Program with Reticulum</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="gettingstartedfast.html#participate-in-reticulum-development">Participate in Reticulum Development</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="examples.html">Examples</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#minimal">Minimal</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#announce">Announce</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#broadcast">Broadcast</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#echo">Echo</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#link">Link</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="examples.html#filetransfer">Filetransfer</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="reference.html">API Reference</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="reference.html#classes">Classes</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#reticulum">Reticulum</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#api-identity">Identity</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#destination">Destination</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#packet">Packet</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#packet-receipt">Packet Receipt</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#link">Link</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#resource">Resource</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="reference.html#transport">Transport</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="understanding.html">Understanding Reticulum</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#motivation">Motivation</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#goals">Goals</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#introduction-basic-functionality">Introduction & Basic Functionality</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#destinations">Destinations</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#public-key-announcements">Public Key Announcements</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#identities">Identities</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#getting-further">Getting Further</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reticulum-transport">Reticulum Transport</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#threading-a-path">Threading a Path</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#crossing-continents">Crossing Continents</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#resourceful-memory">Resourceful Memory</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#reference-system-setup">Reference System Setup</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="understanding.html#protocol-specifics">Protocol Specifics</a><ul>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#node-types">Node Types</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#packet-prioritisation">Packet Prioritisation</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#path-calculation">Path Calculation</a></li>
|
||||||
|
<li class="toctree-l3"><a class="reference internal" href="understanding.html#binary-packet-format">Binary Packet Format</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="current-status">
|
||||||
|
<h2>Current Status<a class="headerlink" href="#current-status" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>Reticulum should currently be considered beta software. All core protocol features are implemented and functioning, but additions will probably occur as real-world use is explored. The API and wire-format can be considered relatively stable at the moment, but could change if warranted.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="caveat-emptor">
|
||||||
|
<h2>Caveat Emptor<a class="headerlink" href="#caveat-emptor" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>Reticulum is experimental software, and should be considered as such. While it has been built with cryptography best-practices very foremost in mind, it has not been externally security audited, and there could very well be privacy-breaking bugs. To be considered secure, Reticulum needs a very thourough security review by independt cryptographers and security researchers. If you want to help out, or help sponsor an audit, please do get in touch.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="indices-and-tables">
|
||||||
|
<h2>Indices and Tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
|
||||||
|
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
|
||||||
|
<li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h3><a href="#">Table of Contents</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li><a class="reference internal" href="#">Reticulum Network Stack Documentation</a><ul>
|
||||||
|
<li><a class="reference internal" href="#table-of-contents">Table of Contents</a></li>
|
||||||
|
<li><a class="reference internal" href="#current-status">Current Status</a></li>
|
||||||
|
<li><a class="reference internal" href="#caveat-emptor">Caveat Emptor</a></li>
|
||||||
|
<li><a class="reference internal" href="#indices-and-tables">Indices and Tables</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Next topic</h4>
|
||||||
|
<p class="topless"><a href="whatis.html"
|
||||||
|
title="next chapter">What is Reticulum?</a></p>
|
||||||
|
<div role="note" aria-label="source link">
|
||||||
|
<h3>This Page</h3>
|
||||||
|
<ul class="this-page-menu">
|
||||||
|
<li><a href="_sources/index.rst.txt"
|
||||||
|
rel="nofollow">Show Source</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="whatis.html" title="What is Reticulum?"
|
||||||
|
>next</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="#">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Reticulum Network Stack Documentation</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
Documentation/html/objects.inv
Normal file
BIN
Documentation/html/objects.inv
Normal file
Binary file not shown.
1046
Documentation/html/reference.html
Normal file
1046
Documentation/html/reference.html
Normal file
File diff suppressed because it is too large
Load Diff
97
Documentation/html/search.html
Normal file
97
Documentation/html/search.html
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Search — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<script src="_static/searchtools.js"></script>
|
||||||
|
<script src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="#" />
|
||||||
|
<script src="searchindex.js" defer></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<h1 id="search-documentation">Search</h1>
|
||||||
|
|
||||||
|
<div id="fallback" class="admonition warning">
|
||||||
|
<script>$('#fallback').hide();</script>
|
||||||
|
<p>
|
||||||
|
Please activate JavaScript to enable the search
|
||||||
|
functionality.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Searching for multiple words only shows matches that contain
|
||||||
|
all words.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="search-documentation" value="" />
|
||||||
|
<input type="submit" value="search" />
|
||||||
|
<span id="search-progress" style="padding-left: 10px"></span>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="search-results">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Search</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
Documentation/html/searchindex.js
Normal file
1
Documentation/html/searchindex.js
Normal file
File diff suppressed because one or more lines are too long
683
Documentation/html/understanding.html
Normal file
683
Documentation/html/understanding.html
Normal file
@ -0,0 +1,683 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Understanding Reticulum — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="prev" title="API Reference" href="reference.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="reference.html" title="API Reference"
|
||||||
|
accesskey="P">previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<div class="section" id="understanding-reticulum">
|
||||||
|
<span id="understanding-main"></span><h1>Understanding Reticulum<a class="headerlink" href="#understanding-reticulum" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>This chapter will briefly describe the overall purpose and operating principles of Reticulum, a
|
||||||
|
networking stack designed for reliable and secure communication over high-latency, low-bandwidth
|
||||||
|
links. It should give you an overview of how the stack works, and an understanding of how to
|
||||||
|
develop networked applications using Reticulum.</p>
|
||||||
|
<p>This document is not an exhaustive source of information on Reticulum, at least not yet. Currently,
|
||||||
|
the best place to go for such information is the Python reference implementation of Reticulum, along
|
||||||
|
with the API reference.</p>
|
||||||
|
<p>After reading this document, you should be well-equipped to understand how a Reticulum network
|
||||||
|
operates, what it can achieve, and how you can use it yourself. If you want to help out with the
|
||||||
|
development, this is also the place to start, since it will also provide a pretty clear overview of the
|
||||||
|
sentiments and the philosophy behind Reticulum.</p>
|
||||||
|
<div class="section" id="motivation">
|
||||||
|
<h2>Motivation<a class="headerlink" href="#motivation" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>The primary motivation for designing and implementing Reticulum has been the current lack of
|
||||||
|
reliable, functional and secure minimal-infrastructure modes of digital communication. It is my
|
||||||
|
belief that it is highly desirable to create a cheap and reliable way to set up a wide-range digital
|
||||||
|
communication network that can securely allow exchange of information between people and
|
||||||
|
machines, with no central point of authority, control, censorship or barrier to entry.</p>
|
||||||
|
<p>Almost all of the various networking stacks in wide use today share a common limitation, namely
|
||||||
|
that they require large amounts of coordination and trust to work. You can’t just plug in a bunch of
|
||||||
|
ethernet cables to the same switch, or turn on a number of WiFi radios, and expect such a setup to
|
||||||
|
provide a reliable platform for communication.</p>
|
||||||
|
<p>This need for coordination and trust inevitably leads to an environment of control, where it’s very
|
||||||
|
easy for infrastructure operators or governments to control or alter traffic.</p>
|
||||||
|
<p>Reticulum aims to require as little coordination and trust as possible. In fact, the only
|
||||||
|
“coordination” required is to know how to get connected to a Reticulum network. Since Reticulum
|
||||||
|
is medium agnostic, this could be whatever is best suited to the situation. In some cases, this might
|
||||||
|
be 1200 baud packet radio links over VHF frequencies, in other cases it might be a microwave
|
||||||
|
network using off-the-shelf radios. At the time of release of this document, the recommended setup
|
||||||
|
is using cheap LoRa radio modules with an open source firmware (see the chapter <em>Reference System
|
||||||
|
Setup</em> ), connected to a small computer like a Raspberry Pi. As an example, the default reference
|
||||||
|
setup provides a channel capacity of 5.4 Kbps, and a usable direct node-to-node range of around 15
|
||||||
|
kilometers (indefinitely extendable by using multiple hops).</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="goals">
|
||||||
|
<h2>Goals<a class="headerlink" href="#goals" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>To be as widely usable and easy to implement as possible, the following goals have been used to
|
||||||
|
guide the design of Reticulum:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Fully useable as open source software stack</strong></dt><dd><p>Reticulum must be implemented, and be able to run using only open source software. This is
|
||||||
|
critical to ensuring availability, security and transparency of the system.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Hardware layer agnosticism</strong></dt><dd><p>Reticulum shall be fully hardware agnostic, and should be useable over a wide range
|
||||||
|
physical networking layers, such as data radios, serial lines, modems, handheld transceivers,
|
||||||
|
wired ethernet, wifi, or anything else that can carry a digital data stream. Hardware made for
|
||||||
|
dedicated Reticulum use shall be as cheap as possible and use off-the-shelf components, so
|
||||||
|
it can be easily replicated.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Very low bandwidth requirements</strong></dt><dd><p>Reticulum should be able to function reliably over links with a data capacity as low as <em>1,</em>
|
||||||
|
<em>bps</em>.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Encryption by default</strong></dt><dd><p>Reticulum must use encryption by default where possible and applicable.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Unlicensed use</strong></dt><dd><p>Reticulum shall be functional over physical communication mediums that do not require any
|
||||||
|
form of license to use. Reticulum must be designed in a way, so it is usable over ISM radio
|
||||||
|
frequency bands, and can provide functional long distance links in such conditions.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Supplied software</strong></dt><dd><p>Apart from the core networking stack and API, that allows any developer to build
|
||||||
|
applications with Reticulum, a basic communication suite using Reticulum must be
|
||||||
|
implemented and released at the same time as Reticulum itself. This shall serve both as a
|
||||||
|
functional communication suite, and as an example and learning resource to others wishing
|
||||||
|
to build applications with Reticulum.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Ease of use</strong></dt><dd><p>The reference implementation of Reticulum is written in Python, to make it very easy to use
|
||||||
|
and understand. Any programmer with only basic experience should be able to use
|
||||||
|
Reticulum in their own applications.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Low cost</strong></dt><dd><p>It shall be as cheap as possible to deploy a communication system based on Reticulum. This
|
||||||
|
should be achieved by using cheap off-the-shelf hardware that potential users might already
|
||||||
|
own. The cost of setting up a functioning node should be less than $100 even if all parts
|
||||||
|
needs to be purchased.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="introduction-basic-functionality">
|
||||||
|
<h2>Introduction & Basic Functionality<a class="headerlink" href="#introduction-basic-functionality" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>Reticulum is a networking stack suited for high-latency, low-bandwidth links. Reticulum is at it’s
|
||||||
|
core <em>message oriented</em> , but can provide connection oriented sessions. It is suited for both local
|
||||||
|
point-to-point or point-to-multipoint scenarios where alle nodes are within range of each other, as
|
||||||
|
well as scenarios where packets need to be transported over multiple hops to reach the recipient.</p>
|
||||||
|
<p>Reticulum does away with the idea of addresses and ports known from IP, TCP and UDP. Instead
|
||||||
|
Reticulum uses the singular concept of <em>destinations</em>. Any application using Reticulum as it’s
|
||||||
|
networking stack will need to create one or more destinations to receive data, and know the
|
||||||
|
destinations it needs to send data to.</p>
|
||||||
|
<p>Reticulum encrypts all data by default using public-key cryptography. Any message sent to a
|
||||||
|
destination is encrypted with that destinations public key. Reticulum also offers symmetric key
|
||||||
|
encryption for group-oriented communications, as well as unencrypted packets for broadcast
|
||||||
|
purposes, or situations where you need the communication to be in plain text. The multi-hop
|
||||||
|
transport, coordination, verification and reliability layers are fully autonomous and based on public
|
||||||
|
key cryptography.</p>
|
||||||
|
<p>Reticulum can connect to a variety of interfaces such as radio modems, data radios and serial ports,
|
||||||
|
and offers the possibility to easily tunnel Reticulum traffic over IP links such as the Internet or
|
||||||
|
private IP networks.</p>
|
||||||
|
<div class="section" id="destinations">
|
||||||
|
<h3>Destinations<a class="headerlink" href="#destinations" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>To receive and send data with the Reticulum stack, an application needs to create one or more
|
||||||
|
destinations. Reticulum uses three different basic destination types, and one special:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Single</strong></dt><dd><p>The <em>single</em> destination type defines a public-key encrypted destination. Any data sent to this
|
||||||
|
destination will be encrypted with the destination’s public key, and will only be readable by
|
||||||
|
the creator of the destination.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Group</strong></dt><dd><p>The <em>group</em> destination type defines a symmetrically encrypted destination. Data sent to this
|
||||||
|
destination will be encrypted with a symmetric key, and will be readable by anyone in
|
||||||
|
possession of the key. The <em>group</em> destination can be used just as well by only two peers, as it
|
||||||
|
can by many.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Plain</strong></dt><dd><p>A <em>plain</em> destination type is unencrypted, and suited for traffic that should be broadcast to a
|
||||||
|
number of users, or should be readable by anyone.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Link</strong></dt><dd><p>A <em>link</em> is a special destination type, that serves as an abstract channel between two <em>single</em>
|
||||||
|
destinations, directly connected or over multiple hops. The <em>link</em> also offers reliability and
|
||||||
|
more efficient encryption, and as such is useful even when nodes are directly connected.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="section" id="destination-naming">
|
||||||
|
<h4>Destination Naming<a class="headerlink" href="#destination-naming" title="Permalink to this headline">¶</a></h4>
|
||||||
|
<p>Destinations are created and named in an easy to understand dotted notation of <em>aspects</em> , and
|
||||||
|
represented on the network as a hash of this value. The hash is a SHA-256 truncated to 80 bits. The
|
||||||
|
top level aspect should always be the a unique identifier for the application using the destination.
|
||||||
|
The next levels of aspects can be defined in any way by the creator of the application. For example,
|
||||||
|
a destination for a messaging application could be made up of the application name and a username,
|
||||||
|
and look like this:</p>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">name</span><span class="p">:</span> <span class="n">simplemessenger</span><span class="o">.</span><span class="n">someuser</span> <span class="nb">hash</span><span class="p">:</span> <span class="mi">2</span><span class="n">a7ddfab5213f916dea</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<p>For the <em>single</em> destination, Reticulum will automatically append the associated public key as a
|
||||||
|
destination aspect before hashing. This is done to ensure only the correct destination is reached,
|
||||||
|
since anyone can listen to any destination name. Appending the public key ensures that a given
|
||||||
|
packet is only directed at the destination that holds the corresponding private key to decrypt the
|
||||||
|
packet. It is important to understand that anyone can use the destination name
|
||||||
|
<em>simplemessenger.myusername</em> , but each person that does so will still have a different destination
|
||||||
|
hash, because their public keys will differ. In actual use of <em>single</em> destination naming, it is advisable
|
||||||
|
not to use any uniquely identifying features in aspect naming, though. In the simple messenger
|
||||||
|
example, when using <em>single</em> destinations, we would instead use a destination naming scheme such
|
||||||
|
as <em>simplemessenger.user</em> where appending the public key expands the destination into a uniquely
|
||||||
|
identifying one.</p>
|
||||||
|
<p>To recap, the destination types should be used in the following situations:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Single</strong></dt><dd><p>When private communication between two endpoints is needed. Supports routing.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Group</strong></dt><dd><p>When private communication between two or more endpoints is needed. More efficient in
|
||||||
|
data usage than <em>single</em> destinations. Supports routing indirectly, but must first be established
|
||||||
|
through a <em>single</em> destination.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Plain</strong></dt><dd><p>When plain-text communication is desirable, for example when broadcasting information.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>To communicate with a <em>single</em> destination, you need to know it’s public key. Any method for
|
||||||
|
obtaining the public key is valid, but Reticulum includes a simple mechanism for making other
|
||||||
|
nodes aware of your destinations public key, called the <em>announce</em>.</p>
|
||||||
|
<p>Note that this information could be shared and verified in many other ways, and that it is therefore
|
||||||
|
not required to use the announce functionality, although it is by far the easiest, and should probably
|
||||||
|
be used if you are not confident in how to verify public keys and signatures manually.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="public-key-announcements">
|
||||||
|
<h3>Public Key Announcements<a class="headerlink" href="#public-key-announcements" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>An <em>announce</em> will send a special packet over any configured interfaces, containing all needed
|
||||||
|
information about the destination hash and public key, and can also contain some additional,
|
||||||
|
application specific data. The entire packet is signed by the sender to ensure authenticity. It is not
|
||||||
|
required to use the announce functionality, but in many cases it will be the simplest way to share
|
||||||
|
public keys on the network. As an example, an announce in a simple messenger application might
|
||||||
|
contain the following information:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>The announcers destination hash</p></li>
|
||||||
|
<li><p>The announcers public key</p></li>
|
||||||
|
<li><p>Application specific data, in this case the users nickname and availability status</p></li>
|
||||||
|
<li><p>A random blob, making each new announce unique</p></li>
|
||||||
|
<li><p>A signature of the above information, verifying authenticity</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>With this information, any Reticulum node that receives it will be able to reconstruct an outgoing
|
||||||
|
destination to securely communicate with that destination. You might have noticed that there is one
|
||||||
|
piece of information lacking to reconstruct full knowledge of the announced destination, and that is
|
||||||
|
the aspect names of the destination. These are intentionally left out to save bandwidth, since they
|
||||||
|
will be implicit in almost all cases. If a destination name is not entirely implicit, information can be
|
||||||
|
included in the application specific data part that will allow the receiver to infer the naming.</p>
|
||||||
|
<p>It is important to note that announcements will be forwarded throughout the network according to a
|
||||||
|
certain pattern. This will be detailed later. Seeing how <em>single</em> destinations are always tied to a
|
||||||
|
private/public key pair leads us to the next topic.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="identities">
|
||||||
|
<h3>Identities<a class="headerlink" href="#identities" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>In Reticulum, an <em>identity</em> does not necessarily represent a personal identity, but is an abstraction that
|
||||||
|
can represent any kind of <em>verified entity</em>. This could very well be a person, but it could also be the
|
||||||
|
control interface of a machine, a program, robot, computer, sensor or something else entirely. In
|
||||||
|
general, any kind of agent that can act, or be acted upon, or store or manipulate information, can be
|
||||||
|
represented as an identity.</p>
|
||||||
|
<p>As we have seen, a <em>single</em> destination will always have an <em>identity</em> tied to it, but not <em>plain</em> or <em>group</em>
|
||||||
|
destinations. Destinations and identities share a multilateral connection. You can create a
|
||||||
|
destination, and if it is not connected to an identity upon creation, it will just create a new one to use
|
||||||
|
automatically. This may be desirable in some situations, but often you will probably want to create
|
||||||
|
the identity first, and then link it to created destinations.</p>
|
||||||
|
<p>Building upon the simple messenger example, we could use an identity to represent the user of the
|
||||||
|
application. Destinations created will then be linked to this identity to allow communication to
|
||||||
|
reach the user. In such a case it is of great importance to store the user’s identity securely and
|
||||||
|
privately.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="getting-further">
|
||||||
|
<h3>Getting Further<a class="headerlink" href="#getting-further" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>The above functions and principles form the core of Reticulum, and would suffice to create
|
||||||
|
functional networked applications in local clusters, for example over radio links where all interested
|
||||||
|
nodes can hear each other. But to be truly useful, we need a way to go further. In the next chapter,
|
||||||
|
two concepts that allow this will be introduced, <em>paths</em> and <em>resources</em>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="reticulum-transport">
|
||||||
|
<h2>Reticulum Transport<a class="headerlink" href="#reticulum-transport" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>I have purposefully avoided the term routing until now, and will continue to do so, because the
|
||||||
|
current methods of routing used in IP based networks are fundamentally incompatible for the link
|
||||||
|
types that Reticulum was designed to handle. These routing methodologies assume trust at the
|
||||||
|
physical layer. Since Reticulum is designed to run over open radio spectrum, no such trust exists.
|
||||||
|
Furthermore, existing routing protocols like BGP or OSPF carry too much overhead to be
|
||||||
|
practically useable over bandwidth-limited, high-latency links.</p>
|
||||||
|
<p>To overcome such challenges, Reticulum’s <em>Transport</em> system uses public-key cryptography to
|
||||||
|
implement the concept of <em>paths</em> that allow discovery of how to get information to a certain
|
||||||
|
destination, and <em>resources</em> that help alleviate congestion and make reliable communication more
|
||||||
|
efficient and less bandwidth-hungry.</p>
|
||||||
|
<div class="section" id="threading-a-path">
|
||||||
|
<h3>Threading a Path<a class="headerlink" href="#threading-a-path" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>In networks with changing topology and trustless connectivity, nodes need a way to establish
|
||||||
|
<em>verified connectivity</em> with each other. To do this, the following process is employed:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>First, the node that wishes to establish connectivity will send out a special packet, that</dt><dd><p>traverses the network and locates the desired destination. Along the way, the nodes that
|
||||||
|
forward the packet will take note of this <em>link request</em>.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>Second, if the destination accepts the <em>link request</em> , it will send back a packet that proves the</dt><dd><p>authenticity of it’s identity (and the receipt of the link request) to the initiating node. All
|
||||||
|
nodes that initially forwarded the packet will also be able to verify this proof, and thus
|
||||||
|
accept the validity of the <em>link</em> throughout the network.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>When the validity of the <em>link</em> has been accepted by forwarding nodes, these nodes will</dt><dd><p>remember the <em>link</em> , and it can subsequently be used by referring to a hash representing it.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>As a part of the <em>link request</em> , a Diffie-Hellman key exchange takes place, that sets up an</dt><dd><p>efficient symmetrically encrypted tunnel between the two nodes, using elliptic curve
|
||||||
|
cryptography. As such, this mode of communication is preferred, even for situations when
|
||||||
|
nodes can directly communicate, when the amount of data to be exchanged numbers in the
|
||||||
|
tens of packets.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>When a <em>link</em> has been set up, it automatically provides message receipt functionality, so the</dt><dd><p>sending node can obtain verified confirmation that the information reached the intended
|
||||||
|
recipient.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>In a moment, we will discuss the specifics of how this methodology is implemented, but let’s first
|
||||||
|
recap what purposes this serves. We first ensure that the node answering our request is actually the
|
||||||
|
one we want to communicate with, and not a malicious actor pretending to be so. At the same time
|
||||||
|
we establish an efficient encrypted channel. The setup of this is relatively cheap in terms of
|
||||||
|
bandwidth, so it can be used just for a short exchange, and then recreated as needed, which will also</p>
|
||||||
|
<p>rotate encryption keys (keys can also be rotated over an existing path), but the link can also be kept
|
||||||
|
alive for longer periods of time, if this is more suitable to the application. The amount of bandwidth
|
||||||
|
used on keeping a link open is practically negligible. The procedure also inserts the <em>link id</em> , a hash
|
||||||
|
calculated from the link request packet, into the memory of forwarding nodes, which means that the
|
||||||
|
communicating nodes can thereafter reach each other simply by referring to this <em>link id</em>.</p>
|
||||||
|
<p><strong>Step 1, pathfinding</strong></p>
|
||||||
|
<p>The pathfinding method builds on the <em>announce</em> functionality discussed earlier. When an announce
|
||||||
|
is sent out by a node, it will be forwarded by any node receiving it, but according to some specific
|
||||||
|
rules:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>If this announce has already been received before, ignore it.</p></li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>Record into a table which node the announce was received from, and how many times in</dt><dd><p>total it has been retransmitted to get here.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>If the announce has been retransmitted <em>m+1</em> times, it will not be forwarded. By default, <em>m</em> is</dt><dd><p>set to 18.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>The announce will be assigned a delay <em>d</em> = <em>ch</em> seconds, where <em>c</em> is a decay constant, by</dt><dd><p>default 2, and <em>h</em> is the amount of times this packet has already been forwarded.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><p>The packet will be given a priority <em>p = 1/d</em>.</p></li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>If at least <em>d</em> seconds has passed since the announce was received, and no other packets with a</dt><dd><p>priority higher than <em>p</em> are waiting in the queue (see Packet Prioritisation), and the channel is
|
||||||
|
not utilized by other traffic, the announce will be forwarded.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>If no other nodes are heard retransmitting the announce with a greater hop count than when</dt><dd><p>it left this node, transmitting it will be retried <em>r</em> times. By default, <em>r</em> is set to 2. Retries follow
|
||||||
|
same rules as above, with the exception that it must wait for at least <em>d = ch+1 + t</em> seconds, ie.,
|
||||||
|
the amount of time it would take the next node to retransmit the packet. By default, <em>t</em> is set to
|
||||||
|
10.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>If a newer announce from the same destination arrives, while an identical one is already in</dt><dd><p>the queue, the newest announce is discarded. If the newest announce contains different
|
||||||
|
application specific data, it will replace the old announce, but will use <em>d</em> and <em>p</em> of the old
|
||||||
|
announce.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>Once an announce has reached a node in the network, any other node in direct contact with that
|
||||||
|
node will be able to reach the destination the announce originated from, simply by sending a packet
|
||||||
|
addressed to that destination. Any node with knowledge of the announce will be able to direct the
|
||||||
|
packet towards the destination by looking up the next node with the shortest amount of hops to the
|
||||||
|
destination. The specifics of this process is detailed in <em>Path Calculation</em>.</p>
|
||||||
|
<p>According to these rules and default constants, an announce will propagate throughout the network
|
||||||
|
in a predictable way. In an example network utilising the default constants, and with an average link</p>
|
||||||
|
<p>distance of <em>Lavg =</em> 15 kilometers, an announce will be able to propagate outwards to a radius of 180
|
||||||
|
kilometers in 34 minutes, and a <em>maximum announce radius</em> of 270 kilometers in approximately 3
|
||||||
|
days. Methods for overcoming the distance limitation of <em>m * Lavg</em> will be introduced later in this
|
||||||
|
chapter.</p>
|
||||||
|
<p><strong>Step 2, link establishment</strong></p>
|
||||||
|
<p>After seeing how the conditions for finding a path through the network are created, we will now
|
||||||
|
explore how two nodes can establish reliable communications over multiple hops. The <em>link</em> in
|
||||||
|
Reticulum terminology should not be viewed as a direct node-to-node link on the physical layer, but
|
||||||
|
as an abstract channel, that can be open for any amount of time, and can span an arbitrary number
|
||||||
|
of hops, where information will be exchanged between two nodes.</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>When a node in the network wants to establish verified connectivity with another node, it</dt><dd><p>will create a <em>link request</em> packet, and broadcast it.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>The <em>link request</em> packet contains the destination hash <em>Hd</em> , and an asymmetrically encrypted</dt><dd><p>part containing the following data: The source hash <em>Hs</em> , a symmetric key <em>Lk</em> , a truncated
|
||||||
|
hash of a random number <em>Hr</em> , and a signature <em>S</em> of the plaintext values of <em>Hd</em> , <em>Hs</em> , <em>Lk</em> and <em>Hr</em>.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>The broadcasted packet will be directed through the network according to the rules laid out</dt><dd><p>previously.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>Any node that forwards the link request will store a <em>link id</em> in it’s <em>link table</em> , along with the</dt><dd><p>amount of hops the packet had taken when received. The link id is a hash of the entire link
|
||||||
|
request packet. If the path is not <em>proven</em> within some set amount of time, the entry will be
|
||||||
|
dropped from the table again.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>When the destination receives the link request packet, it will decide whether to accept the</dt><dd><p>request. If it is accepted, it will create a special packet called a <em>proof</em>. A <em>proof</em> is a simple
|
||||||
|
construct, consisting of a truncated hash of the message that needs to be proven, and a
|
||||||
|
signature (made by the destination’s private key) of this hash. This <em>proof</em> effectively verifies
|
||||||
|
that the intended recipient got the packet, and also serves to verify the discovered path
|
||||||
|
through the network. Since the <em>proof</em> hash matches the <em>path id</em> in the intermediary nodes’
|
||||||
|
<em>path tables</em> , the intermediary nodes can forward the proof all the way back to the source.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt>When the source receives the <em>proof</em> , it will know unequivocally that a verified path has been</dt><dd><p>established to the destination, and that information can now be exchanged reliably and
|
||||||
|
securely.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>It’s important to note that this methodology ensures that the source of the request does not need to
|
||||||
|
reveal any identifying information. Only the intended destination will know “who called”, so to
|
||||||
|
speak. This is a huge improvement to protocols like IP, where by design, you have to reveal your
|
||||||
|
own address to communicate with anyone, unless you jump through a lot of hoops to hide it.
|
||||||
|
Reticulum offers initiator anonymity by design.</p>
|
||||||
|
<p>When using <em>links</em> , Reticulum will automatically verify anything sent over the link, and also
|
||||||
|
automates retransmissions if parts of a message was lost along the way. Due to the caching features
|
||||||
|
of Reticulum, such a retransmission does not need to travel the entire length of an established path.
|
||||||
|
If a packet is lost on the 8th hop of a 12 hop path, it can be fetched from the last hop that received it
|
||||||
|
reliably.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="crossing-continents">
|
||||||
|
<h3>Crossing Continents<a class="headerlink" href="#crossing-continents" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>When a packet needs to travel farther than local network topology knowledge stretches, a system of
|
||||||
|
geographical or topological hinting is used to direct the packet towards a network segment with
|
||||||
|
direct knowledge of the intended destination. This functionality is currently left out of the protocol
|
||||||
|
for simplicity of testing other parts, but will be activated in a future release. For more information
|
||||||
|
on when, refer to the roadmap on the website.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="resourceful-memory">
|
||||||
|
<h3>Resourceful Memory<a class="headerlink" href="#resourceful-memory" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>In traditional networks, large amounts of data is rapidly exchanged with very low latency. Links of
|
||||||
|
several thousand kilometers will often only have round-trip latency in the tens of milliseconds, and
|
||||||
|
as such, traditional protocols are often designed to not store any transmitted data at intermediary
|
||||||
|
hops. If a transmission error occurs, the sending node will simply notice the lack of a packet
|
||||||
|
acknowledgement, and retransmit the packet all the way, until it hears back from the receiver that it
|
||||||
|
got the intended data.</p>
|
||||||
|
<p>In bandwidth-limited and high-latency conditions, such behaviour quickly causes congestion on the
|
||||||
|
network, and communications that span many hops become exceedingly expensive in terms of
|
||||||
|
bandwidth usage, due to the higher risk of some packets failing.</p>
|
||||||
|
<p>Reticulum alleviates this in part with it’s <em>path</em> discovery methodology, and in part by implementing
|
||||||
|
<em>resource</em> caching at all nodes that can support it. Network operation can be made much more
|
||||||
|
efficient by caching everything for a period of time, and given the availability of cheap memory and
|
||||||
|
storage, this is a very welcome tradeoff. A gigabyte of memory can store millions of Reticulum
|
||||||
|
packets, and since everything is encrypted by default, the storing poses very little privacy risk.</p>
|
||||||
|
<p>In a Reticulum network, any node that is able to do so, should cache as many packets as it’s
|
||||||
|
memory will allow for. When a packet is received, a timestamp and a hash of the packet is stored
|
||||||
|
along with the full packet itself, and it will be kept in storage until the allocated cache storage is
|
||||||
|
full, whereupon the packet that was last accessed in the cache will be deleted. If a packet is accessed
|
||||||
|
from the cache, it’s timestamp will be updated to the current time, to ensure that packets that are
|
||||||
|
used stay in the cache, and packets that are not used are dropped from memory.</p>
|
||||||
|
<p>Some packet types are stored in separate caching tables, that allow easier lookup for other nodes.
|
||||||
|
For example, an announce is stored in a way, that allows other nodes to request the public key for a
|
||||||
|
certain destination, and as such the network as a whole operates as a distributed key ledger.</p>
|
||||||
|
<p>For more details on how the caching works and is used, see the reference implementation source
|
||||||
|
code.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="reference-system-setup">
|
||||||
|
<h2>Reference System Setup<a class="headerlink" href="#reference-system-setup" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This section will detail the recommended <em>Reference System Setup</em> for Reticulum. It is important to
|
||||||
|
note that Reticulum is designed to be usable over more or less any medium that allows you to send
|
||||||
|
and receive data in a digital form, and satisfies some very low minimum requirements. The
|
||||||
|
communication channel must support at least half-duplex operation, and provide an average
|
||||||
|
throughput of around 1000 bits per second, and supports a physical layer MTU of 500 bytes. The
|
||||||
|
Reticulum software should be able to run on more or less any hardware that can provide a Python 3.x
|
||||||
|
runtime environment.</p>
|
||||||
|
<p>That being said, the reference setup has been outlined to provide a common platform for anyone
|
||||||
|
who wants to help in the development of Reticulum, and for everyone who wants to know a
|
||||||
|
recommended setup to get started. A reference system consists of three parts:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>A channel access device</strong></dt><dd><p>Or <em>CAD</em> , in short, provides access to the physical medium whereupon the communication
|
||||||
|
takes place, for example a radio with an integrated modem. A setup with a separate modem
|
||||||
|
connected to a radio would also be termed a “channel access device”.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>A host device</strong></dt><dd><p>Some sort of computing device that can run the necessary software, communicates with the
|
||||||
|
channel access device, and provides user interaction.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>A software stack</strong></dt><dd><p>The software implementing the Reticulum protocol and applications using it.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>The reference setup can be considered a relatively stable platform to develop on, and also to start
|
||||||
|
building networks on. While details of the implementation might change at the current stage of
|
||||||
|
development, it is the goal to maintain hardware compatibility for as long as entirely possible, and
|
||||||
|
the current reference setup has been determined to provide a functional platform for many years
|
||||||
|
into the future. The current Reference System Setup is as follows:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Channel Access Device</strong></dt><dd><p>A data radio consisting of a LoRa radio module, and a microcontroller with open source
|
||||||
|
firmware, that can connect to host devices via USB. It operates in either the 430, 868 or 900
|
||||||
|
MHz frequency bands. More details on the exact parts and how to get/make one can be
|
||||||
|
found on the website.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Host device</strong></dt><dd><p>Any computer device running Linux and Python. A Raspberry Pi with Raspbian is
|
||||||
|
recommended.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
<li><dl class="simple">
|
||||||
|
<dt><strong>Software stack</strong></dt><dd><p>The current Reference Implementation Release of Reticulum, running on a Debian based
|
||||||
|
operating system.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>It is very important to note, that the reference channel access device <strong>does not</strong> use the LoRaWAN
|
||||||
|
standard, but uses a custom MAC layer on top of the plain LoRa modulation! As such, you will
|
||||||
|
need a plain LoRa radio module connected to an MCU with the correct Reticulum firmware. Full
|
||||||
|
details on how to get or make such a device is available on the website.</p>
|
||||||
|
<p>With the current reference setup, it should be possible to get on a Reticulum network for around 70$
|
||||||
|
even if you have none of the hardware already.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="protocol-specifics">
|
||||||
|
<h2>Protocol Specifics<a class="headerlink" href="#protocol-specifics" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>This chapter will detail protocol specific information that is essential to the implementation of
|
||||||
|
Reticulum, but non critical in understanding how the protocol works on a general level. It should be
|
||||||
|
treated more as a reference than as essential reading.</p>
|
||||||
|
<div class="section" id="node-types">
|
||||||
|
<h3>Node Types<a class="headerlink" href="#node-types" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p>Currently Reticulum defines two node types, the <em>Station</em> and the <em>Peer</em>. A node is a <em>station</em> if it fixed
|
||||||
|
in one place, and if it is intended to be kept online at all times. Otherwise the node is a <em>peer</em>. This
|
||||||
|
distinction is made by the user configuring the node, and is used to determine what nodes on the
|
||||||
|
network will help forward traffic, and what nodes rely on other nodes for connectivity.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="packet-prioritisation">
|
||||||
|
<h3>Packet Prioritisation<a class="headerlink" href="#packet-prioritisation" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p><em>The packet prioritisation algorithms are subject to rapid change at the moment, and for now, they
|
||||||
|
are not documented here. See the reference implementation for more info on how this functionality
|
||||||
|
works.</em></p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="path-calculation">
|
||||||
|
<h3>Path Calculation<a class="headerlink" href="#path-calculation" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p><em>The path calculation algorithms are subject to rapid change at the moment, and for now, they are
|
||||||
|
not documented here. See the reference implementation for more info on how this functionality
|
||||||
|
works.</em></p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="binary-packet-format">
|
||||||
|
<h3>Binary Packet Format<a class="headerlink" href="#binary-packet-format" title="Permalink to this headline">¶</a></h3>
|
||||||
|
<p><em>The binary packet format is subject to rapid change at the moment, and for now, it is not
|
||||||
|
documented here. See the reference implementation for the specific details on this topic.</em></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h3><a href="index.html">Table of Contents</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li><a class="reference internal" href="#">Understanding Reticulum</a><ul>
|
||||||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||||||
|
<li><a class="reference internal" href="#goals">Goals</a></li>
|
||||||
|
<li><a class="reference internal" href="#introduction-basic-functionality">Introduction & Basic Functionality</a><ul>
|
||||||
|
<li><a class="reference internal" href="#destinations">Destinations</a><ul>
|
||||||
|
<li><a class="reference internal" href="#destination-naming">Destination Naming</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a class="reference internal" href="#public-key-announcements">Public Key Announcements</a></li>
|
||||||
|
<li><a class="reference internal" href="#identities">Identities</a></li>
|
||||||
|
<li><a class="reference internal" href="#getting-further">Getting Further</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a class="reference internal" href="#reticulum-transport">Reticulum Transport</a><ul>
|
||||||
|
<li><a class="reference internal" href="#threading-a-path">Threading a Path</a></li>
|
||||||
|
<li><a class="reference internal" href="#crossing-continents">Crossing Continents</a></li>
|
||||||
|
<li><a class="reference internal" href="#resourceful-memory">Resourceful Memory</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a class="reference internal" href="#reference-system-setup">Reference System Setup</a></li>
|
||||||
|
<li><a class="reference internal" href="#protocol-specifics">Protocol Specifics</a><ul>
|
||||||
|
<li><a class="reference internal" href="#node-types">Node Types</a></li>
|
||||||
|
<li><a class="reference internal" href="#packet-prioritisation">Packet Prioritisation</a></li>
|
||||||
|
<li><a class="reference internal" href="#path-calculation">Path Calculation</a></li>
|
||||||
|
<li><a class="reference internal" href="#binary-packet-format">Binary Packet Format</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Previous topic</h4>
|
||||||
|
<p class="topless"><a href="reference.html"
|
||||||
|
title="previous chapter">API Reference</a></p>
|
||||||
|
<div role="note" aria-label="source link">
|
||||||
|
<h3>This Page</h3>
|
||||||
|
<ul class="this-page-menu">
|
||||||
|
<li><a href="_sources/understanding.rst.txt"
|
||||||
|
rel="nofollow">Show Source</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="reference.html" title="API Reference"
|
||||||
|
>previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">Understanding Reticulum</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
176
Documentation/html/whatis.html
Normal file
176
Documentation/html/whatis.html
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>What is Reticulum? — Reticulum Network Stack 0.2.0 beta documentation</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/classic.css" />
|
||||||
|
|
||||||
|
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||||
|
<script src="_static/jquery.js"></script>
|
||||||
|
<script src="_static/underscore.js"></script>
|
||||||
|
<script src="_static/doctools.js"></script>
|
||||||
|
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="Getting Started Fast" href="gettingstartedfast.html" />
|
||||||
|
<link rel="prev" title="Reticulum Network Stack Documentation" href="index.html" />
|
||||||
|
</head><body>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
accesskey="I">index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
|
accesskey="N">next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="index.html" title="Reticulum Network Stack Documentation"
|
||||||
|
accesskey="P">previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<div class="section" id="what-is-reticulum">
|
||||||
|
<h1>What is Reticulum?<a class="headerlink" href="#what-is-reticulum" title="Permalink to this headline">¶</a></h1>
|
||||||
|
<p>Reticulum is a cryptography-based networking stack for wide-area networks built on readily available hardware, and can operate even with very high latency and extremely low bandwidth. Reticulum allows you to build very wide-area networks with off-the-shelf tools, and offers end-to-end encryption, autoconfiguring cryptographically backed multi-hop transport, efficient addressing, unforgeable packet acknowledgements and more.</p>
|
||||||
|
<p>Reticulum is a complete networking stack, and does not use IP or higher layers, although it is easy to utilise IP (with TCP or UDP) as the underlying carrier for Reticulum. It is therefore trivial to tunnel Reticulum over the Internet or private IP networks. Reticulum is built directly on cryptographic principles, allowing resilience and stable functionality in open and trustless networks.</p>
|
||||||
|
<p>No kernel modules or drivers are required. Reticulum runs completely in userland, and can run on practically any system that runs Python 3.</p>
|
||||||
|
<div class="section" id="what-does-reticulum-offer">
|
||||||
|
<h2>What does Reticulum Offer?<a class="headerlink" href="#what-does-reticulum-offer" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Coordination-less globally unique adressing and identification</p></li>
|
||||||
|
<li><p>Fully self-configuring multi-hop routing</p></li>
|
||||||
|
<li><p>Asymmetric RSA encryption and signatures as basis for all communication</p></li>
|
||||||
|
<li><p>Perfect Forward Secrecy on links with ephemereal Elliptic Curve Diffie-Hellman keys (on the SECP256R1 curve)</p></li>
|
||||||
|
<li><p>Reticulum uses the Fernet specification for encryption on links and to group destinations</p>
|
||||||
|
<ul>
|
||||||
|
<li><p>AES-128 in CBC mode with PKCS7 padding</p></li>
|
||||||
|
<li><p>HMAC using SHA256 for authentication</p></li>
|
||||||
|
<li><p>IVs are generated through os.urandom()</p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><p>Unforgeable packet delivery confirmations</p></li>
|
||||||
|
<li><p>A variety of supported interface types</p></li>
|
||||||
|
<li><p>An intuitive and easy-to-use API</p></li>
|
||||||
|
<li><p>Reliable and efficient transfer of arbritrary amounts of data</p>
|
||||||
|
<ul>
|
||||||
|
<li><p>Reticulum can handle a few bytes of data or files of many gigabytes</p></li>
|
||||||
|
<li><p>Sequencing, transfer coordination and checksumming is automatic</p></li>
|
||||||
|
<li><p>The API is very easy to use, and provides transfer progress</p></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="where-can-reticulum-be-used">
|
||||||
|
<h2>Where can Reticulum be Used?<a class="headerlink" href="#where-can-reticulum-be-used" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>On practically any hardware that can support at least a half-duplex channel
|
||||||
|
with 1.000 bits per second throughput, and an MTU of 500 bytes. Data radios,
|
||||||
|
modems, LoRa radios, serial lines, AX.25 TNCs, amateur radio digital modes,
|
||||||
|
ad-hoc WiFi, free-space optical links and similar systems are all examples
|
||||||
|
of the types of interfaces Reticulum was designed for.</p>
|
||||||
|
<p>An open-source LoRa-based interface called RNode has been designed
|
||||||
|
specifically for use with Reticulum. It is possible to build yourself, or it
|
||||||
|
can be purchased as a complete transceiver that just needs a USB connection
|
||||||
|
to the host.</p>
|
||||||
|
<p>Reticulum can also be encapsulated over existing IP networks, so there’s
|
||||||
|
nothing stopping you from using it over wired ethernet or your local WiFi
|
||||||
|
network, where it’ll work just as well. In fact, one of the strengths of
|
||||||
|
Reticulum is how easily it allows you to connect different mediums into a
|
||||||
|
self-configuring, resilient and encrypted mesh.</p>
|
||||||
|
<p>As an example, it’s possible to set up a Raspberry Pi connected to both a
|
||||||
|
LoRa radio, a packet radio TNC and a WiFi network. Once the interfaces are
|
||||||
|
configured, Reticulum will take care of the rest, and any device on the WiFi
|
||||||
|
network can communicate with nodes on the LoRa and packet radio sides of the
|
||||||
|
network, and vice versa.</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="supported-interface-types-and-devices">
|
||||||
|
<h2>Supported Interface Types and Devices<a class="headerlink" href="#supported-interface-types-and-devices" title="Permalink to this headline">¶</a></h2>
|
||||||
|
<p>Reticulum implements a range of generalised interface types that covers most of the communications hardware that Reticulum can run over. If your hardware is not supported, it’s relatively simple to implement an interface class. Currently, the following interfaces are supported:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Any ethernet device</p></li>
|
||||||
|
<li><p>LoRa using <a class="reference external" href="https://unsigned.io/rnode">RNode</a></p></li>
|
||||||
|
<li><p>Packet Radio TNCs, such as <a class="reference external" href="https://unsigned.io/openmodem">OpenModem</a></p></li>
|
||||||
|
<li><p>Any device with a serial port</p></li>
|
||||||
|
<li><p>TCP over IP networks</p></li>
|
||||||
|
<li><p>UDP over IP networks</p></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h3><a href="index.html">Table of Contents</a></h3>
|
||||||
|
<ul>
|
||||||
|
<li><a class="reference internal" href="#">What is Reticulum?</a><ul>
|
||||||
|
<li><a class="reference internal" href="#what-does-reticulum-offer">What does Reticulum Offer?</a></li>
|
||||||
|
<li><a class="reference internal" href="#where-can-reticulum-be-used">Where can Reticulum be Used?</a></li>
|
||||||
|
<li><a class="reference internal" href="#supported-interface-types-and-devices">Supported Interface Types and Devices</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Previous topic</h4>
|
||||||
|
<p class="topless"><a href="index.html"
|
||||||
|
title="previous chapter">Reticulum Network Stack Documentation</a></p>
|
||||||
|
<h4>Next topic</h4>
|
||||||
|
<p class="topless"><a href="gettingstartedfast.html"
|
||||||
|
title="next chapter">Getting Started Fast</a></p>
|
||||||
|
<div role="note" aria-label="source link">
|
||||||
|
<h3>This Page</h3>
|
||||||
|
<ul class="this-page-menu">
|
||||||
|
<li><a href="_sources/whatis.rst.txt"
|
||||||
|
rel="nofollow">Show Source</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="searchbox" style="display: none" role="search">
|
||||||
|
<h3 id="searchlabel">Quick search</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>$('#searchbox').show(0);</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="related" role="navigation" aria-label="related navigation">
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="right" style="margin-right: 10px">
|
||||||
|
<a href="genindex.html" title="General Index"
|
||||||
|
>index</a></li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="gettingstartedfast.html" title="Getting Started Fast"
|
||||||
|
>next</a> |</li>
|
||||||
|
<li class="right" >
|
||||||
|
<a href="index.html" title="Reticulum Network Stack Documentation"
|
||||||
|
>previous</a> |</li>
|
||||||
|
<li class="nav-item nav-item-0"><a href="index.html">Reticulum Network Stack 0.2.0 beta documentation</a> »</li>
|
||||||
|
<li class="nav-item nav-item-this"><a href="">What is Reticulum?</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer" role="contentinfo">
|
||||||
|
© Copyright 2021, Mark Qvist.
|
||||||
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.0.1.
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user