change claude proxy name and added ws support in adroid app

This commit is contained in:
2026-03-11 22:35:26 +01:00
parent e951fc712f
commit dd12a49aaf
116 changed files with 485 additions and 247 deletions
+64 -9
View File
@@ -30,12 +30,22 @@ export interface ConnectionConfig {
type MessageCallback = (message: RVSMessage) => void;
type StateCallback = (state: ConnectionState) => void;
/** Einzelner Eintrag im Verbindungslog */
export interface ConnectionLogEntry {
timestamp: number;
level: 'info' | 'warn' | 'error';
message: string;
}
type LogCallback = (entry: ConnectionLogEntry) => void;
// --- Konstanten ---
const HEARTBEAT_INTERVAL_MS = 25_000;
const INITIAL_RECONNECT_DELAY_MS = 1_000;
const MAX_RECONNECT_DELAY_MS = 30_000;
const RECONNECT_BACKOFF_FACTOR = 2;
const MAX_LOG_ENTRIES = 100;
// --- RVS-Klasse ---
@@ -51,6 +61,9 @@ class RVSConnection {
private messageListeners: MessageCallback[] = [];
private stateListeners: StateCallback[] = [];
private logListeners: LogCallback[] = [];
private connectionLog: ConnectionLogEntry[] = [];
private usingTLSFallback: boolean = false;
// --- Konfiguration ---
@@ -73,17 +86,19 @@ class RVSConnection {
/** Verbindung zum RVS aufbauen */
connect(): void {
if (!this.config) {
console.warn('[RVS] Keine Verbindungskonfiguration vorhanden');
this.log('warn', 'Keine Verbindungskonfiguration vorhanden');
return;
}
if (this.ws?.readyState === WebSocket.OPEN) {
console.log('[RVS] Bereits verbunden');
this.log('info', 'Bereits verbunden');
return;
}
this.shouldReconnect = true;
this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
this.usingTLSFallback = false;
this.log('info', `Verbindungsaufbau zu ${this.config.host}:${this.config.port} (TLS: ${this.config.useTLS ? 'ja' : 'nein'})`);
this.establishConnection();
}
@@ -97,6 +112,7 @@ class RVSConnection {
this.ws = null;
}
this.log('info', 'Verbindung getrennt (manuell)');
this.setState('disconnected');
}
@@ -135,21 +151,47 @@ class RVSConnection {
};
}
/** Callback fuer Verbindungslog-Eintraege registrieren */
onLog(callback: LogCallback): () => void {
this.logListeners.push(callback);
return () => {
this.logListeners = this.logListeners.filter(cb => cb !== callback);
};
}
/** Gesamten Verbindungslog abrufen */
getConnectionLog(): ConnectionLogEntry[] {
return [...this.connectionLog];
}
// --- Interne Methoden ---
/** Eintrag ins Verbindungslog schreiben */
private log(level: ConnectionLogEntry['level'], message: string): void {
const entry: ConnectionLogEntry = { timestamp: Date.now(), level, message };
this.connectionLog = [...this.connectionLog.slice(-(MAX_LOG_ENTRIES - 1)), entry];
this.logListeners.forEach(cb => cb(entry));
const prefix = level === 'error' ? 'ERROR' : level === 'warn' ? 'WARN' : 'INFO';
console.log(`[RVS] [${prefix}] ${message}`);
}
private establishConnection(): void {
if (!this.config) return;
this.setState('connecting');
const protocol = this.config.useTLS ? 'wss' : 'ws';
const useTLS = this.config.useTLS && !this.usingTLSFallback;
const protocol = useTLS ? 'wss' : 'ws';
const url = `${protocol}://${this.config.host}:${this.config.port}?token=${this.config.token}`;
this.log('info', `Verbinde: ${protocol}://${this.config.host}:${this.config.port}`);
try {
this.ws = new WebSocket(url);
this.ws.onopen = () => {
console.log('[RVS] Verbunden');
const tlsInfo = this.usingTLSFallback ? ' (TLS-Fallback: ws://)' : '';
this.log('info', `Verbunden${tlsInfo}`);
this.setState('connected');
this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
this.startHeartbeat();
@@ -160,12 +202,12 @@ class RVSConnection {
const message: RVSMessage = JSON.parse(event.data as string);
this.notifyMessageListeners(message);
} catch (err) {
console.error('[RVS] Fehler beim Parsen der Nachricht:', err);
this.log('error', `Nachricht parsen fehlgeschlagen: ${err}`);
}
};
this.ws.onclose = (event) => {
console.log(`[RVS] Verbindung geschlossen (Code: ${event.code})`);
this.log('info', `Verbindung geschlossen (Code: ${event.code}, Reason: ${event.reason || '-'})`);
this.clearTimers();
this.ws = null;
this.setState('disconnected');
@@ -176,10 +218,23 @@ class RVSConnection {
};
this.ws.onerror = (error) => {
console.error('[RVS] WebSocket-Fehler:', error);
const errorMsg = (error as any)?.message || 'Unbekannter Fehler';
this.log('error', `WebSocket-Fehler: ${errorMsg}`);
// TLS-Fallback: Wenn wss:// fehlschlaegt, auf ws:// wechseln
if (this.config?.useTLS && !this.usingTLSFallback) {
this.usingTLSFallback = true;
this.log('warn', 'TLS fehlgeschlagen — Fallback auf ws:// (ohne TLS)');
this.clearTimers();
this.ws?.close();
this.ws = null;
this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
this.establishConnection();
return;
}
};
} catch (err) {
console.error('[RVS] Verbindungsfehler:', err);
this.log('error', `Verbindungsfehler: ${err}`);
this.setState('disconnected');
if (this.shouldReconnect) {
@@ -190,7 +245,7 @@ class RVSConnection {
/** Reconnect mit exponentiellem Backoff planen */
private scheduleReconnect(): void {
console.log(`[RVS] Reconnect in ${this.reconnectDelay / 1000}s...`);
this.log('info', `Reconnect in ${this.reconnectDelay / 1000}s...`);
this.reconnectTimer = setTimeout(() => {
this.establishConnection();