|
|
|
@ -23,8 +23,11 @@ import ( |
|
|
|
|
|
|
|
|
|
|
|
"tailscale.com/client/tailscale/apitype" |
|
|
|
"tailscale.com/client/tailscale/apitype" |
|
|
|
"tailscale.com/feature/taildrop" |
|
|
|
"tailscale.com/feature/taildrop" |
|
|
|
|
|
|
|
"tailscale.com/ipn" |
|
|
|
"tailscale.com/ipn/ipnlocal" |
|
|
|
"tailscale.com/ipn/ipnlocal" |
|
|
|
"tailscale.com/tailcfg" |
|
|
|
"tailscale.com/tailcfg" |
|
|
|
|
|
|
|
"tailscale.com/util/progresstracking" |
|
|
|
|
|
|
|
"tailscale.com/util/rands" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Compile-time check that jsFileOps implements taildrop.FileOps.
|
|
|
|
// Compile-time check that jsFileOps implements taildrop.FileOps.
|
|
|
|
@ -78,7 +81,8 @@ func (i *jsIPN) listFileTargets() js.Value { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// sendFile sends data as filename to the peer identified by stableNodeID.
|
|
|
|
// sendFile sends data as filename to the peer identified by stableNodeID,
|
|
|
|
|
|
|
|
// reporting progress via notifyOutgoingFiles callbacks roughly once per second.
|
|
|
|
func (i *jsIPN) sendFile(stableNodeID, filename string, data js.Value) js.Value { |
|
|
|
func (i *jsIPN) sendFile(stableNodeID, filename string, data js.Value) js.Value { |
|
|
|
return makePromise(func() (any, error) { |
|
|
|
return makePromise(func() (any, error) { |
|
|
|
ext, err := i.taildropExt() |
|
|
|
ext, err := i.taildropExt() |
|
|
|
@ -105,20 +109,46 @@ func (i *jsIPN) sendFile(stableNodeID, filename string, data js.Value) js.Value |
|
|
|
} |
|
|
|
} |
|
|
|
b := make([]byte, data.Get("byteLength").Int()) |
|
|
|
b := make([]byte, data.Get("byteLength").Int()) |
|
|
|
js.CopyBytesToGo(b, data) |
|
|
|
js.CopyBytesToGo(b, data) |
|
|
|
req, err := http.NewRequest("PUT", dstURL.String()+"/v0/put/"+url.PathEscape(filename), bytes.NewReader(b)) |
|
|
|
|
|
|
|
|
|
|
|
outgoing := &ipn.OutgoingFile{ |
|
|
|
|
|
|
|
ID: rands.HexString(30), |
|
|
|
|
|
|
|
PeerID: tailcfg.StableNodeID(stableNodeID), |
|
|
|
|
|
|
|
Name: filename, |
|
|
|
|
|
|
|
DeclaredSize: int64(len(b)), |
|
|
|
|
|
|
|
Started: time.Now(), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
updates := map[string]*ipn.OutgoingFile{outgoing.ID: outgoing} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Report final state (success or failure) when the function returns.
|
|
|
|
|
|
|
|
var sendErr error |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
outgoing.Finished = true |
|
|
|
|
|
|
|
outgoing.Succeeded = sendErr == nil |
|
|
|
|
|
|
|
ext.UpdateOutgoingFiles(updates) |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
body := progresstracking.NewReader(bytes.NewReader(b), time.Second, func(n int, _ error) { |
|
|
|
|
|
|
|
outgoing.Sent = int64(n) |
|
|
|
|
|
|
|
ext.UpdateOutgoingFiles(updates) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
req, err := http.NewRequest("PUT", dstURL.String()+"/v0/put/"+url.PathEscape(filename), body) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
sendErr = err |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
req.ContentLength = int64(len(b)) |
|
|
|
req.ContentLength = int64(len(b)) |
|
|
|
client := &http.Client{Transport: i.lb.Dialer().PeerAPITransport()} |
|
|
|
client := &http.Client{Transport: i.lb.Dialer().PeerAPITransport()} |
|
|
|
resp, err := client.Do(req) |
|
|
|
resp, err := client.Do(req) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
sendErr = err |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
defer resp.Body.Close() |
|
|
|
defer resp.Body.Close() |
|
|
|
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { |
|
|
|
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { |
|
|
|
body, _ := io.ReadAll(resp.Body) |
|
|
|
respBody, _ := io.ReadAll(resp.Body) |
|
|
|
return nil, fmt.Errorf("send file: %s: %s", resp.Status, bytes.TrimSpace(body)) |
|
|
|
sendErr = fmt.Errorf("send file: %s: %s", resp.Status, bytes.TrimSpace(respBody)) |
|
|
|
|
|
|
|
return nil, sendErr |
|
|
|
} |
|
|
|
} |
|
|
|
return nil, nil |
|
|
|
return nil, nil |
|
|
|
}) |
|
|
|
}) |
|
|
|
|