itk-protocol
Wire protocol definitions with serialization, validation, and integrity checking. Every IPC message uses a 20-byte binary header followed by a bitcode-serialized payload.
Header Format
Constants
pub const MAGIC: [u8; 4] = *b"ITKP";
pub const VERSION: u32 = 2; // bumped for bitcode migration
pub const HEADER_SIZE: usize = 20;
pub const MAX_PAYLOAD_SIZE: usize = 1_048_576; // 1 MB
pub const MAX_STRING_LENGTH: usize = 256;
pub const MAX_DATA_LENGTH: usize = 65_536; // 64 KB
MessageType Enum
| Range | Variants | Purpose |
|---|---|---|
| 0-1 | Ping, Pong | Health check / latency |
| 10-12 | ScreenRect, WindowState, OverlayUpdate | Window geometry |
| 20-23 | StateSnapshot, StateEvent, StateQuery, StateResponse | Game state exchange |
| 30-32 | SyncState, ClockPing, ClockPong | Clock and playback sync |
| 40-46 | VideoLoad through VideoError | Video control and state |
| 255 | Error | Error response |
Validation
All payload structs implement the Validate trait. Validation rules:
- Float fields reject
NaNandInfinity - String fields capped at 256 bytes
- Data fields capped at 64 KB
- DPI scale must be in range 0.1–10.0
- Playback rate must be positive
Encode / Decode
// Encode a message
let bytes = itk_protocol::encode(MessageType::Ping, &())?;
// Decode with validation
let (msg_type, payload): (MessageType, ScreenRect) =
itk_protocol::decode_validated(&bytes)?;
// Decode header only (for routing)
let header = itk_protocol::decode_header(&bytes)?;
Error Types
pub enum ProtocolError {
InvalidMagic,
UnsupportedVersion,
PayloadTooLarge,
CrcMismatch,
UnknownMessageType,
Serialization(String),
IncompleteHeader,
IncompletePayload,
ValidationFailed(String),
}
itk-shmem
Cross-platform shared memory with seqlock synchronization for lock-free single-writer, multi-reader frame transport.
SeqlockHeader
#[repr(C)] // 64 bytes, cache-line aligned
pub struct SeqlockHeader {
pub seq: AtomicU32, // odd = writing, even = consistent
pub read_idx: AtomicU32, // current read buffer (0-2)
pub pts_ms: AtomicU64, // presentation timestamp
pub frame_width: AtomicU32,
pub frame_height: AtomicU32,
pub is_playing: AtomicU32,
pub content_id_hash: AtomicU64,
pub duration_ms: AtomicU64,
pub writer_count: AtomicU32, // multi-writer detection
_padding: [u8; 8],
}
FrameBuffer API
Triple-buffered RGBA frame transport. Layout: [Header: 64B][Buf0: W*H*4][Buf1: W*H*4][Buf2: W*H*4]
// Writer (daemon)
let fb = FrameBuffer::create("nms_video", 1280, 720)?;
fb.write_frame(&rgba_data, pts_ms, content_hash)?;
// Reader (injector or overlay)
let fb = FrameBuffer::open("nms_video", 1280, 720)?;
let mut buf = vec![0u8; 1280 * 720 * 4];
let (pts, changed) = fb.read_frame(last_pts, &mut buf)?;
SharedMemory API
// Create (owner)
let shmem = SharedMemory::create("itk_frames", size)?;
// Open (reader)
let shmem = SharedMemory::open("itk_frames", size)?;
// Raw access (unsafe)
unsafe { shmem.write(offset, &data)?; }
unsafe { shmem.read(offset, &mut buf)?; }
Seqlock Algorithm
Writer operations use Acquire/Release memory ordering. ARM-compatible with explicit fence(Acquire) on the reader side. The begin_write() method checks writer_count to detect multiple-writer violations at runtime.
Read Strategies
| Method | Behavior | Use Case |
|---|---|---|
try_read() | Returns Option<SeqlockState> | Non-blocking poll |
read_blocking() | Spins until consistent read | Guaranteed latest state |
read_with_timeout(n) | Retries up to N times | Bounded wait |
Size Reference
| Resolution | Total Size |
|---|---|
| 720p (1280×720) | 64 + 11,059,200 bytes (~11 MB) |
| 1080p (1920×1080) | 64 + 24,883,200 bytes (~24 MB) |
| 4K (3840×2160) | 64 + 99,532,800 bytes (~95 MB) |
Maximum dimension: 8192×8192. Checked arithmetic prevents integer overflow in size calculations.
itk-ipc
Cross-platform IPC via trait abstractions. Named pipes on Windows, Unix domain sockets on Linux.
IpcChannel Trait
pub trait IpcChannel: Send + Sync {
fn send(&self, data: &[u8]) -> Result<()>;
fn recv(&self) -> Result<Vec<u8>>; // blocking
fn try_recv(&self) -> Result<Option<Vec<u8>>>; // non-blocking
fn is_connected(&self) -> bool;
fn close(&self);
}
IpcServer Trait
pub trait IpcServer: Send + Sync {
type Channel: IpcChannel;
fn accept(&self) -> Result<Self::Channel>; // blocking
fn close(&self);
}
Factory Functions
// Connect as client
let channel = itk_ipc::connect("video_control")?;
// Listen as server
let server = itk_ipc::listen("video_control")?;
let client = server.accept()?;
// Channel naming
itk_ipc::make_channel_name("video_control")
// Windows: "\\.\pipe\itk_video_control"
// Linux: "/tmp/itk_video_control.sock"
Message Helpers
// Read a length-prefixed message
let data = itk_ipc::read_message(&mut reader)?;
// Write a length-prefixed message
itk_ipc::write_message(&mut writer, &data)?;
Platform Implementations
| Platform | Client | Server |
|---|---|---|
| Windows | NamedPipeClient | NamedPipeServer |
| Unix | UnixSocketClient | UnixSocketServer |
itk-sync
Clock synchronization and playback drift correction for multiplayer video sync.
Sync Model
Position is calculated from a reference point rather than absolute timestamps:
current_pos = position_at_ref + (now - ref_wallclock) * playback_rate
ClockSync
NTP-lite algorithm that processes ping/pong exchanges to estimate clock offset between peers.
let mut clock = ClockSync::new();
// After receiving a pong:
clock.process_pong(send_time_ms, remote_time_ms, recv_time_ms);
// Convert timestamps between clocks:
let remote_ts = clock.local_to_remote(local_ms)?;
let local_ts = clock.remote_to_local(remote_ms)?;
Uses the median of the best-half (lowest RTT) of up to 10 samples for robustness against network jitter.
PlaybackSync
pub struct PlaybackSync {
pub content_id: String,
pub position_at_ref_ms: u64,
pub ref_wallclock_ms: u64,
pub is_playing: bool,
pub playback_rate: f64, // 0.95-1.05 for drift correction
}
let sync = PlaybackSync::new("video_123");
let pos = sync.current_position_ms(); // computed from ref point
sync.set_playing(true); // captures position first
sync.seek(30_000); // seek to 30s
DriftCorrector
Combines a target PlaybackSync with a ClockSync to smoothly correct playback drift across peers.
| Drift Range | Correction Rate | Action |
|---|---|---|
| 0 – 150 ms | 1.0x | No correction (within tolerance) |
| 151 – 500 ms | 0.98x / 1.02x | Gentle speed adjustment |
| 501 – 1500 ms | 0.95x / 1.05x | Moderate speed adjustment |
| > 1500 ms | 0.0x (pause) | Recommend hard seek |
let mut corrector = DriftCorrector::new(target_sync, clock_sync);
// Get corrected playback rate
let rate = corrector.calculate_rate(current_position_ms);
// Check if hard seek is needed
if let Some(target) = corrector.should_seek(current_position_ms) {
player.seek(target);
}
// Get current drift
let drift = corrector.current_drift_ms(current_position_ms);
itk-video
Video decoding pipeline powered by ffmpeg-next with hardware acceleration and shared memory frame output.
Pipeline
StreamSource (file/URL)
→ VideoDecoder (ffmpeg-next)
→ FrameScaler (to 1280×720 RGBA)
→ FrameWriter (to shared memory)
Constants
pub const DEFAULT_WIDTH: u32 = 1280;
pub const DEFAULT_HEIGHT: u32 = 720;
pub const BYTES_PER_PIXEL: usize = 4; // RGBA
pub const fn frame_size(width: u32, height: u32) -> usize {
width as usize * height as usize * BYTES_PER_PIXEL
}
StreamSource
Supports local files and network URLs. YouTube support is gated behind the youtube feature flag and requires yt-dlp to be installed.
Hardware Acceleration
The decoder tries D3D11VA hardware acceleration first, with automatic fallback to software decoding. The hwaccel module handles device negotiation and format conversion.
Modules
| Module | Purpose |
|---|---|
decoder | VideoDecoder wrapping ffmpeg-next |
scaler | FrameScaler for pixel format/resolution conversion |
frame_writer | FrameWriter to shared memory via itk-shmem |
hwaccel | Hardware acceleration negotiation |
stream | StreamSource URL/file resolution |
youtube | yt-dlp integration (feature-gated) |
itk-net
P2P networking for multiplayer session management and playback synchronization via laminar.
Architecture
Session
+-- Discovery (UDP broadcast on port 7332)
+-- PeerManager (laminar connections on port 7331)
+-- SyncManager (ClockSync + PlaybackSync per peer)
Constants
pub const DEFAULT_PORT: u16 = 7331;
pub const DISCOVERY_PORT: u16 = 7332;
pub const SYNC_INTERVAL_MS: u64 = 500;
pub const CLOCK_PING_INTERVAL_MS: u64 = 2000;
Sync Flow
- Leader broadcasts
SyncStateevery 500ms (unreliable delivery) - Followers use
DriftCorrectorfor smooth catch-up ClockPing/ClockPongexchanges estimate clock offset every 2s- Commands (play, pause, seek) sent via reliable delivery
Session Roles
One peer is elected leader (the host). The leader is the authoritative source for playback state. Discovery uses UDP broadcast to find peers on the local network.
Public API
pub use session::{Session, SessionConfig, SessionEvent, SessionRole};
pub use discovery::Discovery;
pub use peer::{Peer, PeerEvent, PeerManager};
pub use sync_manager::SyncManager;
Templates
Starter templates for building new game mod projects on the ITK framework.
itk-daemon
Central coordinator daemon template. Handles IPC server setup, shared memory creation, and event loop scaffolding.
daemon/
itk-overlay
wgpu-based transparent overlay window template. Includes egui integration, click-through setup, and shared memory reading.
overlay/
itk-native-dll
Windows DLL injection template using retour for function hooking. Includes DllMain entry point and hook setup scaffolding.
injectors/windows/native-dll/
itk-ld-preload
Linux LD_PRELOAD injection template. Intercepts library calls at the dynamic linker level for non-invasive hooking.
injectors/linux/ld-preload/
CI/CD Pipeline
All CI runs inside Docker containers via docker compose --profile ci on a self-hosted runner.
Pipeline Stages
| Stage | Command | Purpose |
|---|---|---|
| 1. Format | cargo fmt --all -- --check | Consistent code style |
| 2. Lint | cargo clippy --all-targets -- -D warnings | Static analysis (warnings = errors) |
| 3. Test | cargo test -- --test-threads=4 | Unit and integration tests |
| 4. Build | cargo build --release | Release binary compilation |
| 5. Audit | cargo deny check | License and advisory checking |
Workflows
- main-ci.yml — Runs on push to main and version tags. Includes binary building and GitHub Release creation with auto-generated changelog.
- pr-validation.yml — Runs on pull requests. Adds AI code review (Gemini primary) with automated fix iterations (up to 5 rounds). (Codex review has been disabled — OpenAI is phased out due to mass surveillance and autonomous weapons concerns. See README for details.)
Release Artifacts
On tagged releases, the pipeline builds Linux x64 binaries:
nms-video-daemon-linux-x64nms-video-overlay-linux-x64mem-scanner-linux-x64
Advisory Exemptions
Two advisories are currently exempted in deny.toml:
RUSTSEC-2025-0141— bincode unmaintained (migration to bitcode in progress)RUSTSEC-2026-0007— bytes integer overflow (update pending)