feat(music): W22 shared listening + release 0.6.0
Personal playlist on a dedicated music player (browse/play/prev/next/ seek/volume/reorder/remove, .pls/.m3u import), plus per-person shared listening: broadcast your track over presence, peers tune in and stream it point-to-point over the files plane. Playback is timeline-synced (play/pause/skip/seek mirror with no drift) with gapless prefetch of the next track and independent per-source volume per listener. In the 3-column layout the playlist gets its own card stacked under the chat, with a resizable divider and its own scrollbar; other layouts keep it in the Controls panel. Breaking wire change: gossip protocol v5 (presence gains music fields), so 0.6.0 peers cannot share a swarm with 0.5.x. Version bumped 0.5.1 -> 0.6.0; CHANGELOG updated. Untrusted-input handling: broadcast track name sanitized and size cap-checked at gossip ingest, fetched bytes confirmed audio before decode, only the descriptor rides gossip (bytes go point-to-point, one fetch in flight). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -645,6 +645,29 @@ impl RoomState for IrohGossipState {
|
||||
let cleaned = crate::sanitize::sanitize_game_label(&g);
|
||||
(!cleaned.is_empty()).then_some(cleaned)
|
||||
});
|
||||
// Music presence is untrusted peer data:
|
||||
// the track name is display text (sanitize
|
||||
// + cap like the game label) and the size
|
||||
// bounds a future fetch (reject anything
|
||||
// outside the attachment cap).
|
||||
state.music = state.music.and_then(|mut m| {
|
||||
let name = crate::sanitize::sanitize_game_label(&m.name);
|
||||
if name.is_empty() || !crate::files::size_within_cap(m.size) {
|
||||
return None;
|
||||
}
|
||||
m.name = name;
|
||||
if m.next_id.is_some() {
|
||||
let ok = m
|
||||
.next_size
|
||||
.map(crate::files::size_within_cap)
|
||||
.unwrap_or(false);
|
||||
if !ok {
|
||||
m.next_id = None;
|
||||
m.next_size = None;
|
||||
}
|
||||
}
|
||||
Some(m)
|
||||
});
|
||||
// Bound an insider's advertised address set
|
||||
// before we retain it / hand it to the dialer
|
||||
// (Tier C F-01).
|
||||
@@ -959,6 +982,7 @@ mod tests {
|
||||
sharing: None,
|
||||
avatar: crate::avatar::Avatar::default(),
|
||||
game: None,
|
||||
music: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user