@tolokoban/p2p 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +5 -0
- package/dist/answer.d.ts +28 -0
- package/dist/answer.js +110 -0
- package/dist/answer.js.map +1 -0
- package/dist/event.d.ts +8 -0
- package/dist/event.js +16 -0
- package/dist/event.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/message.d.ts +20 -0
- package/dist/message.js +63 -0
- package/dist/message.js.map +1 -0
- package/dist/offer.d.ts +29 -0
- package/dist/offer.js +140 -0
- package/dist/offer.js.map +1 -0
- package/dist/peer.d.ts +60 -0
- package/dist/peer.js +201 -0
- package/dist/peer.js.map +1 -0
- package/package.json +18 -0
package/dist/answer.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Peer } from "./peer";
|
|
2
|
+
export declare class PeerAnswer extends Peer {
|
|
3
|
+
/**
|
|
4
|
+
* @param iceServers By default the connection works only on local network.
|
|
5
|
+
* But you can specify a list of STUN servers to overcome this issue.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* [
|
|
11
|
+
* { urls: "stun:stun.l.google.com:19302" },
|
|
12
|
+
* { urls: "stun:stun1.l.google.com:19302" },
|
|
13
|
+
* { urls: "stun:stun2.l.google.com:19302" },
|
|
14
|
+
* { urls: "stun:stun3.l.google.com:19302" },
|
|
15
|
+
* ]
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
static connect(signalServerURL: string, id: string, iceServers?: RTCIceServer[]): Promise<PeerAnswer>;
|
|
19
|
+
private _id;
|
|
20
|
+
private _address;
|
|
21
|
+
private constructor();
|
|
22
|
+
get id(): string;
|
|
23
|
+
get address(): string;
|
|
24
|
+
private connect;
|
|
25
|
+
private readOffer;
|
|
26
|
+
private signalAnswer;
|
|
27
|
+
private createAnswer;
|
|
28
|
+
}
|
package/dist/answer.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { assertType, assertType$ } from "@tolokoban/type-guards";
|
|
11
|
+
import { Peer } from "./peer.js";
|
|
12
|
+
export class PeerAnswer extends Peer {
|
|
13
|
+
/**
|
|
14
|
+
* @param iceServers By default the connection works only on local network.
|
|
15
|
+
* But you can specify a list of STUN servers to overcome this issue.
|
|
16
|
+
*
|
|
17
|
+
* Example:
|
|
18
|
+
*
|
|
19
|
+
* ```js
|
|
20
|
+
* [
|
|
21
|
+
* { urls: "stun:stun.l.google.com:19302" },
|
|
22
|
+
* { urls: "stun:stun1.l.google.com:19302" },
|
|
23
|
+
* { urls: "stun:stun2.l.google.com:19302" },
|
|
24
|
+
* { urls: "stun:stun3.l.google.com:19302" },
|
|
25
|
+
* ]
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
static connect(signalServerURL_1, id_1) {
|
|
29
|
+
return __awaiter(this, arguments, void 0, function* (signalServerURL, id, iceServers = []) {
|
|
30
|
+
const peerOffer = new PeerAnswer(signalServerURL, id, iceServers);
|
|
31
|
+
yield peerOffer.connect();
|
|
32
|
+
return peerOffer;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
constructor(signalServerURL, id, iceServers) {
|
|
36
|
+
super(signalServerURL, iceServers);
|
|
37
|
+
this._id = "";
|
|
38
|
+
this._address = "";
|
|
39
|
+
this._id = id;
|
|
40
|
+
}
|
|
41
|
+
get id() {
|
|
42
|
+
return this._id;
|
|
43
|
+
}
|
|
44
|
+
get address() {
|
|
45
|
+
return this._address;
|
|
46
|
+
}
|
|
47
|
+
connect() {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
const offer = yield this.readOffer();
|
|
50
|
+
const answer = yield this.createAnswer(offer);
|
|
51
|
+
yield this.signalAnswer(answer);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
readOffer() {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const data = yield this.signal({
|
|
57
|
+
service: "get-offer",
|
|
58
|
+
key: this.id,
|
|
59
|
+
});
|
|
60
|
+
assertType(data, { offer: "string" });
|
|
61
|
+
const offer = JSON.parse(data.offer);
|
|
62
|
+
assertType$(offer, {
|
|
63
|
+
type: ["literal", "offer"],
|
|
64
|
+
sdp: "string",
|
|
65
|
+
});
|
|
66
|
+
return offer;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
signalAnswer(answer) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const answerAsString = JSON.stringify(answer);
|
|
72
|
+
const response = yield this.signal({
|
|
73
|
+
service: "set-answer",
|
|
74
|
+
input: answerAsString,
|
|
75
|
+
key: this.id,
|
|
76
|
+
});
|
|
77
|
+
assertType(response, { id: "string" });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
createAnswer(offer) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
const action = () => __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
try {
|
|
85
|
+
const { peerConnection, dataChannel } = this;
|
|
86
|
+
peerConnection.setRemoteDescription(offer);
|
|
87
|
+
dataChannel.onopen = () => {
|
|
88
|
+
console.log("ANSWER: Connection established!");
|
|
89
|
+
this.eventConnected.dispatch(this);
|
|
90
|
+
};
|
|
91
|
+
dataChannel.onmessage = (e) => this.onMessage(e.data);
|
|
92
|
+
const answer = yield peerConnection.createAnswer();
|
|
93
|
+
yield peerConnection.setLocalDescription(answer);
|
|
94
|
+
peerConnection.onicecandidate = (event) => {
|
|
95
|
+
if (!event.candidate) {
|
|
96
|
+
resolve(peerConnection.localDescription);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (ex) {
|
|
101
|
+
console.error("Unable to create an offer:", ex);
|
|
102
|
+
reject(ex);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
action();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=answer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer.js","sourceRoot":"","sources":["../library/src/answer.ts"],"names":[],"mappings":"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"}
|
package/dist/event.d.ts
ADDED
package/dist/event.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class GenericEvent {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.listeners = new Set();
|
|
4
|
+
}
|
|
5
|
+
addListener(listener) {
|
|
6
|
+
this.listeners.add(listener);
|
|
7
|
+
}
|
|
8
|
+
removeListener(listener) {
|
|
9
|
+
this.listeners.delete(listener);
|
|
10
|
+
}
|
|
11
|
+
dispatch(value) {
|
|
12
|
+
for (const listener of this.listeners)
|
|
13
|
+
listener(value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.js","sourceRoot":"","sources":["../library/src/event.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAY;IAAzB;QACqB,cAAS,GAAG,IAAI,GAAG,EAAe,CAAA;IAavD,CAAC;IAXG,WAAW,CAAC,QAAqB;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED,cAAc,CAAC,QAAqB;QAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACnC,CAAC;IAED,QAAQ,CAAC,KAAQ;QACb,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC1D,CAAC;CACJ"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../library/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PeerMessage {
|
|
2
|
+
getString(): string;
|
|
3
|
+
}
|
|
4
|
+
export declare class Message implements PeerMessage {
|
|
5
|
+
private readonly buffer;
|
|
6
|
+
readonly byteLength: number;
|
|
7
|
+
private offset;
|
|
8
|
+
private readonly view;
|
|
9
|
+
constructor(buffer: ArrayBuffer);
|
|
10
|
+
getString(): string;
|
|
11
|
+
getArrayBuffer(): ArrayBuffer;
|
|
12
|
+
getUint8(): number;
|
|
13
|
+
getInt8(): number;
|
|
14
|
+
getUint16(): number;
|
|
15
|
+
getInt16(): number;
|
|
16
|
+
getUint32(): number;
|
|
17
|
+
getInt32(): number;
|
|
18
|
+
getFloat32(): number;
|
|
19
|
+
getFloat64(): number;
|
|
20
|
+
}
|
package/dist/message.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class Message {
|
|
2
|
+
constructor(buffer) {
|
|
3
|
+
this.buffer = buffer;
|
|
4
|
+
this.offset = 0;
|
|
5
|
+
this.view = new DataView(buffer);
|
|
6
|
+
this.byteLength = buffer.byteLength;
|
|
7
|
+
}
|
|
8
|
+
getString() {
|
|
9
|
+
const byteLength = this.view.getUint32(this.offset);
|
|
10
|
+
this.offset += 4;
|
|
11
|
+
const chunk = this.buffer.slice(this.offset, this.offset + byteLength);
|
|
12
|
+
this.offset += chunk.byteLength;
|
|
13
|
+
return new TextDecoder().decode(chunk);
|
|
14
|
+
}
|
|
15
|
+
getArrayBuffer() {
|
|
16
|
+
const byteLength = this.view.getUint32(this.offset);
|
|
17
|
+
this.offset += 4;
|
|
18
|
+
const chunk = this.buffer.slice(this.offset, this.offset + byteLength);
|
|
19
|
+
this.offset += chunk.byteLength;
|
|
20
|
+
return chunk;
|
|
21
|
+
}
|
|
22
|
+
getUint8() {
|
|
23
|
+
const value = this.view.getUint8(this.offset);
|
|
24
|
+
this.offset += 1;
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
getInt8() {
|
|
28
|
+
const value = this.view.getInt8(this.offset);
|
|
29
|
+
this.offset += 1;
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
getUint16() {
|
|
33
|
+
const value = this.view.getUint16(this.offset);
|
|
34
|
+
this.offset += 2;
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
getInt16() {
|
|
38
|
+
const value = this.view.getInt16(this.offset);
|
|
39
|
+
this.offset += 2;
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
getUint32() {
|
|
43
|
+
const value = this.view.getUint32(this.offset);
|
|
44
|
+
this.offset += 4;
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
getInt32() {
|
|
48
|
+
const value = this.view.getInt32(this.offset);
|
|
49
|
+
this.offset += 4;
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
getFloat32() {
|
|
53
|
+
const value = this.view.getFloat32(this.offset);
|
|
54
|
+
this.offset += 4;
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
getFloat64() {
|
|
58
|
+
const value = this.view.getFloat64(this.offset);
|
|
59
|
+
this.offset += 8;
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../library/src/message.ts"],"names":[],"mappings":"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"}
|
package/dist/offer.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Peer } from "./peer";
|
|
2
|
+
export declare class PeerOffer extends Peer {
|
|
3
|
+
/**
|
|
4
|
+
* @param iceServers By default the connection works only on local network.
|
|
5
|
+
* But you can specify a list of STUN servers to overcome this issue.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* [
|
|
11
|
+
* { urls: "stun:stun.l.google.com:19302" },
|
|
12
|
+
* { urls: "stun:stun1.l.google.com:19302" },
|
|
13
|
+
* { urls: "stun:stun2.l.google.com:19302" },
|
|
14
|
+
* { urls: "stun:stun3.l.google.com:19302" },
|
|
15
|
+
* ]
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
static connect(signalServerURL: string, iceServers?: RTCIceServer[]): Promise<PeerOffer>;
|
|
19
|
+
private _id;
|
|
20
|
+
private _address;
|
|
21
|
+
private constructor();
|
|
22
|
+
get id(): string;
|
|
23
|
+
get address(): string;
|
|
24
|
+
private connect;
|
|
25
|
+
private pollAnswer;
|
|
26
|
+
private readAnswer;
|
|
27
|
+
private signalOffer;
|
|
28
|
+
private createOffer;
|
|
29
|
+
}
|
package/dist/offer.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { assertType, assertType$ } from "@tolokoban/type-guards";
|
|
11
|
+
import { Peer } from "./peer.js";
|
|
12
|
+
export class PeerOffer extends Peer {
|
|
13
|
+
/**
|
|
14
|
+
* @param iceServers By default the connection works only on local network.
|
|
15
|
+
* But you can specify a list of STUN servers to overcome this issue.
|
|
16
|
+
*
|
|
17
|
+
* Example:
|
|
18
|
+
*
|
|
19
|
+
* ```js
|
|
20
|
+
* [
|
|
21
|
+
* { urls: "stun:stun.l.google.com:19302" },
|
|
22
|
+
* { urls: "stun:stun1.l.google.com:19302" },
|
|
23
|
+
* { urls: "stun:stun2.l.google.com:19302" },
|
|
24
|
+
* { urls: "stun:stun3.l.google.com:19302" },
|
|
25
|
+
* ]
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
static connect(signalServerURL_1) {
|
|
29
|
+
return __awaiter(this, arguments, void 0, function* (signalServerURL, iceServers = []) {
|
|
30
|
+
const peerOffer = new PeerOffer(signalServerURL, iceServers);
|
|
31
|
+
yield peerOffer.connect();
|
|
32
|
+
return peerOffer;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
constructor(signalServerURL, iceServers = []) {
|
|
36
|
+
super(signalServerURL, iceServers);
|
|
37
|
+
this._id = "";
|
|
38
|
+
this._address = "";
|
|
39
|
+
}
|
|
40
|
+
get id() {
|
|
41
|
+
return this._id;
|
|
42
|
+
}
|
|
43
|
+
get address() {
|
|
44
|
+
return this._address;
|
|
45
|
+
}
|
|
46
|
+
connect() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const offer = yield this.createOffer();
|
|
49
|
+
yield this.signalOffer(offer);
|
|
50
|
+
this.pollAnswer();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
pollAnswer() {
|
|
54
|
+
globalThis.setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
try {
|
|
56
|
+
const answer = yield this.readAnswer();
|
|
57
|
+
if (answer) {
|
|
58
|
+
this.peerConnection.setRemoteDescription(answer);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.pollAnswer();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (ex) {
|
|
65
|
+
console.error("Error in PeerOffer.pollAnswer():", ex);
|
|
66
|
+
}
|
|
67
|
+
}), 1000);
|
|
68
|
+
}
|
|
69
|
+
readAnswer() {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
try {
|
|
72
|
+
const data = yield this.signal({
|
|
73
|
+
service: "get-answer",
|
|
74
|
+
key: this.id,
|
|
75
|
+
});
|
|
76
|
+
assertType$(data, {
|
|
77
|
+
answer: ["|", "string", "null"],
|
|
78
|
+
});
|
|
79
|
+
if (!data.answer)
|
|
80
|
+
return null;
|
|
81
|
+
const answer = JSON.parse(data.answer);
|
|
82
|
+
assertType$(answer, {
|
|
83
|
+
type: ["literal", "answer"],
|
|
84
|
+
sdp: "string",
|
|
85
|
+
});
|
|
86
|
+
return answer;
|
|
87
|
+
}
|
|
88
|
+
catch (ex) {
|
|
89
|
+
console.error("Error in PeerOffer.readAnswer():", ex);
|
|
90
|
+
throw ex;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
signalOffer(offer) {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const offerAsString = JSON.stringify(offer);
|
|
97
|
+
const response = yield this.signal({
|
|
98
|
+
service: "set-offer",
|
|
99
|
+
input: offerAsString,
|
|
100
|
+
});
|
|
101
|
+
assertType(response, { id: "string", address: "string" });
|
|
102
|
+
this._id = response.id;
|
|
103
|
+
this._address = response.address;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
createOffer() {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const action = () => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
try {
|
|
111
|
+
const { peerConnection, dataChannel } = this;
|
|
112
|
+
dataChannel.onopen = () => {
|
|
113
|
+
console.log("OFFER: Connection established!");
|
|
114
|
+
this.eventConnected.dispatch(this);
|
|
115
|
+
};
|
|
116
|
+
dataChannel.onmessage = (e) => this.onMessage(e.data);
|
|
117
|
+
const offer = yield peerConnection.createOffer();
|
|
118
|
+
yield peerConnection.setLocalDescription(offer);
|
|
119
|
+
peerConnection.onicecandidate = (event) => {
|
|
120
|
+
if (!event.candidate) {
|
|
121
|
+
if (peerConnection.localDescription) {
|
|
122
|
+
resolve(peerConnection.localDescription);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
reject(new Error("Unable to create Offer!"));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (ex) {
|
|
131
|
+
console.error("Unable to create an offer:", ex);
|
|
132
|
+
reject(ex);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
action();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=offer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offer.js","sourceRoot":"","sources":["../library/src/offer.ts"],"names":[],"mappings":"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"}
|
package/dist/peer.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { GenericEvent } from "./event";
|
|
2
|
+
import { PeerMessage } from "./message";
|
|
3
|
+
type SignalParameters = {
|
|
4
|
+
service: "get-offer" | "get-answer";
|
|
5
|
+
key: string;
|
|
6
|
+
} | {
|
|
7
|
+
service: "set-offer";
|
|
8
|
+
input: string;
|
|
9
|
+
} | {
|
|
10
|
+
service: "set-answer";
|
|
11
|
+
input: string;
|
|
12
|
+
key: string;
|
|
13
|
+
};
|
|
14
|
+
declare const SIZES: {
|
|
15
|
+
Uint8: number;
|
|
16
|
+
Uint16: number;
|
|
17
|
+
Uint32: number;
|
|
18
|
+
Int8: number;
|
|
19
|
+
Int16: number;
|
|
20
|
+
Int32: number;
|
|
21
|
+
Float32: number;
|
|
22
|
+
Float64: number;
|
|
23
|
+
};
|
|
24
|
+
export declare abstract class Peer {
|
|
25
|
+
protected readonly signalServerURL: string;
|
|
26
|
+
readonly eventConnected: GenericEvent<Peer>;
|
|
27
|
+
readonly eventMessage: GenericEvent<PeerMessage>;
|
|
28
|
+
readonly eventClose: GenericEvent<Peer>;
|
|
29
|
+
protected readonly peerConnection: RTCPeerConnection;
|
|
30
|
+
protected readonly dataChannel: RTCDataChannel;
|
|
31
|
+
private remoteChannel;
|
|
32
|
+
private readonly messageToBeSent;
|
|
33
|
+
/**
|
|
34
|
+
* @param iceServers By default the connection works only on local network.
|
|
35
|
+
* But you can specify a list of STUN servers to overcome this issue.
|
|
36
|
+
*
|
|
37
|
+
* Example:
|
|
38
|
+
*
|
|
39
|
+
* ```js
|
|
40
|
+
* [
|
|
41
|
+
* { urls: "stun:stun.l.google.com:19302" },
|
|
42
|
+
* { urls: "stun:stun1.l.google.com:19302" },
|
|
43
|
+
* { urls: "stun:stun2.l.google.com:19302" },
|
|
44
|
+
* { urls: "stun:stun3.l.google.com:19302" },
|
|
45
|
+
* ]
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
protected constructor(signalServerURL: string, iceServers?: RTCIceServer[]);
|
|
49
|
+
close(): void;
|
|
50
|
+
clear(): this;
|
|
51
|
+
putString(message: string): this;
|
|
52
|
+
putArrayBuffer(arrayBuffer: ArrayBuffer): this;
|
|
53
|
+
putNumber(type: keyof typeof SIZES, value: number): this;
|
|
54
|
+
send(): void;
|
|
55
|
+
sendString(message: string): void;
|
|
56
|
+
private readonly handleMessage;
|
|
57
|
+
protected signal(args: SignalParameters): Promise<Record<string, string>>;
|
|
58
|
+
protected readonly onMessage: (data: unknown) => void;
|
|
59
|
+
}
|
|
60
|
+
export {};
|