Skip to content

Commit 8c5a667

Browse files
committed
address most of wills review feedback, fix serialization and stringly error handling in DiagTask::start
1 parent 067e3d9 commit 8c5a667

5 files changed

Lines changed: 47 additions & 59 deletions

File tree

daemon/src/diag.rs

Lines changed: 31 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const DISK_CHECK_BYTES_INTERVAL: usize = 256 * 1024;
4040
pub enum DiagDeviceCtrlMessage {
4141
StopRecording,
4242
StartRecording {
43-
response_tx: Option<oneshot::Sender<Result<(), String>>>,
43+
response_tx: Option<oneshot::Sender<Result<(), RecordingStoreError>>>,
4444
},
4545
DeleteEntry {
4646
name: String,
@@ -129,7 +129,7 @@ impl DiagTask {
129129
}
130130

131131
/// Start recording, returning an error if disk space is too low.
132-
async fn start(&mut self, qmdl_store: &mut RecordingStore) -> Result<(), String> {
132+
async fn start(&mut self, qmdl_store: &mut RecordingStore) -> Result<(), RecordingStoreError> {
133133
self.max_type_seen = EventType::Informational;
134134
self.bytes_since_space_check = 0;
135135
self.low_space_warned = false;
@@ -140,66 +140,54 @@ impl DiagTask {
140140
self.min_space_to_continue_mb,
141141
) {
142142
DiskSpaceCheck::Critical(mb) | DiskSpaceCheck::Warning(mb) => {
143-
let msg = format!(
144-
"Insufficient disk space: {}MB available, {}MB required",
145-
mb, self.min_space_to_start_mb
146-
);
147-
error!("{msg}");
148-
return Err(msg);
143+
return Err(RecordingStoreError::InsufficientDiskSpace(
144+
mb,
145+
self.min_space_to_start_mb,
146+
));
149147
}
150148
DiskSpaceCheck::Ok(mb) => {
151149
info!("Starting recording with {}MB disk space available", mb);
152150
}
153151
DiskSpaceCheck::Failed => {}
154152
}
155153

156-
let (qmdl_file, analysis_file) = match qmdl_store.new_entry(self.gps_mode).await {
157-
Ok(files) => files,
158-
Err(e) => {
159-
let msg = format!("failed creating QMDL file entry: {e}");
160-
error!("{msg}");
161-
return Err(msg);
162-
}
163-
};
154+
let (qmdl_file, analysis_file) = qmdl_store.new_entry(self.gps_mode).await?;
155+
164156
// For fixed-mode sessions, write the configured coordinates to the sidecar
165157
// immediately so the per-session GPS is stored durably and isn't affected
166158
// by future config changes or GPS API calls.
167159
if self.gps_mode == GpsMode::Fixed
168160
&& let Some((lat, lon)) = self.gps_fixed_coords
169161
&& let Some((entry_idx, _)) = qmdl_store.get_current_entry()
170162
{
171-
match qmdl_store.open_entry_gps_for_append(entry_idx).await {
172-
Ok(Some(mut gps_file)) => {
173-
let record = GpsRecord {
174-
unix_ts: 0,
175-
lat,
176-
lon,
177-
};
178-
if let Ok(json) = serde_json::to_string(&record) {
179-
let _ = gps_file.write_all(format!("{json}\n").as_bytes()).await;
180-
}
181-
}
182-
Ok(None) => {
183-
error!("GPS sidecar directory not found, cannot write fixed-mode coordinates")
184-
}
185-
Err(e) => error!("failed to open GPS sidecar for fixed-mode entry: {e}"),
186-
}
163+
let mut gps_file = qmdl_store
164+
.open_entry_gps_for_append(entry_idx)
165+
.await?
166+
.ok_or(RecordingStoreError::GpsSidecarNotFound)?;
167+
168+
let record = GpsRecord {
169+
unix_ts: chrono::Utc::now().timestamp(),
170+
lat,
171+
lon,
172+
};
173+
let json = serde_json::to_string(&record)?;
174+
gps_file
175+
.write_all(format!("{json}\n").as_bytes())
176+
.await
177+
.map_err(RecordingStoreError::WriteFileError)?;
187178
}
179+
188180
self.stop_current_recording().await;
189181
let qmdl_writer = QmdlWriter::new(qmdl_file);
190-
let analysis_writer = match AnalysisWriter::new(analysis_file, &self.analyzer_config).await
191-
{
192-
Ok(writer) => Box::new(writer),
193-
Err(e) => {
194-
let msg = format!("failed to create analysis writer: {e}");
195-
error!("{msg}");
196-
return Err(msg);
197-
}
198-
};
182+
let analysis_writer = AnalysisWriter::new(analysis_file, &self.analyzer_config)
183+
.await
184+
.map_err(RecordingStoreError::WriteFileError)?;
185+
199186
self.state = DiagState::Recording {
200187
qmdl_writer,
201-
analysis_writer,
188+
analysis_writer: Box::new(analysis_writer),
202189
};
190+
203191
if let Err(e) = self
204192
.ui_update_sender
205193
.send(display::DisplayState::Recording)
@@ -530,7 +518,7 @@ pub async fn start_recording(
530518

531519
match response_rx.await {
532520
Ok(Ok(())) => Ok((StatusCode::ACCEPTED, "ok".to_string())),
533-
Ok(Err(reason)) => Err((StatusCode::INSUFFICIENT_STORAGE, reason)),
521+
Ok(Err(reason)) => Err((StatusCode::INSUFFICIENT_STORAGE, reason.to_string())),
534522
Err(e) => Err((
535523
StatusCode::INTERNAL_SERVER_ERROR,
536524
format!("failed to receive start recording response: {e}"),

daemon/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,14 +306,12 @@ async fn run_with_config(
306306
config.webdav.clone().into(),
307307
);
308308
}
309-
// For fixed configuration, we use timestamp 0 to not break other
310-
// the GET request for GPS but user won't see the 0 in PCAPs
311309
let initial_gps = if config.gps_mode == GpsMode::Fixed {
312310
match (config.gps_fixed_latitude, config.gps_fixed_longitude) {
313311
(Some(lat), Some(lon)) => Some(gps::GpsData {
314312
latitude: lat,
315313
longitude: lon,
316-
timestamp: 0,
314+
timestamp: chrono::Utc::now().timestamp(),
317315
}),
318316
_ => {
319317
warn!(

daemon/src/qmdl_store.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub enum RecordingStoreError {
2323
CreateFileError(tokio::io::Error),
2424
#[error("Couldn't read file: {0}")]
2525
ReadFileError(tokio::io::Error),
26+
#[error("Couldn't write file: {0}")]
27+
WriteFileError(tokio::io::Error),
2628
#[error("Couldn't delete file: {0}")]
2729
DeleteFileError(tokio::io::Error),
2830
#[error("Couldn't open directory at path: {0}")]
@@ -33,6 +35,12 @@ pub enum RecordingStoreError {
3335
WriteManifestError(tokio::io::Error),
3436
#[error("Couldn't parse QMDL store manifest file: {0}")]
3537
ParseManifestError(toml::de::Error),
38+
#[error("Insufficient disk space: {0}MB available, {1}MB required")]
39+
InsufficientDiskSpace(u64, u64),
40+
#[error("GPS sidecar directory not found")]
41+
GpsSidecarNotFound,
42+
#[error("Serialization error: {0}")]
43+
SerializationError(#[from] serde_json::Error),
3644
}
3745

3846
pub struct RecordingStore {

daemon/src/webdav.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ pub fn run_webdav_upload_worker(
245245
#[cfg(test)]
246246
mod tests {
247247
use super::*;
248+
use crate::config::GpsMode;
248249
use axum::{
249250
Router,
250251
body::Bytes,

lib/src/pcap.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use pcap_file_tokio::pcapng::blocks::enhanced_packet::{EnhancedPacketBlock, Enha
1010
use pcap_file_tokio::pcapng::blocks::interface_description::InterfaceDescriptionBlock;
1111
use pcap_file_tokio::pcapng::blocks::section_header::{SectionHeaderBlock, SectionHeaderOption};
1212
use pcap_file_tokio::{Endianness, PcapError};
13+
use serde::Serialize;
1314
use std::borrow::Cow;
1415
use thiserror::Error;
1516
use tokio::io::AsyncWrite;
@@ -26,11 +27,13 @@ pub enum GsmtapPcapError {
2627
Deku(#[from] DekuError),
2728
}
2829

30+
#[derive(Serialize)]
2931
pub struct GpsPoint {
32+
pub unix_ts: i64,
33+
#[serde(rename = "lat")]
3034
pub latitude: f64,
35+
#[serde(rename = "lon")]
3136
pub longitude: f64,
32-
/// Unix timestamp of the GPS fix. 0 means fixed/synthetic (no real GPS time).
33-
pub unix_ts: i64,
3437
}
3538

3639
pub struct GsmtapPcapWriter<T>
@@ -148,17 +151,7 @@ where
148151

149152
let mut options = vec![];
150153
if let Some(p) = gps {
151-
let comment = if p.unix_ts == 0 {
152-
format!(
153-
r#"{{"latitude":{:.7},"longitude":{:.7}}}"#,
154-
p.latitude, p.longitude
155-
)
156-
} else {
157-
format!(
158-
r#"{{"latitude":{:.7},"longitude":{:.7},"timestamp":{}}}"#,
159-
p.latitude, p.longitude, p.unix_ts
160-
)
161-
};
154+
let comment = serde_json::to_string(p).expect("GpsPoint serialization cannot fail");
162155
options.push(EnhancedPacketOption::Comment(Cow::Owned(comment)));
163156
}
164157
let packet = EnhancedPacketBlock {

0 commit comments

Comments
 (0)