Publish radio linking rfc
This commit is contained in:
parent
1261194a49
commit
455035ccb8
10
content/rfc/_index.md
Normal file
10
content/rfc/_index.md
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Proposals
|
||||
extra:
|
||||
inject_rfcs: true
|
||||
---
|
||||
|
||||
# Proposals & RFCs
|
||||
|
||||
This section contains project proposals that I either lack the time or resources to complete. This is a bit of a public TODO list.
|
||||
|
150
content/rfc/modern-repeater-linking.md
Normal file
150
content/rfc/modern-repeater-linking.md
Normal file
@ -0,0 +1,150 @@
|
||||
---
|
||||
title: "RFC: A fast system for repeater linking using modern web technology"
|
||||
date: 2021-11-17
|
||||
extra:
|
||||
is_rfc: true
|
||||
uses_graphviz: true
|
||||
---
|
||||
|
||||
The three common standards for amateur radio repeater linking are all built on old and cumbersome technology. In the world of repeater linking, the most predominant standards for interconnection are:
|
||||
|
||||
- [Echolink](https://secure.echolink.org/)
|
||||
- Closed-source
|
||||
- Strict governance
|
||||
- A strong lack of APIs
|
||||
- Does not allow cross-system linking
|
||||
- ex: cannot link Echolink conferences to Allstar nodes
|
||||
- [AllStarLink](https://allstarlink.org/)
|
||||
- Absolute overkill
|
||||
- Most node configurations require special hardware to set up
|
||||
- Built on the Asterisk PBX
|
||||
- Uses phone networks to link repeaters
|
||||
- [IRLP](http://www.irlp.net/)
|
||||
- Requires specialized hardware
|
||||
- Uses old connection standards
|
||||
- Closed-source
|
||||
|
||||
In my ideal world, there would be a small, lightweight, and configurable linking backend that developers could extend in any way they wished. This proposal is not the end-all-be-all solution, but a step in the direction of this vision.
|
||||
|
||||
## Node discovery
|
||||
|
||||
In a linking system like Echolink, *all* clients announce themselves to a central directory server. This server then decides if a client is "worthy" (verified license, not banned from the service, ...) then lists the client on [a somewhat parsable webpage](https://secure.echolink.org/logins.jsp). The topology for such a setup is as follows:
|
||||
|
||||
<div class="mermaid">
|
||||
flowchart LR
|
||||
You(You) --- D1((Directory Server))
|
||||
D1 --- NA(Node A) & NB(Node B) & P1(Proxy) & ND(Node D)
|
||||
P1 --- NC(Node C)
|
||||
</div>
|
||||
|
||||
In most cases, this works just fine. However, there are two off the top of my head that raise an issue:
|
||||
|
||||
- `Node A` and `Node B` are owned by a club that wants to keep the nodes private for member use only.
|
||||
- `Node C` is behind a restrictive firewall, or does not want to expose a host to the public internet.
|
||||
|
||||
The second of the two scenarios is solved already in the above graph using a proxy. Echolink proxies have become extremely common due to the fact very few people have access to a network where their host can be exposed publicly for other nodes to directly connect to when making a link.
|
||||
|
||||
Echolink's solution to the first issue is fairly lacking in my opinion. Nodes only have the option to restrict connections based on a REGEX on their callsign. This means maintaining a list of allowed users, and updating *every* club-owned node when that changes.
|
||||
|
||||
### Decentralizing directory services
|
||||
|
||||
While I like Echolink a lot, I think some improvements could be made to both the node directory system, and how nodes link to each other. Ideally, I see a setup as follows:
|
||||
|
||||
<div class="mermaid">
|
||||
flowchart TD
|
||||
D1((Directory A))
|
||||
D1 --- NA(Node A) & NB(Node B) & NC(Node C)
|
||||
D2((Directory B))
|
||||
D2 --- NC & ND(Node D)
|
||||
D3((Private Directory))
|
||||
D3 --- NE(Node E) & NF(Node F)
|
||||
NE --> D2
|
||||
</div>
|
||||
|
||||
In this world, anyone could host a directory server, and either open it up to the public, or restrict it by means of their choosing (callsign rules, password, key-based access, ...). Nodes can then connect to one or many directories of their choosing. This could allow situations where a node could sit on the edge between two private intranets and have access to other nodes on *both* sides of the boundary without requiring either side to expose some part of itself to the public internet.
|
||||
|
||||
### Routing
|
||||
|
||||
I also envision a routing system where nodes attached to more than one directory service would periodically propagate information about their first-hop directories to other first-hop directories. An example of such interaction from the perspective of `Node C` would be:
|
||||
|
||||
```text
|
||||
Node C -> Directory A: You can find Directory B at <address>
|
||||
Node C -> Directory B: You can find Directory A at <address>
|
||||
```
|
||||
|
||||
`Node E` would have a different interaction. Since `Private Directory` is *private*, its announcement would *exclude* that directory:
|
||||
|
||||
```text
|
||||
Node E -> Private Directory: You can find Directory B at <address>
|
||||
```
|
||||
|
||||
At this point, the directory servers should then be able to directly query eachother about their "routing tables". Over time, each directory server would build a list of which directory servers it can reach for information about nodes.
|
||||
|
||||
The rable for `Private Directory` would look like this:
|
||||
|
||||
| Server | Address | Hops |
|
||||
|-------------|-------------|------|
|
||||
| Directory B | `<address>` | 1 |
|
||||
| Directory A | `<address>` | 2 |
|
||||
|
||||
If `Node F` were to try connecting to `Node A`, the order of messages would be:
|
||||
|
||||
```text
|
||||
Node F -> Private Directory: Do you know Node A?
|
||||
|
||||
# Private Directory queries the first table entry
|
||||
Private Directory -> Directory B: Do you know Node A?
|
||||
Directory B -> Private Directory: No
|
||||
|
||||
# Private Directory queries the second table entry
|
||||
Private Directory -> Directory A: Do you know Node A?
|
||||
Directory A -> Private Directory: Node A is at <address>
|
||||
|
||||
# Node F is informed of the address of Node A
|
||||
Private Directory -> Node F: Node A is at <address>
|
||||
```
|
||||
|
||||
Of course, since `Node F` is *only* connected to a *private* directory service, if `Node A` were to try connecting to `Node F`, the order of messages would be:
|
||||
|
||||
```text
|
||||
Node A -> Directory A: Do you know Node F?
|
||||
|
||||
# Directory A queries the first table entry
|
||||
Directory A -> Directory B: Do you know Node F?
|
||||
Directory B -> Directory A: No
|
||||
|
||||
# Directory A was never informed that Private Directory exists, since it is private
|
||||
# Thus, there is no route to Node F
|
||||
Directory A -> Node A: No
|
||||
```
|
||||
|
||||
Like every other piece of amateur radio backbone software, this routing system relies on trust. I am not an expert in identity verification, and I will not attempt to devise a system for stopping bad actors from poisoning the routing tables in this document.
|
||||
|
||||
## Audio transport using modern tech
|
||||
|
||||
So far in this document, node addresses have been used extensively, yet nodes are not expected to expose any ports to the internet. In the real-world, it has become very common to see peer-to-peer real-time media links in the form of video conferencing services. These services largely rely on WebRTC, a standardized, strong, and reliable protocol for peer-to-peer content streams.
|
||||
|
||||
While WebRTC still struggles to deliver perfect quality audio and video simultaneously, it is more than capable of *just* streaming audio, with the added benefit that basically every browser supports it natively. Most programming languages also have one or many strong WebRTC libraries to work with.
|
||||
|
||||
This means that a full implementation of this document would result in something similar to the following:
|
||||
|
||||
- Directory server
|
||||
- Handles incoming clients
|
||||
- Handles routing tables
|
||||
- Handles access rules
|
||||
- Performs client lookups when requested
|
||||
- Possibly provides telemetry information
|
||||
- Client library
|
||||
- Establishes connections with one or more directories
|
||||
- Periodically propagates information about connected directories
|
||||
- Can request to create or destroy a link
|
||||
- When a link is created, it exposes a direct WebRTC connection to the remote node
|
||||
- Hands off responsibility for the connection to whatever software wraps the library
|
||||
|
||||
The wrapping software could be one of:
|
||||
|
||||
- A website
|
||||
- A smartphone app
|
||||
- A headless application running on a Raspberry Pi that connects straight to a radio for a simplex node
|
||||
- An application running on a repeater controller
|
||||
- Anything else
|
@ -132,3 +132,8 @@ ul {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mermaid {
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
}
|
||||
|
@ -78,7 +78,8 @@
|
||||
<p>
|
||||
<a href="/">Home</a> |
|
||||
<a href="/blog">Blog</a> |
|
||||
<a href="/hobbies">Hobbies</a>
|
||||
<a href="/hobbies">Hobbies</a> |
|
||||
<a href="/rfc">RFC</a>
|
||||
</p>
|
||||
<hr>
|
||||
</div>
|
||||
|
@ -67,7 +67,7 @@ MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], displayMat
|
||||
</div>
|
||||
|
||||
{# Comments only on blog posts #}
|
||||
{% if page.description and page.date %}
|
||||
{% if page.extra.is_rfc or page.description and page.date %}
|
||||
<br>
|
||||
<hr>
|
||||
<script src="https://utteranc.es/client.js" repo="ewpratten/va3zza.com" issue-term="title" label="comment"
|
||||
@ -80,4 +80,7 @@ MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], displayMat
|
||||
{% if page.extra.uses_twitter %}
|
||||
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
{% endif %}
|
||||
{% if page.extra.uses_graphviz %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
@ -49,6 +49,7 @@
|
||||
{% block content %}
|
||||
{{section.content | safe}}
|
||||
|
||||
{# Blog posts #}
|
||||
{% if section.extra.inject_blog_posts %}
|
||||
<ul>
|
||||
{% for page in section.pages %}
|
||||
@ -59,4 +60,16 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{# RFCs #}
|
||||
{% if section.extra.inject_rfcs %}
|
||||
<ul>
|
||||
{% for page in section.pages %}
|
||||
{% if not page.extra.hidden %}
|
||||
<li class="blog-post-li"><a href="{{page.path}}">{{page.title}}</a> <span style="color:gray;">({{page.date}})</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
Loading…
x
Reference in New Issue
Block a user