cli: use hostname-based generation instead of bird names (#173220)

Fixes #167708 by using a more predictable naming scheme.

```
me> Write a haiku about the extinction of birds
chatgpt>
	Silent skies above,
	Once lively songs now gone,
	Fading memories.
```
This commit is contained in:
Connor Peet 2023-02-02 15:05:38 -08:00 committed by GitHub
parent ddd71a222d
commit 953a039549
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 231 deletions

View file

@ -10,14 +10,13 @@ pub mod paths;
pub mod shutdown_signal;
mod control_server;
mod name_generator;
mod nosleep;
#[cfg(target_os = "linux")]
mod nosleep_linux;
#[cfg(target_os = "macos")]
mod nosleep_macos;
#[cfg(target_os = "windows")]
mod nosleep_windows;
#[cfg(target_os = "linux")]
mod nosleep_linux;
mod port_forwarder;
mod protocol;
#[cfg_attr(unix, path = "tunnels/server_bridge_unix.rs")]

View file

@ -4,7 +4,8 @@
*--------------------------------------------------------------------------------------------*/
use crate::auth;
use crate::constants::{
CONTROL_PORT, PROTOCOL_VERSION_TAG, PROTOCOL_VERSION_TAG_PREFIX, TUNNEL_SERVICE_USER_AGENT, IS_INTERACTIVE_CLI,
CONTROL_PORT, IS_INTERACTIVE_CLI, PROTOCOL_VERSION_TAG, PROTOCOL_VERSION_TAG_PREFIX,
TUNNEL_SERVICE_USER_AGENT,
};
use crate::state::{LauncherPaths, PersistedState};
use crate::util::errors::{
@ -31,8 +32,6 @@ use tunnels::management::{
NO_REQUEST_OPTIONS,
};
use super::name_generator;
#[derive(Clone, Serialize, Deserialize)]
pub struct PersistedTunnel {
pub name: String,
@ -636,10 +635,14 @@ impl DevTunnels {
mut use_random_name: bool,
) -> Result<String, AnyError> {
let existing_tunnels = self.list_all_server_tunnels().await?;
println!("{:?}", existing_tunnels);
let is_name_free = |n: &str| {
!existing_tunnels
.iter()
.any(|v| v.tags.iter().any(|t| t == n))
!existing_tunnels.iter().any(|v| {
v.status
.as_ref()
.and_then(|s| s.host_connection_count.as_ref().map(|c| c.get_count()))
.unwrap_or(0) > 0 && v.tags.iter().any(|t| t == n)
})
};
if let Some(machine_name) = preferred_name {
@ -658,11 +661,19 @@ impl DevTunnels {
use_random_name = true;
}
let mut placeholder_name = name_generator::generate_name(MAX_TUNNEL_NAME_LENGTH);
if use_random_name || !*IS_INTERACTIVE_CLI {
while !is_name_free(&placeholder_name) {
placeholder_name = name_generator::generate_name(MAX_TUNNEL_NAME_LENGTH);
let mut placeholder_name =
clean_hostname_for_tunnel(&gethostname::gethostname().to_string_lossy());
if !is_name_free(&placeholder_name) {
for i in 2.. {
let fixed_name = format!("{}{}", placeholder_name, i);
if is_name_free(&fixed_name) {
placeholder_name = fixed_name;
break;
}
}
}
if use_random_name || !*IS_INTERACTIVE_CLI {
return Ok(placeholder_name);
}
@ -959,3 +970,49 @@ impl Backoff {
self.failures = 0;
}
}
/// Cleans up the hostname so it can be used as a tunnel name.
/// See TUNNEL_NAME_PATTERN in the tunnels SDK for the rules we try to use.
fn clean_hostname_for_tunnel(hostname: &str) -> String {
let mut out = String::new();
for char in hostname.chars().take(60) {
match char {
'-' | '_' | ' ' => {
out.push('-');
}
'0'..='9' | 'a'..='z' | 'A'..='Z' => {
out.push(char);
}
_ => {}
}
}
let trimmed = out.trim_matches('-');
if trimmed.len() < 2 {
"remote-machine".to_string() // placeholder if the result was empty
} else {
trimmed.to_owned()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_clean_hostname_for_tunnel() {
assert_eq!(
clean_hostname_for_tunnel("hello123"),
"hello123".to_string()
);
assert_eq!(
clean_hostname_for_tunnel("-cool-name-"),
"cool-name".to_string()
);
assert_eq!(
clean_hostname_for_tunnel("cool!name with_chars"),
"coolname-with-chars".to_string()
);
assert_eq!(clean_hostname_for_tunnel("z"), "remote-machine".to_string());
}
}

View file

@ -1,218 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
use rand::prelude::*;
// Adjectives in LEFT from Moby :
static LEFT: &[&str] = &[
"admiring",
"adoring",
"affectionate",
"agitated",
"amazing",
"angry",
"awesome",
"beautiful",
"blissful",
"bold",
"boring",
"brave",
"busy",
"charming",
"clever",
"cool",
"compassionate",
"competent",
"condescending",
"confident",
"cranky",
"crazy",
"dazzling",
"determined",
"distracted",
"dreamy",
"eager",
"ecstatic",
"elastic",
"elated",
"elegant",
"eloquent",
"epic",
"exciting",
"fervent",
"festive",
"flamboyant",
"focused",
"friendly",
"frosty",
"funny",
"gallant",
"gifted",
"goofy",
"gracious",
"great",
"happy",
"hardcore",
"heuristic",
"hopeful",
"hungry",
"infallible",
"inspiring",
"interesting",
"intelligent",
"jolly",
"jovial",
"keen",
"kind",
"laughing",
"loving",
"lucid",
"magical",
"mystifying",
"modest",
"musing",
"naughty",
"nervous",
"nice",
"nifty",
"nostalgic",
"objective",
"optimistic",
"peaceful",
"pedantic",
"pensive",
"practical",
"priceless",
"quirky",
"quizzical",
"recursing",
"relaxed",
"reverent",
"romantic",
"sad",
"serene",
"sharp",
"silly",
"sleepy",
"stoic",
"strange",
"stupefied",
"suspicious",
"sweet",
"tender",
"thirsty",
"trusting",
"unruffled",
"upbeat",
"vibrant",
"vigilant",
"vigorous",
"wizardly",
"wonderful",
"xenodochial",
"youthful",
"zealous",
"zen",
];
static RIGHT: &[&str] = &[
"albatross",
"antbird",
"antpitta",
"antshrike",
"antwren",
"babbler",
"barbet",
"blackbird",
"brushfinch",
"bulbul",
"bunting",
"cisticola",
"cormorant",
"crow",
"cuckoo",
"dove",
"drongo",
"duck",
"eagle",
"falcon",
"fantail",
"finch",
"flowerpecker",
"flycatcher",
"goose",
"goshawk",
"greenbul",
"grosbeak",
"gull",
"hawk",
"heron",
"honeyeater",
"hornbill",
"hummingbird",
"ibis",
"jay",
"kestrel",
"kingfisher",
"kite",
"lark",
"lorikeet",
"magpie",
"mockingbird",
"monarch",
"nightjar",
"oriole",
"owl",
"parakeet",
"parrot",
"partridge",
"penguin",
"petrel",
"pheasant",
"piculet",
"pigeon",
"pitta",
"prinia",
"puffin",
"quail",
"robin",
"sandpiper",
"seedeater",
"shearwater",
"sparrow",
"spinetail",
"starling",
"sunbird",
"swallow",
"swift",
"swiftlet",
"tanager",
"tapaculo",
"tern",
"thornbill",
"tinamou",
"trogon",
"tyrannulet",
"vireo",
"warbler",
"waxbill",
"weaver",
"whistler",
"woodpecker",
"wren",
];
/// Generates a random avian name, with the optional extra_random_length added
/// to reduce chance of in-flight collisions.
pub fn generate_name(max_length: usize) -> String {
let mut rng = rand::thread_rng();
loop {
let left = LEFT[rng.gen_range(0..LEFT.len())];
let right = RIGHT[rng.gen_range(0..RIGHT.len())];
let s = format!("{}-{}", left, right);
if s.len() < max_length {
return s;
}
}
}