Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Castr

A cross-platform LAN multicast file transfer tool. A trusted sender broadcasts a file once over IP multicast; any number of receivers on the network pick it up simultaneously, verify it via a signed, chunk-hashed manifest, decrypt it (chunk payloads are encrypted end-to-end with ChaCha20-Poly1305, not just signed — see below), and repair any lost chunks by requesting them from peer receivers rather than re-asking the sender.

Runs on Windows, macOS, and Linux with full IP multicast; iOS and Android join the same swarm as unicast clients over LAN-discovered peers, since neither OS allows apps to reliably join true multicast groups.

See it in action

Castr desktop GUI: a live multicast transfer between two windows, trust prompt and progress in real time

One sender, any number of receivers, one broadcast — a LAN party mod pack push, a sysadmin scripting a fleet config rollout, a test lab loading the same dataset onto every bench machine at once. See all three, with GIFs of the CLI, the colorful TUI dashboard, and the desktop GUI →

Interested in how the performance work was actually done — including the fix we shipped first and had to reverse, and why we read UFTP's source and then declined to copy its congestion control? METHODOLOGY.md covers the approaches and the reasoning; docs/benchmarks/throughput-runs.md keeps every raw measurement behind it.

Status

M0 (scaffolding) through M8 are complete. M5 shipped the showcase docs below; M6 root-caused and fixed a receiver-side throughput bottleneck (wiki/synthesis/m6-throughput-pipelining.md); M7 removed a self-inflicted repair storm that was sending the file roughly twice, cutting wire amplification from 2.39× to 1.13× and eliminating a burst/stall delivery pattern (wiki/synthesis/m7-repair-amplification.md); M8 raised the default chunk size to the 256 KB that Castr.Core and the wire protocol had specified all along. Throughput work is not finished — per-datagram syscall cost currently caps transfers near ~37 MB/s, and raising the datagram budget is the tracked next step. Formal release automation (tag-triggered releases, checksums/signatures) also remains open. Both are in wiki/synthesis/roadmap.md, and every measurement behind these claims is in docs/benchmarks/throughput-runs.md. Chunk payloads are ChaCha20-Poly1305-encrypted end-to-end and travel over MTU-safe wire packets (chunks split/reassembled below the crypto layer) — see wiki/synthesis/m1.5-encryption-summary.md and wiki/synthesis/m3-test-ci-hardening-summary.md. castr send/castr receive/castr trust, a live Spectre.Console dashboard (--tui), and an Avalonia desktop GUI are all working — see wiki/synthesis/m2-ui-summary.md. Mobile (iOS/Android) joins as a unicast swarm client over LAN-discovered peers (native NsdManager/NWBrowser discovery, TCP pull, the same signed-manifest/Merkle/AEAD verification the desktop multicast tier uses) — Castr.Gui.Android produces a real debug-signed sideloadable APK; Castr.Gui.iOS builds and links its native discovery bindings against real Xcode, though the full app-level Simulator link is currently blocked by an upstream libsodium packaging gap — see wiki/synthesis/m4-mobile-summary.md. CI runs a real 3-OS build+test matrix, a Docker-gated multi-container E2E fan-out job with real induced packet loss, and dedicated Android/iOS mobile-build workflows on real SDK/Xcode-provisioned runners — see wiki/synthesis/m3-test-ci-hardening-summary.md and wiki/synthesis/m4-mobile-summary.md. See wiki/synthesis/roadmap.md for milestone status and wiki/ generally for the accumulated design decisions (ADRs, spike results). The full architecture — wire protocol, repair algorithm, security model, and milestone plan — lives in the project plan; a synthesis of it is ingested into wiki/ as the project's first source so it survives session restarts.

Repo layout

  • src/Castr.Core — protocol state machines, chunker, Merkle/manifest, trust store, transport abstractions (no UI, no platform-specific code)
  • src/Castr.Core.Discovery — peer discovery abstraction + platform mDNS impls (used by the mobile unicast tier)
  • src/Castr.Cli — command-line entrypoint (System.CommandLine): send, receive, trust list|add|block|remove
  • src/Castr.Tui — colorful live transfer dashboard (Spectre.Console), consumed by Castr.Cli --tui
  • src/Castr.Gui, src/Castr.Gui.Desktop — Avalonia GUI: shared views/viewmodels and the Windows/macOS/Linux desktop head
  • src/Castr.Gui.Android, src/Castr.Gui.iOS — Avalonia mobile GUI heads (unicast swarm client), built on top of Castr.Core.Discovery + the TCP swarm-pull tier in Castr.Core; each opt-in-multitargeted so a default dotnet build/CI matrix never requires mobile workloads
  • tests/ — unit, loopback-multicast integration, CLI, TUI, GUI, and discovery test projects, one per corresponding src/ project's concerns, plus Castr.Core.E2ETests: a Testcontainers-driven multi-container fan-out suite (real Docker bridge multicast + kernel-level tc netem loss), opt-in via CASTR_E2E=1 and gated on Docker being reachable
  • wiki/, raw/ — the project's persistent knowledge base (llm-wiki), the durable memory across sessions
  • graphify-out/ — generated codebase knowledge graph (query this instead of re-reading the whole tree when resuming work)

Building

dotnet build
dotnet test

Requires the .NET 10 SDK (LTS, pinned via global.json).

Every push to main also builds self-contained, per-platform zips of castr (CLI) and the desktop GUI for win-x64, win-arm64, osx-x64, osx-arm64, and linux-x64, uploaded as downloadable artifacts on that CI run's Actions page (see the package job in .github/workflows/ci.yml). These are unsigned CI convenience builds, not versioned/checksummed releases — that's tracked for M5.

License

Apache-2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages