[TSM.ID].[11031972] PXE : Platform X Ecosystem I [118 Module -LIVE-]
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
/* eslint-disable */
|
||||
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
|
||||
import CryptoJS from 'crypto-js';
|
||||
|
||||
export interface EncryptedMessage {
|
||||
id: string;
|
||||
sender: string;
|
||||
ciphertext: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface DecryptedMessage {
|
||||
id: string;
|
||||
sender: string;
|
||||
content: string;
|
||||
timestamp: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* XCUTelepathyMatrix FASE 2:
|
||||
* Telah berevolusi meninggalkan NodeJS, Yjs, dan WebSockets usang.
|
||||
* Menggunakan arsitektur WebTransport Datagrams yang menembak langsung ke Rust Engine (Port 8443).
|
||||
*/
|
||||
export class XCUTelepathyMatrix {
|
||||
private roomName: string;
|
||||
private secretKey: string;
|
||||
private transport: any = null; // WebTransport instance
|
||||
private isActive: boolean = false;
|
||||
private participantId: number;
|
||||
private username: string = "";
|
||||
|
||||
public onMessagesUpdate: ((messages: DecryptedMessage[]) => void) | null = null;
|
||||
public onTypingUpdate: ((typingUsers: Record<string, number>) => void) | null = null;
|
||||
public onQuantumResonance: ((senderId: number, type: string) => void) | null = null;
|
||||
public onSovereignSignal: ((command: string, targetId?: number) => void) | null = null;
|
||||
|
||||
// Local state untuk dirender
|
||||
private messages: DecryptedMessage[] = [];
|
||||
private typingState: Record<string, number> = {};
|
||||
|
||||
constructor(roomName: string, secretKey: string = 'QUANTUM-X-SECRET-256') {
|
||||
this.roomName = roomName;
|
||||
this.secretKey = secretKey;
|
||||
this.participantId = Math.floor(Math.random() * 65534) + 1;
|
||||
}
|
||||
|
||||
public async ignite(serverUrl: string, username: string) {
|
||||
this.username = username;
|
||||
this.isActive = true;
|
||||
|
||||
try {
|
||||
// 1. Ekstrak host dari serverUrl
|
||||
let host = window.location.hostname;
|
||||
if (serverUrl && serverUrl !== "/") {
|
||||
const urlObj = new URL(serverUrl);
|
||||
host = urlObj.hostname;
|
||||
}
|
||||
|
||||
const secureProto = window.location.protocol;
|
||||
const wtUrl = `${secureProto}//${host}:8443/neural-link/${this.roomName}`;
|
||||
console.log("[XTM] Menginisialisasi WebTransport ke:", wtUrl);
|
||||
|
||||
// 2. Setup WebTransport
|
||||
// Gunakan any cast karena WebTransport mungkin belum diakui di semua tsconfig
|
||||
const WT = (window as any).WebTransport;
|
||||
if (!WT) {
|
||||
throw new Error("WebTransport tidak didukung di browser ini!");
|
||||
}
|
||||
|
||||
this.transport = new WT(wtUrl);
|
||||
await this.transport.ready;
|
||||
console.log("[XTM] Pipa WebTransport Kuantum TERHUBUNG!");
|
||||
|
||||
// 3. Mulai Membaca Datagrams
|
||||
this.readDatagrams();
|
||||
|
||||
} catch (e) {
|
||||
console.error("[XTM] Ignition Failed:", e);
|
||||
// Fallback: Jika WebTransport diblokir firewall, XTM akan mengaktifkan SSE Relay (TBD)
|
||||
}
|
||||
}
|
||||
|
||||
private async readDatagrams() {
|
||||
if (!this.transport || !this.transport.datagrams) return;
|
||||
|
||||
try {
|
||||
const reader = this.transport.datagrams.readable.getReader();
|
||||
while (this.isActive) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
if (value && value.length >= 8) {
|
||||
const type = value[0];
|
||||
// byte 2-3 = participantId pengirim
|
||||
const senderId = new DataView(value.buffer).getUint16(2, true);
|
||||
|
||||
if (senderId === this.participantId) continue;
|
||||
|
||||
const payload = value.slice(8);
|
||||
|
||||
if (type === 7) { // 7 = Chat Text
|
||||
this.decryptAndPush(payload);
|
||||
} else if (type === 8) { // 8 = Telepathic Resonance (Typing)
|
||||
// Mendekripsi siapa yang mengetik
|
||||
this.handleTypingResonance(payload);
|
||||
} else if (type === 9) { // 9 = PKEPX Resonance (Emoji)
|
||||
this.handleQuantumResonance(payload, senderId);
|
||||
} else if (type === 10) { // 10 = PKEPX Sovereign Command
|
||||
this.handleSovereignCommand(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (this.isActive) console.error("[XTM] Datagram Reader terputus:", e);
|
||||
}
|
||||
}
|
||||
|
||||
private async decryptAndPush(payload: Uint8Array) {
|
||||
try {
|
||||
// Convert Uint8Array to WordArray
|
||||
const wordArr = CryptoJS.lib.WordArray.create(payload as any);
|
||||
const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
|
||||
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
|
||||
const originalText = bytes.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
if (originalText) {
|
||||
const parsed = JSON.parse(originalText);
|
||||
this.messages.push({
|
||||
id: Math.random().toString(),
|
||||
sender: parsed.sender,
|
||||
content: parsed.text,
|
||||
timestamp: parsed.timestamp,
|
||||
status: 'delivered'
|
||||
});
|
||||
|
||||
if (this.onMessagesUpdate) {
|
||||
this.onMessagesUpdate([...this.messages]);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Gagal dekripsi pesan XTM", e);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleTypingResonance(payload: Uint8Array) {
|
||||
try {
|
||||
const wordArr = CryptoJS.lib.WordArray.create(payload as any);
|
||||
const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
|
||||
const name = bytes.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
if (name) {
|
||||
this.typingState[name] = Date.now();
|
||||
if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState});
|
||||
|
||||
setTimeout(() => {
|
||||
delete this.typingState[name];
|
||||
if (this.onTypingUpdate) this.onTypingUpdate({...this.typingState});
|
||||
}, 3000);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// PKEPX ZOOM-KILLER: JUMPA CHAT PORT
|
||||
// =====================================
|
||||
|
||||
private async handleQuantumResonance(payload: Uint8Array, senderId: number) {
|
||||
try {
|
||||
const wordArr = CryptoJS.lib.WordArray.create(payload as any);
|
||||
const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
|
||||
const reactionType = bytes.toString(CryptoJS.enc.Utf8);
|
||||
if (reactionType && this.onQuantumResonance) {
|
||||
this.onQuantumResonance(senderId, reactionType);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
private async handleSovereignCommand(payload: Uint8Array) {
|
||||
try {
|
||||
const wordArr = CryptoJS.lib.WordArray.create(payload as any);
|
||||
const ciphertext = CryptoJS.enc.Base64.stringify(wordArr);
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, this.secretKey);
|
||||
const cmdStr = bytes.toString(CryptoJS.enc.Utf8);
|
||||
if (cmdStr && this.onSovereignSignal) {
|
||||
const cmd = JSON.parse(cmdStr);
|
||||
this.onSovereignSignal(cmd.command, cmd.targetId);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
public async emitResonance(reactionType: string) {
|
||||
if (!this.transport || !this.transport.datagrams) return;
|
||||
|
||||
const ciphertext = CryptoJS.AES.encrypt(reactionType, this.secretKey).toString();
|
||||
const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
|
||||
const encPayload = new Uint8Array(encWordArr.sigBytes);
|
||||
for (let i = 0; i < encWordArr.sigBytes; i++) {
|
||||
encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
}
|
||||
|
||||
const header = new Uint8Array(8);
|
||||
header[0] = 9; // Tipe 9 = Resonance
|
||||
new DataView(header.buffer).setUint16(2, this.participantId, true);
|
||||
|
||||
const fullPacket = new Uint8Array(8 + encPayload.length);
|
||||
fullPacket.set(header, 0);
|
||||
fullPacket.set(encPayload, 8);
|
||||
|
||||
let writer: any = null;
|
||||
try {
|
||||
writer = this.transport.datagrams.writable.getWriter();
|
||||
await writer.write(fullPacket);
|
||||
if (this.onQuantumResonance) this.onQuantumResonance(this.participantId, reactionType);
|
||||
} catch (e) {} finally {
|
||||
if (writer) writer.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
public async broadcastSovereignSignal(command: string, targetId?: number) {
|
||||
if (!this.transport || !this.transport.datagrams) return;
|
||||
|
||||
const payloadStr = JSON.stringify({ command, targetId });
|
||||
const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString();
|
||||
const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
|
||||
const encPayload = new Uint8Array(encWordArr.sigBytes);
|
||||
for (let i = 0; i < encWordArr.sigBytes; i++) {
|
||||
encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
}
|
||||
|
||||
const header = new Uint8Array(8);
|
||||
header[0] = 10; // Tipe 10 = Sovereign
|
||||
new DataView(header.buffer).setUint16(2, this.participantId, true);
|
||||
|
||||
const fullPacket = new Uint8Array(8 + encPayload.length);
|
||||
fullPacket.set(header, 0);
|
||||
fullPacket.set(encPayload, 8);
|
||||
|
||||
let writer: any = null;
|
||||
try {
|
||||
writer = this.transport.datagrams.writable.getWriter();
|
||||
await writer.write(fullPacket);
|
||||
} catch (e) {} finally {
|
||||
if (writer) writer.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt and send
|
||||
public async sendMessage(sender: string, content: string) {
|
||||
if (!this.transport || !this.transport.datagrams) {
|
||||
// Fallback simpan ke local buffer jika belum konek
|
||||
this.messages.push({
|
||||
id: Math.random().toString(),
|
||||
sender,
|
||||
content,
|
||||
timestamp: Date.now(),
|
||||
status: 'failed_offline'
|
||||
});
|
||||
if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]);
|
||||
return;
|
||||
}
|
||||
|
||||
const payloadStr = JSON.stringify({ sender, text: content, timestamp: Date.now() });
|
||||
|
||||
// E2EE: AES Encryption
|
||||
const ciphertext = CryptoJS.AES.encrypt(payloadStr, this.secretKey).toString();
|
||||
const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
|
||||
// Convert WordArray to Uint8Array
|
||||
const encPayload = new Uint8Array(encWordArr.sigBytes);
|
||||
for (let i = 0; i < encWordArr.sigBytes; i++) {
|
||||
encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
}
|
||||
|
||||
// Header
|
||||
const header = new Uint8Array(8);
|
||||
header[0] = 7; // Tipe 7 = Text Message
|
||||
header[1] = 0;
|
||||
new DataView(header.buffer).setUint16(2, this.participantId, true);
|
||||
|
||||
const fullPacket = new Uint8Array(8 + encPayload.length);
|
||||
fullPacket.set(header, 0);
|
||||
fullPacket.set(encPayload, 8);
|
||||
|
||||
let writer: any = null;
|
||||
try {
|
||||
writer = this.transport.datagrams.writable.getWriter();
|
||||
await writer.write(fullPacket);
|
||||
|
||||
// Optimistic UI Update
|
||||
this.messages.push({
|
||||
id: Math.random().toString(),
|
||||
sender,
|
||||
content,
|
||||
timestamp: Date.now(),
|
||||
status: 'delivered'
|
||||
});
|
||||
if (this.onMessagesUpdate) this.onMessagesUpdate([...this.messages]);
|
||||
} catch (e) {
|
||||
console.error("Gagal mengirim pesan Kuantum:", e);
|
||||
} finally {
|
||||
if (writer) writer.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
public async setTyping(username: string, charCount: number) {
|
||||
if (!this.transport || !this.transport.datagrams) return;
|
||||
|
||||
const ciphertext = CryptoJS.AES.encrypt(username, this.secretKey).toString();
|
||||
const encWordArr = CryptoJS.enc.Base64.parse(ciphertext);
|
||||
const encPayload = new Uint8Array(encWordArr.sigBytes);
|
||||
for (let i = 0; i < encWordArr.sigBytes; i++) {
|
||||
encPayload[i] = (encWordArr.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
}
|
||||
|
||||
const header = new Uint8Array(8);
|
||||
header[0] = 8; // Tipe 8 = Typing
|
||||
new DataView(header.buffer).setUint16(2, this.participantId, true);
|
||||
|
||||
const fullPacket = new Uint8Array(8 + encPayload.length);
|
||||
fullPacket.set(header, 0);
|
||||
fullPacket.set(encPayload, 8);
|
||||
|
||||
let writer: any = null;
|
||||
try {
|
||||
writer = this.transport.datagrams.writable.getWriter();
|
||||
await writer.write(fullPacket);
|
||||
} catch (e) {} finally {
|
||||
if (writer) writer.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
public shutdown() {
|
||||
this.isActive = false;
|
||||
if (this.transport) {
|
||||
try { this.transport.close(); } catch(e){}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user