From 8dda128e59a40e533c4662ed764818bfd1e10e07 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 e2263a4af..388b66c5f 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. @@ -148,13 +150,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 }