Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CXXFLAGS := $(CXXFLAGS) -DMAVLINK_SIGNING_TIMESTAMP_LIMIT=600
LIBS := -ltdb -lssl -lcrypto

# Source files
SOURCES := supportproxy.cpp mavlink.cpp util.cpp keydb.cpp conntdb.cpp tlog.cpp session.cpp binlog.cpp cleanup.cpp websocket.cpp
SOURCES := supportproxy.cpp mavlink.cpp util.cpp keydb.cpp conntdb.cpp tlog.cpp session.cpp binlog.cpp cleanup.cpp websocket.cpp video.cpp videoauth.cpp videots.cpp videostream.cpp videorec.cpp videoview.cpp httpreq.cpp videortsp.cpp videortmp.cpp
OBJECTS := $(SOURCES:.cpp=.o)
TARGET := supportproxy

Expand Down Expand Up @@ -73,7 +73,7 @@ mavlink.o: mavlink.cpp mavlink.h $(MAVLINK_DIR)/protocol.h

# Dependencies. mavlink.h includes keydb.h, so any object that pulls in
# mavlink.h transitively depends on keydb.h too.
supportproxy.o: supportproxy.cpp mavlink.h util.h keydb.h conntdb.h tlog.h binlog.h session.h cleanup.h websocket.h
supportproxy.o: supportproxy.cpp mavlink.h util.h keydb.h conntdb.h tlog.h binlog.h session.h cleanup.h websocket.h video.h videots.h
mavlink.o: mavlink.cpp mavlink.h keydb.h $(MAVLINK_DIR)/protocol.h
util.o: util.cpp util.h
keydb.o: keydb.cpp keydb.h
Expand All @@ -83,6 +83,15 @@ session.o: session.cpp session.h
binlog.o: binlog.cpp binlog.h session.h mavlink.h util.h cleanup.h $(MAVLINK_DIR)/protocol.h
cleanup.o: cleanup.cpp cleanup.h keydb.h
websocket.o: websocket.cpp websocket.h util.h
video.o: video.cpp video.h videoauth.h videots.h videostream.h videorec.h videoview.h httpreq.h videortsp.h videortmp.h conntdb.h keydb.h util.h
videoauth.o: videoauth.cpp videoauth.h conntdb.h keydb.h
videots.o: videots.cpp videots.h
videostream.o: videostream.cpp videostream.h
videorec.o: videorec.cpp videorec.h session.h cleanup.h
videoview.o: videoview.cpp videoview.h httpreq.h videostream.h videots.h videoauth.h keydb.h
httpreq.o: httpreq.cpp httpreq.h
videortsp.o: videortsp.cpp videortsp.h
videortmp.o: videortmp.cpp videortmp.h httpreq.h

# Testing
test: $(TARGET)
Expand Down
167 changes: 165 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ For more information on using the support proxy see https://support.ardupilot.or
- Supports WebSocket and WebSocket+SSL TCP connections for both user
and support engineer
- supports up to 8 simultaneous connections by support engineer
- Optional video proxying alongside the MAVLink link, with recording

## How It Works

Expand All @@ -32,6 +33,59 @@ secure, authenticated connections.

Both sides can optionally use WebSocket+SSL to get a fully encrypted link.

## Video

Optional, off unless an entry has it enabled. A user points a camera at
one of their entry's video ports and any number of ground stations can
watch, with the same NAT traversal and per-entry credentials the MAVLink
side already provides. Recordings land beside the tlogs under
`logs/<port2>/<date>/` and are covered by the same retention.

Video is deliberately independent of the MAVLink session: it survives a
telemetry dropout, and with a publish password it needs no MAVLink at
all.

**Ports.** Up to three per entry, allocated by an admin from the web UI
(suggested from 40001). Each carries one stream, on TCP and UDP.
**These are public listening ports and must be open in the firewall.**

**Publishing.**

| Transport | Credential |
|---|---|
| MPEG-TS over UDP | none possible — see below |
| RTSP | `?pw=` on the request URI |
| RTMP | `?pw=` on the stream key, e.g. `FPV?pw=secret` |

Plain MPEG-TS over UDP has nowhere to carry a password, so it is
admitted on the MAVLink-session path only: a publisher is accepted when
a MAVLink session for the entry was seen from the same address within
the grace window. On a non-bidi entry *any* datagram latches the user
side, so a scanner between flights can become the authorised address and
the aircraft's video is then refused until the grace expires. **Entries
used for video should set `bidi_sign` or a publish password.**

**Watching.** In the browser from the web UI, or outside it with the
`ffplay`/`vlc` command the page offers. The browser player needs H.264:
Chrome and Firefox will not decode HEVC in Media Source Extensions on
desktop Linux, and nothing here transcodes.

**Disk.** Video has its own budget, separate from telemetry, so a busy
camera can never evict a user's tlogs. Set it per entry in the web UI;
a free-space floor stops recording before the disk fills.

**Log rotation.** The daemon's own log is not rotated by default.
Install the supplied config once, as root:

```bash
sudo install -m 644 scripts/supportproxy.logrotate \
/etc/logrotate.d/supportproxy
```

It uses `copytruncate`, which is required rather than preferred when the
daemon's stdout is a file systemd holds open — see the comments in that
file.

## Building

### Prerequisites
Expand All @@ -40,6 +94,9 @@ Both sides can optionally use WebSocket+SSL to get a fully encrypted link.
# Ubuntu/Debian
sudo apt install libtdb-dev python3-tdb python3-venv gcc g++ git libssl-dev

# Only if video is used: RTSP and RTMP ingest hand the stream to an
# ffmpeg child for demuxing. Plain MPEG-TS over UDP needs nothing extra.
sudo apt install ffmpeg
```

### Get the source
Expand All @@ -65,7 +122,60 @@ source venv/bin/activate
pip install pymavlink
```

### Building SupportProxy
### Video

Optional, off unless an entry has it enabled. A user points a camera at
one of their entry's video ports and any number of ground stations can
watch, with the same NAT traversal and per-entry credentials the MAVLink
side already provides. Recordings land beside the tlogs under
`logs/<port2>/<date>/` and are covered by the same retention.

Video is deliberately independent of the MAVLink session: it survives a
telemetry dropout, and with a publish password it needs no MAVLink at
all.

**Ports.** Up to three per entry, allocated by an admin from the web UI
(suggested from 40001). Each carries one stream, on TCP and UDP.
**These are public listening ports and must be open in the firewall.**

**Publishing.**

| Transport | Credential |
|---|---|
| MPEG-TS over UDP | none possible — see below |
| RTSP | `?pw=` on the request URI |
| RTMP | `?pw=` on the stream key, e.g. `FPV?pw=secret` |

Plain MPEG-TS over UDP has nowhere to carry a password, so it is
admitted on the MAVLink-session path only: a publisher is accepted when
a MAVLink session for the entry was seen from the same address within
the grace window. On a non-bidi entry *any* datagram latches the user
side, so a scanner between flights can become the authorised address and
the aircraft's video is then refused until the grace expires. **Entries
used for video should set `bidi_sign` or a publish password.**

**Watching.** In the browser from the web UI, or outside it with the
`ffplay`/`vlc` command the page offers. The browser player needs H.264:
Chrome and Firefox will not decode HEVC in Media Source Extensions on
desktop Linux, and nothing here transcodes.

**Disk.** Video has its own budget, separate from telemetry, so a busy
camera can never evict a user's tlogs. Set it per entry in the web UI;
a free-space floor stops recording before the disk fills.

**Log rotation.** The daemon's own log is not rotated by default.
Install the supplied config once, as root:

```bash
sudo install -m 644 scripts/supportproxy.logrotate \
/etc/logrotate.d/supportproxy
```

It uses `copytruncate`, which is required rather than preferred when the
daemon's stdout is a file systemd holds open — see the comments in that
file.

## Building SupportProxy

```bash
# Build everything (initializes submodules, generates headers, compiles)
Expand Down Expand Up @@ -207,7 +317,60 @@ netstat -ln | grep ":1000[0-9]"

SupportProxy can also be run using Docker for easier deployment and management.

### Building the Docker Image
### Video

Optional, off unless an entry has it enabled. A user points a camera at
one of their entry's video ports and any number of ground stations can
watch, with the same NAT traversal and per-entry credentials the MAVLink
side already provides. Recordings land beside the tlogs under
`logs/<port2>/<date>/` and are covered by the same retention.

Video is deliberately independent of the MAVLink session: it survives a
telemetry dropout, and with a publish password it needs no MAVLink at
all.

**Ports.** Up to three per entry, allocated by an admin from the web UI
(suggested from 40001). Each carries one stream, on TCP and UDP.
**These are public listening ports and must be open in the firewall.**

**Publishing.**

| Transport | Credential |
|---|---|
| MPEG-TS over UDP | none possible — see below |
| RTSP | `?pw=` on the request URI |
| RTMP | `?pw=` on the stream key, e.g. `FPV?pw=secret` |

Plain MPEG-TS over UDP has nowhere to carry a password, so it is
admitted on the MAVLink-session path only: a publisher is accepted when
a MAVLink session for the entry was seen from the same address within
the grace window. On a non-bidi entry *any* datagram latches the user
side, so a scanner between flights can become the authorised address and
the aircraft's video is then refused until the grace expires. **Entries
used for video should set `bidi_sign` or a publish password.**

**Watching.** In the browser from the web UI, or outside it with the
`ffplay`/`vlc` command the page offers. The browser player needs H.264:
Chrome and Firefox will not decode HEVC in Media Source Extensions on
desktop Linux, and nothing here transcodes.

**Disk.** Video has its own budget, separate from telemetry, so a busy
camera can never evict a user's tlogs. Set it per entry in the web UI;
a free-space floor stops recording before the disk fills.

**Log rotation.** The daemon's own log is not rotated by default.
Install the supplied config once, as root:

```bash
sudo install -m 644 scripts/supportproxy.logrotate \
/etc/logrotate.d/supportproxy
```

It uses `copytruncate`, which is required rather than preferred when the
daemon's stdout is a file systemd holds open — see the comments in that
file.

## Building the Docker Image

```bash
docker build -f docker/Dockerfile -t ap-supportproxy .
Expand Down
Loading
Loading