@ -90,6 +90,27 @@ func DoLocalRequest(req *http.Request) (*http.Response, error) {
return tsClient . Do ( req )
}
func doLocalRequestNiceError ( req * http . Request ) ( * http . Response , error ) {
res , err := DoLocalRequest ( req )
if err == nil {
if server := res . Header . Get ( "Tailscale-Version" ) ; server != "" && server != version . Long && onVersionMismatch != nil {
onVersionMismatch ( version . Long , server )
}
return res , nil
}
if ue , ok := err . ( * url . Error ) ; ok {
if oe , ok := ue . Err . ( * net . OpError ) ; ok && oe . Op == "dial" {
path := req . URL . Path
pathPrefix := path
if i := strings . Index ( path , "?" ) ; i != - 1 {
pathPrefix = path [ : i ]
}
return nil , fmt . Errorf ( "Failed to connect to local Tailscale daemon for %s; %s Error: %w" , pathPrefix , tailscaledConnectHint ( ) , oe )
}
}
return nil , err
}
type errorJSON struct {
Error string
}
@ -140,23 +161,11 @@ func send(ctx context.Context, method, path string, wantStatus int, body io.Read
if err != nil {
return nil , err
}
res , err := DoLocalRequest ( req )
res , err := doLocalRequestNiceError ( req )
if err != nil {
if ue , ok := err . ( * url . Error ) ; ok {
if oe , ok := ue . Err . ( * net . OpError ) ; ok && oe . Op == "dial" {
pathPrefix := path
if i := strings . Index ( path , "?" ) ; i != - 1 {
pathPrefix = path [ : i ]
}
return nil , fmt . Errorf ( "Failed to connect to local Tailscale daemon for %s; %s Error: %w" , pathPrefix , tailscaledConnectHint ( ) , oe )
}
}
return nil , err
}
defer res . Body . Close ( )
if server := res . Header . Get ( "Tailscale-Version" ) ; server != "" && server != version . Long && onVersionMismatch != nil {
onVersionMismatch ( version . Long , server )
}
slurp , err := ioutil . ReadAll ( res . Body )
if err != nil {
return nil , err
@ -295,6 +304,30 @@ func FileTargets(ctx context.Context) ([]apitype.FileTarget, error) {
return fts , nil
}
// PushFile sends Taildrop file r to target.
//
// A size of -1 means unknown.
// The name parameter is the original filename, not escaped.
func PushFile ( ctx context . Context , target tailcfg . StableNodeID , size int64 , name string , r io . Reader ) error {
req , err := http . NewRequestWithContext ( ctx , "PUT" , "http://local-tailscaled.sock/localapi/v0/file-put/" + string ( target ) + "/" + url . PathEscape ( name ) , r )
if err != nil {
return err
}
if size != - 1 {
req . ContentLength = size
}
res , err := doLocalRequestNiceError ( req )
if err != nil {
return err
}
if res . StatusCode == 200 {
io . Copy ( io . Discard , res . Body )
return nil
}
all , _ := io . ReadAll ( res . Body )
return fmt . Errorf ( "%s: %s" , res . Status , all )
}
func CheckIPForwarding ( ctx context . Context ) error {
body , err := get200 ( ctx , "/localapi/v0/check-ip-forwarding" )
if err != nil {