Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 45 of 56

FTP: client and server

Outbound-only transfers streamed through a callback, and an anonymous server that exposes your filesystems to a desktop — both on the socket facade.

The client: passive, binary, streamed

A small RFC 959 client written entirely against GNAT.Sockets, so like DNS and NTP the same source runs on a desktop and on the board.

Passive mode only, deliberately. An embedded client should only ever make outbound connections, so every transfer asks the server to listen (PASV) and the client connects to it. No listening socket, and NAT/firewall friendly. A session uses two sockets at a time — the persistent control connection plus one transient data connection per transfer — comfortably within the W5500's eight.

Transfers are streamed through a caller callback, so a file never has to be held whole in RAM — which on a board with a few hundred KB is the difference between working and not. As with every callback in this HAL, the sink and source must obey the closure-free rule: library-level, no captured state, context passed explicitly.

Transfers are binary (TYPE I). There is no ASCII mode, which is the right call — ASCII mode's line-ending translation silently corrupts every non-text file.

The server: your filesystems, over the network

An anonymous passive-mode server that exposes one or more ext4 filesystems, so a desktop FTP client can browse, download, upload and manage the board's files.

Filesystems are presented through ESP32S3.Ext4.VFS: register each under a name before calling Run, and they appear as top-level directories in one tree — /flash, /sd. The virtual root lists the mount names. Adding a second storage device later is one more VFS.Add call and nothing else changes.

Anonymous means exactly that: no authentication. This is for a bench, a closed lab network or a deliberately isolated segment — not for anything reachable from a wider network. If the board is on a routable network, pin the socket to the interface you intend (Set_Interface) rather than letting the routing table choose.

FTP: client and server · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 45 of 56

FTP: client and server

Outbound-only transfers streamed through a callback, and an anonymous server that exposes your filesystems to a desktop — both on the socket facade.

The client: passive, binary, streamed

A small RFC 959 client written entirely against GNAT.Sockets, so like DNS and NTP the same source runs on a desktop and on the board.

Passive mode only, deliberately. An embedded client should only ever make outbound connections, so every transfer asks the server to listen (PASV) and the client connects to it. No listening socket, and NAT/firewall friendly. A session uses two sockets at a time — the persistent control connection plus one transient data connection per transfer — comfortably within the W5500's eight.

Transfers are streamed through a caller callback, so a file never has to be held whole in RAM — which on a board with a few hundred KB is the difference between working and not. As with every callback in this HAL, the sink and source must obey the closure-free rule: library-level, no captured state, context passed explicitly.

Transfers are binary (TYPE I). There is no ASCII mode, which is the right call — ASCII mode's line-ending translation silently corrupts every non-text file.

The server: your filesystems, over the network

An anonymous passive-mode server that exposes one or more ext4 filesystems, so a desktop FTP client can browse, download, upload and manage the board's files.

Filesystems are presented through ESP32S3.Ext4.VFS: register each under a name before calling Run, and they appear as top-level directories in one tree — /flash, /sd. The virtual root lists the mount names. Adding a second storage device later is one more VFS.Add call and nothing else changes.

Anonymous means exactly that: no authentication. This is for a bench, a closed lab network or a deliberately isolated segment — not for anything reachable from a wider network. If the board is on a routable network, pin the socket to the interface you intend (Set_Interface) rather than letting the routing table choose.

FTP: client and server · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 45 of 56

FTP: client and server

Outbound-only transfers streamed through a callback, and an anonymous server that exposes your filesystems to a desktop — both on the socket facade.

The client: passive, binary, streamed

A small RFC 959 client written entirely against GNAT.Sockets, so like DNS and NTP the same source runs on a desktop and on the board.

Passive mode only, deliberately. An embedded client should only ever make outbound connections, so every transfer asks the server to listen (PASV) and the client connects to it. No listening socket, and NAT/firewall friendly. A session uses two sockets at a time — the persistent control connection plus one transient data connection per transfer — comfortably within the W5500's eight.

Transfers are streamed through a caller callback, so a file never has to be held whole in RAM — which on a board with a few hundred KB is the difference between working and not. As with every callback in this HAL, the sink and source must obey the closure-free rule: library-level, no captured state, context passed explicitly.

Transfers are binary (TYPE I). There is no ASCII mode, which is the right call — ASCII mode's line-ending translation silently corrupts every non-text file.

The server: your filesystems, over the network

An anonymous passive-mode server that exposes one or more ext4 filesystems, so a desktop FTP client can browse, download, upload and manage the board's files.

Filesystems are presented through ESP32S3.Ext4.VFS: register each under a name before calling Run, and they appear as top-level directories in one tree — /flash, /sd. The virtual root lists the mount names. Adding a second storage device later is one more VFS.Add call and nothing else changes.

Anonymous means exactly that: no authentication. This is for a bench, a closed lab network or a deliberately isolated segment — not for anything reachable from a wider network. If the board is on a routable network, pin the socket to the interface you intend (Set_Interface) rather than letting the routing table choose.

FTP: client and server · Bare-Metal Ada on the ESP32-S3
Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 45 of 56

FTP: client and server

Outbound-only transfers streamed through a callback, and an anonymous server that exposes your filesystems to a desktop — both on the socket facade.

The client: passive, binary, streamed

A small RFC 959 client written entirely against GNAT.Sockets, so like DNS and NTP the same source runs on a desktop and on the board.

Passive mode only, deliberately. An embedded client should only ever make outbound connections, so every transfer asks the server to listen (PASV) and the client connects to it. No listening socket, and NAT/firewall friendly. A session uses two sockets at a time — the persistent control connection plus one transient data connection per transfer — comfortably within the W5500's eight.

Transfers are streamed through a caller callback, so a file never has to be held whole in RAM — which on a board with a few hundred KB is the difference between working and not. As with every callback in this HAL, the sink and source must obey the closure-free rule: library-level, no captured state, context passed explicitly.

Transfers are binary (TYPE I). There is no ASCII mode, which is the right call — ASCII mode's line-ending translation silently corrupts every non-text file.

The server: your filesystems, over the network

An anonymous passive-mode server that exposes one or more ext4 filesystems, so a desktop FTP client can browse, download, upload and manage the board's files.

Filesystems are presented through ESP32S3.Ext4.VFS: register each under a name before calling Run, and they appear as top-level directories in one tree — /flash, /sd. The virtual root lists the mount names. Adding a second storage device later is one more VFS.Add call and nothing else changes.

Anonymous means exactly that: no authentication. This is for a bench, a closed lab network or a deliberately isolated segment — not for anything reachable from a wider network. If the board is on a routable network, pin the socket to the interface you intend (Set_Interface) rather than letting the routing table choose.