-
-
Notifications
You must be signed in to change notification settings - Fork 69
/
json-rpc-impl.ts
118 lines (100 loc) · 3 KB
/
json-rpc-impl.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { v4 as uuidv4 } from 'uuid';
import { Signal } from '.';
import { Trickle } from '../client';
class IonSFUJSONRPCSignal implements Signal {
protected socket: WebSocket;
private _onopen?: () => void;
private _onclose?: (ev: Event) => void;
private _onerror?: (error: Event) => void;
onnegotiate?: (jsep: RTCSessionDescriptionInit) => void;
ontrickle?: (trickle: Trickle) => void;
private _notifyhandlers: { [method: string]: (params: any) => void };
constructor(uri: string) {
this.socket = new WebSocket(uri);
this._notifyhandlers = {};
this.socket.addEventListener('open', () => {
if (this._onopen) this._onopen();
});
this.socket.addEventListener('error', (e) => {
if (this._onerror) this._onerror(e);
});
this.socket.addEventListener('close', (e) => {
if (this._onclose) this._onclose(e);
});
this.socket.addEventListener('message', async (event) => {
const resp = JSON.parse(event.data);
if (resp.method === 'offer') {
if (this.onnegotiate) this.onnegotiate(resp.params);
} else if (resp.method === 'trickle') {
if (this.ontrickle) this.ontrickle(resp.params);
} else {
const handler = this._notifyhandlers[resp.method];
if (handler) {
handler(resp.params);
}
}
});
}
on_notify<T>(method: string, cb: (params: T) => void) {
this._notifyhandlers[method] = cb;
}
// JsonRPC2 Call
async call<T>(method: string, params: any): Promise<T> {
const id = uuidv4();
this.socket.send(
JSON.stringify({
method,
params,
id,
}),
);
return new Promise<T>((resolve, reject) => {
const handler = (event: MessageEvent<any>) => {
const resp = JSON.parse(event.data);
if (resp.id === id) {
if (resp.error) reject(resp.error);
else resolve(resp.result);
this.socket.removeEventListener('message', handler);
}
};
this.socket.addEventListener('message', handler);
});
}
// JsonRPC2 Notification
notify(method: string, params: any) {
this.socket.send(
JSON.stringify({
method,
params,
}),
);
}
async join(sid: string, uid: string, offer: RTCSessionDescriptionInit) {
return this.call<RTCSessionDescriptionInit>('join', { sid, uid, offer });
}
trickle(trickle: Trickle) {
this.notify('trickle', trickle);
}
async offer(offer: RTCSessionDescriptionInit) {
return this.call<RTCSessionDescriptionInit>('offer', { desc: offer });
}
answer(answer: RTCSessionDescriptionInit) {
this.notify('answer', { desc: answer });
}
close() {
this.socket.close();
}
set onopen(onopen: () => void) {
if (this.socket.readyState === WebSocket.OPEN) {
onopen();
}
this._onopen = onopen;
}
set onerror(onerror: (error: Event) => void) {
this._onerror = onerror;
}
set onclose(onclose: (ev: Event) => void) {
this._onclose = onclose;
}
}
export { IonSFUJSONRPCSignal };