mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
it builds
This commit is contained in:
2
core/Cargo.lock
generated
2
core/Cargo.lock
generated
@@ -7419,10 +7419,12 @@ dependencies = [
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml",
|
||||
"tor-cell",
|
||||
"tor-hscrypto",
|
||||
"tor-hsservice",
|
||||
"tor-keymgr",
|
||||
"tor-llcrypto",
|
||||
"tor-proto",
|
||||
"tor-rtcompat",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
||||
@@ -225,10 +225,12 @@ tokio-stream = { version = "0.1.14", features = ["io-util", "sync", "net"] }
|
||||
tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" }
|
||||
tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] }
|
||||
tokio-util = { version = "0.7.9", features = ["io"] }
|
||||
tor-cell = { version = "0.33" }
|
||||
tor-hscrypto = { version = "0.33", features = ["full"] }
|
||||
tor-hsservice = { version = "0.33" }
|
||||
tor-keymgr = { version = "0.33", features = ["ephemeral-keystore"] }
|
||||
tor-llcrypto = { version = "0.33", features = ["full"] }
|
||||
tor-proto = { version = "0.33" }
|
||||
tor-rtcompat = { version = "0.33", features = ["tokio", "rustls"] }
|
||||
tower-service = "0.3.3"
|
||||
tracing = "0.1.39"
|
||||
|
||||
@@ -622,8 +622,8 @@ async fn watch_ip(
|
||||
.chain(ip6_proxy.address_data().await?)
|
||||
.collect_vec();
|
||||
let lan_ip = [
|
||||
ip4_proxy.gateway().await?.parse::<IpAddr>()?,
|
||||
ip6_proxy.gateway().await?.parse::<IpAddr>()?,
|
||||
dbg!(ip4_proxy.gateway().await?).parse::<IpAddr>()?,
|
||||
dbg!(ip6_proxy.gateway().await?).parse::<IpAddr>()?,
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
@@ -852,7 +852,13 @@ impl NetworkInterfaceController {
|
||||
) -> Result<(), Error> {
|
||||
tracing::debug!("syncronizing {info:?} to db");
|
||||
|
||||
let dns = todo!();
|
||||
// let dns = todo!();
|
||||
let dns = info
|
||||
.values()
|
||||
.filter_map(|i| i.ip_info.as_ref())
|
||||
.flat_map(|i| &i.dns_servers)
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
db.mutate(|db| {
|
||||
let net = db.as_public_mut().as_server_info_mut().as_network_mut();
|
||||
|
||||
@@ -12,8 +12,8 @@ use ts_rs::TS;
|
||||
use crate::context::{CliContext, RpcContext};
|
||||
use crate::db::model::public::NetworkInterfaceInfo;
|
||||
use crate::net::forward::AvailablePorts;
|
||||
use crate::net::host::HostApiKind;
|
||||
use crate::net::gateway::InterfaceFilter;
|
||||
use crate::net::host::HostApiKind;
|
||||
use crate::net::vhost::AlpnInfo;
|
||||
use crate::prelude::*;
|
||||
use crate::util::serde::{display_serializable, HandlerExtSerde};
|
||||
@@ -58,8 +58,10 @@ pub struct BindInfo {
|
||||
#[ts(export)]
|
||||
pub struct NetInfo {
|
||||
#[ts(as = "BTreeSet::<GatewayId>")]
|
||||
#[serde(default)]
|
||||
pub private_disabled: OrdSet<GatewayId>,
|
||||
#[ts(as = "BTreeSet::<GatewayId>")]
|
||||
#[serde(default)]
|
||||
pub public_enabled: OrdSet<GatewayId>,
|
||||
pub assigned_port: Option<u16>,
|
||||
pub assigned_ssl_port: Option<u16>,
|
||||
|
||||
@@ -9,7 +9,7 @@ use arti_client::{TorClient, TorClientConfig};
|
||||
use base64::Engine;
|
||||
use clap::Parser;
|
||||
use color_eyre::eyre::eyre;
|
||||
use futures::FutureExt;
|
||||
use futures::{FutureExt, Stream, StreamExt};
|
||||
use helpers::NonDetachingJoinHandle;
|
||||
use imbl_value::InternedString;
|
||||
use itertools::Itertools;
|
||||
@@ -18,15 +18,21 @@ use regex::Regex;
|
||||
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler};
|
||||
use safelog::DisplayRedacted;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::oneshot;
|
||||
use tor_cell::relaycell::msg::Connected;
|
||||
use tor_hscrypto::pk::{HsId, HsIdKeypair};
|
||||
use tor_hsservice::status::State as ArtiOnionServiceState;
|
||||
use tor_hsservice::{HsNickname, RunningOnionService};
|
||||
use tor_hsservice::{HsNickname, RendRequest, RunningOnionService};
|
||||
use tor_keymgr::config::ArtiKeystoreKind;
|
||||
use tor_proto::stream::IncomingStreamRequest;
|
||||
use tor_rtcompat::tokio::TokioRustlsRuntime;
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::context::{CliContext, RpcContext};
|
||||
use crate::prelude::*;
|
||||
use crate::util::actor::background::BackgroundJobQueue;
|
||||
use crate::util::serde::{
|
||||
deserialize_from_str, display_serializable, serialize_display, Base64, HandlerExtSerde,
|
||||
WithIoFormat, BASE64,
|
||||
@@ -210,25 +216,6 @@ impl std::fmt::Debug for OnionStore {
|
||||
}
|
||||
}
|
||||
|
||||
enum ErrorLogSeverity {
|
||||
Fatal { wipe_state: bool },
|
||||
Unknown { wipe_state: bool },
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref LOG_REGEXES: Vec<(Regex, ErrorLogSeverity)> = vec![(
|
||||
Regex::new("This could indicate a route manipulation attack, network overload, bad local network connectivity, or a bug\\.").unwrap(),
|
||||
ErrorLogSeverity::Unknown { wipe_state: true }
|
||||
),(
|
||||
Regex::new("died due to an invalid selected path").unwrap(),
|
||||
ErrorLogSeverity::Fatal { wipe_state: false }
|
||||
),(
|
||||
Regex::new("Tor has not observed any network activity for the past").unwrap(),
|
||||
ErrorLogSeverity::Unknown { wipe_state: false }
|
||||
)];
|
||||
static ref PROGRESS_REGEX: Regex = Regex::new("PROGRESS=([0-9]+)").unwrap();
|
||||
}
|
||||
|
||||
pub fn tor_api<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
@@ -368,6 +355,11 @@ pub enum OnionServiceState {
|
||||
Recovering,
|
||||
Broken,
|
||||
}
|
||||
impl From<ArtiOnionServiceState> for OnionServiceState {
|
||||
fn from(value: ArtiOnionServiceState) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_services(
|
||||
ctx: RpcContext,
|
||||
@@ -403,7 +395,9 @@ impl TorController {
|
||||
let addr = key.onion_address();
|
||||
match s.entry(addr) {
|
||||
Entry::Occupied(e) => Ok(e.get().clone()),
|
||||
Entry::Vacant(e) => Ok(e.insert(OnionService::launch(&self.client, key)?).clone()),
|
||||
Entry::Vacant(e) => Ok(e
|
||||
.insert(OnionService::launch(self.client.clone(), key)?)
|
||||
.clone()),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -457,31 +451,123 @@ impl TorController {
|
||||
#[derive(Clone)]
|
||||
pub struct OnionService(Arc<OnionServiceData>);
|
||||
struct OnionServiceData {
|
||||
service: Arc<RunningOnionService>,
|
||||
service: Arc<SyncMutex<Option<Arc<RunningOnionService>>>>,
|
||||
bindings: Arc<SyncRwLock<BTreeMap<u16, BTreeMap<SocketAddr, Weak<()>>>>>,
|
||||
_thread: NonDetachingJoinHandle<()>,
|
||||
}
|
||||
impl OnionService {
|
||||
fn launch(client: &TorClient<TokioRustlsRuntime>, key: TorSecretKey) -> Result<Self, Error> {
|
||||
let (service, stream) = client.launch_onion_service_with_hsid(
|
||||
OnionServiceConfigBuilder::default()
|
||||
.nickname(
|
||||
key.onion_address()
|
||||
.to_string()
|
||||
.trim_end_matches(".onion")
|
||||
.parse::<HsNickname>()
|
||||
.with_kind(ErrorKind::Tor)?,
|
||||
)
|
||||
.build()
|
||||
.with_kind(ErrorKind::Tor)?,
|
||||
key.0,
|
||||
)?;
|
||||
let bindings = Arc::new(SyncRwLock::new(BTreeMap::new()));
|
||||
fn launch(client: TorClient<TokioRustlsRuntime>, key: TorSecretKey) -> Result<Self, Error> {
|
||||
let service = Arc::new(SyncMutex::new(None));
|
||||
let bindings = Arc::new(SyncRwLock::new(BTreeMap::<
|
||||
u16,
|
||||
BTreeMap<SocketAddr, Weak<()>>,
|
||||
>::new()));
|
||||
Ok(Self(Arc::new(OnionServiceData {
|
||||
service: service.clone(),
|
||||
bindings: bindings.clone(),
|
||||
_thread: tokio::spawn(async move {
|
||||
todo!();
|
||||
let (bg, mut runner) = BackgroundJobQueue::new();
|
||||
runner
|
||||
.run_while(async {
|
||||
loop {
|
||||
if let Err(e) = async {
|
||||
let (new_service, mut stream) = client
|
||||
.launch_onion_service_with_hsid(
|
||||
OnionServiceConfigBuilder::default()
|
||||
.nickname(
|
||||
key.onion_address()
|
||||
.to_string()
|
||||
.trim_end_matches(".onion")
|
||||
.parse::<HsNickname>()
|
||||
.with_kind(ErrorKind::Tor)?,
|
||||
)
|
||||
.build()
|
||||
.with_kind(ErrorKind::Tor)?,
|
||||
key.clone().0,
|
||||
)
|
||||
.with_kind(ErrorKind::Tor)?;
|
||||
service.replace(Some(new_service));
|
||||
while let Some(req) = stream.next().await {
|
||||
bg.add_job({
|
||||
let bg = bg.clone();
|
||||
let bindings = bindings.clone();
|
||||
async move {
|
||||
if let Err(e) = async {
|
||||
let mut stream =
|
||||
req.accept().await.with_kind(ErrorKind::Tor)?;
|
||||
while let Some(req) = stream.next().await {
|
||||
let IncomingStreamRequest::Begin(begin) =
|
||||
req.request()
|
||||
else {
|
||||
continue; // TODO: reject instead?
|
||||
};
|
||||
let Some(target) = bindings.peek(|b| {
|
||||
b.get(&begin.port()).and_then(|a| {
|
||||
a.iter()
|
||||
.find(|(_, rc)| {
|
||||
rc.strong_count() > 0
|
||||
})
|
||||
.map(|(addr, _)| *addr)
|
||||
})
|
||||
}) else {
|
||||
continue; // TODO: reject instead?
|
||||
};
|
||||
bg.add_job(async move {
|
||||
if let Err(e) = async {
|
||||
let mut outgoing =
|
||||
TcpStream::connect(target)
|
||||
.await
|
||||
.with_kind(
|
||||
ErrorKind::Network,
|
||||
)?;
|
||||
let mut incoming = req
|
||||
.accept(Connected::new_empty())
|
||||
.await
|
||||
.with_kind(ErrorKind::Tor)?;
|
||||
if let Err(e) =
|
||||
tokio::io::copy_bidirectional(
|
||||
&mut outgoing,
|
||||
&mut incoming,
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::error!("{e}");
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
incoming.flush().await?;
|
||||
outgoing.flush().await?;
|
||||
incoming.shutdown().await?;
|
||||
outgoing.shutdown().await?;
|
||||
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("{e}");
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("{e}");
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
.await
|
||||
{
|
||||
tracing::error!("{e}");
|
||||
tracing::debug!("{e:?}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.await
|
||||
})
|
||||
.into(),
|
||||
})))
|
||||
@@ -491,14 +577,35 @@ impl OnionService {
|
||||
&self,
|
||||
bindings: impl IntoIterator<Item = (u16, SocketAddr)>,
|
||||
) -> Rcs {
|
||||
todo!()
|
||||
self.0.bindings.mutate(|b| {
|
||||
bindings
|
||||
.into_iter()
|
||||
.map(|(port, target)| {
|
||||
let entry = b.entry(port).or_default().entry(target).or_default();
|
||||
if let Some(rc) = entry.upgrade() {
|
||||
rc
|
||||
} else {
|
||||
let rc = Arc::new(());
|
||||
*entry = Arc::downgrade(&rc);
|
||||
rc
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn gc(&self) -> bool {
|
||||
todo!()
|
||||
self.0.bindings.mutate(|b| {
|
||||
b.retain(|_, targets| {
|
||||
targets.retain(|_, rc| rc.strong_count() > 0);
|
||||
!targets.is_empty()
|
||||
});
|
||||
!b.is_empty()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn shutdown(self) -> Result<(), Error> {
|
||||
todo!()
|
||||
self.0._thread.abort();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ pub mod recipe;
|
||||
├── manifest.json
|
||||
├── icon.<ext>
|
||||
├── LICENSE.md
|
||||
├── instructions.md
|
||||
├── dependencies
|
||||
│ └── <id>
|
||||
│ ├── metadata.json
|
||||
|
||||
@@ -147,8 +147,6 @@ pub struct PackParams {
|
||||
pub icon: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
pub license: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
pub instructions: Option<PathBuf>,
|
||||
#[arg(long, conflicts_with = "no-assets")]
|
||||
pub assets: Option<PathBuf>,
|
||||
#[arg(long, conflicts_with = "assets")]
|
||||
@@ -240,12 +238,6 @@ impl PackParams {
|
||||
.await?
|
||||
}
|
||||
}
|
||||
fn instructions(&self) -> PathBuf {
|
||||
self.instructions
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| self.path().join("instructions.md"))
|
||||
}
|
||||
fn assets(&self) -> PathBuf {
|
||||
self.assets
|
||||
.as_ref()
|
||||
@@ -797,20 +789,10 @@ pub async fn list_ingredients(_: CliContext, params: PackParams) -> Result<Vec<P
|
||||
Err(e) => {
|
||||
warn!("failed to load manifest: {e}");
|
||||
debug!("{e:?}");
|
||||
return Ok(vec![
|
||||
js_path,
|
||||
params.icon().await?,
|
||||
params.license().await?,
|
||||
params.instructions(),
|
||||
]);
|
||||
return Ok(vec![js_path, params.icon().await?, params.license().await?]);
|
||||
}
|
||||
};
|
||||
let mut ingredients = vec![
|
||||
js_path,
|
||||
params.icon().await?,
|
||||
params.license().await?,
|
||||
params.instructions(),
|
||||
];
|
||||
let mut ingredients = vec![js_path, params.icon().await?, params.license().await?];
|
||||
|
||||
for (_, dependency) in manifest.dependencies.0 {
|
||||
if let Some(PathOrUrl::Path(p)) = dependency.s9pk {
|
||||
|
||||
@@ -63,3 +63,29 @@ impl Future for BackgroundJobRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl BackgroundJobRunner {
|
||||
pub fn run_while<Fut: Future + Send>(
|
||||
&mut self,
|
||||
fut: Fut,
|
||||
) -> impl Future<Output = Fut::Output> + Send {
|
||||
#[pin_project::pin_project]
|
||||
struct RunWhile<'a, Fut> {
|
||||
#[pin]
|
||||
runner: &'a mut BackgroundJobRunner,
|
||||
#[pin]
|
||||
fut: Fut,
|
||||
}
|
||||
impl<'a, Fut: Future> Future for RunWhile<'a, Fut> {
|
||||
type Output = Fut::Output;
|
||||
fn poll(
|
||||
self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
this.runner.poll(cx);
|
||||
this.fut.poll(cx)
|
||||
}
|
||||
}
|
||||
RunWhile { runner: self, fut }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ impl<T> SyncMutex<T> {
|
||||
pub fn peek<F: FnOnce(&T) -> U, U>(&self, f: F) -> U {
|
||||
f(&*self.0.lock().unwrap())
|
||||
}
|
||||
pub fn replace(&self, value: T) -> T {
|
||||
std::mem::replace(&mut *self.0.lock().unwrap(), value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
||||
Reference in New Issue
Block a user