mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-16 11:48:13 +01:00
Bail when trying to nest stream sessions using the same relay URL
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -99,6 +99,7 @@ dependencies = [
|
|||||||
"scraper",
|
"scraper",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"termion",
|
"termion",
|
||||||
@@ -1627,16 +1628,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.17.7"
|
version = "0.17.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
|
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
"getrandom 0.2.12",
|
"getrandom 0.2.12",
|
||||||
"libc",
|
"libc",
|
||||||
"spin",
|
"spin",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
|||||||
rgb = "0.8.37"
|
rgb = "0.8.37"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
tokio-tungstenite = { version = "0.21.0", features = ["rustls-tls-webpki-roots"] }
|
tokio-tungstenite = { version = "0.21.0", features = ["rustls-tls-webpki-roots"] }
|
||||||
|
sha2 = "0.10.8"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|||||||
@@ -26,10 +26,14 @@ fn build_exec_command(command: Option<String>) -> Vec<String> {
|
|||||||
vec!["/bin/sh".to_owned(), "-c".to_owned(), command]
|
vec!["/bin/sh".to_owned(), "-c".to_owned(), command]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_exec_extra_env() -> HashMap<String, String> {
|
fn build_exec_extra_env(vars: &[(String, String)]) -> HashMap<String, String> {
|
||||||
let mut env = HashMap::new();
|
let mut env = HashMap::new();
|
||||||
|
|
||||||
env.insert("ASCIINEMA_REC".to_owned(), "1".to_owned());
|
env.insert("ASCIINEMA_REC".to_owned(), "1".to_owned());
|
||||||
|
|
||||||
|
for (k, v) in vars {
|
||||||
|
env.insert(k.clone(), v.clone());
|
||||||
|
}
|
||||||
|
|
||||||
env
|
env
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ impl Cli {
|
|||||||
let notifier = super::get_notifier(config);
|
let notifier = super::get_notifier(config);
|
||||||
let record_input = self.input || config.cmd_rec_input();
|
let record_input = self.input || config.cmd_rec_input();
|
||||||
let exec_command = super::build_exec_command(command.as_ref().cloned());
|
let exec_command = super::build_exec_command(command.as_ref().cloned());
|
||||||
let exec_extra_env = super::build_exec_extra_env();
|
let exec_extra_env = super::build_exec_extra_env(&[]);
|
||||||
|
|
||||||
logger::info!("Recording session started, writing to {}", self.filename);
|
logger::info!("Recording session started, writing to {}", self.filename);
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,16 @@ use crate::logger;
|
|||||||
use crate::pty;
|
use crate::pty;
|
||||||
use crate::streamer::{self, KeyBindings};
|
use crate::streamer::{self, KeyBindings};
|
||||||
use crate::tty;
|
use crate::tty;
|
||||||
|
use crate::util;
|
||||||
|
use anyhow::bail;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use reqwest::header;
|
use reqwest::header;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
@@ -96,9 +101,20 @@ impl Cli {
|
|||||||
let notifier = super::get_notifier(config);
|
let notifier = super::get_notifier(config);
|
||||||
let record_input = self.input || config.cmd_stream_input();
|
let record_input = self.input || config.cmd_stream_input();
|
||||||
let exec_command = super::build_exec_command(command.as_ref().cloned());
|
let exec_command = super::build_exec_command(command.as_ref().cloned());
|
||||||
let exec_extra_env = super::build_exec_extra_env();
|
|
||||||
let listener = self.get_listener()?;
|
let listener = self.get_listener()?;
|
||||||
let relay = self.get_relay(config)?;
|
let relay = self.get_relay(config)?;
|
||||||
|
let relay_id = relay.as_ref().map(|r| r.id());
|
||||||
|
let exec_extra_env = build_exec_extra_env(relay_id.as_ref());
|
||||||
|
|
||||||
|
if let (Some(id), Some(parent_id)) = (relay_id, parent_session_relay_id()) {
|
||||||
|
if id == parent_id {
|
||||||
|
if let Some(Relay { url: Some(url), .. }) = relay {
|
||||||
|
bail!("This shell is already being streamed at {url}");
|
||||||
|
} else {
|
||||||
|
bail!("This shell is already being streamed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger::info!("Streaming session started");
|
logger::info!("Streaming session started");
|
||||||
|
|
||||||
@@ -212,6 +228,12 @@ impl Cli {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Relay {
|
||||||
|
fn id(&self) -> String {
|
||||||
|
util::sha2_digest(self.ws_producer_url.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_server_stream(stream_id: String, config: &Config) -> Result<GetStreamResponse> {
|
fn get_server_stream(stream_id: String, config: &Config) -> Result<GetStreamResponse> {
|
||||||
let response = Client::new()
|
let response = Client::new()
|
||||||
.get(stream_api_url(&config.get_server_url()?, stream_id))
|
.get(stream_api_url(&config.get_server_url()?, stream_id))
|
||||||
@@ -251,3 +273,14 @@ fn get_key_bindings(config: &Config) -> Result<KeyBindings> {
|
|||||||
|
|
||||||
Ok(keys)
|
Ok(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_exec_extra_env(relay_id: Option<&String>) -> HashMap<String, String> {
|
||||||
|
match relay_id {
|
||||||
|
Some(id) => super::build_exec_extra_env(&[("ASCIINEMA_RELAY_ID".to_string(), id.clone())]),
|
||||||
|
None => super::build_exec_extra_env(&[]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent_session_relay_id() -> Option<String> {
|
||||||
|
env::var("ASCIINEMA_RELAY_ID").ok()
|
||||||
|
}
|
||||||
|
|||||||
13
src/util.rs
13
src/util.rs
@@ -1,5 +1,6 @@
|
|||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
|
use sha2::Digest;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
@@ -115,6 +116,18 @@ impl Utf8Decoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sha2_digest(s: &str) -> String {
|
||||||
|
let mut hasher = sha2::Sha224::new();
|
||||||
|
hasher.update(s.as_bytes());
|
||||||
|
|
||||||
|
hasher
|
||||||
|
.finalize()
|
||||||
|
.as_slice()
|
||||||
|
.iter()
|
||||||
|
.map(|byte| format!("{:02x}", byte))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Utf8Decoder;
|
use super::Utf8Decoder;
|
||||||
|
|||||||
Reference in New Issue
Block a user