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 @@