mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
ipn, tailscale/cli: add TaildropTargetStatus and remove race with FileTargets (#15017)
Introduce new TaildropTargetStatus in PeerStatus Refactor getTargetStableID to solely rely on Status() instead of calling FileTargets(). This removes a possible race condition between the two calls and provides more detailed failure information if a peer can't receive files. Updates tailscale/tailscale#14393 Signed-off-by: kari-ts <kari@tailscale.com>
This commit is contained in:
@@ -1256,6 +1256,7 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) {
|
||||
SSH_HostKeys: p.Hostinfo().SSH_HostKeys().AsSlice(),
|
||||
Location: p.Hostinfo().Location().AsStruct(),
|
||||
Capabilities: p.Capabilities().AsSlice(),
|
||||
TaildropTarget: b.taildropTargetStatus(p),
|
||||
}
|
||||
if cm := p.CapMap(); cm.Len() > 0 {
|
||||
ps.CapMap = make(tailcfg.NodeCapMap, cm.Len())
|
||||
@@ -6522,6 +6523,41 @@ func (b *LocalBackend) FileTargets() ([]*apitype.FileTarget, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (b *LocalBackend) taildropTargetStatus(p tailcfg.NodeView) ipnstate.TaildropTargetStatus {
|
||||
if b.netMap == nil || b.state != ipn.Running {
|
||||
return ipnstate.TaildropTargetIpnStateNotRunning
|
||||
}
|
||||
if b.netMap == nil {
|
||||
return ipnstate.TaildropTargetNoNetmapAvailable
|
||||
}
|
||||
if !b.capFileSharing {
|
||||
return ipnstate.TaildropTargetMissingCap
|
||||
}
|
||||
|
||||
if !p.Online().Get() {
|
||||
return ipnstate.TaildropTargetOffline
|
||||
}
|
||||
|
||||
if !p.Valid() {
|
||||
return ipnstate.TaildropTargetNoPeerInfo
|
||||
}
|
||||
if b.netMap.User() != p.User() {
|
||||
// Different user must have the explicit file sharing target capability
|
||||
if p.Addresses().Len() == 0 ||
|
||||
!b.peerHasCapLocked(p.Addresses().At(0).Addr(), tailcfg.PeerCapabilityFileSharingTarget) {
|
||||
return ipnstate.TaildropTargetOwnedByOtherUser
|
||||
}
|
||||
}
|
||||
|
||||
if p.Hostinfo().OS() == "tvOS" {
|
||||
return ipnstate.TaildropTargetUnsupportedOS
|
||||
}
|
||||
if peerAPIBase(b.netMap, p) == "" {
|
||||
return ipnstate.TaildropTargetNoPeerAPI
|
||||
}
|
||||
return ipnstate.TaildropTargetAvailable
|
||||
}
|
||||
|
||||
// peerIsTaildropTargetLocked reports whether p is a valid Taildrop file
|
||||
// recipient from this node according to its ownership and the capabilities in
|
||||
// the netmap.
|
||||
|
@@ -270,6 +270,12 @@ type PeerStatus struct {
|
||||
// PeerAPIURL are the URLs of the node's PeerAPI servers.
|
||||
PeerAPIURL []string
|
||||
|
||||
// TaildropTargetStatus represents the node's eligibility to have files shared to it.
|
||||
TaildropTarget TaildropTargetStatus
|
||||
|
||||
// Reason why this peer cannot receive files. Empty if CanReceiveFiles=true
|
||||
NoFileSharingReason string
|
||||
|
||||
// Capabilities are capabilities that the node has.
|
||||
// They're free-form strings, but should be in the form of URLs/URIs
|
||||
// such as:
|
||||
@@ -318,6 +324,21 @@ type PeerStatus struct {
|
||||
Location *tailcfg.Location `json:",omitempty"`
|
||||
}
|
||||
|
||||
type TaildropTargetStatus int
|
||||
|
||||
const (
|
||||
TaildropTargetUnknown TaildropTargetStatus = iota
|
||||
TaildropTargetAvailable
|
||||
TaildropTargetNoNetmapAvailable
|
||||
TaildropTargetIpnStateNotRunning
|
||||
TaildropTargetMissingCap
|
||||
TaildropTargetOffline
|
||||
TaildropTargetNoPeerInfo
|
||||
TaildropTargetUnsupportedOS
|
||||
TaildropTargetNoPeerAPI
|
||||
TaildropTargetOwnedByOtherUser
|
||||
)
|
||||
|
||||
// HasCap reports whether ps has the given capability.
|
||||
func (ps *PeerStatus) HasCap(cap tailcfg.NodeCapability) bool {
|
||||
return ps.CapMap.Contains(cap)
|
||||
|
Reference in New Issue
Block a user