fix (tracker-assist & frontend-assist): connection logic fix

This commit is contained in:
ShiKhu 2021-07-07 18:06:01 +03:00
parent bedcf9dd08
commit 2e77aa3ca7
3 changed files with 113 additions and 37 deletions

View file

@ -14,14 +14,26 @@ export enum CallingState {
False,
};
export enum ConnectionStatus {
Connecting,
Connected,
Inactive,
Disconnected,
Error,
};
export interface State {
calling: CallingState,
peerConnectionStatus: ConnectionStatus,
}
export const INITIAL_STATE: State = {
calling: CallingState.False,
peerConnectionStatus: ConnectionStatus.Connecting,
}
const MAX_RECONNECTION_COUNT = 6;
function resolveURL(baseURL: string, relURL: string): string {
if (relURL.startsWith('#') || relURL === "") {
@ -90,6 +102,7 @@ export default class AssistManager {
}
private peer: Peer | null = null;
connectionAttempts: number = 0;
connect() {
if (this.peer != null) {
console.error("AssistManager: trying to connect more than once");
@ -107,9 +120,16 @@ export default class AssistManager {
this.peer = peer;
this.peer.on('error', e => {
if (e.type === 'peer-unavailable') {
this.connectToPeer(); // TODO: MAX_ATTEMPT_TIME
if (this.peer && this.connectionAttempts++ < MAX_RECONNECTION_COUNT) {
update({ peerConnectionStatus: ConnectionStatus.Connecting })
this.connectToPeer();
} else {
update({ peerConnectionStatus: ConnectionStatus.Disconnected })
}
} else {
console.error(`PeerJS error (on peer). Type ${e.type}`, e);
update({ peerConnectionStatus: ConnectionStatus.Error })
}
})
peer.on("open", me => {
@ -126,13 +146,20 @@ export default class AssistManager {
const conn = this.peer.connect(id, { serialization: 'json'});
conn.on('open', () => {
this.md.setMessagesLoading(false);
let i = 0;
update({ peerConnectionStatus: ConnectionStatus.Inactive });
console.log("peer connected")
let i = 0;
let firstMessage = true;
conn.on('data', (data) => {
if (typeof data === 'string') { return this.handleCommand(data); }
if (!Array.isArray(data)) { return; }
if (firstMessage) {
firstMessage = false;
this.md.setMessagesLoading(false);
update({ peerConnectionStatus: ConnectionStatus.Connected })
}
let time = 0;
let ts0 = 0;
(data as Array<Message & { _id: number}>).forEach(msg => {
@ -174,38 +201,58 @@ export default class AssistManager {
});
});
});
conn.on('close', () => {
this.md.setMessagesLoading(true);
this.endCall();
console.log('closed peer conn. Reconnecting...')
setTimeout(() => this.connectToPeer(), 300); // reconnect
});
conn.on('close', () => this.onDataClose());// Doesn't work ?
}
private get dataConnection(): DataConnection | null {
return this.peer?.connections[this.peerID]?.[0] || null;
private onDataClose() {
this.md.setMessagesLoading(true);
this.assistentCallEnd();
console.log('closed peer conn. Reconnecting...')
setTimeout(() => this.connectToPeer(), 0); // reconnect
}
private get callConnection(): MediaConnection | null {
return this.peer?.connections[this.peerID]?.[1] || null;
private get dataConnection(): DataConnection | undefined {
return this.peer?.connections[this.peerID]?.find(c => c.type === 'data' && c.open);
}
private get callConnection(): MediaConnection | undefined {
return this.peer?.connections[this.peerID]?.find(c => c.type === 'media' && c.open);
}
private onCallEnd: null | (()=>void) = null;
private endCall = () => {
const conn = this.callConnection;
private assistentCallEnd = () => {
console.log('assistentCallEnd')
const conn = this.callConnection?.close();
const dataConn = this.dataConnection;
if (dataConn) {
console.log("call_end send")
dataConn.send("call_end");
}
this.onCallEnd?.();
if (!conn || !conn.open) { return; }
conn.close(); //calls onCallEnd twice
this.dataConnection?.send("call_end"); //
}
private onTrackerCallEnd = () => {
const conn = this.callConnection;
if (conn && conn.open) {
conn.close();
}
this.onCallEnd?.();
}
private handleCommand(command: string) {
switch (command) {
case "call_end":
console.log("Call end recieved")
this.endCall();
this.onTrackerCallEnd();
return;
case "call_error":
this.onTrackerCallEnd();
update({ peerConnectionStatus: ConnectionStatus.Error });
return;
}
}
@ -247,18 +294,23 @@ export default class AssistManager {
update({ calling: CallingState.False });
this.onCallEnd = null;
}
call.on("close", this.onCallEnd);
//call.on("close", this.onCallEnd);
call.on("error", (e) => {
console.error("PeerJS error (on call):", e)
this.onCallEnd?.();
onError?.();
});
window.addEventListener("beforeunload", this.assistentCallEnd)
return this.endCall;
return this.assistentCallEnd;
}
clear() {
this.assistentCallEnd();
console.log("destroying peer...")
this.peer?.destroy();
this.peer = null;
}
}

View file

@ -1,9 +1,10 @@
const declineIcon = `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 128 128" ><g id="Circle_Grid" data-name="Circle Grid"><circle cx="64" cy="64" fill="#ef5261" r="64"/></g><g id="icon"><path d="m57.831 70.1c8.79 8.79 17.405 12.356 20.508 9.253l4.261-4.26a7.516 7.516 0 0 1 10.629 0l9.566 9.566a7.516 7.516 0 0 1 0 10.629l-7.453 7.453c-7.042 7.042-27.87-2.358-47.832-22.319-9.976-9.981-16.519-19.382-20.748-28.222s-5.086-16.091-1.567-19.61l7.453-7.453a7.516 7.516 0 0 1 10.629 0l9.566 9.563a7.516 7.516 0 0 1 0 10.629l-4.264 4.271c-3.103 3.1.462 11.714 9.252 20.5z" fill="#eeefee"/></g></svg>`;
export default function confirm(text: string, styles?: Object): Promise<boolean> {
return new Promise(resolve => {
export default class Confirm {
private wrapper: HTMLDivElement;
constructor(text: string, styles?: Object) {
const wrapper = document.createElement('div');
const popup = document.createElement('div');
const p = document.createElement('p');
@ -60,17 +61,30 @@ export default function confirm(text: string, styles?: Object): Promise<boolean>
pointerEvents: "none",
})
wrapper.appendChild(popup);
document.body.appendChild(wrapper);
this.wrapper = wrapper;
answerBtn.onclick = () => {
document.body.removeChild(wrapper);
resolve(true);
this.remove();
this.callback(true);
}
declineBtn.onclick = () => {
document.body.removeChild(wrapper);
resolve(false);
this.remove();
this.callback(false);
}
})
}
}
mount() {
document.body.appendChild(this.wrapper);
}
private callback: (result: boolean) => void = ()=>{};
onAnswer(callback: (result: boolean) => void) {
this.callback = callback;
}
remove() {
if (!this.wrapper.parentElement) { return; }
document.body.removeChild(this.wrapper);
}
}

View file

@ -5,7 +5,7 @@ import type Message from '@openreplay/tracker';
import Mouse from './Mouse';
import CallWindow from './CallWindow';
import confirm from './confirm';
import Confirm from './Confirm';
export interface Options {
@ -61,10 +61,20 @@ export default function(opts: Partial<Options> = {}) {
.connections[call.peer].find(c => c.type === 'data');
if (calling || !dataConn) {
call.close();
dataConn?.send("call_end");
dataConn?.send("call_error");
return;
}
confirm(options.confirmText, options.confirmStyle).then(conf => {
window.addEventListener("beforeunload", () => {
dataConn.open && dataConn.send("call_end");
});
dataConn.on('data', (data) => { // if call closed be a caller before confirm
if (data === "call_end") {
confirm.remove();
}
});
const confirm = new Confirm(options.confirmText, options.confirmStyle);
confirm.mount();
confirm.onAnswer(conf => {
if (!conf || !dataConn.open) {
call.close();
dataConn.open && dataConn.send("call_end");
@ -80,7 +90,7 @@ export default function(opts: Partial<Options> = {}) {
const onClose = () => {
console.log("close call...")
if (call.open) { call.close(); }
mouse?.remove();
mouse.remove();
callUI?.remove();
oStream.getTracks().forEach(t => t.stop());