171 lines
4.3 KiB
JavaScript
171 lines
4.3 KiB
JavaScript
/**
|
|
* WebSocket client for backone-webhub (127.0.0.1, authtoken auth).
|
|
*/
|
|
window.BackOneWebHubClient = (function () {
|
|
let ws = null;
|
|
let connected = false;
|
|
let reconnectDelay = 1000;
|
|
let reconnectTimer = null;
|
|
let pollTimer = null;
|
|
let port = 9994;
|
|
let selfPeerId = '';
|
|
const seenIncoming = new Set();
|
|
const handlers = new Map();
|
|
|
|
function emit(type, msg) {
|
|
const set = handlers.get(type);
|
|
if (!set) return;
|
|
set.forEach(fn => {
|
|
try { fn(msg); } catch (_) { /* ignore */ }
|
|
});
|
|
const all = handlers.get('*');
|
|
if (all) {
|
|
all.forEach(fn => {
|
|
try { fn(type, msg); } catch (_) { /* ignore */ }
|
|
});
|
|
}
|
|
}
|
|
|
|
function subscribe(type, fn) {
|
|
if (!handlers.has(type)) handlers.set(type, new Set());
|
|
handlers.get(type).add(fn);
|
|
return () => handlers.get(type)?.delete(fn);
|
|
}
|
|
|
|
function send(msg) {
|
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
ws.send(JSON.stringify(msg));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function registerPeer() {
|
|
const core = BackOneNetworkSession.getCoreStatus();
|
|
selfPeerId = ((core && core.address) || '').toLowerCase();
|
|
const networkId = BackOneNetworkSession.getNetworkId();
|
|
if (!selfPeerId) return;
|
|
send({ type: 'register', peerId: selfPeerId, networkId });
|
|
}
|
|
|
|
function stopHttpPoll() {
|
|
if (pollTimer) {
|
|
clearInterval(pollTimer);
|
|
pollTimer = null;
|
|
}
|
|
}
|
|
|
|
function startHttpPoll() {
|
|
stopHttpPoll();
|
|
pollTimer = setInterval(async () => {
|
|
if (connected) return;
|
|
const peerId = selfPeerId || ((BackOneNetworkSession.getCoreStatus().address || '').toLowerCase());
|
|
if (!peerId) return;
|
|
try {
|
|
const res = await BackOneAuth.fetchWithAuth(
|
|
`/controller/comms/call/incoming?peerId=${encodeURIComponent(peerId)}`
|
|
);
|
|
if (!res.ok) return;
|
|
const data = await res.json();
|
|
const calls = Array.isArray(data.calls) ? data.calls : [];
|
|
for (const call of calls) {
|
|
if (seenIncoming.has(call.callId)) continue;
|
|
seenIncoming.add(call.callId);
|
|
emit('incoming_call', {
|
|
type: 'incoming_call',
|
|
callId: call.callId,
|
|
callType: call.callType || 'voice',
|
|
callerId: call.callerId,
|
|
callerName: call.callerName || call.callerId,
|
|
networkId: call.networkId,
|
|
sdp: call.sdp
|
|
});
|
|
}
|
|
} catch (_) { /* ignore */ }
|
|
}, 2000);
|
|
}
|
|
|
|
function scheduleReconnect() {
|
|
if (reconnectTimer) return;
|
|
reconnectTimer = setTimeout(() => {
|
|
reconnectTimer = null;
|
|
connect();
|
|
}, reconnectDelay);
|
|
reconnectDelay = Math.min(reconnectDelay * 2, 30000);
|
|
}
|
|
|
|
async function loadPort() {
|
|
try {
|
|
const res = await BackOneAuth.fetchWithAuth('/app/api/webrtc-config');
|
|
if (res.ok) {
|
|
const cfg = await res.json();
|
|
if (cfg.webhubPort) port = cfg.webhubPort;
|
|
}
|
|
} catch (_) { /* ignore */ }
|
|
}
|
|
|
|
async function connect() {
|
|
await loadPort();
|
|
const token = await BackOneAuth.getToken();
|
|
if (!token) return false;
|
|
|
|
if (ws) {
|
|
try { ws.close(); } catch (_) { /* ignore */ }
|
|
ws = null;
|
|
}
|
|
|
|
return new Promise((resolve) => {
|
|
const url = `ws://127.0.0.1:${port}/?auth=${encodeURIComponent(token)}`;
|
|
try {
|
|
ws = new WebSocket(url);
|
|
} catch (_) {
|
|
connected = false;
|
|
startHttpPoll();
|
|
scheduleReconnect();
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
ws.onopen = () => {
|
|
connected = true;
|
|
reconnectDelay = 1000;
|
|
stopHttpPoll();
|
|
send({ type: 'auth', token });
|
|
registerPeer();
|
|
resolve(true);
|
|
};
|
|
|
|
ws.onmessage = (ev) => {
|
|
try {
|
|
const msg = JSON.parse(ev.data);
|
|
if (msg && msg.type) emit(msg.type, msg);
|
|
} catch (_) { /* ignore */ }
|
|
};
|
|
|
|
ws.onclose = () => {
|
|
connected = false;
|
|
ws = null;
|
|
startHttpPoll();
|
|
scheduleReconnect();
|
|
};
|
|
|
|
ws.onerror = () => {
|
|
connected = false;
|
|
};
|
|
});
|
|
}
|
|
|
|
BackOneNetworkSession.subscribe(() => {
|
|
if (connected) registerPeer();
|
|
});
|
|
|
|
return {
|
|
connect,
|
|
send,
|
|
subscribe,
|
|
isConnected: () => connected,
|
|
getSelfPeerId: () => selfPeerId,
|
|
registerPeer
|
|
};
|
|
})();
|