add missing files

This commit is contained in:
2025-04-27 10:11:10 -07:00
parent 15c95e5c59
commit 63d7b276db
8 changed files with 3859 additions and 282 deletions

7
package-lock.json generated
View File

@@ -9,10 +9,11 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.5.4", "version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"

View File

@@ -5,7 +5,7 @@
// how? do "perfect negotiation" with bootstrap peer. All logic here moves to BP. // how? do "perfect negotiation" with bootstrap peer. All logic here moves to BP.
import { generateID } from "IDUtils"; import { generateID } from "IDUtils";
import { log } from "log"; import { log, logID } from "log";
// Use a broadcast channel to only have one peer manager for multiple tabs, // Use a broadcast channel to only have one peer manager for multiple tabs,
// then we won't need to have a session ID as all queries for a peerID will be coming from the same peer manager // then we won't need to have a session ID as all queries for a peerID will be coming from the same peer manager
@@ -29,6 +29,15 @@ export class PeerManager {
connectPromise: { resolve: Function, reject: Function } | null = null; connectPromise: { resolve: Function, reject: Function } | null = null;
pingPeers: RTCPeerConnection[] = []; pingPeers: RTCPeerConnection[] = [];
watchdogPeriodSeconds: number = 10;
// async watchdog() {
// // Check that we're connected to at least N peers. If not, reconnect to the bootstrap server.
// if (this.peers.size === 0) {
// await this.sendHello2();
// }
// }
websocketSend(message: any) { websocketSend(message: any) {
if (!this.websocket) { if (!this.websocket) {
@@ -168,18 +177,55 @@ export class PeerManager {
this.routingTable = new Map(); this.routingTable = new Map();
this.userID = userID; this.userID = userID;
this.peerID = peerID; this.peerID = peerID;
}
disconnect() {
this.websocket?.close();
for (let peer of this.peers.values()) {
peer.disconnect();
}
} }
connect() { connect() {
// setInterval(this.watchdog.bind(this), this.watchdogPeriodSeconds * 1000);
setInterval(()=>{
if (!this.isBootstrapPeer && this.peers.size === 0) {
console.log.apply(null, log("No peers connected :("));
if (this.websocket?.readyState === WebSocket.OPEN) {
this.sendHello2();
}
}
let output = `local peerID:${logID(this.peerID)}` + "\n";
for (let [peerID, peer] of this.peers) {
output += `${logID(peerID)}: ${peer.rtcPeer?.connectionState}` + "\n";
}
console.log.apply(null, log(output));
}, 5000);
let connectPromise = new Promise((resolve, reject) => { let connectPromise = new Promise((resolve, reject) => {
this.connectPromise = { resolve, reject }; this.connectPromise = { resolve, reject };
}); });
try { try {
this.websocket = new WebSocket( let hostname = globalThis?.location?.hostname ?? 'ddln.app';
`wss://${window.location.hostname}:${window.location.port}/ws`,
); let port = globalThis?.location?.port ?? '443';
let wsURL = `wss://${hostname}:${port}/ws`;
console.log(`wsURL: ${wsURL}`);
this.websocket = new WebSocket(wsURL);
} catch (error: any) { } catch (error: any) {
throw new Error(error.message); throw new Error(error.message);
} }
@@ -237,14 +283,15 @@ export class PeerManager {
} }
async disconnect(remotePeerID: string) { async disconnectFromPeer(remotePeerID: string) {
let peer = this.peers.get(remotePeerID); let peer = this.peers.get(remotePeerID);
if (!peer) { if (!peer) {
console.log.apply(null, log(`PeerManager.disconnect: couln't find peer ${remotePeerID}`)); console.log.apply(null, log(`PeerManager.disconnect: couldn't find peer ${remotePeerID}`));
return; return;
} }
console.log.apply(null, log(`PeerManager.disconnect: disconnecting peer ${remotePeerID}`));
await peer.disconnect(); await peer.disconnect();
this.peers.delete(remotePeerID); this.peers.delete(remotePeerID);
} }
@@ -295,8 +342,6 @@ export class PeerManager {
} }
} }
interface Message { interface Message {
type: string; type: string;
from_peer: string; from_peer: string;
@@ -306,98 +351,6 @@ interface Message {
peer_message: any; peer_message: any;
} }
// // Initially this wil be the bootstrap peer, We'll keep a connection to it and it will keep a list of all connected peers.
// // Eventually we will replace this with connecting via other peers.
// class Signaler {
// websocket: WebSocket;
// sessionID: string;
// userID: string;
// peerID: string;
// bootstrapPeerID: string = "";
// private isBootstrapPeer: boolean = false;
// private onConnected: Function;
// peerRoutes: Map<string, PeerConnection> = new Map();
// constructor(userID: string, peerID: string, isBootstrapPeer: boolean, onConnected: Function) {
// this.onConnected = onConnected;
// this.isBootstrapPeer = isBootstrapPeer;
// this.sessionID = generateID();
// this.userID = userID;
// this.peerID = peerID;
// try {
// this.websocket = new WebSocket(
// `wss://${window.location.hostname}:${window.location.port}/ws`,
// );
// } catch (error: any) {
// throw new Error(error.message);
// }
// this.websocket.onopen = async (event) => {
// console.log.apply(null, log("signaler:ws:onopen");
// await this.sendHello2();
// };
// this.websocket.onmessage = this.onMessage.bind(this);
// }
// connect() {
// }
// onMessage(event: MessageEvent) {
// let messageJSON = event.data;
// let message: any = null;
// try {
// message = JSON.parse(messageJSON);
// } catch (e) {
// console.log.apply(null, log(e);
// throw new Error();
// }
// console.log.apply(null, log("->signaler:", message);
// if (message.type === "hello2") {
// if (!this.isBootstrapPeer) {
// this.bootstrapPeerID = message.bootstrapPeers[0];
// }
// this.onConnected(this.bootstrapPeerID);
// }
// if (message.type == "peer_message") {
// if (message.message.type = "rtc_connect") {
// }
// let connection = this.peerRoutes.get(message.from_peer);
// if (!connection) {
// console.log.apply(null, log("Can't find peer for peer message:", message);
// return;
// }
// connection.onSignalerMessage(message);
// }
// }
// route(remotePeerID:string, peerConnection:PeerConnection) {
// this.peerRoutes.set(remotePeerID, peerConnection)
// }
// // sendPeerMessage
// }
class PeerConnection { class PeerConnection {
private remotePeerID: string; private remotePeerID: string;
// private signaler: Signaler; // private signaler: Signaler;
@@ -462,7 +415,7 @@ class PeerConnection {
if (!this.dataChannel) { if (!this.dataChannel) {
throw new Error(); throw new Error();
} }
console.log.apply(null, log("data channel is open!")); console.log.apply(null, log("data channel is open to: ", this.remotePeerID, " from: ", this.peerManager.peerID));
this.send({ type: "hello datachannel", from: this.peerManager.peerID, to: this.remotePeerID}); this.send({ type: "hello datachannel", from: this.peerManager.peerID, to: this.remotePeerID});
// this.dataChannel?.send(`{typeHello datachannel from: ${this.peerManager.peerID}`); // this.dataChannel?.send(`{typeHello datachannel from: ${this.peerManager.peerID}`);
@@ -480,6 +433,11 @@ class PeerConnection {
console.log.apply(null, log("->datachannel: ", e.data)) console.log.apply(null, log("->datachannel: ", e.data))
this.onMessage(e.data); this.onMessage(e.data);
} }
this.dataChannel.onclose = (e: Event) => {
console.log.apply(null, log(`datachannel from peer ${this.remotePeerID} closed, disconnecting peer.`));
this.peerManager.disconnectFromPeer(this.remotePeerID);
}
} }
async connect() { async connect() {
@@ -494,10 +452,10 @@ class PeerConnection {
} }
// When the connection is closed, tell the peer manager that this connection has gone away // When the connection is closed, tell the peer manager that this connection has gone away
if (this.rtcPeer.connectionState === "disconnected") { if (this.rtcPeer.connectionState === "failed") {
this.peerManager.onPeerDisconnected(this.remotePeerID); this.peerManager.onPeerDisconnected(this.remotePeerID);
// window.setTimeout(async () => { await this.peerManager.connectToPeer(this.remotePeerID) }, 10_000); // globalThis.setTimeout(async () => { await this.peerManager.connectToPeer(this.remotePeerID) }, 10_000);
} }
if (this.rtcPeer.connectionState === "connected") { if (this.rtcPeer.connectionState === "connected") {
@@ -640,8 +598,9 @@ class PeerConnection {
} }
async disconnect() { disconnect() {
this.rtcPeer?.close(); this.rtcPeer?.close();
this.rtcPeer = null;
} }
send(message: any) { send(message: any) {
@@ -715,166 +674,3 @@ class PeerConnection {
// this.peerManger.onMessage(this.remotePeerID, message); // this.peerManger.onMessage(this.remotePeerID, message);
} }
} }
// export class PeerConnection2 {
// id: string;
// private makingOffer:boolean = false;
// private ignoreOffer:boolean = false;
// rtcPeer: RTCPeerConnection;
// signaler:WebSocket;
// static config = {
// iceServers: [
// { urls: "stun:stun.l.google.com" },
// { urls: "stun:stun1.l.google.com" },
// { urls: "stun:stun2.l.google.com" },
// { urls: "stun:stun3.l.google.com" },
// { urls: "stun:stun4.l.google.com" },
// ],
// };
// constructor(remotePeerID: string, signaler:WebSocket) {
// this.id = remotePeerID;
// this.rtcPeer = new RTCPeerConnection(PeerConnection2.config);
// this.signaler = signaler;;
// this.rtcPeer.onnegotiationneeded = async () => {
// try {
// this.makingOffer = true;
// await this.rtcPeer.setLocalDescription();
// signaler.send(JSON.stringify({ description: this.rtcPeer.localDescription }));
// } catch (err) {
// console.error(err);
// } finally {
// this.makingOffer = false;
// }
// };
// this.rtcPeer.onicecandidate = ({ candidate }) => signaler.send(JSON.stringify({ candidate }));
// this.ignoreOffer = false;
// }
// onSignallerMessage = async ({ data: { description, candidate } }: MessageEvent) => {
// try {
// if (description) {
// // const offerCollision =
// // description.type === "offer" &&
// // (this.makingOffer || this.rtcPeer.signalingState !== "stable");
// // this.ignoreOffer = !polite && offerCollision;
// if (this.ignoreOffer) {
// return;
// }
// await this.rtcPeer.setRemoteDescription(description);
// if (description.type === "offer") {
// await this.rtcPeer.setLocalDescription();
// this.signaler.send(JSON.stringify({ description: this.rtcPeer.localDescription }));
// }
// } else if (candidate) {
// try {
// await this.rtcPeer.addIceCandidate(candidate);
// } catch (err) {
// if (!this.ignoreOffer) {
// throw err;
// }
// }
// }
// } catch (err) {
// console.error(err);
// }
// };
// }
// // const config = {
// // iceServers: [{ urls: "stun:stun.mystunserver.tld" }],
// // };
// // let polite = true;
// // const signaler = new SignalingChannel();
// // const signaler: any = {}
// // const rtcPeer = new RTCPeerConnection(config);
// // // const constraints = { audio: true, video: true };
// // const selfVideo = document.querySelector("video.selfview");
// // const remoteVideo = document.querySelector("video.remoteview");
// // async function start() {
// // try {
// // const stream = await navigator.mediaDevices.getUserMedia(constraints);
// // for (const track of stream.getTracks()) {
// // pc.addTrack(track, stream);
// // }
// // selfVideo.srcObject = stream;
// // } catch (err) {
// // console.error(err);
// // }
// // }
// // rtcPeer.ontrack = ({ track, streams }) => {
// // track.onunmute = () => {
// // if (remoteVideo.srcObject) {
// // return;
// // }
// // remoteVideo.srcObject = streams[0];
// // };
// // };
// // makingOffer = false;
// // rtcPeer.onnegotiationneeded = async () => {
// // try {
// // // makingOffer = true;
// // await rtcPeer.setLocalDescription();
// // signaler.send({ description: rtcPeer.localDescription });
// // } catch (err) {
// // console.error(err);
// // } finally {
// // makingOffer = false;
// // }
// // };
// // rtcPeer.onicecandidate = ({ candidate }) => signaler.send({ candidate });
// // let ignoreOffer = false;
// // signaler.onmessage = async ({ data: { description, candidate } }: MessageEvent) => {
// // try {
// // if (description) {
// // const offerCollision =
// // description.type === "offer" &&
// // // (makingOffer || rtcPeer.signalingState !== "stable");
// // ignoreOffer = !polite && offerCollision;
// // if (ignoreOffer) {
// // return;
// // }
// // await rtcPeer.setRemoteDescription(description);
// // if (description.type === "offer") {
// // await rtcPeer.setLocalDescription();
// // signaler.send({ description: rtcPeer.localDescription });
// // }
// // } else if (candidate) {
// // try {
// // await rtcPeer.addIceCandidate(candidate);
// // } catch (err) {
// // if (!ignoreOffer) {
// // throw err;
// // }
// // }
// // }
// // } catch (err) {
// // console.error(err);
// // }
// // };

2157
src/bootstrap_main.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,10 @@ let logLines: string[] = [];
let logLength = 100; let logLength = 100;
let logVisible = false; let logVisible = false;
export function logID(ID: string) {
return ID.substring(0, 5);
}
export function setLogVisibility(visible:boolean) { export function setLogVisibility(visible:boolean) {
logVisible = visible; logVisible = visible;
} }

View File

@@ -35,7 +35,7 @@ import { openDatabase, getData, addData, addDataArray, clearData, deleteData, me
import { generateID } from "IDUtils"; import { generateID } from "IDUtils";
import { PeerManager } from "PeerManager"; import { PeerManager } from "PeerManager";
import {log, renderLog, setLogVisibility} from "log" import {log, logID, renderLog, setLogVisibility} from "log"
// import {PeerConnection} from "webRTC"; // import {PeerConnection} from "webRTC";
@@ -109,12 +109,6 @@ function uuidToBase58(uuid: string): string {
return encodeBase58(bytes); return encodeBase58(bytes);
} }
function logID(ID: string) {
return ID.substring(0, 5);
}
// function log(message:string) { // function log(message:string) {
// console.log.apply(null, log(message); // console.log.apply(null, log(message);
// let log = document.getElementById("log"); // let log = document.getElementById("log");
@@ -175,8 +169,8 @@ window.addEventListener('scroll', () => {
// Check if scrolled to bottom // Check if scrolled to bottom
if (scrollPoint >= totalPageHeight) { if (scrollPoint >= totalPageHeight) {
console.log.apply(null, log('Scrolled to the bottom!')); // console.log.apply(null, log('Scrolled to the bottom!'));
console.log.apply(null, log(scrollPoint, totalPageHeight)); // console.log.apply(null, log(scrollPoint, totalPageHeight));
} }
}); });

1
static/main2.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

1623
static/main2.js Normal file

File diff suppressed because it is too large Load Diff

1
static/main2.js.map Normal file

File diff suppressed because one or more lines are too long