cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
197 lines (196 loc) • 6.24 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
class WebRTC {
constructor(host, port) {
__publicField(this, "host");
__publicField(this, "port");
__publicField(this, "userId");
__publicField(this, "isReady");
__publicField(this, "messageList");
__publicField(this, "icecandidateList");
__publicField(this, "handlerMap");
__publicField(this, "socket");
__publicField(this, "peer");
this.host = host;
this.port = port;
this.userId = 0;
this.isReady = false;
this.messageList = [];
this.icecandidateList = [];
this.handlerMap = {};
this.socket = null;
this.peer = null;
this.init();
}
static checkSupport() {
const RTCPeer = RTCPeerConnection || webkitRTCPeerConnection || mozRTCPeerConnection;
return !!RTCPeer;
}
static createPeer() {
const RTCPeer = RTCPeerConnection || webkitRTCPeerConnection || mozRTCPeerConnection;
const config = {
iceServers: [{ urls: ["stun:stun.xten.com", "stun:stun.l.google.com:19302"] }]
};
return new RTCPeer(config);
}
static createIceCan(data) {
const RTCIce = RTCIceCandidate || webkitRTCIceCandidate || mozRTCIceCandidate;
return new RTCIce(data);
}
static createDescript(data) {
const RTCDesc = RTCSessionDescription || webkitRTCSessionDescription || mozRTCSessionDescription;
return new RTCDesc(data);
}
init() {
const connectionStr = `wss://${this.host}${this.port ? `:${this.port}` : ""}/webrtc?password=123`;
const socket = new WebSocket(connectionStr);
this.socket = socket;
socket.onopen = this.onOpen.bind(this);
socket.onmessage = this.onMessage.bind(this);
socket.onclose = this.onClose.bind(this);
socket.onerror = this.onError.bind(this);
}
initPeer(msg) {
const peer = WebRTC.createPeer();
this.peer = peer;
this.initPeerBind(msg);
}
initPeerBind(msg) {
const peer = this.peer;
peer.onconnectionstatechange = this.onPeerConnectionChange.bind(this, msg);
peer.onicecandidate = this.onPeerIceCandidate.bind(this, msg);
peer.ontrack = this.onPeerAddTrack.bind(this, msg);
}
onPeerConnectionChange(msg, event) {
this.debug("peer connection change", this.peer.connectionState);
let status = 0;
if (this.peer.connectionState === "connecting")
status = 1;
if (this.peer.connectionState === "connected") {
status = 2;
this.excuteHandler("connected", {});
}
if (this.peer.connectionState === "disconnected") {
status = 0;
this.excuteHandler("disconnected", {});
}
this.send({ event: "status", userId: this.userId, data: { hasConnection: status } });
}
onPeerAddTrack(msg, event) {
this.excuteHandler("track", event);
}
onPeerIceCandidate(msg, event) {
if (event.candidate && event.candidate.protocol == "udp") {
const data = event.candidate;
const sendMsg = { event: "ice", userId: this.userId, toUserId: msg.fromUserId, data };
this.send(sendMsg);
}
}
onOpen() {
this.isReady = true;
}
onMessage(event) {
const { data } = event;
const msg = typeof data === "string" ? JSON.parse(data) : data;
const handler = this[msg.event];
if (msg.status === 500)
return this.debug("fail", msg.msg);
if (msg.event === "connection") {
this.userId = Number(msg.userId) || 0;
this.send({ event: "info", userId: this.userId, data: { userName: "SDA", desc: "SDA\u7EC4\u4EF6", type: "window", canP2P: false } });
this.excuteHandler("connection", {});
return;
}
if (!handler)
return this.debug("fail", "\u5904\u7406\u51FD\u6570\u4E0D\u5B58\u5728");
handler.call(this, msg);
}
onClose() {
this.isReady = false;
}
onError(error) {
this.debug("error", error);
}
publisher(msg) {
const { userId, toUserId } = msg;
const sendMsg = { event: "subscriber", userId: this.userId, toUserId };
if (this.peer) {
this.peer.close();
this.peer = null;
}
this.initPeer({ userId, fromUserId: toUserId });
this.send(sendMsg);
}
async offer(msg) {
const { data, toUserId } = msg;
const desc = WebRTC.createDescript(data);
let ans;
let ice;
if (!desc)
return;
try {
await this.peer.setRemoteDescription(desc);
ans = await this.peer.createAnswer();
await this.peer.setLocalDescription(ans);
this.send({ event: "answer", userId: this.userId, toUserId, data: this.peer.localDescription });
ice = this.icecandidateList.shift();
while (ice) {
const iceItem = WebRTC.createIceCan(ice);
this.peer.addIceCandidate(iceItem);
ice = this.icecandidateList.shift();
}
} catch (error) {
this.debug("offer", error);
}
}
ice(msg) {
const { data } = msg;
if (this.peer.remoteDescription) {
const ice = WebRTC.createIceCan(data);
this.peer.addIceCandidate(ice);
} else {
this.icecandidateList.push(data);
}
}
excuteHandler(event, data) {
const handlerList = this.handlerMap[event];
if (!handlerList)
return;
for (let i = 0; i < handlerList.length; i++) {
const func = handlerList[i];
func(data);
}
}
debug(key, data) {
console.log(`============>:${key}`);
console.log(data);
}
send(data) {
const msg = JSON.stringify(data);
if (!this.isReady)
return this.messageList.push(msg);
this.socket.send(msg);
}
on(event, func) {
const handlerList = this.handlerMap[event];
if (!handlerList)
this.handlerMap[event] = [];
this.handlerMap[event].push(func);
}
off(event, func) {
const handlerList = this.handlerMap[event];
let index;
if (!handlerList)
return;
index = handlerList.findIndex((it) => it == func);
if (index >= 0)
handlerList.splice(index, 1);
if (!handlerList.length)
delete this.handlerMap[event];
}
}
export { WebRTC as default };