style: cargo fmt — clear formatting drift blocking the release gate
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8e51164321
commit
5c19effdd1
@ -198,8 +198,7 @@ impl RpcHandler {
|
|||||||
.and_then(|v| v.as_array())
|
.and_then(|v| v.as_array())
|
||||||
.and_then(|arr| {
|
.and_then(|arr| {
|
||||||
arr.iter().find(|p| {
|
arr.iter().find(|p| {
|
||||||
p.get("payment_hash").and_then(|v| v.as_str())
|
p.get("payment_hash").and_then(|v| v.as_str()) == Some(hash_lower.as_str())
|
||||||
== Some(hash_lower.as_str())
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,9 @@ fn parse_family(s: &str) -> Result<DeviceType> {
|
|||||||
"meshcore" => Ok(DeviceType::Meshcore),
|
"meshcore" => Ok(DeviceType::Meshcore),
|
||||||
"meshtastic" => Ok(DeviceType::Meshtastic),
|
"meshtastic" => Ok(DeviceType::Meshtastic),
|
||||||
"reticulum" | "rnode" => Ok(DeviceType::Reticulum),
|
"reticulum" | "rnode" => Ok(DeviceType::Reticulum),
|
||||||
other => anyhow::bail!("Unknown firmware family: {other} (expected meshcore|meshtastic|reticulum)"),
|
other => anyhow::bail!(
|
||||||
|
"Unknown firmware family: {other} (expected meshcore|meshtastic|reticulum)"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,12 +80,7 @@ fn manifest_declares_ui(app_id: &str) -> Option<bool> {
|
|||||||
if m.app.interfaces.is_empty() {
|
if m.app.interfaces.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
return Some(
|
return Some(m.app.interfaces.values().any(|i| i.interface_type == "ui"));
|
||||||
m.app
|
|
||||||
.interfaces
|
|
||||||
.values()
|
|
||||||
.any(|i| i.interface_type == "ui"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Malformed manifests are already reported by the orchestrator's
|
// Malformed manifests are already reported by the orchestrator's
|
||||||
// loader; here they simply don't count as a declaration.
|
// loader; here they simply don't count as a declaration.
|
||||||
|
|||||||
@ -6,39 +6,7 @@
|
|||||||
//! no listener, so allowing them is inert.
|
//! no listener, so allowing them is inert.
|
||||||
|
|
||||||
pub const APP_LAUNCH_PORTS: &[u16] = &[
|
pub const APP_LAUNCH_PORTS: &[u16] = &[
|
||||||
2283,
|
2283, 2342, 3000, 3001, 3002, 4080, 5180, 7778, 8080, 8081, 8082, 8083, 8084, 8085, 8087, 8088,
|
||||||
2342,
|
8089, 8090, 8096, 8123, 8175, 8176, 8240, 8334, 8888, 8999, 9000, 9100, 10380, 11434, 18081,
|
||||||
3000,
|
18083, 23000, 32838, 50002,
|
||||||
3001,
|
|
||||||
3002,
|
|
||||||
4080,
|
|
||||||
5180,
|
|
||||||
7778,
|
|
||||||
8080,
|
|
||||||
8081,
|
|
||||||
8082,
|
|
||||||
8083,
|
|
||||||
8084,
|
|
||||||
8085,
|
|
||||||
8087,
|
|
||||||
8088,
|
|
||||||
8089,
|
|
||||||
8090,
|
|
||||||
8096,
|
|
||||||
8123,
|
|
||||||
8175,
|
|
||||||
8176,
|
|
||||||
8240,
|
|
||||||
8334,
|
|
||||||
8888,
|
|
||||||
8999,
|
|
||||||
9000,
|
|
||||||
9100,
|
|
||||||
10380,
|
|
||||||
11434,
|
|
||||||
18081,
|
|
||||||
18083,
|
|
||||||
23000,
|
|
||||||
32838,
|
|
||||||
50002,
|
|
||||||
];
|
];
|
||||||
|
|||||||
@ -287,7 +287,10 @@ pub async fn install(identity_dir: &Path) -> Result<()> {
|
|||||||
app_install?;
|
app_install?;
|
||||||
// Make the allowance live immediately; a no-op error when the
|
// Make the allowance live immediately; a no-op error when the
|
||||||
// hardening baseline isn't installed on this node yet.
|
// hardening baseline isn't installed on this node yet.
|
||||||
if tokio::fs::try_exists("/etc/fips/fips.nft").await.unwrap_or(false) {
|
if tokio::fs::try_exists("/etc/fips/fips.nft")
|
||||||
|
.await
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
match Command::new("sudo")
|
match Command::new("sudo")
|
||||||
.args(["nft", "-f", "/etc/fips/fips.nft"])
|
.args(["nft", "-f", "/etc/fips/fips.nft"])
|
||||||
.output()
|
.output()
|
||||||
|
|||||||
@ -376,13 +376,9 @@ impl<'a> PeerRequest<'a> {
|
|||||||
let onion = self.onion_host.to_string();
|
let onion = self.onion_host.to_string();
|
||||||
let transport = kind.to_string();
|
let transport = kind.to_string();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _ = crate::federation::record_peer_transport(
|
let _ =
|
||||||
&dir,
|
crate::federation::record_peer_transport(&dir, None, Some(&onion), &transport)
|
||||||
None,
|
.await;
|
||||||
Some(&onion),
|
|
||||||
&transport,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,17 +104,15 @@ pub fn spawn_fips_supervisor(data_dir: std::path::PathBuf) {
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let seed = anchors::load(&data_dir).await.unwrap_or_default();
|
let seed = anchors::load(&data_dir).await.unwrap_or_default();
|
||||||
let mut warm_npubs: std::collections::BTreeSet<String> = nodes
|
let mut warm_npubs: std::collections::BTreeSet<String> =
|
||||||
.iter()
|
nodes.iter().filter_map(|n| n.fips_npub.clone()).collect();
|
||||||
.filter_map(|n| n.fips_npub.clone())
|
|
||||||
.collect();
|
|
||||||
warm_npubs.extend(seed.iter().map(|a| a.npub.clone()));
|
warm_npubs.extend(seed.iter().map(|a| a.npub.clone()));
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
for npub in warm_npubs {
|
for npub in warm_npubs {
|
||||||
// Service-active was checked once above for the whole batch.
|
// Service-active was checked once above for the whole batch.
|
||||||
handles.push(tokio::spawn(
|
handles.push(tokio::spawn(async move {
|
||||||
async move { dial::warm_path_unchecked(&npub).await },
|
dial::warm_path_unchecked(&npub).await
|
||||||
));
|
}));
|
||||||
}
|
}
|
||||||
for h in handles {
|
for h in handles {
|
||||||
let _ = h.await;
|
let _ = h.await;
|
||||||
|
|||||||
@ -420,7 +420,9 @@ pub async fn start_flash_job(
|
|||||||
|
|
||||||
match &result {
|
match &result {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
bg_job.push_log("Flash completed successfully".to_string()).await;
|
bg_job
|
||||||
|
.push_log("Flash completed successfully".to_string())
|
||||||
|
.await;
|
||||||
bg_job.finish().await;
|
bg_job.finish().await;
|
||||||
info!(path = %path, board = ?board, family = %family, "LoRa firmware flash succeeded");
|
info!(path = %path, board = ?board, family = %family, "LoRa firmware flash succeeded");
|
||||||
}
|
}
|
||||||
@ -586,7 +588,8 @@ async fn fetch_meshtastic_image(
|
|||||||
if tokio::fs::metadata(&zip_path).await.is_err() {
|
if tokio::fs::metadata(&zip_path).await.is_err() {
|
||||||
download_to_file(client, &zip_asset.browser_download_url, &zip_path, job).await?;
|
download_to_file(client, &zip_asset.browser_download_url, &zip_path, job).await?;
|
||||||
} else {
|
} else {
|
||||||
job.push_log(format!("Using cached {}", zip_asset.name)).await;
|
job.push_log(format!("Using cached {}", zip_asset.name))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "*.factory.bin" is Meshtastic's full merged image (bootloader +
|
// "*.factory.bin" is Meshtastic's full merged image (bootloader +
|
||||||
@ -594,26 +597,20 @@ async fn fetch_meshtastic_image(
|
|||||||
// erased chip — confirmed by inspecting the real zip's contents, as
|
// erased chip — confirmed by inspecting the real zip's contents, as
|
||||||
// opposed to the plain "*.bin" OTA-update image which assumes an
|
// opposed to the plain "*.bin" OTA-update image which assumes an
|
||||||
// existing bootloader/partition table already on the chip.
|
// existing bootloader/partition table already on the chip.
|
||||||
let entry_name = format!(
|
let entry_name = format!("firmware-{}-{}.factory.bin", board.meshtastic_id(), version);
|
||||||
"firmware-{}-{}.factory.bin",
|
|
||||||
board.meshtastic_id(),
|
|
||||||
version
|
|
||||||
);
|
|
||||||
let out_path = cache.join(&entry_name);
|
let out_path = cache.join(&entry_name);
|
||||||
if tokio::fs::metadata(&out_path).await.is_ok() {
|
if tokio::fs::metadata(&out_path).await.is_ok() {
|
||||||
return Ok(out_path);
|
return Ok(out_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
job.push_log(format!(
|
job.push_log(format!("Extracting {entry_name} from {}", zip_asset.name))
|
||||||
"Extracting {entry_name} from {}",
|
.await;
|
||||||
zip_asset.name
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
let zip_path_owned = zip_path.clone();
|
let zip_path_owned = zip_path.clone();
|
||||||
let entry_name_owned = entry_name.clone();
|
let entry_name_owned = entry_name.clone();
|
||||||
let out_path_owned = out_path.clone();
|
let out_path_owned = out_path.clone();
|
||||||
tokio::task::spawn_blocking(move || -> Result<()> {
|
tokio::task::spawn_blocking(move || -> Result<()> {
|
||||||
let file = std::fs::File::open(&zip_path_owned).context("Opening downloaded firmware zip")?;
|
let file =
|
||||||
|
std::fs::File::open(&zip_path_owned).context("Opening downloaded firmware zip")?;
|
||||||
let mut archive = zip::ZipArchive::new(file).context("Reading firmware zip")?;
|
let mut archive = zip::ZipArchive::new(file).context("Reading firmware zip")?;
|
||||||
let mut entry = archive
|
let mut entry = archive
|
||||||
.by_name(&entry_name_owned)
|
.by_name(&entry_name_owned)
|
||||||
|
|||||||
@ -802,7 +802,10 @@ impl MeshService {
|
|||||||
// the server name — it existed as write-only config with no reader
|
// the server name — it existed as write-only config with no reader
|
||||||
// until this line, which is why renaming on the Mesh page never
|
// until this line, which is why renaming on the Mesh page never
|
||||||
// changed anything on the air.
|
// changed anything on the air.
|
||||||
self.config.advert_name.clone().or_else(|| self.server_name.clone()),
|
self.config
|
||||||
|
.advert_name
|
||||||
|
.clone()
|
||||||
|
.or_else(|| self.server_name.clone()),
|
||||||
self.config.lora_region.clone(),
|
self.config.lora_region.clone(),
|
||||||
self.config.lora_radio_params,
|
self.config.lora_radio_params,
|
||||||
self.config.channel_name.clone(),
|
self.config.channel_name.clone(),
|
||||||
@ -1333,20 +1336,21 @@ impl MeshService {
|
|||||||
// federation branch: the fall-through LoRa path twin-resolves the
|
// federation branch: the fall-through LoRa path twin-resolves the
|
||||||
// routing key via peer_dest_prefix.
|
// routing key via peer_dest_prefix.
|
||||||
let device_connected = self.state.status.read().await.device_connected;
|
let device_connected = self.state.status.read().await.device_connected;
|
||||||
let radio_twin_reachable = is_federation_synthetic && !exceeds_lora && device_connected && {
|
let radio_twin_reachable =
|
||||||
let peers = self.state.peers.read().await;
|
is_federation_synthetic && !exceeds_lora && device_connected && {
|
||||||
peers
|
let peers = self.state.peers.read().await;
|
||||||
.get(&contact_id)
|
peers
|
||||||
.and_then(|p| p.arch_pubkey_hex.clone())
|
.get(&contact_id)
|
||||||
.map(|arch| {
|
.and_then(|p| p.arch_pubkey_hex.clone())
|
||||||
peers.values().any(|p| {
|
.map(|arch| {
|
||||||
p.contact_id < FEDERATION_CONTACT_ID_BASE
|
peers.values().any(|p| {
|
||||||
&& p.reachable
|
p.contact_id < FEDERATION_CONTACT_ID_BASE
|
||||||
&& p.arch_pubkey_hex.as_deref() == Some(arch.as_str())
|
&& p.reachable
|
||||||
|
&& p.arch_pubkey_hex.as_deref() == Some(arch.as_str())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.unwrap_or(false)
|
||||||
.unwrap_or(false)
|
};
|
||||||
};
|
|
||||||
let mesh_only_mode = load_config(&self.data_dir)
|
let mesh_only_mode = load_config(&self.data_dir)
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
|
|||||||
@ -623,12 +623,14 @@ impl ReticulumLink {
|
|||||||
dest_pubkey_prefix: &[u8; 6],
|
dest_pubkey_prefix: &[u8; 6],
|
||||||
payload: &[u8],
|
payload: &[u8],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| {
|
let dest_hash = self
|
||||||
format!(
|
.resolve_dest_hash(dest_pubkey_prefix)
|
||||||
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
.with_context(|| {
|
||||||
hex::encode(dest_pubkey_prefix)
|
format!(
|
||||||
)
|
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
||||||
})?;
|
hex::encode(dest_pubkey_prefix)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
// Typed-envelope payloads (ReadReceipt/Reaction/etc. — anything small
|
// Typed-envelope payloads (ReadReceipt/Reaction/etc. — anything small
|
||||||
// enough for the single-frame path) are raw binary CBOR, not text.
|
// enough for the single-frame path) are raw binary CBOR, not text.
|
||||||
// `from_utf8_lossy` would irreversibly mangle them since `content`
|
// `from_utf8_lossy` would irreversibly mangle them since `content`
|
||||||
@ -663,12 +665,14 @@ impl ReticulumLink {
|
|||||||
caption: Option<&str>,
|
caption: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use base64::{engine::general_purpose::STANDARD as B64, Engine as _};
|
use base64::{engine::general_purpose::STANDARD as B64, Engine as _};
|
||||||
let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| {
|
let dest_hash = self
|
||||||
format!(
|
.resolve_dest_hash(dest_pubkey_prefix)
|
||||||
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
.with_context(|| {
|
||||||
hex::encode(dest_pubkey_prefix)
|
format!(
|
||||||
)
|
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
||||||
})?;
|
hex::encode(dest_pubkey_prefix)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
self.send_rpc(serde_json::json!({
|
self.send_rpc(serde_json::json!({
|
||||||
"cmd": "send",
|
"cmd": "send",
|
||||||
"dest_hash": hex::encode(dest_hash),
|
"dest_hash": hex::encode(dest_hash),
|
||||||
@ -691,12 +695,14 @@ impl ReticulumLink {
|
|||||||
/// `handle_event`, not awaited here.
|
/// `handle_event`, not awaited here.
|
||||||
pub async fn send_resource(&mut self, dest_pubkey_prefix: &[u8; 6], data: &[u8]) -> Result<()> {
|
pub async fn send_resource(&mut self, dest_pubkey_prefix: &[u8; 6], data: &[u8]) -> Result<()> {
|
||||||
use base64::{engine::general_purpose::STANDARD as B64, Engine as _};
|
use base64::{engine::general_purpose::STANDARD as B64, Engine as _};
|
||||||
let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| {
|
let dest_hash = self
|
||||||
format!(
|
.resolve_dest_hash(dest_pubkey_prefix)
|
||||||
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
.with_context(|| {
|
||||||
hex::encode(dest_pubkey_prefix)
|
format!(
|
||||||
)
|
"Unknown Reticulum prefix {} — peer hasn't announced yet",
|
||||||
})?;
|
hex::encode(dest_pubkey_prefix)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
let req_id = self.next_resource_id();
|
let req_id = self.next_resource_id();
|
||||||
self.send_rpc(serde_json::json!({
|
self.send_rpc(serde_json::json!({
|
||||||
"cmd": "send_resource",
|
"cmd": "send_resource",
|
||||||
@ -886,13 +892,15 @@ impl ReticulumLink {
|
|||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(protocol::parse_identity_broadcast);
|
.and_then(protocol::parse_identity_broadcast);
|
||||||
let is_legacy_blob = legacy_identity.is_some();
|
let is_legacy_blob = legacy_identity.is_some();
|
||||||
let identity_blob_text = explicit_blob.or_else(|| {
|
let identity_blob_text =
|
||||||
app_data_text.clone().filter(|_| is_legacy_blob)
|
explicit_blob.or_else(|| app_data_text.clone().filter(|_| is_legacy_blob));
|
||||||
});
|
|
||||||
let parsed_identity = identity_blob_text
|
let parsed_identity = identity_blob_text
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(protocol::parse_identity_broadcast);
|
.and_then(protocol::parse_identity_broadcast);
|
||||||
if let Some(text) = identity_blob_text.as_deref().filter(|_| parsed_identity.is_some()) {
|
if let Some(text) = identity_blob_text
|
||||||
|
.as_deref()
|
||||||
|
.filter(|_| parsed_identity.is_some())
|
||||||
|
{
|
||||||
let mut data = Vec::with_capacity(7 + text.len());
|
let mut data = Vec::with_capacity(7 + text.len());
|
||||||
data.push(0); // channel index — unused by the identity path
|
data.push(0); // channel index — unused by the identity path
|
||||||
data.extend_from_slice(&prefix);
|
data.extend_from_slice(&prefix);
|
||||||
@ -1387,7 +1395,10 @@ mod tests {
|
|||||||
pick_announced_name(None, Some("\u{FFFD}\u{FFFD}Shaza\u{FFFD}".into()), false),
|
pick_announced_name(None, Some("\u{FFFD}\u{FFFD}Shaza\u{FFFD}".into()), false),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
assert_eq!(pick_announced_name(None, Some("has\u{1}ctl".into()), false), None);
|
assert_eq!(
|
||||||
|
pick_announced_name(None, Some("has\u{1}ctl".into()), false),
|
||||||
|
None
|
||||||
|
);
|
||||||
// Nothing at all.
|
// Nothing at all.
|
||||||
assert_eq!(pick_announced_name(None, None, false), None);
|
assert_eq!(pick_announced_name(None, None, false), None);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -381,21 +381,16 @@ pub async fn send_to_peer(
|
|||||||
if let Some(dir) = record_data_dir {
|
if let Some(dir) = record_data_dir {
|
||||||
req = req.record_transport(dir);
|
req = req.record_transport(dir);
|
||||||
}
|
}
|
||||||
let (resp, transport) = req
|
let (resp, transport) = req.send_json(&body).await.map_err(|e| {
|
||||||
.send_json(&body)
|
let msg = e.to_string();
|
||||||
.await
|
if msg.contains("connection refused") || msg.contains("Connection refused") {
|
||||||
.map_err(|e| {
|
anyhow::anyhow!("Peer unreachable. Check Tor (127.0.0.1:9050) and FIPS daemon status.")
|
||||||
let msg = e.to_string();
|
} else if msg.contains("timeout") || msg.contains("timed out") {
|
||||||
if msg.contains("connection refused") || msg.contains("Connection refused") {
|
anyhow::anyhow!("Connection timed out. The peer may be offline.")
|
||||||
anyhow::anyhow!(
|
} else {
|
||||||
"Peer unreachable. Check Tor (127.0.0.1:9050) and FIPS daemon status."
|
anyhow::anyhow!("Failed to send: {}", msg)
|
||||||
)
|
}
|
||||||
} else if msg.contains("timeout") || msg.contains("timed out") {
|
})?;
|
||||||
anyhow::anyhow!("Connection timed out. The peer may be offline.")
|
|
||||||
} else {
|
|
||||||
anyhow::anyhow!("Failed to send: {}", msg)
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !resp.status().is_success() {
|
if !resp.status().is_success() {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user