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) }); }