Skip to content

MAVLink FTP: session idle timer ignores outgoing burst stream, closes session mid-transfer #28695

Description

@DonLakeFlyer

Describe the bug

MavlinkFTP closes an open session when no request has been received for a fixed idle time, even while the server itself is actively streaming a BurstReadFile to the client. Outgoing stream packets do not count as activity.

_last_work_buffer_access is only updated in _ensure_buffers_exist(), which is called from _process_request() — i.e. only when an FTP request arrives. send() then does:

} else if (_session_info.fd != -1) {
    // close session without activity
    if (hrt_elapsed_time(&_last_work_buffer_access) > 10_s) {   // 30_s on main
        ::close(_session_info.fd);
        _session_info.fd = -1;
        _session_info.stream_download = false;
        _last_reply_valid = false;
        PX4_WARN("Session was closed without activity");
    }
}

During a burst the GCS is not supposed to send anything — it just receives the stream. So on a slow link the server can spend most of that window busily transmitting a 35 KB chunk to the client and then declare the session idle.

Sequence observed with QGC over a SiK radio (57600 baud, PX4 v1.17):

  1. OpenFileRO + BurstReadFile at t=0. Last request the server will see for a while.
  2. Server streams the 35 KB chunk. On this link that takes ~7 s. The final packet carrying burst_complete=1 is lost.
  3. GCS waits its silence timeout (3 s) and re-requests BurstReadFile from the last good offset at t=10.6 s.
  4. Server has already closed the session at t=10 s → Nak InvalidSession. Download fails.

With a slower or rate-limited link the chunk alone can exceed the window (35 KB at 1200 B/s = 29 s), so even the 30 s value on main is reachable without any packet loss.

To Reproduce

  • PX4 v1.17 (or main, with a link slow enough that a 35 KB burst chunk plus the client's retry delay exceeds 30 s).
  • Telemetry link ~1–4 KB/s (SiK radio at 57600 is enough).
  • Download a file ≥ 35 KB via MAVLink FTP burst (e.g. /etc/extras/parameters.json.xz).
  • Have the client wait ≥ 3 s before re-requesting after the burst goes quiet.

Expected behavior

Streaming burst packets to the client should count as session activity. The idle timer should be reset (or not run) while _session_info.stream_download is true / while send() is emitting stream packets, so a session can only expire when the server is genuinely doing nothing for it.

Additional context

  • The MAVLink FTP spec allows the server to expire idle sessions, so the client will also handle InvalidSession by re-opening. This issue is about the server mis-measuring "idle".
  • Suggested fix: update _last_work_buffer_access in send() whenever a stream packet is emitted (or skip the idle check while stream_download is set). Two lines.
  • Relevant: _workBurst sets stream_download = true; send() streams in 35 KB chunks (stream_chunk_transmitted > 35000).

Log excerpt from the GCS side (QGC Vehicle.FTPManager), times in seconds:

28.808 Open File RO Ack, openFileLength 70256
28.809 Burst Read File request, offset 0            <- last request server sees
29.180 .. 36.291  burst data arriving (lossy link)
36.291 last accepted burst packet, offset 32982      <- chunk ends ~35000; burst_complete packet lost
39.386 Burst Read File retry, offset 33221           <- 10.58 s after last request
39.495 Nak "Invalid Session"

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

status:needs-triageAuto-assigned to new issues and removed after maintainers review it and assign the specific label.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions