Compare commits
8 Commits
a96d7e28c8
...
b9ad1e3c8f
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ad1e3c8f | |||
| eba5413c36 | |||
| 63643f0f9a | |||
| ed9dfb990f | |||
| 83debdace8 | |||
| 2a71830258 | |||
| 234c45059f | |||
| d0fd041f7e |
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
user_data_dir="${1:-./profile}"
|
user_data_dir="${1:-./profile}"
|
||||||
user_id="${2:-b38b623c-c3fa-4351-9cab-50233c99fa4e}"
|
user_id="${2:-b38b623c-c3fa-4351-9cab-50233c99fa4e}"
|
||||||
chromium-browser \
|
chromium \
|
||||||
--disable-setuid-sandbox \
|
--disable-setuid-sandbox \
|
||||||
--disable-infobars \
|
--disable-infobars \
|
||||||
--no-first-run \
|
--no-first-run \
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ function connectWebsocket(request: Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function devServerWatchFiles() {
|
async function devServerWatchFiles() {
|
||||||
const watcher = Deno.watchFs("../static/");
|
const watcher = Deno.watchFs(["../static/", "../src/"]);
|
||||||
for await (const event of watcher) {
|
for await (const event of watcher) {
|
||||||
if (event.kind === "modify") {
|
if (event.kind === "modify") {
|
||||||
for (const path of event.paths) {
|
for (const path of event.paths) {
|
||||||
@@ -320,6 +320,10 @@ function handler(request: Request, info: any): Promise<Response> | Response {
|
|||||||
return new Response("Not serving video", { status: 404 });
|
return new Response("Not serving video", { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (url.pathname.includes("/src")) {
|
||||||
|
return serveFile(url.pathname);
|
||||||
|
}
|
||||||
|
|
||||||
if (url.pathname === "/") {
|
if (url.pathname === "/") {
|
||||||
return serveFile("/static/index.html")
|
return serveFile("/static/index.html")
|
||||||
}
|
}
|
||||||
@@ -357,7 +361,8 @@ async function main() {
|
|||||||
messageDispatch.set('peer_message', peerMessageHandler);
|
messageDispatch.set('peer_message', peerMessageHandler);
|
||||||
|
|
||||||
Deno.serve({
|
Deno.serve({
|
||||||
port: 6789,
|
hostname: "[::]",
|
||||||
|
port: 443,
|
||||||
cert: Deno.readTextFileSync("/etc/letsencrypt/live/ddln.app/fullchain.pem"),
|
cert: Deno.readTextFileSync("/etc/letsencrypt/live/ddln.app/fullchain.pem"),
|
||||||
key: Deno.readTextFileSync("/etc/letsencrypt/live/ddln.app/privkey.pem"),
|
key: Deno.readTextFileSync("/etc/letsencrypt/live/ddln.app/privkey.pem"),
|
||||||
}, handler);
|
}, handler);
|
||||||
|
|||||||
2
deno_bootstrap/compile.sh
Executable file
2
deno_bootstrap/compile.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
deno compile --allow-scripts --allow-all --no-check ddln_bootstrap.ts
|
||||||
BIN
deno_bootstrap/ddln_bootstrap
Executable file
BIN
deno_bootstrap/ddln_bootstrap
Executable file
Binary file not shown.
58
deno_bootstrap/ddln_bootstrap.ts
Normal file
58
deno_bootstrap/ddln_bootstrap.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { PeerManager } from "../src/PeerManager.ts";
|
||||||
|
import { generateID } from "IDUtils";
|
||||||
|
import nodeDataChannel from 'npm:node-datachannel';
|
||||||
|
import nodeDatachannelPolyfill from 'npm:node-datachannel/polyfill';
|
||||||
|
|
||||||
|
nodeDataChannel.initLogger('Info');
|
||||||
|
|
||||||
|
// import {RTCPeerConnection} from 'npm:node-datachannel/polyfill';
|
||||||
|
|
||||||
|
// deno install --allow-scripts=npm:node-datachannel --entrypoint ddln_bootstrap.ts
|
||||||
|
// constructor(userID: string, peerID: string, isBootstrapPeer: boolean) {
|
||||||
|
|
||||||
|
declare type ID = string;
|
||||||
|
|
||||||
|
interface Config {
|
||||||
|
userID:ID
|
||||||
|
peerID:ID
|
||||||
|
}
|
||||||
|
|
||||||
|
let configJSON;
|
||||||
|
let config:Config;
|
||||||
|
let configFilename = 'ddln_bootstrap_config.json';
|
||||||
|
try {
|
||||||
|
configJSON = Deno.readTextFileSync(configFilename);
|
||||||
|
config = JSON.parse(configJSON) as Config;
|
||||||
|
console.log("Loaded config file: ", config);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Config file not found, creating...");
|
||||||
|
const initialConfig = {
|
||||||
|
userID: generateID(),
|
||||||
|
peerID: generateID()
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(initialConfig);
|
||||||
|
|
||||||
|
Deno.writeTextFileSync(configFilename, JSON.stringify(initialConfig));
|
||||||
|
|
||||||
|
config = initialConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polyfill RTCPeerConnection and friends
|
||||||
|
const global = (globalThis as any);
|
||||||
|
for (const [functionName, func] of Object.entries(nodeDatachannelPolyfill)) {
|
||||||
|
global[functionName] = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("ddln bootstrap peer starting...");
|
||||||
|
|
||||||
|
// console.log(nodeDatachannelPolyfill);
|
||||||
|
|
||||||
|
const isBootstrapPeer = true;
|
||||||
|
const peerManager = new PeerManager(config.userID, config.peerID, isBootstrapPeer);
|
||||||
|
|
||||||
|
peerManager.registerRPC('announceUsers', (sendingPeerID: string, userIDs: string[]) => {
|
||||||
|
console.log(`Got announceUsers from ${sendingPeerID} ${userIDs}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
peerManager.connect();
|
||||||
11
deno_bootstrap/deno.json
Normal file
11
deno_bootstrap/deno.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"log": "../src/log.ts",
|
||||||
|
"IDUtils": "../src/IDUtils.ts",
|
||||||
|
"App": "../src/App.ts"
|
||||||
|
},
|
||||||
|
"nodeModulesDir": "auto",
|
||||||
|
"lock": {
|
||||||
|
"frozen": true
|
||||||
|
}
|
||||||
|
}
|
||||||
207
deno_bootstrap/deno.lock
generated
Normal file
207
deno_bootstrap/deno.lock
generated
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
{
|
||||||
|
"version": "5",
|
||||||
|
"specifiers": {
|
||||||
|
"npm:@types/node@*": "22.15.15",
|
||||||
|
"npm:node-datachannel@*": "0.26.0"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"@types/node@22.15.15": {
|
||||||
|
"integrity": "sha512-R5muMcZob3/Jjchn5LcO8jdKwSCbzqmPB6ruBxMcf9kbxtniZHP327s6C37iOfuw8mbKK3cAQa7sEl7afLrQ8A==",
|
||||||
|
"dependencies": [
|
||||||
|
"undici-types"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"base64-js@1.5.1": {
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||||
|
},
|
||||||
|
"bl@4.1.0": {
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"dependencies": [
|
||||||
|
"buffer",
|
||||||
|
"inherits",
|
||||||
|
"readable-stream"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"buffer@5.7.1": {
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"base64-js",
|
||||||
|
"ieee754"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chownr@1.1.4": {
|
||||||
|
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||||
|
},
|
||||||
|
"decompress-response@6.0.0": {
|
||||||
|
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"mimic-response"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"deep-extend@0.6.0": {
|
||||||
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||||
|
},
|
||||||
|
"detect-libc@2.0.4": {
|
||||||
|
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="
|
||||||
|
},
|
||||||
|
"end-of-stream@1.4.4": {
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"dependencies": [
|
||||||
|
"once"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"expand-template@2.0.3": {
|
||||||
|
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
|
||||||
|
},
|
||||||
|
"fs-constants@1.0.0": {
|
||||||
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
|
||||||
|
},
|
||||||
|
"github-from-package@0.0.0": {
|
||||||
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
|
||||||
|
},
|
||||||
|
"ieee754@1.2.1": {
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||||
|
},
|
||||||
|
"inherits@2.0.4": {
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
|
"ini@1.3.8": {
|
||||||
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||||
|
},
|
||||||
|
"mimic-response@3.1.0": {
|
||||||
|
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
|
||||||
|
},
|
||||||
|
"minimist@1.2.8": {
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
|
||||||
|
},
|
||||||
|
"mkdirp-classic@0.5.3": {
|
||||||
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||||
|
},
|
||||||
|
"napi-build-utils@2.0.0": {
|
||||||
|
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="
|
||||||
|
},
|
||||||
|
"node-abi@3.74.0": {
|
||||||
|
"integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
|
||||||
|
"dependencies": [
|
||||||
|
"semver"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node-datachannel@0.26.0": {
|
||||||
|
"integrity": "sha512-i9ZcFNszK1HeV6Ym2AoQokmRHE5jk0L5023CdRLzbQl8rqyjJkOGecMxEjo1WSjNHDvRO3I3ay9waclBdD3jRQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"prebuild-install"
|
||||||
|
],
|
||||||
|
"scripts": true
|
||||||
|
},
|
||||||
|
"once@1.4.0": {
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dependencies": [
|
||||||
|
"wrappy"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prebuild-install@7.1.3": {
|
||||||
|
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||||
|
"dependencies": [
|
||||||
|
"detect-libc",
|
||||||
|
"expand-template",
|
||||||
|
"github-from-package",
|
||||||
|
"minimist",
|
||||||
|
"mkdirp-classic",
|
||||||
|
"napi-build-utils",
|
||||||
|
"node-abi",
|
||||||
|
"pump",
|
||||||
|
"rc",
|
||||||
|
"simple-get",
|
||||||
|
"tar-fs",
|
||||||
|
"tunnel-agent"
|
||||||
|
],
|
||||||
|
"bin": true
|
||||||
|
},
|
||||||
|
"pump@3.0.2": {
|
||||||
|
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||||
|
"dependencies": [
|
||||||
|
"end-of-stream",
|
||||||
|
"once"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rc@1.2.8": {
|
||||||
|
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||||
|
"dependencies": [
|
||||||
|
"deep-extend",
|
||||||
|
"ini",
|
||||||
|
"minimist",
|
||||||
|
"strip-json-comments"
|
||||||
|
],
|
||||||
|
"bin": true
|
||||||
|
},
|
||||||
|
"readable-stream@3.6.2": {
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"dependencies": [
|
||||||
|
"inherits",
|
||||||
|
"string_decoder",
|
||||||
|
"util-deprecate"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"safe-buffer@5.2.1": {
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
|
},
|
||||||
|
"semver@7.7.1": {
|
||||||
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||||
|
"bin": true
|
||||||
|
},
|
||||||
|
"simple-concat@1.0.1": {
|
||||||
|
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
|
||||||
|
},
|
||||||
|
"simple-get@4.0.1": {
|
||||||
|
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
|
||||||
|
"dependencies": [
|
||||||
|
"decompress-response",
|
||||||
|
"once",
|
||||||
|
"simple-concat"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"string_decoder@1.3.0": {
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"dependencies": [
|
||||||
|
"safe-buffer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"strip-json-comments@2.0.1": {
|
||||||
|
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="
|
||||||
|
},
|
||||||
|
"tar-fs@2.1.2": {
|
||||||
|
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
|
||||||
|
"dependencies": [
|
||||||
|
"chownr",
|
||||||
|
"mkdirp-classic",
|
||||||
|
"pump",
|
||||||
|
"tar-stream"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tar-stream@2.2.0": {
|
||||||
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
|
"dependencies": [
|
||||||
|
"bl",
|
||||||
|
"end-of-stream",
|
||||||
|
"fs-constants",
|
||||||
|
"inherits",
|
||||||
|
"readable-stream"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tunnel-agent@0.6.0": {
|
||||||
|
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||||
|
"dependencies": [
|
||||||
|
"safe-buffer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"undici-types@6.21.0": {
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
|
||||||
|
},
|
||||||
|
"util-deprecate@1.0.2": {
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
|
},
|
||||||
|
"wrappy@1.0.2": {
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
deno_bootstrap/dev.sh
Executable file
2
deno_bootstrap/dev.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
deno --allow-scripts --allow-all ddln_bootstrap.ts
|
||||||
26
package-lock.json
generated
26
package-lock.json
generated
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "dandelion",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^5.5.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript": {
|
|
||||||
"version": "5.8.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
|
||||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc",
|
|
||||||
"tsserver": "bin/tsserver"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.17"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.5.4"
|
"typescript": "5.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/App.ts
90
src/App.ts
@@ -1,7 +1,7 @@
|
|||||||
import { generateID } from "IDUtils";
|
import { generateID } from "IDUtils";
|
||||||
import { PeerManager, PeerEventTypes } from "PeerManager";
|
import { PeerManager, PeerEventTypes } from "PeerManager";
|
||||||
import { Sync } from "Sync";
|
import { Sync } from "Sync";
|
||||||
import { openDatabase, getData, addData, addDataArray, clearData, deleteData, mergeDataArray, getAllData, checkPostIds, getAllIds, getPostsByIds } from "db";
|
import { openDatabase, getData, addData, addDataArray, clearData, deleteData, mergeDataArray, getAllData, checkPostIds, getAllIds, getPostsByIds, getPostForUser } from "db";
|
||||||
import { arrayBufferToBase64, compressString } from "dataUtils";
|
import { arrayBufferToBase64, compressString } from "dataUtils";
|
||||||
import { log, logID, renderLog, setLogVisibility } from "log"
|
import { log, logID, renderLog, setLogVisibility } from "log"
|
||||||
|
|
||||||
@@ -60,35 +60,35 @@ class StatusBar {
|
|||||||
peerStatus = new Map();
|
peerStatus = new Map();
|
||||||
headless = false;
|
headless = false;
|
||||||
|
|
||||||
setMessageHTML(html:string) {
|
setMessageHTML(html: string) {
|
||||||
let statusBarElement = document.getElementById('status_bar');
|
let statusBarElement = document.getElementById('status_bar');
|
||||||
|
|
||||||
if (!statusBarElement) {
|
if (!statusBarElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBarElement.innerHTML = html;
|
statusBarElement.innerHTML = html;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setHeadless(headless:boolean) {
|
setHeadless(headless: boolean) {
|
||||||
this.headless = headless;
|
this.headless = headless;
|
||||||
}
|
}
|
||||||
updatePeerMessage(peerID: string, message: string) {
|
updatePeerMessage(peerID: string, message: string) {
|
||||||
this.peerStatus.set(peerID, {message, data:this.peerStatus.get(peerID)?.data});
|
this.peerStatus.set(peerID, { message, data: this.peerStatus.get(peerID)?.data });
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePeerData(peerID:PeerID, data:any) {
|
updatePeerData(peerID: PeerID, data: any) {
|
||||||
this.peerStatus.set(peerID, {message:this.peerStatus.get(peerID)?.message, data:data});
|
this.peerStatus.set(peerID, { message: this.peerStatus.get(peerID)?.message, data: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePeerStatus(peerID:PeerID, message:string="", data={}) {
|
updatePeerStatus(peerID: PeerID, message: string = "", data = {}) {
|
||||||
this.peerStatus.set(peerID, {message, data});
|
this.peerStatus.set(peerID, { message, data });
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
getPeerData(peerID:PeerID) {
|
getPeerData(peerID: PeerID) {
|
||||||
let status = this.peerStatus.get(peerID);
|
let status = this.peerStatus.get(peerID);
|
||||||
if (status) {
|
if (status) {
|
||||||
return status.data;
|
return status.data;
|
||||||
@@ -105,8 +105,8 @@ class StatusBar {
|
|||||||
|
|
||||||
let newStatus = "";
|
let newStatus = "";
|
||||||
for (let [peerID, status] of this.peerStatus.entries()) {
|
for (let [peerID, status] of this.peerStatus.entries()) {
|
||||||
let statusBarItem = `<span>(${logID(peerID)} | ${status.message}) </span>`;
|
let statusBarItem = `<span>(${logID(peerID)} | ${status.message}) </span>`;
|
||||||
newStatus += statusBarItem;
|
newStatus += statusBarItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setMessageHTML(newStatus);
|
this.setMessageHTML(newStatus);
|
||||||
@@ -187,9 +187,9 @@ export class App {
|
|||||||
if (neededPostIDs.length > 0) {
|
if (neededPostIDs.length > 0) {
|
||||||
console.log.apply(null, log(`[app] Need (${neededPostIDs.length}) posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
console.log.apply(null, log(`[app] Need (${neededPostIDs.length}) posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
||||||
let neededPostCount = neededPostIDs.length;
|
let neededPostCount = neededPostIDs.length;
|
||||||
this.statusBar.updatePeerStatus(peerID, `need(${logID(userID)} | ${neededPostCount})`, {havePostCount:0, neededPostCount:neededPostCount});
|
this.statusBar.updatePeerStatus(peerID, `need(${logID(userID)} | ${neededPostCount})`, { havePostCount: 0, neededPostCount: neededPostCount });
|
||||||
|
|
||||||
let neededPosts = await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs);
|
await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log.apply(null, log(`[app] Don't need any posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
console.log.apply(null, log(`[app] Don't need any posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
||||||
@@ -236,15 +236,34 @@ export class App {
|
|||||||
for (let userID of userIDs) {
|
for (let userID of userIDs) {
|
||||||
// console.log.apply(null, log(`[app] announceUsers, got user:${userID} from peer ${sendingPeerID}`));
|
// console.log.apply(null, log(`[app] announceUsers, got user:${userID} from peer ${sendingPeerID}`));
|
||||||
this.sync.addUserPeer(userID, sendingPeerID);
|
this.sync.addUserPeer(userID, sendingPeerID);
|
||||||
if (!(this.sync.shouldSyncUserID(userID) || (this.router.route === App.Route.USER && userID === this.router.userID))) {
|
|
||||||
console.log.apply(null, log(`[app] announceUser_rpc_response skipping user[${logID(userID)}] from[${logID(sendingPeerID)}]`));
|
const isUserOrPostRoute = (this.router.route & (App.Route.USER | App.Route.POST)) !== 0;
|
||||||
continue;
|
|
||||||
|
if (isUserOrPostRoute) {
|
||||||
|
if (userID !== this.router.userID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!this.sync.shouldSyncUserID(userID)) {
|
||||||
|
console.log.apply(null, log(`[app] announceUser_rpc_response skipping user[${logID(userID)}] from[${logID(sendingPeerID)}]`));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log.apply(null, log(`[app] calling getPostIDsForUser for user [${logID(userID)}] on peer [${logID(sendingPeerID)}]`));
|
console.log.apply(null, log(`[app] calling getPostIDsForUser for user [${logID(userID)}] on peer [${logID(sendingPeerID)}]`));
|
||||||
this.statusBar.updatePeerStatus(sendingPeerID, `getPostIDs(${logID(userID)})⬆️`);
|
this.statusBar.updatePeerStatus(sendingPeerID, `getPostIDs(${logID(userID)})⬆️`);
|
||||||
|
|
||||||
let postIDs = await this.peerManager?.rpc.getPostIDsForUser(sendingPeerID, userID);
|
|
||||||
|
let postIDs = null;
|
||||||
|
if (this.router.route === App.Route.POST && this.router.userID == userID) {
|
||||||
|
postIDs = [this.router.postID];
|
||||||
|
} else {
|
||||||
|
postIDs = await this.peerManager?.rpc.getPostIDsForUser(sendingPeerID, userID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!postIDs) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
this.statusBar.updatePeerStatus(sendingPeerID, `syncing(${logID(userID)} ${postIDs.length})`);
|
this.statusBar.updatePeerStatus(sendingPeerID, `syncing(${logID(userID)} ${postIDs.length})`);
|
||||||
|
|
||||||
@@ -272,8 +291,9 @@ export class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let knownUsers = await this.sync.getKnownUsers();
|
let knownUsers = await this.sync.getKnownUsers();
|
||||||
this.peerManager.rpc.announceUsers(event.peerID, this.peerID, knownUsers);
|
|
||||||
// rpc saying what peers we have
|
// rpc saying what peers we have
|
||||||
|
this.peerManager.rpc.announceUsers(event.peerID, this.peerID, knownUsers);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.peerManager.addEventListener(PeerEventTypes.PEER_DISCONNECTED, async (event: any) => {
|
this.peerManager.addEventListener(PeerEventTypes.PEER_DISCONNECTED, async (event: any) => {
|
||||||
@@ -305,12 +325,14 @@ export class App {
|
|||||||
if (postIDs) {
|
if (postIDs) {
|
||||||
return postIDs;
|
return postIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
this.peerManager.registerRPC('getPostsForUser', async (requestingPeerID: string, userID: string, postIDs: string[]) => {
|
this.peerManager.registerRPC('getPostsForUser', async (requestingPeerID: string, userID: string, postIDs: string[]) => {
|
||||||
let posts = await this.sync.getPostsForUser(userID, postIDs);
|
let posts = await this.sync.getPostsForUser(userID, postIDs);
|
||||||
|
|
||||||
let i=0;
|
let i = 0;
|
||||||
for (let post of posts) {
|
for (let post of posts) {
|
||||||
console.log.apply(null, log(`[app] sendPostForUser sending post [${logID(post.post_id)}] to [${logID(requestingPeerID)}]`, userID, post.author, post.text));
|
console.log.apply(null, log(`[app] sendPostForUser sending post [${logID(post.post_id)}] to [${logID(requestingPeerID)}]`, userID, post.author, post.text));
|
||||||
|
|
||||||
@@ -1077,17 +1099,23 @@ export class App {
|
|||||||
this.timerStart();
|
this.timerStart();
|
||||||
let posts: StoragePost[] = [];
|
let posts: StoragePost[] = [];
|
||||||
|
|
||||||
// if (postID) {
|
if (postID) {
|
||||||
// posts = await gePostForUser(userID, postID);
|
const post = await getPostForUser(userID, postID);
|
||||||
// }
|
|
||||||
|
|
||||||
posts = await getData(userID, new Date(2022, 8), new Date());
|
posts = post ? [post] : [];
|
||||||
|
|
||||||
if (posts.length > 0) {
|
} else {
|
||||||
|
posts = await getData(userID, new Date(2022, 8), new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (posts?.length) {
|
||||||
console.log.apply(null, log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`));;
|
console.log.apply(null, log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`));;
|
||||||
return posts;
|
return posts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log.apply(null, log(`No posts found for userID:${userID}, postID:${postID}`));;
|
||||||
|
|
||||||
// posts = await createTestData2(userID);
|
// posts = await createTestData2(userID);
|
||||||
|
|
||||||
// log("Adding test data...");
|
// log("Adding test data...");
|
||||||
@@ -1601,11 +1629,11 @@ export class App {
|
|||||||
|
|
||||||
export namespace App {
|
export namespace App {
|
||||||
export enum Route {
|
export enum Route {
|
||||||
USER,
|
USER = 1,
|
||||||
POST,
|
POST = 2,
|
||||||
MEDIA,
|
MEDIA = 4,
|
||||||
GROUP,
|
GROUP = 8,
|
||||||
HOME,
|
HOME = 16,
|
||||||
CONNECT,
|
CONNECT = 32,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import { generateID } from "IDUtils";
|
import { generateID } from "IDUtils";
|
||||||
import { log, logID } from "log";
|
import { log, logID } from "log";
|
||||||
import { App } from "./App";
|
// import { App } from "./App";
|
||||||
|
|
||||||
// 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
|
||||||
@@ -26,7 +26,7 @@ export class PeerManager {
|
|||||||
searchQueryFunctions: Map<string, Function> = new Map();
|
searchQueryFunctions: Map<string, Function> = new Map();
|
||||||
RPC_remote: Map<string, Function> = new Map();
|
RPC_remote: Map<string, Function> = new Map();
|
||||||
rpc: { [key: string]: Function } = {};
|
rpc: { [key: string]: Function } = {};
|
||||||
isBootstrapPeer: boolean = false;
|
_isBootstrapPeer: boolean = false;
|
||||||
bootstrapPeerConnections: Map<string, PeerConnection> | null = null;
|
bootstrapPeerConnections: Map<string, PeerConnection> | null = null;
|
||||||
sessionID = generateID();
|
sessionID = generateID();
|
||||||
userID: string;
|
userID: string;
|
||||||
@@ -84,6 +84,11 @@ export class PeerManager {
|
|||||||
return peername;
|
return peername;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isBootstrapPeer(peerID: string) {
|
||||||
|
return this.bootstrapPeerIDs?.has(peerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
websocketSend(message: any) {
|
websocketSend(message: any) {
|
||||||
if (!this.websocket) {
|
if (!this.websocket) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@@ -118,7 +123,7 @@ export class PeerManager {
|
|||||||
|
|
||||||
if (message.type === "hello2") {
|
if (message.type === "hello2") {
|
||||||
|
|
||||||
if (!this.isBootstrapPeer && Array.isArray(message?.bootstrapPeers)) {
|
if (!this._isBootstrapPeer && Array.isArray(message?.bootstrapPeers)) {
|
||||||
this.bootstrapPeerIDs = new Set(message.bootstrapPeers);
|
this.bootstrapPeerIDs = new Set(message.bootstrapPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +149,7 @@ export class PeerManager {
|
|||||||
if (!peerConnection) {
|
if (!peerConnection) {
|
||||||
let remotePeerID = message.from;
|
let remotePeerID = message.from;
|
||||||
let newPeer = new PeerConnection(this, remotePeerID, this.websocketSendPeerMessage.bind(this));
|
let newPeer = new PeerConnection(this, remotePeerID, this.websocketSendPeerMessage.bind(this));
|
||||||
if (this.isBootstrapPeer) {
|
if (this._isBootstrapPeer) {
|
||||||
newPeer.setPolite(false);
|
newPeer.setPolite(false);
|
||||||
}
|
}
|
||||||
peerConnection = newPeer;
|
peerConnection = newPeer;
|
||||||
@@ -177,7 +182,7 @@ export class PeerManager {
|
|||||||
|
|
||||||
async onHello2Received(bootstrapPeerIDs: Set<string> | null) {
|
async onHello2Received(bootstrapPeerIDs: Set<string> | null) {
|
||||||
|
|
||||||
if (this.isBootstrapPeer) {
|
if (this._isBootstrapPeer) {
|
||||||
this.connectPromiseCallbacks?.resolve();
|
this.connectPromiseCallbacks?.resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -195,7 +200,7 @@ export class PeerManager {
|
|||||||
// this.bootstrapPeerConnection = await this.connectToPeer(peerID);
|
// this.bootstrapPeerConnection = await this.connectToPeer(peerID);
|
||||||
|
|
||||||
|
|
||||||
let bootstrapPeerConnectionPromise = new Promise( async (resolve, reject)=>{
|
let bootstrapPeerConnectionPromise = new Promise(async (resolve, reject) => {
|
||||||
let peerConnection = await this.connectToPeer(peerID);
|
let peerConnection = await this.connectToPeer(peerID);
|
||||||
if (!peerConnection) {
|
if (!peerConnection) {
|
||||||
reject(peerConnection);
|
reject(peerConnection);
|
||||||
@@ -221,7 +226,7 @@ export class PeerManager {
|
|||||||
peer_id: this.peerID,
|
peer_id: this.peerID,
|
||||||
session_id: this.sessionID,
|
session_id: this.sessionID,
|
||||||
// peer_name: app.peername,
|
// peer_name: app.peername,
|
||||||
is_bootstrap_peer: this.isBootstrapPeer,
|
is_bootstrap_peer: this._isBootstrapPeer,
|
||||||
// peer_description: this.rtcPeerDescription
|
// peer_description: this.rtcPeerDescription
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -246,7 +251,7 @@ export class PeerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(userID: string, peerID: string, isBootstrapPeer: boolean) {
|
constructor(userID: string, peerID: string, isBootstrapPeer: boolean) {
|
||||||
this.isBootstrapPeer = isBootstrapPeer;
|
this._isBootstrapPeer = isBootstrapPeer;
|
||||||
this.peers = new Map();
|
this.peers = new Map();
|
||||||
this.routingTable = new Map();
|
this.routingTable = new Map();
|
||||||
this.userID = userID;
|
this.userID = userID;
|
||||||
@@ -324,7 +329,7 @@ export class PeerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!this.isBootstrapPeer && numActive === 0) {
|
if (!this._isBootstrapPeer && numActive === 0) {
|
||||||
console.log.apply(null, log(`No peers connected, will attempt to reconnect in ${this.reconnectPeriod} seconds...`));
|
console.log.apply(null, log(`No peers connected, will attempt to reconnect in ${this.reconnectPeriod} seconds...`));
|
||||||
|
|
||||||
// Websocket reconnect
|
// Websocket reconnect
|
||||||
@@ -342,6 +347,13 @@ export class PeerManager {
|
|||||||
let output = `Current status:` + "\n" + `[${logID(this.peerID)}]${this.getPeername(this.peerID)}[local]` + "\n";
|
let output = `Current status:` + "\n" + `[${logID(this.peerID)}]${this.getPeername(this.peerID)}[local]` + "\n";
|
||||||
for (let [peerID, peer] of this.peers) {
|
for (let [peerID, peer] of this.peers) {
|
||||||
output += `[${logID(peerID)}]${peer.rtcPeer?.connectionState}:${this.getPeername(peerID)}${this.bootstrapPeerIDs?.has(peerID) ? "[Bootstrap]" : ""}` + "\n";
|
output += `[${logID(peerID)}]${peer.rtcPeer?.connectionState}:${this.getPeername(peerID)}${this.bootstrapPeerIDs?.has(peerID) ? "[Bootstrap]" : ""}` + "\n";
|
||||||
|
|
||||||
|
if (peer.rpcSuperlog) {
|
||||||
|
for (let transactionID of peer.pendingRPCs.keys()) {
|
||||||
|
output += `[${logID(transactionID)}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output += `numActivePeers: ${numActive}` + "\n";
|
output += `numActivePeers: ${numActive}` + "\n";
|
||||||
@@ -521,8 +533,8 @@ class PeerConnection {
|
|||||||
private ignoreOffer: boolean = false;
|
private ignoreOffer: boolean = false;
|
||||||
private isSettingRemoteAnswerPending: boolean = false;
|
private isSettingRemoteAnswerPending: boolean = false;
|
||||||
private polite = true;
|
private polite = true;
|
||||||
private webRTCSuperlog = false;
|
private webRTCSuperlog = true;
|
||||||
private dataChannelSuperlog = false;
|
private dataChannelSuperlog = true;
|
||||||
private chunkSize = (16 * 1024) - 100;
|
private chunkSize = (16 * 1024) - 100;
|
||||||
messageSuperlog: boolean = false;
|
messageSuperlog: boolean = false;
|
||||||
sendQueueSuperLog: boolean = false;
|
sendQueueSuperLog: boolean = false;
|
||||||
@@ -541,12 +553,7 @@ class PeerConnection {
|
|||||||
static config = {
|
static config = {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{ urls: "stun:ddln.app" },
|
{ urls: "stun:ddln.app" },
|
||||||
// { urls: "turn:ddln.app", username: "a", credential: "b" },
|
{ urls: "turn:ddln.app", username: "ddln1", credential: "ddln1" },
|
||||||
{ urls: "stun:stun.l.google.com" }, // keeping this for now as my STUN server is not returning ipv6
|
|
||||||
{ urls: "stun:stun1.l.google.com" },
|
|
||||||
{ urls: "stun:stun2.l.google.com" },
|
|
||||||
{ urls: "stun:stun3.l.google.com" },
|
|
||||||
{ urls: "stun:stun4.l.google.com" },
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
// longMessageQueue: string[] = [];
|
// longMessageQueue: string[] = [];
|
||||||
@@ -588,7 +595,7 @@ class PeerConnection {
|
|||||||
|
|
||||||
// console.log.apply(null, log([...this.peerManager.peers.keys()]));
|
// console.log.apply(null, log([...this.peerManager.peers.keys()]));
|
||||||
|
|
||||||
if (this.peerManager.isBootstrapPeer) {
|
if (this.peerManager._isBootstrapPeer) {
|
||||||
this.send({ type: 'initial_peers', from: this.peerManager.peerID, peers: [...this.peerManager.peers.keys()].filter(entry => entry !== this.remotePeerID) });
|
this.send({ type: 'initial_peers', from: this.peerManager.peerID, peers: [...this.peerManager.peers.keys()].filter(entry => entry !== this.remotePeerID) });
|
||||||
// this.dataChannel.send(JSON.stringify());
|
// this.dataChannel.send(JSON.stringify());
|
||||||
}
|
}
|
||||||
@@ -616,6 +623,11 @@ class PeerConnection {
|
|||||||
|
|
||||||
async connect() {
|
async connect() {
|
||||||
let connectionPromise = new Promise((resolve, reject) => { this.connectionPromise = { resolve, reject } });
|
let connectionPromise = new Promise((resolve, reject) => { this.connectionPromise = { resolve, reject } });
|
||||||
|
|
||||||
|
if (!(typeof RTCPeerConnection === "function")) {
|
||||||
|
throw new Error("RTCPeerConnection is not a function, exiting.");
|
||||||
|
}
|
||||||
|
|
||||||
this.rtcPeer = new RTCPeerConnection(PeerConnection.config);
|
this.rtcPeer = new RTCPeerConnection(PeerConnection.config);
|
||||||
|
|
||||||
this.rtcPeer.onconnectionstatechange = async (e: any) => {
|
this.rtcPeer.onconnectionstatechange = async (e: any) => {
|
||||||
@@ -720,7 +732,11 @@ class PeerConnection {
|
|||||||
|
|
||||||
async onWebsocketMessage(message: any) {
|
async onWebsocketMessage(message: any) {
|
||||||
if (message.type == "rtc_connect") {
|
if (message.type == "rtc_connect") {
|
||||||
this.rtcPeer?.setRemoteDescription(message.description);
|
try {
|
||||||
|
this.rtcPeer?.setRemoteDescription(message.description);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -734,7 +750,7 @@ class PeerConnection {
|
|||||||
|
|
||||||
|
|
||||||
if (!this.rtcPeer) {
|
if (!this.rtcPeer) {
|
||||||
throw new Error();
|
throw new Error("Unable to instantiate RTCPeerConnection, exiting.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let description = null;
|
let description = null;
|
||||||
@@ -760,7 +776,12 @@ class PeerConnection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isSettingRemoteAnswerPending = description.type == "answer";
|
this.isSettingRemoteAnswerPending = description.type == "answer";
|
||||||
await this.rtcPeer.setRemoteDescription(description);
|
|
||||||
|
try {
|
||||||
|
await this.rtcPeer.setRemoteDescription(description);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PeerConnection:setRemoteDescription:failed:", e, description);
|
||||||
|
}
|
||||||
this.isSettingRemoteAnswerPending = false;
|
this.isSettingRemoteAnswerPending = false;
|
||||||
if (description.type === "offer") {
|
if (description.type === "offer") {
|
||||||
await this.rtcPeer.setLocalDescription();
|
await this.rtcPeer.setLocalDescription();
|
||||||
@@ -769,9 +790,11 @@ class PeerConnection {
|
|||||||
} else if (candidate) {
|
} else if (candidate) {
|
||||||
try {
|
try {
|
||||||
await this.rtcPeer.addIceCandidate(candidate);
|
await this.rtcPeer.addIceCandidate(candidate);
|
||||||
} catch (err) {
|
} catch (e) {
|
||||||
if (!this.ignoreOffer) {
|
if (!this.ignoreOffer) {
|
||||||
throw err;
|
console.log("PeerConnection:addIceCandidate:failed:", e, candidate);
|
||||||
|
throw e;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,7 +892,7 @@ class PeerConnection {
|
|||||||
// Think about a timeout here to auto reject it after a while.
|
// Think about a timeout here to auto reject it after a while.
|
||||||
let promise = new Promise((resolve, reject) => {
|
let promise = new Promise((resolve, reject) => {
|
||||||
this.pendingRPCs.set(transactionID, { resolve, reject, functionName });
|
this.pendingRPCs.set(transactionID, { resolve, reject, functionName });
|
||||||
// setTimeout(() => reject("bad"), 1000);
|
setTimeout(() => reject(`function:${functionName}[${transactionID}] failed to resolve after 10 seconds.`), 10_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
let message = {
|
let message = {
|
||||||
@@ -909,6 +932,7 @@ class PeerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pendingRPC.resolve(message.response);
|
pendingRPC.resolve(message.response);
|
||||||
|
this.pendingRPCs.delete(message.transaction_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "rpc_call") {
|
if (type === "rpc_call") {
|
||||||
@@ -920,12 +944,6 @@ class PeerConnection {
|
|||||||
|
|
||||||
this.rpcSuperlog && console.log.apply(null, log(`[rpc] call: response:`, response));
|
this.rpcSuperlog && console.log.apply(null, log(`[rpc] call: response:`, response));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (response === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let responseMessage = { type: 'rpc_response', function_name: message.function_name, transaction_id: message.transaction_id, response: response };
|
let responseMessage = { type: 'rpc_response', function_name: message.function_name, transaction_id: message.transaction_id, response: response };
|
||||||
this.send(responseMessage);
|
this.send(responseMessage);
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ export class Sync {
|
|||||||
'e01eff89-5100-4b35-af4c-1c1bcb007dd0',
|
'e01eff89-5100-4b35-af4c-1c1bcb007dd0',
|
||||||
'194696a2-d850-4bb0-98f7-47416b3d1662',
|
'194696a2-d850-4bb0-98f7-47416b3d1662',
|
||||||
'f6b21eb1-a0ff-435b-8efc-6a3dd70c0dca',
|
'f6b21eb1-a0ff-435b-8efc-6a3dd70c0dca',
|
||||||
'dd1d92aa-aa24-4166-a925-94ba072a9048'
|
'dd1d92aa-aa24-4166-a925-94ba072a9048',
|
||||||
|
'290dbb4f-6ce1-491a-b90d-51d8efcd3d60'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
getFollowing(userID: string): string[] {
|
getFollowing(userID: string): string[] {
|
||||||
@@ -161,6 +162,7 @@ export class Sync {
|
|||||||
following.push(...[
|
following.push(...[
|
||||||
'b38b623c-c3fa-4351-9cab-50233c99fa4e', // Rob
|
'b38b623c-c3fa-4351-9cab-50233c99fa4e', // Rob
|
||||||
'05a495a0-0dd8-4186-94c3-b8309ba6fc4c', // Martin
|
'05a495a0-0dd8-4186-94c3-b8309ba6fc4c', // Martin
|
||||||
|
'622ecc28-2eff-44b9-b89d-fdea7c8dd2d5', // Hazel
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export async function compressString(input: string) {
|
|||||||
const compressedArray = await new Response(compressionStream.readable).arrayBuffer();
|
const compressedArray = await new Response(compressionStream.readable).arrayBuffer();
|
||||||
|
|
||||||
// Convert the compressed data to a Uint8Array
|
// Convert the compressed data to a Uint8Array
|
||||||
return new Uint8Array(compressedArray);
|
return compressedArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base58 character set
|
// Base58 character set
|
||||||
|
|||||||
35
src/db.ts
35
src/db.ts
@@ -198,15 +198,28 @@ export async function clearData(userID: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO - this function can return before the data is stored!
|
||||||
export async function addDataArray(userID: string, array: any[]): Promise<void> {
|
export async function addDataArray(userID: string, array: any[]): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { db, transaction, store } = await getDBTransactionStore(userID, "readwrite");
|
const { db, transaction, store } = await getDBTransactionStore(userID, "readwrite");
|
||||||
|
|
||||||
|
|
||||||
transaction.onerror = (event: Event) => {
|
|
||||||
console.error('Error in adding data:', event);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
let completionPromise = new Promise<void>((resolve, reject) => {
|
||||||
|
transaction.oncomplete = (event: Event) => {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
transaction.onerror = (event: Event) => {
|
||||||
|
console.error('Error in adding data:', event);
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let count = 0;
|
// let count = 0;
|
||||||
|
|
||||||
array.reverse();
|
array.reverse();
|
||||||
@@ -230,6 +243,8 @@ export async function addDataArray(userID: string, array: any[]): Promise<void>
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return completionPromise;
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in opening database:', error);
|
console.error('Error in opening database:', error);
|
||||||
@@ -342,7 +357,21 @@ export async function mergeDataArray(userID: string, array: any[]): Promise<void
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getPostForUser(userID: string, postID: string): Promise<any | undefined> {
|
export async function getPostForUser(userID: string, postID: string): Promise<any | undefined> {
|
||||||
|
const { store } = await getDBTransactionStore(userID);
|
||||||
|
const index = store.index("postIDIndex");
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const getPostRequest = index.get(postID);
|
||||||
|
|
||||||
|
getPostRequest.onsuccess = () => {
|
||||||
|
resolve(getPostRequest.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
getPostRequest.onerror = () => {
|
||||||
|
console.error('Transaction failed:', getPostRequest.error?.message);
|
||||||
|
reject(getPostRequest.error);
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { generateID } from "IDUtils";
|
import { generateID } from "IDUtils";
|
||||||
import { PeerManager, PeerEventTypes } from "PeerManager";
|
import { PeerManager, PeerEventTypes } from "PeerManager";
|
||||||
import { Sync } from "Sync";
|
import { Sync } from "Sync";
|
||||||
import { openDatabase, getData, addData, deleteData, getAllData } from "db";
|
import { openDatabase, getData, addData, deleteData, getAllData, getPostForUser } from "db";
|
||||||
import { arrayBufferToBase64, compressString } from "dataUtils";
|
import { arrayBufferToBase64, compressString } from "dataUtils";
|
||||||
import { log, logID, renderLog, setLogVisibility } from "log";
|
import { log, logID, renderLog, setLogVisibility } from "log";
|
||||||
class Post {
|
class Post {
|
||||||
@@ -139,7 +139,7 @@ export class App {
|
|||||||
console.log.apply(null, log(`[app] Need (${neededPostIDs.length}) posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
console.log.apply(null, log(`[app] Need (${neededPostIDs.length}) posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
||||||
let neededPostCount = neededPostIDs.length;
|
let neededPostCount = neededPostIDs.length;
|
||||||
this.statusBar.updatePeerStatus(peerID, `need(${logID(userID)} | ${neededPostCount})`, { havePostCount: 0, neededPostCount: neededPostCount });
|
this.statusBar.updatePeerStatus(peerID, `need(${logID(userID)} | ${neededPostCount})`, { havePostCount: 0, neededPostCount: neededPostCount });
|
||||||
let neededPosts = await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs);
|
await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log.apply(null, log(`[app] Don't need any posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
console.log.apply(null, log(`[app] Don't need any posts for user ${logID(userID)} from peer ${logID(peerID)}`));
|
||||||
@@ -172,13 +172,30 @@ export class App {
|
|||||||
for (let userID of userIDs) {
|
for (let userID of userIDs) {
|
||||||
// console.log.apply(null, log(`[app] announceUsers, got user:${userID} from peer ${sendingPeerID}`));
|
// console.log.apply(null, log(`[app] announceUsers, got user:${userID} from peer ${sendingPeerID}`));
|
||||||
this.sync.addUserPeer(userID, sendingPeerID);
|
this.sync.addUserPeer(userID, sendingPeerID);
|
||||||
if (!(this.sync.shouldSyncUserID(userID) || (this.router.route === App.Route.USER && userID === this.router.userID))) {
|
const isUserOrPostRoute = (this.router.route & (App.Route.USER | App.Route.POST)) !== 0;
|
||||||
console.log.apply(null, log(`[app] announceUser_rpc_response skipping user[${logID(userID)}] from[${logID(sendingPeerID)}]`));
|
if (isUserOrPostRoute) {
|
||||||
continue;
|
if (userID !== this.router.userID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.sync.shouldSyncUserID(userID)) {
|
||||||
|
console.log.apply(null, log(`[app] announceUser_rpc_response skipping user[${logID(userID)}] from[${logID(sendingPeerID)}]`));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log.apply(null, log(`[app] calling getPostIDsForUser for user [${logID(userID)}] on peer [${logID(sendingPeerID)}]`));
|
console.log.apply(null, log(`[app] calling getPostIDsForUser for user [${logID(userID)}] on peer [${logID(sendingPeerID)}]`));
|
||||||
this.statusBar.updatePeerStatus(sendingPeerID, `getPostIDs(${logID(userID)})⬆️`);
|
this.statusBar.updatePeerStatus(sendingPeerID, `getPostIDs(${logID(userID)})⬆️`);
|
||||||
let postIDs = await this.peerManager?.rpc.getPostIDsForUser(sendingPeerID, userID);
|
let postIDs = null;
|
||||||
|
if (this.router.route === App.Route.POST && this.router.userID == userID) {
|
||||||
|
postIDs = [this.router.postID];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
postIDs = await this.peerManager?.rpc.getPostIDsForUser(sendingPeerID, userID);
|
||||||
|
}
|
||||||
|
if (!postIDs) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this.statusBar.updatePeerStatus(sendingPeerID, `syncing(${logID(userID)} ${postIDs.length})`);
|
this.statusBar.updatePeerStatus(sendingPeerID, `syncing(${logID(userID)} ${postIDs.length})`);
|
||||||
console.log.apply(null, log(`[app] Got (${postIDs.length}) post IDs for user [${logID(userID)}] from peer [${logID(sendingPeerID)}]`));
|
console.log.apply(null, log(`[app] Got (${postIDs.length}) post IDs for user [${logID(userID)}] from peer [${logID(sendingPeerID)}]`));
|
||||||
this.addPostIDsToSyncQueue(userID, sendingPeerID, postIDs);
|
this.addPostIDsToSyncQueue(userID, sendingPeerID, postIDs);
|
||||||
@@ -199,8 +216,8 @@ export class App {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let knownUsers = await this.sync.getKnownUsers();
|
let knownUsers = await this.sync.getKnownUsers();
|
||||||
this.peerManager.rpc.announceUsers(event.peerID, this.peerID, knownUsers);
|
|
||||||
// rpc saying what peers we have
|
// rpc saying what peers we have
|
||||||
|
this.peerManager.rpc.announceUsers(event.peerID, this.peerID, knownUsers);
|
||||||
});
|
});
|
||||||
this.peerManager.addEventListener(PeerEventTypes.PEER_DISCONNECTED, async (event) => {
|
this.peerManager.addEventListener(PeerEventTypes.PEER_DISCONNECTED, async (event) => {
|
||||||
console.log.apply(null, log(`[app]: peer disconnected:${event.peerID}`));
|
console.log.apply(null, log(`[app]: peer disconnected:${event.peerID}`));
|
||||||
@@ -223,6 +240,7 @@ export class App {
|
|||||||
if (postIDs) {
|
if (postIDs) {
|
||||||
return postIDs;
|
return postIDs;
|
||||||
}
|
}
|
||||||
|
return [];
|
||||||
});
|
});
|
||||||
this.peerManager.registerRPC('getPostsForUser', async (requestingPeerID, userID, postIDs) => {
|
this.peerManager.registerRPC('getPostsForUser', async (requestingPeerID, userID, postIDs) => {
|
||||||
let posts = await this.sync.getPostsForUser(userID, postIDs);
|
let posts = await this.sync.getPostsForUser(userID, postIDs);
|
||||||
@@ -798,15 +816,20 @@ export class App {
|
|||||||
async loadPostsFromStorage(userID, postID) {
|
async loadPostsFromStorage(userID, postID) {
|
||||||
this.timerStart();
|
this.timerStart();
|
||||||
let posts = [];
|
let posts = [];
|
||||||
// if (postID) {
|
if (postID) {
|
||||||
// posts = await gePostForUser(userID, postID);
|
const post = await getPostForUser(userID, postID);
|
||||||
// }
|
posts = post ? [post] : [];
|
||||||
posts = await getData(userID, new Date(2022, 8), new Date());
|
}
|
||||||
if (posts.length > 0) {
|
else {
|
||||||
|
posts = await getData(userID, new Date(2022, 8), new Date());
|
||||||
|
}
|
||||||
|
if (posts?.length) {
|
||||||
console.log.apply(null, log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`));
|
console.log.apply(null, log(`Loaded ${posts.length} posts in ${this.timerDelta().toFixed(2)}ms`));
|
||||||
;
|
;
|
||||||
return posts;
|
return posts;
|
||||||
}
|
}
|
||||||
|
console.log.apply(null, log(`No posts found for userID:${userID}, postID:${postID}`));
|
||||||
|
;
|
||||||
// posts = await createTestData2(userID);
|
// posts = await createTestData2(userID);
|
||||||
// log("Adding test data...");
|
// log("Adding test data...");
|
||||||
// addDataArray(userID, posts);
|
// addDataArray(userID, posts);
|
||||||
@@ -1174,12 +1197,13 @@ export class App {
|
|||||||
(function (App) {
|
(function (App) {
|
||||||
let Route;
|
let Route;
|
||||||
(function (Route) {
|
(function (Route) {
|
||||||
Route[Route["USER"] = 0] = "USER";
|
Route[Route["USER"] = 1] = "USER";
|
||||||
Route[Route["POST"] = 1] = "POST";
|
Route[Route["POST"] = 2] = "POST";
|
||||||
Route[Route["MEDIA"] = 2] = "MEDIA";
|
Route[Route["MEDIA"] = 4] = "MEDIA";
|
||||||
Route[Route["GROUP"] = 3] = "GROUP";
|
Route[Route["GROUP"] = 8] = "GROUP";
|
||||||
Route[Route["HOME"] = 4] = "HOME";
|
Route[Route["HOME"] = 16] = "HOME";
|
||||||
Route[Route["CONNECT"] = 5] = "CONNECT";
|
Route[Route["CONNECT"] = 32] = "CONNECT";
|
||||||
})(Route = App.Route || (App.Route = {}));
|
})(Route = App.Route || (App.Route = {}));
|
||||||
})(App || (App = {}));
|
})(App || (App = {}));
|
||||||
;
|
;
|
||||||
|
//# sourceMappingURL=App.js.map
|
||||||
1
static/App.js.map
Normal file
1
static/App.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -7,3 +7,4 @@ export function generateID() {
|
|||||||
}
|
}
|
||||||
return uuidv4();
|
return uuidv4();
|
||||||
}
|
}
|
||||||
|
//# sourceMappingURL=IDUtils.js.map
|
||||||
1
static/IDUtils.js.map
Normal file
1
static/IDUtils.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"IDUtils.js","sourceRoot":"","sources":["../src/IDUtils.ts"],"names":[],"mappings":"AAAA,SAAS,MAAM;IACX,OAAO,sCAAsC,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAM,EAAE,EAAE,CACvE,CAAC,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAChF,CAAC;AACN,CAAC;AAED,MAAM,UAAU,UAAU;IACtB,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IACpC,CAAC;IAED,OAAO,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
||||||
@@ -33,6 +33,9 @@ export class PeerManager {
|
|||||||
let peername = `${adjective}_${snake}`;
|
let peername = `${adjective}_${snake}`;
|
||||||
return peername;
|
return peername;
|
||||||
}
|
}
|
||||||
|
isBootstrapPeer(peerID) {
|
||||||
|
return this.bootstrapPeerIDs?.has(peerID);
|
||||||
|
}
|
||||||
websocketSend(message) {
|
websocketSend(message) {
|
||||||
if (!this.websocket) {
|
if (!this.websocket) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@@ -60,7 +63,7 @@ export class PeerManager {
|
|||||||
}
|
}
|
||||||
this.messageSuperlog && console.log.apply(null, log("->signaler:", message));
|
this.messageSuperlog && console.log.apply(null, log("->signaler:", message));
|
||||||
if (message.type === "hello2") {
|
if (message.type === "hello2") {
|
||||||
if (!this.isBootstrapPeer && Array.isArray(message?.bootstrapPeers)) {
|
if (!this._isBootstrapPeer && Array.isArray(message?.bootstrapPeers)) {
|
||||||
this.bootstrapPeerIDs = new Set(message.bootstrapPeers);
|
this.bootstrapPeerIDs = new Set(message.bootstrapPeers);
|
||||||
}
|
}
|
||||||
this.onHello2Received(this.bootstrapPeerIDs);
|
this.onHello2Received(this.bootstrapPeerIDs);
|
||||||
@@ -79,7 +82,7 @@ export class PeerManager {
|
|||||||
if (!peerConnection) {
|
if (!peerConnection) {
|
||||||
let remotePeerID = message.from;
|
let remotePeerID = message.from;
|
||||||
let newPeer = new PeerConnection(this, remotePeerID, this.websocketSendPeerMessage.bind(this));
|
let newPeer = new PeerConnection(this, remotePeerID, this.websocketSendPeerMessage.bind(this));
|
||||||
if (this.isBootstrapPeer) {
|
if (this._isBootstrapPeer) {
|
||||||
newPeer.setPolite(false);
|
newPeer.setPolite(false);
|
||||||
}
|
}
|
||||||
peerConnection = newPeer;
|
peerConnection = newPeer;
|
||||||
@@ -105,7 +108,7 @@ export class PeerManager {
|
|||||||
return newPeer;
|
return newPeer;
|
||||||
}
|
}
|
||||||
async onHello2Received(bootstrapPeerIDs) {
|
async onHello2Received(bootstrapPeerIDs) {
|
||||||
if (this.isBootstrapPeer) {
|
if (this._isBootstrapPeer) {
|
||||||
this.connectPromiseCallbacks?.resolve();
|
this.connectPromiseCallbacks?.resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -139,7 +142,7 @@ export class PeerManager {
|
|||||||
peer_id: this.peerID,
|
peer_id: this.peerID,
|
||||||
session_id: this.sessionID,
|
session_id: this.sessionID,
|
||||||
// peer_name: app.peername,
|
// peer_name: app.peername,
|
||||||
is_bootstrap_peer: this.isBootstrapPeer,
|
is_bootstrap_peer: this._isBootstrapPeer,
|
||||||
// peer_description: this.rtcPeerDescription
|
// peer_description: this.rtcPeerDescription
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -164,7 +167,7 @@ export class PeerManager {
|
|||||||
this.searchQueryFunctions = new Map();
|
this.searchQueryFunctions = new Map();
|
||||||
this.RPC_remote = new Map();
|
this.RPC_remote = new Map();
|
||||||
this.rpc = {};
|
this.rpc = {};
|
||||||
this.isBootstrapPeer = false;
|
this._isBootstrapPeer = false;
|
||||||
this.bootstrapPeerConnections = null;
|
this.bootstrapPeerConnections = null;
|
||||||
this.sessionID = generateID();
|
this.sessionID = generateID();
|
||||||
this.websocket = null;
|
this.websocket = null;
|
||||||
@@ -188,7 +191,7 @@ export class PeerManager {
|
|||||||
this.animals = ['shrew', 'jerboa', 'lemur', 'weasel', 'possum', 'possum', 'marmoset', 'planigale', 'mole', 'narwhal'];
|
this.animals = ['shrew', 'jerboa', 'lemur', 'weasel', 'possum', 'possum', 'marmoset', 'planigale', 'mole', 'narwhal'];
|
||||||
this.adjectives = ['snazzy', 'whimsical', 'jazzy', 'bonkers', 'wobbly', 'spiffy', 'chirpy', 'zesty', 'bubbly', 'perky', 'sassy'];
|
this.adjectives = ['snazzy', 'whimsical', 'jazzy', 'bonkers', 'wobbly', 'spiffy', 'chirpy', 'zesty', 'bubbly', 'perky', 'sassy'];
|
||||||
this.snakes = ['mamba', 'cobra', 'python', 'viper', 'krait', 'sidewinder', 'constrictor', 'boa', 'asp', 'anaconda', 'krait'];
|
this.snakes = ['mamba', 'cobra', 'python', 'viper', 'krait', 'sidewinder', 'constrictor', 'boa', 'asp', 'anaconda', 'krait'];
|
||||||
this.isBootstrapPeer = isBootstrapPeer;
|
this._isBootstrapPeer = isBootstrapPeer;
|
||||||
this.peers = new Map();
|
this.peers = new Map();
|
||||||
this.routingTable = new Map();
|
this.routingTable = new Map();
|
||||||
this.userID = userID;
|
this.userID = userID;
|
||||||
@@ -244,7 +247,7 @@ export class PeerManager {
|
|||||||
}
|
}
|
||||||
numActive++;
|
numActive++;
|
||||||
}
|
}
|
||||||
if (!this.isBootstrapPeer && numActive === 0) {
|
if (!this._isBootstrapPeer && numActive === 0) {
|
||||||
console.log.apply(null, log(`No peers connected, will attempt to reconnect in ${this.reconnectPeriod} seconds...`));
|
console.log.apply(null, log(`No peers connected, will attempt to reconnect in ${this.reconnectPeriod} seconds...`));
|
||||||
// Websocket reconnect
|
// Websocket reconnect
|
||||||
if (this.websocket?.readyState === WebSocket.OPEN) {
|
if (this.websocket?.readyState === WebSocket.OPEN) {
|
||||||
@@ -257,6 +260,11 @@ export class PeerManager {
|
|||||||
let output = `Current status:` + "\n" + `[${logID(this.peerID)}]${this.getPeername(this.peerID)}[local]` + "\n";
|
let output = `Current status:` + "\n" + `[${logID(this.peerID)}]${this.getPeername(this.peerID)}[local]` + "\n";
|
||||||
for (let [peerID, peer] of this.peers) {
|
for (let [peerID, peer] of this.peers) {
|
||||||
output += `[${logID(peerID)}]${peer.rtcPeer?.connectionState}:${this.getPeername(peerID)}${this.bootstrapPeerIDs?.has(peerID) ? "[Bootstrap]" : ""}` + "\n";
|
output += `[${logID(peerID)}]${peer.rtcPeer?.connectionState}:${this.getPeername(peerID)}${this.bootstrapPeerIDs?.has(peerID) ? "[Bootstrap]" : ""}` + "\n";
|
||||||
|
if (peer.rpcSuperlog) {
|
||||||
|
for (let transactionID of peer.pendingRPCs.keys()) {
|
||||||
|
output += `[${logID(transactionID)}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output += `numActivePeers: ${numActive}` + "\n";
|
output += `numActivePeers: ${numActive}` + "\n";
|
||||||
console.log.apply(null, log(output));
|
console.log.apply(null, log(output));
|
||||||
@@ -386,8 +394,8 @@ class PeerConnection {
|
|||||||
this.ignoreOffer = false;
|
this.ignoreOffer = false;
|
||||||
this.isSettingRemoteAnswerPending = false;
|
this.isSettingRemoteAnswerPending = false;
|
||||||
this.polite = true;
|
this.polite = true;
|
||||||
this.webRTCSuperlog = false;
|
this.webRTCSuperlog = true;
|
||||||
this.dataChannelSuperlog = false;
|
this.dataChannelSuperlog = true;
|
||||||
this.chunkSize = (16 * 1024) - 100;
|
this.chunkSize = (16 * 1024) - 100;
|
||||||
this.messageSuperlog = false;
|
this.messageSuperlog = false;
|
||||||
this.sendQueueSuperLog = false;
|
this.sendQueueSuperLog = false;
|
||||||
@@ -421,7 +429,7 @@ class PeerConnection {
|
|||||||
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}`);
|
||||||
// console.log.apply(null, log([...this.peerManager.peers.keys()]));
|
// console.log.apply(null, log([...this.peerManager.peers.keys()]));
|
||||||
if (this.peerManager.isBootstrapPeer) {
|
if (this.peerManager._isBootstrapPeer) {
|
||||||
this.send({ type: 'initial_peers', from: this.peerManager.peerID, peers: [...this.peerManager.peers.keys()].filter(entry => entry !== this.remotePeerID) });
|
this.send({ type: 'initial_peers', from: this.peerManager.peerID, peers: [...this.peerManager.peers.keys()].filter(entry => entry !== this.remotePeerID) });
|
||||||
// this.dataChannel.send(JSON.stringify());
|
// this.dataChannel.send(JSON.stringify());
|
||||||
}
|
}
|
||||||
@@ -442,6 +450,9 @@ class PeerConnection {
|
|||||||
}
|
}
|
||||||
async connect() {
|
async connect() {
|
||||||
let connectionPromise = new Promise((resolve, reject) => { this.connectionPromise = { resolve, reject }; });
|
let connectionPromise = new Promise((resolve, reject) => { this.connectionPromise = { resolve, reject }; });
|
||||||
|
if (!(typeof RTCPeerConnection === "function")) {
|
||||||
|
throw new Error("RTCPeerConnection is not a function, exiting.");
|
||||||
|
}
|
||||||
this.rtcPeer = new RTCPeerConnection(PeerConnection.config);
|
this.rtcPeer = new RTCPeerConnection(PeerConnection.config);
|
||||||
this.rtcPeer.onconnectionstatechange = async (e) => {
|
this.rtcPeer.onconnectionstatechange = async (e) => {
|
||||||
this.webRTCSuperlog && console.log.apply(null, log(`rtcPeer: onconnectionstatechange: ${this.rtcPeer?.connectionState}: ${this.remotePeerID}`));
|
this.webRTCSuperlog && console.log.apply(null, log(`rtcPeer: onconnectionstatechange: ${this.rtcPeer?.connectionState}: ${this.remotePeerID}`));
|
||||||
@@ -519,14 +530,19 @@ class PeerConnection {
|
|||||||
}
|
}
|
||||||
async onWebsocketMessage(message) {
|
async onWebsocketMessage(message) {
|
||||||
if (message.type == "rtc_connect") {
|
if (message.type == "rtc_connect") {
|
||||||
this.rtcPeer?.setRemoteDescription(message.description);
|
try {
|
||||||
|
this.rtcPeer?.setRemoteDescription(message.description);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// /*
|
// /*
|
||||||
// let ignoreOffer = false;
|
// let ignoreOffer = false;
|
||||||
// let isSettingRemoteAnswerPending = false;
|
// let isSettingRemoteAnswerPending = false;
|
||||||
// signaler.onmessage = async ({ data: { description, candidate } }) => {
|
// signaler.onmessage = async ({ data: { description, candidate } }) => {
|
||||||
if (!this.rtcPeer) {
|
if (!this.rtcPeer) {
|
||||||
throw new Error();
|
throw new Error("Unable to instantiate RTCPeerConnection, exiting.");
|
||||||
}
|
}
|
||||||
let description = null;
|
let description = null;
|
||||||
if (message.type == "rtc_description") {
|
if (message.type == "rtc_description") {
|
||||||
@@ -547,7 +563,12 @@ class PeerConnection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isSettingRemoteAnswerPending = description.type == "answer";
|
this.isSettingRemoteAnswerPending = description.type == "answer";
|
||||||
await this.rtcPeer.setRemoteDescription(description);
|
try {
|
||||||
|
await this.rtcPeer.setRemoteDescription(description);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log("PeerConnection:setRemoteDescription:failed:", e, description);
|
||||||
|
}
|
||||||
this.isSettingRemoteAnswerPending = false;
|
this.isSettingRemoteAnswerPending = false;
|
||||||
if (description.type === "offer") {
|
if (description.type === "offer") {
|
||||||
await this.rtcPeer.setLocalDescription();
|
await this.rtcPeer.setLocalDescription();
|
||||||
@@ -558,9 +579,10 @@ class PeerConnection {
|
|||||||
try {
|
try {
|
||||||
await this.rtcPeer.addIceCandidate(candidate);
|
await this.rtcPeer.addIceCandidate(candidate);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (e) {
|
||||||
if (!this.ignoreOffer) {
|
if (!this.ignoreOffer) {
|
||||||
throw err;
|
console.log("PeerConnection:addIceCandidate:failed:", e, candidate);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -632,7 +654,7 @@ class PeerConnection {
|
|||||||
// Think about a timeout here to auto reject it after a while.
|
// Think about a timeout here to auto reject it after a while.
|
||||||
let promise = new Promise((resolve, reject) => {
|
let promise = new Promise((resolve, reject) => {
|
||||||
this.pendingRPCs.set(transactionID, { resolve, reject, functionName });
|
this.pendingRPCs.set(transactionID, { resolve, reject, functionName });
|
||||||
// setTimeout(() => reject("bad"), 1000);
|
setTimeout(() => reject(`function:${functionName}[${transactionID}] failed to resolve after 10 seconds.`), 10000);
|
||||||
});
|
});
|
||||||
let message = {
|
let message = {
|
||||||
type: "rpc_call",
|
type: "rpc_call",
|
||||||
@@ -661,14 +683,12 @@ class PeerConnection {
|
|||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
pendingRPC.resolve(message.response);
|
pendingRPC.resolve(message.response);
|
||||||
|
this.pendingRPCs.delete(message.transaction_id);
|
||||||
}
|
}
|
||||||
if (type === "rpc_call") {
|
if (type === "rpc_call") {
|
||||||
this.rpcSuperlog && console.log.apply(null, log(`[${logID(this.remotePeerID)}]->[rpc][${logID(this.peerManager.peerID)}] call: `, message.function_name, message.transaction_id, JSON.stringify(message.args, null, 2)));
|
this.rpcSuperlog && console.log.apply(null, log(`[${logID(this.remotePeerID)}]->[rpc][${logID(this.peerManager.peerID)}] call: `, message.function_name, message.transaction_id, JSON.stringify(message.args, null, 2)));
|
||||||
let response = await this.peerManager.callFromRemote(message.function_name, message.args);
|
let response = await this.peerManager.callFromRemote(message.function_name, message.args);
|
||||||
this.rpcSuperlog && console.log.apply(null, log(`[rpc] call: response:`, response));
|
this.rpcSuperlog && console.log.apply(null, log(`[rpc] call: response:`, response));
|
||||||
if (response === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let responseMessage = { type: 'rpc_response', function_name: message.function_name, transaction_id: message.transaction_id, response: response };
|
let responseMessage = { type: 'rpc_response', function_name: message.function_name, transaction_id: message.transaction_id, response: response };
|
||||||
this.send(responseMessage);
|
this.send(responseMessage);
|
||||||
}
|
}
|
||||||
@@ -707,11 +727,7 @@ class PeerConnection {
|
|||||||
PeerConnection.config = {
|
PeerConnection.config = {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{ urls: "stun:ddln.app" },
|
{ urls: "stun:ddln.app" },
|
||||||
// { urls: "turn:ddln.app", username: "a", credential: "b" },
|
{ urls: "turn:ddln.app", username: "ddln1", credential: "ddln1" },
|
||||||
{ urls: "stun:stun.l.google.com" }, // keeping this for now as my STUN server is not returning ipv6
|
|
||||||
{ urls: "stun:stun1.l.google.com" },
|
|
||||||
{ urls: "stun:stun2.l.google.com" },
|
|
||||||
{ urls: "stun:stun3.l.google.com" },
|
|
||||||
{ urls: "stun:stun4.l.google.com" },
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
//# sourceMappingURL=PeerManager.js.map
|
||||||
1
static/PeerManager.js.map
Normal file
1
static/PeerManager.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -44,7 +44,8 @@ export class Sync {
|
|||||||
'e01eff89-5100-4b35-af4c-1c1bcb007dd0',
|
'e01eff89-5100-4b35-af4c-1c1bcb007dd0',
|
||||||
'194696a2-d850-4bb0-98f7-47416b3d1662',
|
'194696a2-d850-4bb0-98f7-47416b3d1662',
|
||||||
'f6b21eb1-a0ff-435b-8efc-6a3dd70c0dca',
|
'f6b21eb1-a0ff-435b-8efc-6a3dd70c0dca',
|
||||||
'dd1d92aa-aa24-4166-a925-94ba072a9048'
|
'dd1d92aa-aa24-4166-a925-94ba072a9048',
|
||||||
|
'290dbb4f-6ce1-491a-b90d-51d8efcd3d60'
|
||||||
]);
|
]);
|
||||||
// async getPostIdsForUserHandler(data: any) {
|
// async getPostIdsForUserHandler(data: any) {
|
||||||
// let message = data.message;
|
// let message = data.message;
|
||||||
@@ -144,6 +145,7 @@ export class Sync {
|
|||||||
following.push(...[
|
following.push(...[
|
||||||
'b38b623c-c3fa-4351-9cab-50233c99fa4e', // Rob
|
'b38b623c-c3fa-4351-9cab-50233c99fa4e', // Rob
|
||||||
'05a495a0-0dd8-4186-94c3-b8309ba6fc4c', // Martin
|
'05a495a0-0dd8-4186-94c3-b8309ba6fc4c', // Martin
|
||||||
|
'622ecc28-2eff-44b9-b89d-fdea7c8dd2d5', // Hazel
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return following;
|
return following;
|
||||||
@@ -224,3 +226,4 @@ export class Sync {
|
|||||||
await mergeDataArray(userID, [post]);
|
await mergeDataArray(userID, [post]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//# sourceMappingURL=Sync.js.map
|
||||||
1
static/Sync.js.map
Normal file
1
static/Sync.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -34,5 +34,28 @@
|
|||||||
"protocol": "web+ddln",
|
"protocol": "web+ddln",
|
||||||
"url": "/%s"
|
"url": "/%s"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"share_target": {
|
||||||
|
"action": "/share-target",
|
||||||
|
"method": "POST",
|
||||||
|
"enctype": "multipart/form-data",
|
||||||
|
"params": {
|
||||||
|
"title": "name",
|
||||||
|
"text": "text",
|
||||||
|
"url": "link",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"name": "photos",
|
||||||
|
"accept": [
|
||||||
|
"image/svg+xml",
|
||||||
|
".svg",
|
||||||
|
".jpg",
|
||||||
|
".jpeg",
|
||||||
|
".png",
|
||||||
|
".gif"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ export async function compressString(input) {
|
|||||||
// Read the compressed data from the stream
|
// Read the compressed data from the stream
|
||||||
const compressedArray = await new Response(compressionStream.readable).arrayBuffer();
|
const compressedArray = await new Response(compressionStream.readable).arrayBuffer();
|
||||||
// Convert the compressed data to a Uint8Array
|
// Convert the compressed data to a Uint8Array
|
||||||
return new Uint8Array(compressedArray);
|
return compressedArray;
|
||||||
}
|
}
|
||||||
// Base58 character set
|
// Base58 character set
|
||||||
// const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
// const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
||||||
@@ -69,3 +69,4 @@ export async function compressString(input) {
|
|||||||
// const bytes = uuidToBytes(uuid);
|
// const bytes = uuidToBytes(uuid);
|
||||||
// return encodeBase58(bytes);
|
// return encodeBase58(bytes);
|
||||||
// }
|
// }
|
||||||
|
//# sourceMappingURL=dataUtils.js.map
|
||||||
1
static/dataUtils.js.map
Normal file
1
static/dataUtils.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"dataUtils.js","sourceRoot":"","sources":["../src/dataUtils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAiB,EAAE,IAAI,GAAG,0BAA0B;IAC7F,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,UAAU,EAAE,EAAE;YAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YACpC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAmB;IAC3D,IAAI,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,MAAM,oBAAoB,CAAC,KAAK,CAAY,CAAA,CAAC,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC,CAAC;AAC5G,CAAC;AAED,6DAA6D;AAC7D,wFAAwF;AACxF,oDAAoD;AACpD,wBAAwB;AACxB,IAAI;AAEJ,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IAChD,qCAAqC;IACrC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7C,6BAA6B;IAC7B,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;IAEtD,sCAAsC;IACtC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACzB,MAAM,CAAC,KAAK,EAAE,CAAC;IAEf,2CAA2C;IAC3C,MAAM,eAAe,GAAG,MAAM,IAAI,QAAQ,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAErF,8CAA8C;IAC9C,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,uBAAuB;AACvB,wFAAwF;AACxF,kBAAkB;AAClB,kBAAkB;AAClB,sDAAsD;AACtD,eAAe;AACf,wBAAwB;AAExB,iCAAiC;AACjC,oBAAoB;AACpB,gDAAgD;AAChD,iCAAiC;AACjC,gCAAgC;AAChC,wCAAwC;AACxC,QAAQ;AACR,0BAA0B;AAC1B,iCAAiC;AACjC,wCAAwC;AACxC,QAAQ;AACR,MAAM;AAEN,qBAAqB;AACrB,4CAA4C;AAC5C,wCAAwC;AACxC,MAAM;AAEN,iCAAiC;AACjC,iCAAiC;AACjC,2BAA2B;AAC3B,8CAA8C;AAC9C,eAAe;AACf,eAAe;AACf,QAAQ;AACR,MAAM;AAEN,mBAAmB;AACnB,IAAI;AAEJ,4BAA4B;AAC5B,gDAAgD;AAChD,qCAAqC;AACrC,gCAAgC;AAChC,IAAI"}
|
||||||
27
static/db.js
27
static/db.js
@@ -147,12 +147,19 @@ export async function clearData(userID) {
|
|||||||
console.error('Error in opening database:', error);
|
console.error('Error in opening database:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO - this function can return before the data is stored!
|
||||||
export async function addDataArray(userID, array) {
|
export async function addDataArray(userID, array) {
|
||||||
try {
|
try {
|
||||||
const { db, transaction, store } = await getDBTransactionStore(userID, "readwrite");
|
const { db, transaction, store } = await getDBTransactionStore(userID, "readwrite");
|
||||||
transaction.onerror = (event) => {
|
let completionPromise = new Promise((resolve, reject) => {
|
||||||
console.error('Error in adding data:', event);
|
transaction.oncomplete = (event) => {
|
||||||
};
|
resolve();
|
||||||
|
};
|
||||||
|
transaction.onerror = (event) => {
|
||||||
|
console.error('Error in adding data:', event);
|
||||||
|
reject();
|
||||||
|
};
|
||||||
|
});
|
||||||
// let count = 0;
|
// let count = 0;
|
||||||
array.reverse();
|
array.reverse();
|
||||||
for (let data of array) {
|
for (let data of array) {
|
||||||
@@ -170,6 +177,7 @@ export async function addDataArray(userID, array) {
|
|||||||
// console.log(`Added ${count} posts...`);
|
// console.log(`Added ${count} posts...`);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
return completionPromise;
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Error in opening database:', error);
|
console.error('Error in opening database:', error);
|
||||||
@@ -260,6 +268,18 @@ export async function mergeDataArray(userID, array) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function getPostForUser(userID, postID) {
|
export async function getPostForUser(userID, postID) {
|
||||||
|
const { store } = await getDBTransactionStore(userID);
|
||||||
|
const index = store.index("postIDIndex");
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const getPostRequest = index.get(postID);
|
||||||
|
getPostRequest.onsuccess = () => {
|
||||||
|
resolve(getPostRequest.result);
|
||||||
|
};
|
||||||
|
getPostRequest.onerror = () => {
|
||||||
|
console.error('Transaction failed:', getPostRequest.error?.message);
|
||||||
|
reject(getPostRequest.error);
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
export async function getData(userID, lowerID, upperID) {
|
export async function getData(userID, lowerID, upperID) {
|
||||||
const { store } = await getDBTransactionStore(userID);
|
const { store } = await getDBTransactionStore(userID);
|
||||||
@@ -345,3 +365,4 @@ export async function getPostsByIds(userID, postIDs) {
|
|||||||
}
|
}
|
||||||
return posts; // Return the array of posts
|
return posts; // Return the array of posts
|
||||||
}
|
}
|
||||||
|
//# sourceMappingURL=db.js.map
|
||||||
File diff suppressed because one or more lines are too long
@@ -37,3 +37,4 @@ export function log(...args) {
|
|||||||
renderLog();
|
renderLog();
|
||||||
return [logLine]; // [...args];
|
return [logLine]; // [...args];
|
||||||
}
|
}
|
||||||
|
//# sourceMappingURL=log.js.map
|
||||||
1
static/log.js.map
Normal file
1
static/log.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAa,EAAE,CAAC;AAC5B,IAAI,SAAS,GAAG,GAAG,CAAC;AACpB,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC5C,UAAU,GAAG,OAAO,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,EAAE,CAAC;IACpB,CAAC;IACD,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,GAAG,IAAW;IAChC,wBAAwB;IAExB,IAAI,OAAO,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE,KAAK,CAAC;IACvD,KAAK,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,YAAY,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,YAAY,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3G,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,YAAY,GAAG,WAAW,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAE9B,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAChC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,SAAS,EAAE,CAAC;IAEZ,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA,aAAa;AAChC,CAAC"}
|
||||||
@@ -1577,3 +1577,4 @@ class App {
|
|||||||
})(App || (App = {}));
|
})(App || (App = {}));
|
||||||
let app = new App();
|
let app = new App();
|
||||||
window.addEventListener("load", app.main.bind(app));
|
window.addEventListener("load", app.main.bind(app));
|
||||||
|
//# sourceMappingURL=main.js.map
|
||||||
@@ -39,3 +39,4 @@ window.addEventListener('scroll', () => {
|
|||||||
});
|
});
|
||||||
let app = new App();
|
let app = new App();
|
||||||
window.addEventListener("load", app.main.bind(app));
|
window.addEventListener("load", app.main.bind(app));
|
||||||
|
//# sourceMappingURL=main2.js.map
|
||||||
File diff suppressed because one or more lines are too long
@@ -121,3 +121,4 @@ addEventListener("message", async (e) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
//# sourceMappingURL=sw.js.map
|
||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"sw.js","sourceRoot":"","sources":["../src/sw.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"sw.js","sourceRoot":"","sources":["../src/sw.ts"],"names":[],"mappings":"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"}
|
||||||
1
static/tests.js.map
Normal file
1
static/tests.js.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"tests.js","sourceRoot":"","sources":["../src/tests.ts"],"names":[],"mappings":";AAAA,kDAAkD;AAGlD,oBAAoB;AACpB,6BAA6B;AAC7B,4BAA4B;AAE5B,yCAAyC;AACzC,gFAAgF;AAChF,0CAA0C;AAE1C,6DAA6D;AAC7D,QAAQ;AACR,IAAI"}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
"sourceMap": false, /* Generates corresponding '.map' file. */
|
"sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
"outDir": "./static", /* Redirect output structure to the directory. */
|
"outDir": "./static", /* Redirect output structure to the directory. */
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
|||||||
83
webRTC.js
83
webRTC.js
@@ -1,83 +0,0 @@
|
|||||||
// https://web.dev/articles/webrtc-basics
|
|
||||||
|
|
||||||
// handles JSON.stringify/parse
|
|
||||||
|
|
||||||
class SignalingChannel {
|
|
||||||
send(message) {
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function createPeerConnection(targetPeer) {
|
|
||||||
|
|
||||||
const signaling = new SignalingChannel();
|
|
||||||
|
|
||||||
// const constraints = {audio: true, video: true};
|
|
||||||
const configuration = { iceServers: [{ urls: 'stun:stunserver2024.stunprotocol.org' }] };
|
|
||||||
const peerConnection = new RTCPeerConnection(configuration);
|
|
||||||
const sendChannel = peerConnection.createDataChannel('default');
|
|
||||||
|
|
||||||
|
|
||||||
// Send any ice candidates to the other peer.
|
|
||||||
peerConnection.onicecandidate = ({ candidate }) => signaling.send({ candidate });
|
|
||||||
|
|
||||||
// Let the "negotiationneeded" event trigger offer generation.
|
|
||||||
peerConnection.onnegotiationneeded = async () => {
|
|
||||||
try {
|
|
||||||
await peerConnection.setLocalDescription(await peerConnection.createOffer());
|
|
||||||
// Send the offer to the other peer.
|
|
||||||
signaling.send({ desc: peerConnection.localDescription });
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// // Once remote track media arrives, show it in remote video element.
|
|
||||||
// peerConnection.ontrack = (event) => {
|
|
||||||
// // Don't set srcObject again if it is already set.
|
|
||||||
// if (remoteView.srcObject) return;
|
|
||||||
// remoteView.srcObject = event.streams[0];
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Call start() to initiate.
|
|
||||||
async function start() {
|
|
||||||
// try {
|
|
||||||
// Get local stream, show it in self-view, and add it to be sent.
|
|
||||||
// const stream =
|
|
||||||
// await navigator.mediaDevices.getUserMedia(constraints);
|
|
||||||
// stream.getTracks().forEach((track) =>
|
|
||||||
// peerConnection.addTrack(track, stream));
|
|
||||||
// selfView.srcObject = stream;
|
|
||||||
// } catch (err) {
|
|
||||||
// console.error(err);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
signaling.onmessage = async ({ desc, candidate }) => {
|
|
||||||
try {
|
|
||||||
if (desc) {
|
|
||||||
// If you get an offer, you need to reply with an answer.
|
|
||||||
if (desc.type === 'offer') {
|
|
||||||
await peerConnection.setRemoteDescription(desc);
|
|
||||||
// const stream =
|
|
||||||
// await navigator.mediaDevices.getUserMedia(constraints);
|
|
||||||
// stream.getTracks().forEach((track) =>
|
|
||||||
// peerConnection.addTrack(track, stream));
|
|
||||||
await peerConnection.setLocalDescription(await peerConnection.createAnswer());
|
|
||||||
signaling.send({ desc: peerConnection.localDescription });
|
|
||||||
} else if (desc.type === 'answer') {
|
|
||||||
await peerConnection.setRemoteDescription(desc);
|
|
||||||
} else {
|
|
||||||
console.log('Unsupported SDP type.');
|
|
||||||
}
|
|
||||||
} else if (candidate) {
|
|
||||||
await peerConnection.addIceCandidate(candidate);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"webRTC.js","sourceRoot":"","sources":["src/webRTC.ts"],"names":[],"mappings":"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"}
|
|
||||||
Reference in New Issue
Block a user