[client] Stage incoming file drop payloads through a platform sink

Android cannot address the user's shared storage by path, so a received
file had to land in app-private storage and be copied out afterwards,
needing twice the space of the transfer.

Put the staging area behind a Sink interface the receiver writes every
payload through. The filesystem spool implements it unchanged and stays
the default; a platform that cannot be addressed by path implements the
gomobile-bound half instead and stages payloads wherever it can reach.

The writer reports its own total rather than returning a written count:
gomobile copies a []byte argument into a fresh Java array and carries no
count back out.

A failed delivery now drops the staged payloads. The filesystem spool
swept them up on its next pass, but a sink holding entries the engine
cannot address by path has no such fallback.
This commit is contained in:
Zoltán Papp
2026-08-25 18:45:38 +02:00
parent b165e0126e
commit 861e0d5609
11 changed files with 518 additions and 26 deletions
+10 -1
View File
@@ -10,6 +10,15 @@ import (
"github.com/netbirdio/netbird/client/internal"
)
// SetFileDropSink installs the platform sink incoming payloads are staged
// through. It takes effect on the next handle the client opens, so the platform
// sets it before asking for one.
func (c *Client) SetFileDropSink(sink FileDropSink) {
c.fileDropMu.Lock()
defer c.fileDropMu.Unlock()
c.fileDropSink = sink
}
// FileDrop returns the handle of the active profile, creating it on first use.
// The UI calls this to list transfers and change settings while disconnected.
func (c *Client) FileDrop(configDir string) (*FileDrop, error) {
@@ -32,7 +41,7 @@ func (c *Client) fileDropFor(configDir, profileID string) (*FileDrop, error) {
return fd, nil
}
fd, err := NewFileDrop(configDir, profileID)
fd, err := NewFileDrop(configDir, profileID, c.fileDropSink)
if err != nil {
c.fileDropMu.Unlock()
return nil, err