/**
* @description Exchange sdp, ice-candidates between chat members.
* @category webrtc2-sign.js
* @package js
* @author Oleg Klenitsky <klenitskiy.oleg@mail.ru>
* @version 1.7.3
* @license GPLv2 or later
*/
/*jshint esversion: 6 */
"use strict";
/**
* Send stop of video-chat to server.
*/
function webrtc2_chat_stop() {
if (webrtc2_dataChannel && "open" == webrtc2_dataChannel.readyState) {
webrtc2_dataChannel.send(JSON.stringify({"name" : "cmd", "text" : "stop_chat"}));
}
if (webrtc2_pc) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_cmd=cmd0" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send stop of video-chat of " + webrtc2_hostId + " to server.");
webrtc2_makeRequest(params)
.then(msg => {
console.log(msg);
if (webrtc2_dataChannel) {
webrtc2_dataChannel.close();
}
if (webrtc2_statChannel) {
webrtc2_statChannel.close();
}
if (webrtc2_ctxChannel) {
webrtc2_ctxChannel.close();
}
});
}
}
/**
* @description Send list name of guests to server.
* @param {string} webrtc2_guestId webrtc2_guestId.
*/
function webrtc2_send_guestId(webrtc2_guestId) {
if ("cancel" == webrtc2_guestId) {
document.getElementById("slogan").innerHTML = webrtc2_hostId + " canceled call";
}
if ("no_name" !== webrtc2_hostId) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_guestId=" + webrtc2_guestId +
"&webrtc2_cmd=cmd1" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send current guest list of " + webrtc2_hostId + " to server.");
webrtc2_makeRequest(params)
.then(msg => console.log(msg));
}
}
/**
* @description Send msg of webrtc2_hostId to autoresponder on server (autoresponder).
* @param {string} message Message for send to autoresponder.
*/
function webrtc2_autoresponder_send( message ) {
let webrtc2_guestId = sessionStorage.getItem("webrtc2_guestId");
if ("no_name" !== webrtc2_hostId) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_guestId=" + webrtc2_guestId +
"&webrtc2_msg=" + message +
"&webrtc2_cmd=cmd2" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send msg to autoresponder: from " + webrtc2_hostId + " to " + webrtc2_guestId);
webrtc2_makeRequest(params)
.then(msg => console.log(msg));
}
}
/**
* @description Receive msg for webrtc2_hostId from autoresponder on server (autoresponder).
* @return {string} Message.
*/
async function webrtc2_autoresponder_receive() {
if ("no_name" !== webrtc2_hostId) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_cmd=cmd3" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
let msg = await webrtc2_makeRequest(params);
if (msg) {
console.log("Receive message from autoresponder: for " + webrtc2_hostId);
return msg;
}
}
}
/**
* @description Send ice-candidate of webrtc2_hostId to server.
* @param {string} webrtc2_ice_candidates ICE candidates of webrtc2_hostId.
*/
function webrtc2_send_ice( webrtc2_ice_candidates ) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_ice_candidates=" + webrtc2_ice_candidates +
"&webrtc2_cmd=cmd4" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send ice-candidates of " + webrtc2_hostId + " to server");
webrtc2_makeRequest(params)
.then(msg => console.log(msg));
}
/**
* @description Receive ice candidates from server.
* @return {array} Ice candidates.
*/
async function webrtc2_receive_ice() {
let webrtc2_guestId = sessionStorage.getItem("webrtc2_guestId");
let params = "webrtc2_guestId=" + webrtc2_guestId +
"&webrtc2_cmd=cmd5" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
let msg = await webrtc2_makeRequest(params);
if (msg) {
console.log("Receive from server ice candidates of " + webrtc2_guestId);
return JSON.parse(msg);
}
}
/**
* @description Send sdp of webrtc2_hostId to server.
* @param {string} sdp SDP of webrtc2_hostId.
* @param {string} type Offer or Answer SDP of webrtc2_hostId.
*/
function webrtc2_send_sdp( sdp, type ) {
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_sdp=" + sdp +
"&webrtc2_type_sdp=" + type +
"&webrtc2_cmd=cmd6" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send " + type + " of " + webrtc2_hostId + " to server.");
webrtc2_makeRequest(params)
.then((msg) => console.log(msg));
}
/**
* @description Receive sdp from server.
* @param {string} webrtc2_type_sdp Offer or Answer.
* @return {string} SDP.
*/
async function webrtc2_receive_sdp( webrtc2_type_sdp ) {
let webrtc2_guestId = sessionStorage.getItem("webrtc2_guestId");
let params = "webrtc2_guestId=" + webrtc2_guestId +
"&webrtc2_type_sdp=" + webrtc2_type_sdp +
"&webrtc2_cmd=cmd7" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
let msg = await webrtc2_makeRequest(params);
if (msg) {
console.log("Receive from server " + webrtc2_type_sdp + " of " + webrtc2_guestId);
return JSON.parse(msg);
}
}
/**
* @description Send call_stat of videochat to server.
* @param {string} state: start or stop.
*/
function webrtc2_call_stat(state) {
let webrtc2_guestId = sessionStorage.getItem("webrtc2_guestId");
let webrtc2_initiator = sessionStorage.getItem("webrtc2_initiator");
if (webrtc2_pc && "new" !== webrtc2_pc.iceConnectionState) {
let curr_time = new Date();
let agentInfo = detect.parse(navigator.userAgent);
let browser = "";
if (!agentInfo.browser.major) {
browser = agentInfo.browser.family;
} else {
browser = agentInfo.browser.family + " version " +
agentInfo.browser.major + "." +
agentInfo.browser.minor + "." +
agentInfo.browser.patch;
}
let params = "webrtc2_hostId=" + webrtc2_hostId +
"&webrtc2_guestId=" + webrtc2_guestId +
"&initiator=" + webrtc2_initiator +
"&state=" + state +
"&browser=" + browser +
"&webrtc2_cmd=cmd8" +
"&action=sign" +
"&nonce=" + webrtc2_nonce;
console.log("Send call_stat signal of videochat (" + webrtc2_hostId + ") to server.");
webrtc2_makeRequest(params)
.then(msg => console.log(msg));
}
}
/**
* @description Peer to Peer video-chat.
*/
function webrtc2_chat_init() {
let webrtc2_guestId = sessionStorage.getItem("webrtc2_guestId");
let timer_receive_answer;
let timer_receive_ice;
if ( "true" == sessionStorage.getItem("webrtc2_initiator") ) {
// Init data channel for statistics data of guestId.
webrtc2_statChannel = webrtc2_pc.createDataChannel("statChannel", {protocol: "json"});
webrtc2_statChannel.binaryType = "arraybuffer";
webrtc2_datachannel_stat();
// Init data channel for receive/send of messages, files.
webrtc2_dataChannel = webrtc2_pc.createDataChannel("dataChannel", {protocol: "json/arraybuffer"});
webrtc2_dataChannel.binaryType = "arraybuffer";
webrtc2_datachannel_data();
// Init data channel for interactive drawing board.
webrtc2_ctxChannel = webrtc2_pc.createDataChannel("ctxChannel", {protocol: "json"});
webrtc2_ctxChannel.binaryType = "arraybuffer";
webrtc2_datachannel_ctx();
webrtc2_pc.createOffer(webrtc2_offerOptions)
// Modifying the SDP to check ice-ufrag, ice-pwd.
.then(offer => {
offer.sdp = webrtc2_chk_ufrag_pwd(webrtc2_hostId, "Offer", offer.sdp);
return offer;
})
.then(offer => {
webrtc2_pc.setLocalDescription(offer);
return offer;
})
// modify the SDP after calling setLocalDescription.
.then(offer => {
offer.sdp = webrtc2_setMediaBitrates(webrtc2_hostId, "Offer", offer.sdp);
return offer;
})
.then(offer => {
webrtc2_log_sdp(webrtc2_hostId, " -> Send [Offer] to " + webrtc2_guestId + ":", offer.sdp);
webrtc2_send_sdp(JSON.stringify(offer), "offer");
})
// Receive answer sdp of webrtc2_guestId from server.
.then(timer_receive_answer = setInterval(() => {
webrtc2_receive_sdp("answer").then(answer => {
if (answer) {
webrtc2_log_sdp(webrtc2_hostId, " -> Receive [Answer] from " + webrtc2_guestId + ":", answer.sdp);
webrtc2_pc.setRemoteDescription(answer);
clearInterval(timer_receive_answer);
}
})
}, 10000))
// Receive ice-candidates of webrtc2_guestId from server.
.then(timer_receive_ice = setInterval(() => {
webrtc2_receive_ice().then(iceCandidates => {
if (iceCandidates) {
webrtc2_ice_remote(iceCandidates);
for (let iceCandidate of iceCandidates) {
webrtc2_pc.addIceCandidate(iceCandidate).catch(err => console.log(err));
}
clearInterval(timer_receive_ice);
}
})
}, 10000));
}else{
// Receive offer sdp of webrtc2_guestId from server.
let timer_receive_offer = setInterval(() => {
webrtc2_receive_sdp("offer").then(offer => {
if (offer) {
webrtc2_log_sdp(webrtc2_hostId, " -> Receive [Offer] from " + webrtc2_guestId + " :", offer.sdp);
webrtc2_pc.setRemoteDescription(offer).then(() => webrtc2_pc.createAnswer())
.then((answer) => {
// Modifying the SDP to check ice-ufrag, ice-pwd.
answer.sdp = webrtc2_chk_ufrag_pwd(webrtc2_hostId, "Answer", answer.sdp);
return answer;
})
.then(answer => {
webrtc2_pc.setLocalDescription(answer);
return answer;
})
// modify the SDP after calling setLocalDescription.
.then(answer => {
answer.sdp = webrtc2_setMediaBitrates(webrtc2_hostId, "Answer", answer.sdp);
return answer;
})
.then(answer => {
webrtc2_log_sdp(webrtc2_hostId, " -> Send [Answer] to " + webrtc2_guestId + ":", answer.sdp);
webrtc2_send_sdp(JSON.stringify(answer), "answer");
})
// Receive ice-candidates of webrtc2_guestId from server.
.then(timer_receive_ice = setInterval(() => {
webrtc2_receive_ice().then(iceCandidates => {
if (iceCandidates) {
webrtc2_ice_remote(iceCandidates);
for (let iceCandidate of iceCandidates) {
webrtc2_pc.addIceCandidate(iceCandidate).catch(err => console.log(err));
}
clearInterval(timer_receive_ice);
}
})
}, 10000));
clearInterval(timer_receive_offer);
}
})
}, 10000);
}
}
/**
* @description Make request XMLHttpRequest.
* @param {string} params Parameter for request.
*/
function webrtc2_makeRequest (params) {
return new Promise( function(resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open("POST", webrtc2_url_ajax, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onload = function() {
if (this.readyState == 4 && this.status == 200) {
resolve(this.response);
}else{
reject({
status: this.status,
statusText: this.statusText
});
}
};
xhr.onerror = function() {
reject({
status: this.status,
statusText: this.statusText
});
};
xhr.send(params);
});
}