diff --git a/.gitignore b/.gitignore index 40b878d..3ec544c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules/ \ No newline at end of file +node_modules/ +.env \ No newline at end of file diff --git a/app.js b/app.js index 1b253f9..3fe159a 100644 --- a/app.js +++ b/app.js @@ -2,12 +2,17 @@ import express from 'express'; import path from 'path'; import { fileURLToPath } from 'url'; import bip39 from 'bip39'; +import crypto from 'crypto'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const trackerUrl = process.env.TRACKER_URL || 'ws://localhost:8106'; +const stunServerUrl = process.env.STUN_SERVER_URL; +const turnServerUrl = process.env.TURN_SERVER_URL; +const turnSecret = process.env.TURN_SECRET; +const turnTTL = 86400; app.set('view engine', 'ejs'); app.use(express.static(path.join(__dirname, 'public'))); @@ -28,6 +33,30 @@ app.get('/get-infohash/:mnemonic', (req, res) => { res.json({ infoHash }); }); +app.get('/turn-credentials', (req, res) => { + const iceServers = []; + + if (stunServerUrl) { + iceServers.push({ urls: stunServerUrl }); + } + + if (turnServerUrl && turnSecret) { + const unixTimeStamp = Math.floor(Date.now() / 1000) + turnTTL; + const username = `${unixTimeStamp}:transfercoffee`; + const hmac = crypto.createHmac('sha1', turnSecret); + hmac.update(username); + const credential = hmac.digest('base64'); + + iceServers.push({ + urls: turnServerUrl, + username: username, + credential: credential + }); + } + + res.json({ iceServers }); +}); + const PORT = process.env.PORT || 8105; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); diff --git a/public/js/index.js b/public/js/index.js index b943eb7..b73766a 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1,6 +1,13 @@ const client = new WebTorrent(); +const trackerUrl = "<%= trackerUrl %>"; -function uploadFile() { +async function getRTCIceServers() { + const response = await fetch("/turn-credentials"); + const data = await response.json(); + return data.iceServers; +} + +async function uploadFile() { const fileInput = document.getElementById("fileInput"); const file = fileInput.files[0]; const uploadProgressBar = document.getElementById("uploadProgressBar"); @@ -10,8 +17,13 @@ function uploadFile() { return; } + const rtcConfig = { + iceServers: await getRTCIceServers(), + }; + const opts = { announce: [trackerUrl], + rtcConfig: rtcConfig, }; client.seed(file, opts, (torrent) => { @@ -19,9 +31,8 @@ function uploadFile() { .then((response) => response.json()) .then((data) => { const uploadResult = document.getElementById("uploadResult"); - uploadResult.innerHTML = `Started sharing file. Share this mnemonic: ${data.mnemonic} -
Note that the file will be available for download as long as this page is open. - `; + uploadResult.innerHTML = `

Sharing your file. Share this mnemonic: ${data.mnemonic}

+

The file will be available for download as long as you keep this page open.

`; }); torrent.on("upload", () => { @@ -32,7 +43,7 @@ function uploadFile() { }); } -function downloadFile() { +async function downloadFile() { const mnemonicInput = document.getElementById("mnemonicInput").value; const downloadProgressBar = document.getElementById("downloadProgressBar"); @@ -41,6 +52,10 @@ function downloadFile() { return; } + const rtcConfig = { + iceServers: await getRTCIceServers(), + }; + fetch(`/get-infohash/${mnemonicInput}`) .then((response) => response.json()) .then((data) => { @@ -48,6 +63,7 @@ function downloadFile() { const opts = { announce: [trackerUrl], + rtcConfig: rtcConfig, }; client.add(torrentId, opts, (torrent) => { diff --git a/views/index.ejs b/views/index.ejs index 314ea7e..55c3dba 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -18,9 +18,9 @@
-

Download File

+

Receive File

- +
0%