From c1c4e014d54ac4b977a379bf1a5e33e600c71f1c Mon Sep 17 00:00:00 2001 From: metabrixkt Date: Wed, 27 May 2026 00:21:40 +0500 Subject: [PATCH] fix: accept concurrent SFTP session channels Previously, Wings handled each accepted SFTP session channel synchronously inside the SSH channel loop. This blocked the server from accepting additional session channels on the same SSH connection until the active SFTP session ended (which may not happen until the client disconnects). Some clients, such as GVFS, open multiple SFTP session channels over a single SSH connection during mount setup. With the accept loop blocked, GVFS would wait for the additional channel to be accepted before timing out and falling back. Now, each accepted session channel is handled in its own goroutine, so SSH session channel multiplexing works as expected. After the SSH channel stream closes, `AcceptInbound` waits for active session handlers before returning. --- sftp/server.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sftp/server.go b/sftp/server.go index 3dbe563da..bcc79453b 100644 --- a/sftp/server.go +++ b/sftp/server.go @@ -12,6 +12,7 @@ import ( "regexp" "strconv" "strings" + "sync" "emperror.dev/errors" "github.com/apex/log" @@ -125,6 +126,7 @@ func (c *SFTPServer) AcceptInbound(conn net.Conn, config *ssh.ServerConfig) erro defer sconn.Close() go ssh.DiscardRequests(reqs) + var wg sync.WaitGroup for ch := range chans { // If its not a session channel we just move on because its not something we // know how to handle at this point. @@ -147,13 +149,22 @@ func (c *SFTPServer) AcceptInbound(conn net.Conn, config *ssh.ServerConfig) erro } }(requests) - if srv, ok := c.manager.Get(sconn.Permissions.Extensions["uuid"]); ok { + srv, ok := c.manager.Get(sconn.Permissions.Extensions["uuid"]) + if !ok { + _ = channel.Close() + continue + } + + wg.Add(1) + go func(srv *server.Server, channel ssh.Channel) { + defer wg.Done() if err := c.Handle(sconn, srv, channel); err != nil { - return err + log.WithField("error", err).WithField("user", sconn.User()).Error("sftp: failed to handle session") } - } + }(srv, channel) } + wg.Wait() return nil }