const channel = document.getElementById("channel");
const status1 = document.getElementById("status");
let button1 = document.getElementById("button1");
const filetdcontent = document.getElementById("filetd").innerHTML;
let button11 = null;
let button12 = null;
const button2 = document.getElementById("button2");
const button3 = document.getElementById("button3");
const button4 = document.getElementById("button4");
let ready = false;
let channelClosedBySelf = false;
let id = "";
let filename = "";
let socket = new WebSocket("wss://" + location.host + "/ws");
//urls: ['stun:stun1.l.google.com:19302', 'stun:stun3.l.google.com:19302']
const config = {
iceServers: [
{
//urls: ['stun:192.168.1.41:3478'] //dev
urls: ['stun:37.27.24.159:3478'] //prod
},
{
//urls: ['turn:192.168.1.41:3478'], //dev
//username: "mau", //dev
//credential: "meow" //dev
urls: ['turn:37.27.24.159:3478'], //prod
username: "kvuebvdhf7efbsmdwqdivn", //prod
credential: "f83wrehfusdf7qugybfj29jfd" //prod //TODO: when encrypting all
},
]
}
peerConnection = new RTCPeerConnection(config); //peer connection
let local = null;
initSocket();
function verifySocket() {
if (!ready) {
socket = new WebSocket("wss://" + location.host + "/ws");
initSocket()
}
}
function initSocket() {
socket.onopen = function (evt) {
console.log("Websocket open");
ready = true;
if (document.URL.includes("?id=")) {
channel.value = document.URL.split("=")[1];
button2Handler()
}
}
socket.onclose = function (evt) {
console.log("Websocket closed");
ready = false;
}
socket.onerror = function (evt) {
console.log("Websocket error: " + evt.data);
ready = false;
}
socket.addEventListener("message", (event) => {
console.log(event.data);
const response = event.data.split(" ");
if (response[0] === "Created") {
channel.value = response[1];
id = response[1];
button2.innerText = "Close channel";
button1.disabled = true;
button1.innerText = "Create channel";
button1.title = "You have to close the channel before creating a new one, or join the channel on another device";
} else if (response[0] === "AskPin") {
let pin = prompt("give pin");
let askpinmessage = "Pin " + id + " " + pin;
console.log(askpinmessage);
socket.send(askpinmessage);
} else if (response[0] === "AskJoin") {
askjoininfo = `Enter Pin for other client: ip= ${response[1]}, pin= ${response[2]}`
console.log(askjoininfo);
status1.value = askjoininfo;
} else if (response[0] === "Joined") {
id = channel.value;
button2.innerText = "Close channel";
button2.disabled = false;
button1.disabled = false;
status1.value = `${event.data}`;
button1.innerText = "Open File";
button1.title = "You have to join the channel on another device before opening a file";
document.getElementById("filetd").innerHTML = "";
document.getElementById("filetd").innerHTML = ``;
document.getElementById("videodiv").innerHTML = "";
document.getElementById("videodiv").innerHTML = ``;
local = document.querySelector("video#local");
button1 = null;
} else if (response[0] === "icecandidate") {
console.log("icecandidate");
const webrtcdata = JSON.parse(event.data.split('\n').slice(1).join('\n'));
peerConnection?.addIceCandidate(webrtcdata);
} else if (response[0] === "offer") {
console.log("offer");
const webrtcdata = JSON.parse(event.data.split('\n').slice(1).join('\n'));
handleOffer(webrtcdata);
} else if (response[0] === "answer") {
console.log("answer");
const webrtcdata = JSON.parse(event.data.split('\n').slice(1).join('\n'));
peerConnection?.setRemoteDescription(webrtcdata);
} else if (response[0] === "NoChannel") {
alert("Enter a valid channel id!");
channel.value = "";
recreateButton1()
button2.innerText = "Join channel";
button2.disabled = false
channel.value = "";
status1.value = "Disconnected";
channelClosedBySelf = true;
button1 = document.getElementById("button1");
} else if (response[0] === "Closed") {
if (channelClosedBySelf) {
recreateButton1()
} else {
status1.value = `Peer closed connection`;
recreateButton1()
button1 = document.getElementById("button1");
button1.disabled = true;
button1.innerText = "Create channel";
button1.title = "You have to close the channel before creating a new one, or join the channel on another device";
}
channelClosedBySelf = false;
} else if (response[0] === "Timeout") {
alert("Connection expired");
}
});
}
async function startLoad() {
channel.value = "";
status1.value = "Disconnected";
}
function recreateButton1() {
document.getElementById("filetd").innerHTML = "";
document.getElementById("filetd").innerHTML = filetdcontent;
}
function startVideoStreaming() {
console.log("videostreM");
peerConnection.addEventListener("icecandidate", e => {
let candidate = null;
if (e.candidate !== null) {
candidate = {
candidate: e.candidate.candidate,
sdpMid: e.candidate.sdpMid,
sdpMLineIndex: e.candidate.sdpMLineIndex,
};
}
//channel.postMessage({ type: "icecandidate", candidate });
console.log("icecandidate ", candidate);
socket.send("icecandidate " + id + " \n" + JSON.stringify(candidate));
});
// Add tracks from the screen share stream
local.srcObject.getTracks().forEach(track => peerConnection.addTrack(track, local.srcObject));
peerConnection.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true })
.then(async offer => {
await peerConnection.setLocalDescription(offer);
console.log("Created offer, sending...", offer.sdp);
//channel.postMessage({ type: "offer", sdp: offer.sdp });
console.log("offer ", offer.sdp);
let oursdp = { type: "offer", sdp: offer.sdp };
let ouroffersdp = JSON.stringify(oursdp);
socket.send("offer " + id + " \n" + ouroffersdp);
});
}
function button11Handler() {
console.log("screenshare button");
navigator.mediaDevices.getDisplayMedia({ video: true, audio: true })
.then((stream) => {
local.srcObject = stream;
// Optional: handle the end of the screen sharing
stream.getVideoTracks()[0].addEventListener('ended', () => {
console.log("Screen sharing stopped");
// You could add additional handling like stopping the peer connection here
});
startVideoStreaming();
})
.catch(err => console.error("Error accessing display media: ", err))
}
function button12Handler() {
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then((stream) => {
local.srcObject = stream;
startVideoStreaming();
})
}
function button1Handler() {
verifySocket()
if (!ready) {
alert("socket not ready, refresh page!");
return;
}
if (button1.innerText === "Create channel") {
button1.disabled = true;
const idtype = document.getElementById('idtype');
if (idtype.value == "words") {
socket.send("createShortID")
} else {
socket.send("createID");
}
}
}
function button2Handler() {
verifySocket()
if (!ready) {
alert("socket not ready, refresh page!");
return;
}
if (button2.innerText === "Close channel") {
socket.send("closeId " + id);
console.log("close channel");
channel.value = "";
document.getElementById("filetd").innerHTML = ""
document.getElementById("filetd").innerHTML = ``;
button2.innerText = "Join channel";
channel.value = "";
status1.value = "Disconnected";
document.getElementById("download").innerHTML = "";
channelClosedBySelf = true;
button1 = document.getElementById("button1");
} else if (button2.innerText === "Join channel") {
if (channel.value === "") {
alert("Enter a valid channel id!");
return;
}
button1.disabled = true;
button2.disabled = true;
id = channel.value
socket.send("joinID " + id);
} else {
console.log("Error, you broke my app!")
}
}
function accept() {
document.getElementById("filetd").innerHTML = "";
document.getElementById("filetd").innerHTML = `DOWNLOAD FILE!`;
socket.send("FileAccepted " + id);
}
function copy() {
const text = `https://${location.host}/videocall?id=${channel.value}`;
navigator.clipboard.writeText(text).then(function () {
console.log('Async: Copying to clipboard was successful!');
}, function (err) {
console.error('Async: Could not copy text: ', err);
});
}
function handleOffer(offer) {
peerConnection = new RTCPeerConnection(config);
peerConnection.addEventListener("track", e => local.srcObject = e.streams[0]);
peerConnection.addEventListener("icecandidate", e => {
let candidate = null;
if (e.candidate !== null) {
candidate = {
candidate: e.candidate.candidate,
sdpMid: e.candidate.sdpMid,
sdpMLineIndex: e.candidate.sdpMLineIndex,
};
}
console.log("icecandidate ", candidate);
socket.send("icecandidate " + id + " \n" + JSON.stringify(candidate));
});
peerConnection.setRemoteDescription(offer)
.then(() => peerConnection.createAnswer())
.then(async answer => {
await peerConnection.setLocalDescription(answer);
console.log("Created answer, sending...", answer.sdp);
/*channel.postMessage({
type: "answer",
sdp: answer.sdp,
});*/
let oursdp = { type: "answer", sdp: answer.sdp };
let ouranswersdp = JSON.stringify(oursdp);
socket.send("answer " + id + " \n" + ouranswersdp)
});
}