Source: webrtc2-sign.js


/**
 * @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);
	});
}