-
Notifications
You must be signed in to change notification settings - Fork 44
Support pooled listener mode #553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
robklg
wants to merge
23
commits into
master
Choose a base branch
from
feat/pooling
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if sessions did not properly shut down some how, it's possible that a session reference was kept in the switchboard. Since it referenced counted, that could even mean the entire session memory would not be freed. So this should fix that.
Collaborator
|
This is really cool Rob. Thank you for the elaborate MR description too. |
hannesdejager
approved these changes
Jan 4, 2026
Collaborator
hannesdejager
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
I'd say we just need to add docs too for unftp.rs e.g. like https://unftp.rs/server/proxy-protocol
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implements #552
The pooled listener mode adds a new mode for the way in which passive data channels are handled, next to legacy and proxy protocol. It reuses a lot of the code for the proxy protocol, particularly the lookup table (switchboard) to associate a passive listening port to a particular FTP control session.
Recall that the legacy way of allocating ports is done within PASV/EPSV:
try_port_rangebinds to a free port, and starts listening. A task is started to await for the incoming connection, upon receiving the connection,spawn_processingis called for the data channel.Benefits of pooled mode
This new mode offers several advantages over the legacy listener, especially for high-traffic servers:
The pooled mode works similar to proxy protocol mode: The listening for passive data connections is delegated to a separate listener (
listen_pooledto replacelisten). In pooled mode, the server listens on all ports in the passive port range continuously, accepting all incoming connections. When a PASV command is received, a port is assigned to the session, it is registered in the switchboard under source ip + passive port. When a subsequent incoming connection is received, the pooled listener can resolve the session that belongs to this incoming data channel, by looking it up in the switchboard baesd on source ip + port. There it dispatches the data channel.For PASV, the way the data port allocation is handled is delegated to the pooled or proxy mode listener via a channel that takes the command to assign a port, plus a oneshot return channel, so that PASV knows the assigned port and can reply it to the client.
The difference between pooled & proxy mode now is: First of all, most obviously, proxy protocol mode extracts information from the proxy header, and listens on only one port. The pooled mode listens on both the control port (same way as listen.rs does, so it just uses the unftp bind_address) and the full range of passive ports. The shared code for pooled and proxy mode is bundled in listen_prebound.
Improvement in switchboard
A scavenger task was added to the switchboard to prevent a memory leak. Previously, if a client disconnected after a PASV command without using the data connection, the port reservation could remain in the switchboard forever. The new scavenger periodically cleans up these "zombie" entries by using Weak pointers to detect when a session has been deallocated.
Other changes in this MR
Some related changes have been made: