Skip to main content

MapResponse

Struct MapResponse 

Source
pub struct MapResponse<'a> {
Show 29 fields pub map_session_handle: &'a str, pub seq: i64, pub keep_alive: Option<bool>, pub ping_request: Option<PingRequest>, pub pop_browser_url: Option<Cow<'a, str>>, pub node: Option<Node<'a>>, pub derp_map: Option<DerpMap<'a>>, pub peers: Option<Vec<Node<'a>>>, pub peers_changed: Option<Vec<Node<'a>>>, pub peers_removed: Option<Vec<NodeId>>, pub peers_changed_patch: Vec<Option<PeerChange<'a>>>, pub peer_seen_change: BTreeMap<NodeId, bool>, pub online_change: BTreeMap<NodeId, bool>, pub dns_config: Option<DnsConfig<'a>>, pub domain: Cow<'a, str>, pub collect_services: Option<bool>, pub packet_filter: Option<Ruleset<'a>>, pub packet_filters: Map<'a>, pub user_profiles: Vec<UserProfile<'a>>, pub health: Vec<&'a str>, pub display_messages: BTreeMap<&'a str, Option<DisplayMessage<'a>>>, pub ssh_policy: Option<SSHPolicy<'a>>, pub control_time: Option<DateTime<Utc>>, pub tka_info: Option<TkaInfo<'a>>, pub domain_data_plane_audit_log_id: Option<&'a str>, pub debug: Option<Debug>, pub control_dial_plan: Option<ControlDialPlan<'a>>, pub client_version: Option<ClientVersion<'a>>, pub default_auto_update: Option<bool>,
}
Expand description

The response to a MapRequest. It describes the state of the local Tailscale node, the peer nodes in the Tailnet, the DNS configuration, the packet filter, and more. A MapRequest, depending on its parameters, may result in the control plane coordination server sending 0, 1, or a stream of multiple MapResponse values.

When a node sends a MapRequest to the control server with the MapRequest::stream flag set to true, the server will respond with a stream of MapResponses. The long-lived HTTP transaction delivering the stream is called a “map poll”. In a map poll, the first MapResponse will be complete; subsequent MapResponses will be incremental updates with only changed information.

In general, fields omitted in the MapResponse JSON (or None in the deserialized struct instance) indicate the field’s value is unchanged from the previous value. However, several older slice-like fields have different semantics; this is noted in the doc comments for the relevant fields. For background, see the [doc comment for MapResponse] in the Go client.

The struct-level #[serde_with::apply] block makes every bare Vec/map field tolerate a wire null (Go marshals empty omitempty slices/maps as null; see crate::util::null_to_default) and auto-covers any such field added later. This is deliberately scoped to non-Option Vec/map fields: the delta-encoded fields whose null/absence means “unchanged from the prior poll” (peers, peers_changed, peers_removed, packet_filter singular, etc.) are all Option<…> — matched by none of the rules below (the apply macro matches the type exactly as written, path qualifier and all), so they are left completely untouched and keep their “unchanged” semantics. Note the path-qualified ts_packetfilter_serde::Map rule: a bare Map token would NOT match it (the field is written with its full path), which is why each alias spelling that appears on the struct needs its own rule.

Fields§

§map_session_handle: &'a str

Optionally specifies a unique opaque handle for this stateful MapResponse session. Servers may choose not to send it, and it’s only sent on the first MapResponse in a stream. The client can determine whether it’s reattaching to a prior stream by seeing whether this value matches the requested MapResponse::map_session_handle.

§seq: i64

Sequence number within a named map session (a response where the first message contains a MapResponse::map_session_handle). The sequence number may be omitted on responses that don’t change the state of the stream, such as KeepAlive or certain types of PingRequests. This is the value to be sent in MapRequest::map_session_seq to resume after this message.

§keep_alive: Option<bool>

If set, represents an empty message just to keep the connection alive. When true, all other fields except MapResponse::ping_request, MapResponse::control_time, and MapResponse::pop_browser_url are ignored.

§ping_request: Option<PingRequest>

If non-None, a request to the client to prove it’s still there by sending an HTTP request to the provided URL. No auth headers are necessary. MapResponse::ping_request may be sent on any MapResponse (ones with MapResponse::keep_alive set to either true or false).

§pop_browser_url: Option<Cow<'a, str>>

If non-None, a URL for the client to open to complete an action. The client should debounce identical URLs and only open it once for the same URL.

A Cow because a URL legitimately carries & in its query string, which Go’s json.Marshal escapes to & by default — a borrowed &str cannot decode that escaped form and would fail the whole MapResponse decode.

Wire key PopBrowserURL (Go’s URL acronym), not the PascalCase default PopBrowserUrl.

§node: Option<Node<'a>>

Describes the Tailscale node making the map request (ie, the “self” node). Starting with capability version 18, a value of None means unchanged.

§derp_map: Option<DerpMap<'a>>

Describes the set of available DERP regions and servers. If None, the set of servers is unchanged from the last set sent from the control plane to this client.

§peers: Option<Vec<Node<'a>>>

The complete list of peer Tailscale nodes in the same Tailnet as this node. This field will always be populated in the first MapResponse in a long-polled stream sent to this node. Subsequent MapResponses in the stream will usually provide delta-encoded updates on nodes that have been added, removed, or changed since the previous MapResponse via the MapResponse::peers_changed and MapResponse::peers_removed fields.

If this field is populated, it takes precedence over the other two fields; in other words, if MapResponse::peers is populated, you must ignore both the MapResponse::peers_changed and MapResponse::peers_removed fields and use only the values in this field.

This list will always be sorted by Node::id in ascending order.

§peers_changed: Option<Vec<Node<'a>>>

The Tailscale nodes in the Tailnet that have changed or been added since the last MapResponse sent to this node. Do not use this field if MapResponse::peers is populated.

This list will always be sorted by Node::id in ascending order.

§peers_removed: Option<Vec<NodeId>>

IDs of Tailscale nodes that are no longer in the peer list for the Tailnet.

§peers_changed_patch: Vec<Option<PeerChange<'a>>>

If present, the indicated nodes have changed.

This is a lighter version of peers_changed that only supports certain types of updates.

These are applied after peers*, but in practice, the control server should only send these on their own, without the peers* fields also set.

§peer_seen_change: BTreeMap<NodeId, bool>

How to update peers’ last_seen times (Go PeerSeenChange).

This is the SOLE driver of last_seen, and it never touches online: true ⇒ set last_seen to now; false ⇒ clear last_seen (its value is unknown), NOT “mark offline”. A peer’s online state is driven exclusively by online_change — conflating the two wrongly reports a peer offline merely because its last-seen is unknown.

§online_change: BTreeMap<NodeId, bool>

Updates to peers’ online states.

§dns_config: Option<DnsConfig<'a>>

The DNS settings for the client to use.

A None value means no change.

§domain: Cow<'a, str>

The name of the network that this node is in. It’s either of the form:

  • “example.com” (for user foo@example.com, for multi-user networks)
  • “foo@gmail.com” (for siloed users on shared email providers)

Do not depend on the exact format of this field; more forms will be added in the future. If empty, the value is unchanged.

§collect_services: Option<bool>

Indicates whether this node’s tailnet has requested that info about services be included in Node::host_info. If None, the most recent non-empty MapResponse value in the HTTP response stream is used.

§packet_filter: Option<Ruleset<'a>>

packet_filter are the firewall rules.

For MapRequest::version >= 6, a None value means the most previously streamed non-None MapResponse::packet_filter within the same HTTP response. A present (Some) but empty list always means no packet_filter (that is, to block everything).

See packet_filters for the newer way to send packet_filter updates.

§packet_filters: Map<'a>

packet_filters encodes incremental packet filter updates to the client without having to send the entire packet filter on any changes as required by the older packet_filter (singular) field above. The map keys are server-assigned arbitrary strings. The map values are the new rules for that key, or nil to delete it. The client then concatenates all the rules together to generate the final packet filter. Because the FilterRules can only match or not match, the ordering of filter rules doesn’t matter.

If the server sends a non-nil packet_filter (above), that is equivalent to a named packet filter with the key “base”. It is valid for the server to send both packet_filter and packet_filters in the same MapResponse or alternate between them within a session. packet_filter is applied first (if set), and then packet_filters.

As a special case, the map key “*” with a value of None means to clear all prior named packet filters (including any implicit “base”) before processing the other map entries.

§user_profiles: Vec<UserProfile<'a>>

The UserProfiles associated with Tailscale nodes in the Tailnet. As of CapabilityVersion::V5, contains only new or updated profiles.

§health: Vec<&'a str>

Sets the health state of the node from the control plane’s perspective (Go capver 24).

In Go, a nil slice means “no change from the previous MapResponse”, a non-nil zero-length slice restores health to good (no known problems), and a non-empty slice is the list of problems the control plane sees. Either this or display_messages is set, but not both.

This fork decodes the wire value into a Vec (the struct-level apply block tolerates a wire null, mapping it to an empty Vec); it does not currently distinguish “no change” (nil) from “all good” (empty) downstream — the field is carried so health warnings are no longer silently dropped.

§display_messages: BTreeMap<&'a str, Option<DisplayMessage<'a>>>

Structured health/display messages from the control plane (Go capver 117).

The map keys are opaque DisplayMessageID strings; a value of None (Go nil, JSON null) deletes that id. Go treats a populated map as a PATCH: new entries are added, null values delete, and existing entries with new values are updated. As a special case, the key "*" with a None value clears all prior display messages before the other entries are processed. A nil/absent map (and, in Go, an empty map) means no change.

Either this or health is set, but not both.

This fork decodes-and-carries the map (the struct-level apply block tolerates a wire null); the PATCH/"*"-clear/null-delete semantics are not yet applied downstream (see the map-stream consumer). Decoding it here is what stops control-pushed display messages from being silently dropped. TODO: wire the patch semantics into the map stream.

§ssh_policy: Option<SSHPolicy<'a>>

If non-None, updates the SSH policy for how incoming SSH connections should be handled. A None value means no change from the previous value.

§control_time: Option<DateTime<Utc>>

The current timestamp according to the control server; otherwise, None.

§tka_info: Option<TkaInfo<'a>>

Encodes the control plane’s view of Tailnet Key Authority (TKA) state.

If populated for an initial MapResponse (not a delta update), the control plane believes TKA should be enabled for this node. If None in an initial MapResponse, the control plane believes TKA should be disabled for this node.

If None in subsequent MapResponse updates in a long-polling map stream (i.e., delta updates), there are no changes to TKA state since the previous value.

§domain_data_plane_audit_log_id: Option<&'a str>

If populated, the per-tailnet log ID to be used when writing data plane audit logs.

§debug: Option<Debug>
👎Deprecated:

use Node::capabilities or c2n requests instead

Deprecated. If populated, contains debug settings from the control server that this Tailscale node should set.

§control_dial_plan: Option<ControlDialPlan<'a>>

If populated, tells this Tailscale node how to connect to the control server. If None, the node should use DNS to look up the IP address of the control server.

Used to maintain connection if the node’s network state changes after the initial connection, or if the control server pushes other changes to the node (such as DNS config updates) that break connectivity.

§client_version: Option<ClientVersion<'a>>

If populated, describes the latest Tailscale version that’s available for download for this node’s platform and package type. If None, the latest version hasn’t changed since the previous value.

§default_auto_update: Option<bool>

The default node auto-update setting for this tailnet. The node is free to opt-in or out locally regardless of this value. This value is only used on first MapResponse from control; the auto-update setting doesn’t change if the tailnet admin flips the default after the node registered.

Trait Implementations§

Source§

impl<'a> Clone for MapResponse<'a>

Source§

fn clone(&self) -> MapResponse<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for MapResponse<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Default for MapResponse<'a>

Source§

fn default() -> MapResponse<'a>

Returns the “default value” for a type. Read more
Source§

impl<'de: 'a, 'a> Deserialize<'de> for MapResponse<'a>
where MapResponse<'a>: Default,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for MapResponse<'a>

§

impl<'a> RefUnwindSafe for MapResponse<'a>

§

impl<'a> Send for MapResponse<'a>

§

impl<'a> Sync for MapResponse<'a>

§

impl<'a> Unpin for MapResponse<'a>

§

impl<'a> UnsafeUnpin for MapResponse<'a>

§

impl<'a> UnwindSafe for MapResponse<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.