chore: consolidate parallel-session WIP (HOLD — do not push)
Local snapshot of intermingled in-flight work, committed to unblock the encode
refactor (a clean ffmpeg_win.rs for the vbv-dedup follow-on). These hunks span
the same files and can't be cleanly split here; the commit bundles three
distinct workstreams that each belong in their own PR:
- logging rework (~43 files: level re-tiering, structured fields, `?e`,
hot-path flood latches)
- conflicting-host detection (detect.rs + detect/{linux,windows}.rs + wiring
in main.rs/mgmt.rs/Cargo.toml/docs/packaging)
- standby-sink DWM-stall attribution (windows/display_events.rs + capture/
vdisplay wiring)
NOT verified as a combination. NOT to be pushed until the refactor is done and
these are re-verified and reorganized into their proper per-workstream PRs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -262,7 +262,7 @@ fn run(
|
||||
punktfunk_core::transport::grow_socket_buffers(&sock);
|
||||
// The client pings the audio port (~every 500ms) so we learn where to send.
|
||||
sock.set_read_timeout(Some(Duration::from_secs(10)))?;
|
||||
tracing::info!(port = AUDIO_PORT, "audio: awaiting client ping");
|
||||
tracing::debug!(port = AUDIO_PORT, "audio: awaiting client ping");
|
||||
let mut probe = [0u8; 256];
|
||||
let (_, client) = sock
|
||||
.recv_from(&mut probe)
|
||||
@@ -275,7 +275,7 @@ fn run(
|
||||
&sock,
|
||||
punktfunk_core::transport::MediaClass::Audio,
|
||||
);
|
||||
tracing::info!(%client, "audio: client endpoint learned");
|
||||
tracing::debug!(%client, "audio: client endpoint learned");
|
||||
|
||||
// Reuse the persistent capturer when its channel count still matches (drain stale
|
||||
// buffered audio); otherwise drop it (clean PipeWire teardown) and open at the new count.
|
||||
@@ -468,7 +468,7 @@ fn audio_body(
|
||||
timestamp = timestamp.wrapping_add(frame_ms as u32);
|
||||
sent += 1;
|
||||
if sent % 400 == 0 {
|
||||
tracing::info!(sent, "audio: streaming");
|
||||
tracing::debug!(sent, "audio: streaming");
|
||||
}
|
||||
|
||||
// Hold each frame to its packet-duration slot (skip if we've fallen behind a burst).
|
||||
|
||||
@@ -101,7 +101,7 @@ pub fn spawn(state: Arc<AppState>) -> Result<()> {
|
||||
},
|
||||
Ok(None) => break,
|
||||
Err(e) => {
|
||||
tracing::warn!(error = %format!("{e:?}"), "control: service error");
|
||||
tracing::warn!(error = ?e, "control: service error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ pub fn spawn(state: Arc<AppState>) -> Result<()> {
|
||||
for wire in out {
|
||||
if let Err(e) = host.peer_mut(pid).send(0, &Packet::reliable(&wire[..]))
|
||||
{
|
||||
tracing::warn!(error = %format!("{e:?}"), "rumble send failed");
|
||||
tracing::warn!(error = ?e, "rumble send failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,12 +214,12 @@ fn on_receive(
|
||||
if inner == 0x0301 {
|
||||
if let Some((first, last)) = decode_rfi_range(&pt) {
|
||||
*state.rfi_range.lock().unwrap() = Some((first, last));
|
||||
tracing::info!(first, last, "control: RFI request → invalidate ref frames");
|
||||
tracing::debug!(first, last, "control: RFI request → invalidate ref frames");
|
||||
} else {
|
||||
state
|
||||
.force_idr
|
||||
.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
tracing::info!("control: RFI request (no range) → keyframe");
|
||||
tracing::debug!("control: RFI request (no range) → keyframe");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -227,8 +227,8 @@ fn on_receive(
|
||||
state
|
||||
.force_idr
|
||||
.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
tracing::info!(
|
||||
ty = format!("{inner:#06x}"),
|
||||
tracing::debug!(
|
||||
ty = %format_args!("{inner:#06x}"),
|
||||
"control: IDR request → keyframe"
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -218,6 +218,17 @@ pub fn serve(
|
||||
gamestream,
|
||||
"punktfunk host"
|
||||
);
|
||||
// Surface a conflicting Moonlight-compatible host (Sunshine/Apollo/…) as early as possible:
|
||||
// scan once (cached for `/local/summary` → tray + web console) and warn loudly if found.
|
||||
let conflicts = crate::detect::init();
|
||||
if !conflicts.is_empty() {
|
||||
tracing::warn!(
|
||||
target: "punktfunk::detect",
|
||||
count = conflicts.len(),
|
||||
"{}",
|
||||
crate::detect::render_report(conflicts)
|
||||
);
|
||||
}
|
||||
if gamestream {
|
||||
tracing::warn!(
|
||||
"GameStream/Moonlight compat ENABLED (--gamestream): its pairing runs over plain HTTP and \
|
||||
|
||||
@@ -265,14 +265,14 @@ impl Pairing {
|
||||
store.push(s.client_cert_der.clone());
|
||||
super::save_paired(&store);
|
||||
}
|
||||
tracing::info!(uniqueid, "pairing phase 4 — SUCCESS, client cert pinned");
|
||||
tracing::info!(uniqueid, "pairing phase 4 complete — client cert pinned");
|
||||
Ok(paired_xml("", true))
|
||||
} else {
|
||||
tracing::warn!(
|
||||
uniqueid,
|
||||
hash_ok,
|
||||
sig_ok,
|
||||
"pairing phase 4 — FAILED (PIN/cert)"
|
||||
"pairing phase 4 rejected — PIN or cert mismatch"
|
||||
);
|
||||
map.remove(uniqueid);
|
||||
Ok(paired_xml("", false))
|
||||
|
||||
@@ -97,10 +97,12 @@ fn handle_conn(mut stream: TcpStream, state: Arc<AppState>) -> Result<()> {
|
||||
// response until EOF, so we answer one message and close the connection (which signals
|
||||
// the end of the response). Session state lives in `AppState`, not the connection.
|
||||
if let Some(req) = read_message(&mut stream, &mut buf)? {
|
||||
tracing::info!(
|
||||
method = %req.method, cseq = %req.cseq,
|
||||
"RTSP {} | {}", req.head.replace("\r\n", " | "),
|
||||
if req.body.is_empty() { String::new() } else { format!("body: {}", req.body.replace("\r\n", " | ")) }
|
||||
tracing::debug!(
|
||||
method = %req.method,
|
||||
cseq = %req.cseq,
|
||||
headers = %req.head.replace("\r\n", " | "),
|
||||
body = %req.body.replace("\r\n", " | "),
|
||||
"RTSP request"
|
||||
);
|
||||
let resp = handle_request(&req, &state, peer);
|
||||
stream.write_all(resp.as_bytes()).context("RTSP write")?;
|
||||
@@ -404,7 +406,7 @@ fn stream_config(map: &HashMap<String, String>) -> Option<StreamConfig> {
|
||||
};
|
||||
let matches_ours = (hdr && csc >> 1 == 2 || !hdr && csc >> 1 == 1) && csc & 1 == 0;
|
||||
if matches_ours {
|
||||
tracing::info!(
|
||||
tracing::debug!(
|
||||
csc,
|
||||
space,
|
||||
range,
|
||||
|
||||
@@ -879,7 +879,7 @@ fn stream_body(
|
||||
"video: streaming (perf)"
|
||||
);
|
||||
} else {
|
||||
tracing::info!(
|
||||
tracing::debug!(
|
||||
fps = fps_count,
|
||||
sent_batches,
|
||||
dropped_batches,
|
||||
|
||||
@@ -49,7 +49,10 @@ pub(crate) async fn serve_https(
|
||||
let (tcp, peer) = match listener.accept().await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
tracing::warn!(error = %e, "HTTPS accept failed");
|
||||
// A persistent accept() error (fd exhaustion / EMFILE) would otherwise hot-spin
|
||||
// this loop and storm the log; back off so a stuck accept can't burn a core.
|
||||
tracing::warn!(error = %e, "HTTPS accept failed — backing off 100ms");
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user