Files
Qlyra/third_party/kolibri/kolibri-net
sevenhill f74057ce9b
Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s
Rebrand application as Qlyra
2026-08-30 13:16:17 +03:00
..
2026-08-30 13:16:17 +03:00
2026-08-30 13:16:17 +03:00
2026-08-30 13:16:17 +03:00
2026-08-30 13:16:17 +03:00
2026-08-30 13:16:17 +03:00
2026-08-30 13:16:17 +03:00

kolibri-net

Reusable Rust core of the Qlyra messaging protocol — a hand-rolled binary framing over a persistent TLS TCP socket, with MessagePack payloads and LZ4/Zstd compression. Extracted from the Flutter client (lib/core/transport/ + lib/core/protocol/) so the same protocol implementation can be shared across Flutter (via flutter_rust_bridge), Python (via PyO3/maturin), and any other host over a C ABI.

Status

Phase Scope State
1 Protocol core: packet codec, framing, compression, opcodes done
2 Async transport: tokio TCP + TLS (rustls), seq/opcode dispatcher done
3 Session state machine: handshake, ping keepalive, reconnect+backoff done
4 FFI: Python (pyo3/maturin) · Dart (flutter_rust_bridge) planned 🚧
5 Swap Dart transport behind a flag, live-compare, remove planned

Proxy: ClientConfig::proxy takes a ProxyConfig (HTTP CONNECT or SOCKS5, with optional user/pass), applied to the main socket, media uploads, and ws2 calls. Parse one from a url with ProxyConfig::parse("http://user:pass@host:port") (http / socks5 / socks5h).

Not yet ported: VPN-bypass (Android). Production TLS uses the bundled Mozilla root store — swap for rustls-platform-verifier to match Dart's OS trust store.

Wire format (10-byte big-endian header)

[0]      ver       protocol version (u8, = 10)
[1]      cmd       0 request/push · 1 ok · 2 not_found · 3 error
[2..4]   seq       sequence number (u16 BE)
[4..6]   opcode    operation code (u16 BE)
[6..10]  packedLen high byte = compression flag, low 24 bits = payload length
[10..]   payload   MessagePack, LZ4-block / LZ4-frame / Zstd (sniffed by magic)

Payloads under 32 bytes are sent uncompressed. Outgoing compression is LZ4 frame; incoming is sniffed by magic number (Zstd 28 B5 2F FD, LZ4 frame 04 22 4D 18, otherwise LZ4 block).

Design

The core is I/O-free and representation-agnostic: encode/decode work on raw MessagePack bytes so a Dart Map, a Python dict, and a Rust struct all come from the same Packet.payload. PacketReceiver de-frames the raw TLS byte stream into complete packets.

use kolibri_net::{encode, decode, protocol::opcodes};

let wire = encode(opcodes::MSG_SEND, &msgpack_bytes, seq);
let packet = decode(&wire)?;
let value = packet.value()?; // rmpv::Value

Build & test

cargo test        # 14 protocol vectors + 5 transport + 6 session + 1 backoff
cargo clippy --all-targets

The transport feature (async client, on by default) can be disabled to build the pure protocol codec with no tokio/rustls dependency:

cargo build --no-default-features

Transport usage

use kolibri_net::{Client, ClientConfig, protocol::opcodes};

let client = Client::connect(ClientConfig::new("host.example", 443)).await?;
let mut pushes = client.subscribe();               // broadcast of server pushes
let resp = client.request(opcodes::CHATS_LIST, &msgpack_bytes).await?;

Session usage (handshake + keepalive + reconnect)

use kolibri_net::{Session, SessionConfig, ClientConfig, HandshakeConfig, UserAgent};

let config = SessionConfig::new(
    ClientConfig::new("host.example", 443),
    HandshakeConfig { /* device values from the host */ },
);
let session = Session::new(config);
let info = session.connect().await?;               // connect + sessionInit → Online
let resp = session.request(opcodes::AUTH_REQUEST, &msgpack_bytes).await?;

The host (Flutter, Python, …) supplies device values for the handshake; the wire shape and the connect → handshake → ping → reconnect sequence live in Rust.