Merge pull request #223 from MotorTruck1221/wisp

TLS
This commit is contained in:
rift 2024-03-07 12:18:28 -06:00 committed by GitHub
commit 6c1ce96036
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 2033 additions and 1809 deletions

View file

@ -3,11 +3,12 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="/epoxy/index.js" defer></script>
<script src="/uv/uv.bundle.js" defer></script> <script src="/uv/uv.bundle.js" defer></script>
<script src="/uv/uv.config.js" defer></script> <script src="/uv/uv.config.js" defer></script>
<script src="/dynamic/dynamic.config.js" defer></script> <script src="/dynamic/dynamic.config.js" defer></script>
<script src="/localforage/localforage.min.js" defer></script> <script src="/localforage/localforage.min.js" defer></script>
<script> <script defer>
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
window.addEventListener("load", () => { window.addEventListener("load", () => {
navigator.serviceWorker.register("/sw.js", { navigator.serviceWorker.register("/sw.js", {
@ -27,11 +28,13 @@
) )
window.location.href = window.location.href; window.location.href = window.location.href;
</script> </script>
<!-- ONLY ENABLE IF USING MASQR!
<script> <script>
if (!localStorage["auth"] && new URL(document.all.rcheck.href).password) { if (!localStorage["auth"] && new URL(document.all.rcheck.href).password) {
window.location.reload(); window.location.reload();
localStorage["auth"] = 1; localStorage["auth"] = 1;
} }
</script> </script>
-->
</body> </body>
</html> </html>

View file

@ -14,45 +14,49 @@
"@fastify/compress": "^6.5.0", "@fastify/compress": "^6.5.0",
"@fastify/cookie": "^9.3.1", "@fastify/cookie": "^9.3.1",
"@fastify/static": "^6.12.0", "@fastify/static": "^6.12.0",
"@mercuryworkshop/bare-mux": "^1.0.4",
"@mercuryworkshop/epoxy-transport": "^1.0.2",
"@nebula-services/bare-server-node": "2.0.1-patch.1", "@nebula-services/bare-server-node": "2.0.1-patch.1",
"@nebula-services/dynamic": "0.7.2-patch.2", "@nebula-services/dynamic": "0.7.2-patch.2",
"@nebula-services/ultraviolet": "1.0.1-1.patch.7", "@titaniumnetwork-dev/ultraviolet": "^3.0.0",
"@types/express": "^4.17.21",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"classnames": "^2.3.2", "classnames": "^2.5.1",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"express": "^4.18.2", "express": "^4.18.3",
"fastify": "^4.25.1", "fastify": "^4.26.2",
"framer-motion": "^10.16.16", "framer-motion": "^10.18.0",
"i18next": "^23.7.9", "i18next": "^23.10.0",
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"million": "^2.6.4", "million": "^2.6.4",
"preact": "^10.13.1", "preact": "^10.19.6",
"preact-iso": "^2.3.2", "preact-iso": "^2.4.0",
"preact-render-to-string": "^6.3.1", "preact-render-to-string": "^6.4.0",
"preact-router": "^4.1.2", "preact-router": "^4.1.2",
"rammerhead": "https://github.com/NebulaServices/rammerhead/releases/download/rammerhead-1.2.41-nebula.8/rammerhead-1.2.41-nebula.7.tgz", "rammerhead": "https://github.com/NebulaServices/rammerhead/releases/download/rammerhead-1.2.41-nebula.8/rammerhead-1.2.41-nebula.7.tgz",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-i18next": "^13.5.0", "react-i18next": "^13.5.0",
"react-icons": "^4.12.0", "react-icons": "^4.12.0",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"tsx": "^4.7.0", "tsx": "^4.7.1",
"wisp-server-node": "^1.0.1" "wisp-server-node": "^1.0.1",
"ws": "^8.16.0"
}, },
"devDependencies": { "devDependencies": {
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.8.1",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.18",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"eslint": "^8.55.0", "eslint": "^8.57.0",
"eslint-config-preact": "^1.3.0", "eslint-config-preact": "^1.3.0",
"postcss": "^8.4.32", "postcss": "^8.4.35",
"prettier": "^3.1.1", "prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.9", "prettier-plugin-tailwindcss": "^0.5.11",
"tailwindcss": "^3.3.6", "tailwindcss": "^3.4.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"vite": "^5.0.9", "vite": "^5.1.4",
"vite-plugin-static-copy": "^1.0.0" "vite-plugin-static-copy": "^1.0.1"
} }
} }

2814
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
importScripts("/epoxy/index.js");
importScripts("/uv/uv.bundle.js"); importScripts("/uv/uv.bundle.js");
importScripts("/uv/uv.config.js"); importScripts("/uv/uv.config.js");
importScripts(__uv$config.sw || "/uv/uv.sw.js"); importScripts(__uv$config.sw || "/uv/uv.sw.js");

View file

@ -9,7 +9,8 @@ import path from "path";
import fs from "fs"; import fs from "fs";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import wisp from "wisp-server-node"; import wisp from "wisp-server-node";
import { Socket } from "net"; import { Request, Response } from "express";
import { Socket, Head } from "ws";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
@ -47,7 +48,7 @@ app.use(
app.use(cookieParser()); app.use(cookieParser());
// Congratulations! Masqr failed to validate, this is either your first visit or you're a FRAUD // Congratulations! Masqr failed to validate, this is either your first visit or you're a FRAUD
async function MasqFail(req, res) { async function MasqFail(req: Request, res: Response) {
if (!req.headers.host) { if (!req.headers.host) {
// no bitch still using HTTP/1.0 go away // no bitch still using HTTP/1.0 go away
return; return;
@ -124,7 +125,7 @@ async function MasqFail(req, res) {
app.use(express.static("dist")); app.use(express.static("dist"));
app.get("/search=:query", async (req, res) => { app.get("/search=:query", async (req: Request, res: Response) => {
const { query } = req.params; const { query } = req.params;
const response = await fetch( const response = await fetch(
@ -142,7 +143,7 @@ const server = createServer();
const bare = createBareServer("/bare/"); const bare = createBareServer("/bare/");
server.on("request", (req, res) => { server.on("request", (req: Request, res: Response) => {
if (bare.shouldRoute(req)) { if (bare.shouldRoute(req)) {
bare.routeRequest(req, res); bare.routeRequest(req, res);
} else if (shouldRouteRh(req)) { } else if (shouldRouteRh(req)) {
@ -152,13 +153,13 @@ server.on("request", (req, res) => {
} }
}); });
server.on("upgrade", (req, socket, head) => { server.on("upgrade", (req: Request, socket: Socket, head: Head) => {
if (bare.shouldRoute(req)) { if (bare.shouldRoute(req)) {
bare.routeUpgrade(req, socket, head); bare.routeUpgrade(req, socket, head);
} else if (shouldRouteRh(req)) { } else if (shouldRouteRh(req)) {
routeRhUpgrade(req, socket, head); routeRhUpgrade(req, socket, head);
} else { } else if (req.url.endsWith("/wisp/")) {
wisp.routeRequest(req, socket as Socket, head); wisp.routeRequest(req, socket, head);
} }
}); });
@ -170,11 +171,11 @@ function shouldRouteRh(req) {
); );
} }
function routeRhRequest(req, res) { function routeRhRequest(req: Request, res: Response) {
rh.emit("request", req, res); rh.emit("request", req, res);
} }
function routeRhUpgrade(req, socket, head) { function routeRhUpgrade(req: Request, socket: Socket, head: Head) {
rh.emit("upgrade", req, socket, head); rh.emit("upgrade", req, socket, head);
} }

View file

@ -2,7 +2,9 @@ import { motion } from "framer-motion";
import { tabContentVariant, settingsPageVariant } from "./Variants"; import { tabContentVariant, settingsPageVariant } from "./Variants";
import Dropdown from "./Dropdown"; import Dropdown from "./Dropdown";
import BareInput from "./BareInput"; import BareInput from "./BareInput";
import WispInput from "./WispInput";
import ProxyInput from "./ProxyInput"; import ProxyInput from "./ProxyInput";
import { changeTransport } from "../../util/transports";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
const Proxy = ({ id, active }) => { const Proxy = ({ id, active }) => {
@ -27,6 +29,13 @@ const Proxy = ({ id, active }) => {
{ id: "https://bing.com/search?q=%s", label: "Bing" } { id: "https://bing.com/search?q=%s", label: "Bing" }
]; ];
const wispUrl =
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/";
//libcurl can be added here when it's stable
const transports = [{ id: "epoxy", label: "Epoxy" }];
return ( return (
<motion.div <motion.div
role="tabpanel" role="tabpanel"
@ -84,6 +93,29 @@ const Proxy = ({ id, active }) => {
</div> </div>
<BareInput placeholder="/bare/" storageKey="bare" /> <BareInput placeholder="/bare/" storageKey="bare" />
</div> </div>
<div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div className="p-2 text-3xl font-bold text-input-text">
Wisp Server
</div>
<div className="text-md p-4 font-bold text-input-text">
Enter the url of a Wisp server
</div>
<WispInput placeholder={wispUrl} />
</div>
<div className="flex h-64 w-80 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div className="p-2 text-3xl font-bold text-input-text">
Transport
</div>
<div className="text-md p-4 font-bold text-input-text">
Select the transport to use
</div>
<Dropdown
storageKey="transport"
options={transports}
refresh={false}
onChange={(value) => changeTransport(value, wispUrl)}
/>
</div>
<div className="flex h-96 w-96 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center"> <div className="flex h-96 w-96 flex-col flex-wrap content-center items-center rounded-lg border border-input-border-color bg-lighter p-2 text-center">
<div className="p-2 text-3xl font-bold text-input-text"> <div className="p-2 text-3xl font-bold text-input-text">
{t("settings.httpProxy.title")} {t("settings.httpProxy.title")}

View file

@ -0,0 +1,66 @@
import { useState, useEffect } from "preact/hooks";
import { useTranslation } from "react-i18next";
import { changeTransport } from "../../util/transports";
import { ToastContainer, toast } from "react-toastify";
interface WispInputProps {
placeholder: string;
}
function WispInput(props: WispInputProps) {
const { t } = useTranslation();
const value =
localStorage.getItem("wispUrl") ||
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/";
const [inputValue, setInputValue] = useState(value);
function validateUrl(url: string) {
let finalUrl = url;
if (finalUrl.startsWith("http://")) {
finalUrl = finalUrl.replace("http://", "ws://");
} else if (finalUrl.startsWith("https://")) {
finalUrl = finalUrl.replace("https://", "wss://");
} else if (finalUrl === "" || finalUrl === null || finalUrl === undefined) {
finalUrl =
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/";
}
return finalUrl;
}
function handleChange() {
const url = validateUrl(
(document.getElementById("wispinput") as HTMLInputElement).value
);
localStorage.setItem("wispUrl", url);
changeTransport(localStorage.getItem("transport") || "epoxy", url);
}
return (
<div>
<ToastContainer position="bottom-right" theme="dark" />
<div className="flex flex-col items-center">
<input
type="text"
placeholder={props.placeholder}
value={inputValue}
onKeyPress={(event) => {
if (event.key === "Enter") {
handleChange();
}
}}
id="wispinput"
className="font-roboto flex h-14 w-56 flex-row rounded-2xl border border-input-border-color bg-input p-4 text-center text-xl text-input-text"
/>
<div
className="font-roboto mt-2 flex h-4 w-36 cursor-pointer flex-row items-center justify-center rounded-xl border border-input-border-color bg-input p-5 text-center text-lg text-input-text"
onClick={handleChange}
>
Select
</div>
</div>
</div>
);
}
export default WispInput;

54
src/util/transports.ts Normal file
View file

@ -0,0 +1,54 @@
import {
SetTransport,
registerRemoteListener
} from "@mercuryworkshop/bare-mux";
declare global {
interface Window {
BareMux: any;
p: any;
}
}
function changeTransport(transport: string, wispUrl: string) {
switch (transport) {
case "epoxy":
localStorage.setItem("transport", "epoxy");
SetTransport("EpxMod.EpoxyClient", { wisp: wispUrl });
break;
//libcurl when supported can be easily added here
//and stuff like bare-as-module3 COULD also be added
default:
SetTransport("EpxMod.EpoxyClient", { wisp: wispUrl });
break;
}
}
function getTransport() {
return localStorage.getItem("transport") || "epoxy";
}
function restartTransport() {
changeTransport(
getTransport(),
localStorage.getItem("wispUrl") ||
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/"
);
}
//restart transport every minute
setInterval(restartTransport, 60000); //60000ms = 60s = 1m
const wispUrl =
(location.protocol === "https:" ? "wss://" : "ws://") +
location.host +
"/wisp/";
registerRemoteListener(navigator.serviceWorker.controller!);
changeTransport(
localStorage.getItem("transport") || "epoxy",
localStorage.getItem("wispUrl") || wispUrl
);
export { changeTransport, getTransport };

View file

@ -2,23 +2,34 @@ import million from "million/compiler";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import preact from "@preact/preset-vite"; import preact from "@preact/preset-vite";
import { viteStaticCopy } from "vite-plugin-static-copy"; import { viteStaticCopy } from "vite-plugin-static-copy";
import { uvPath } from "@nebula-services/ultraviolet"; import { uvPath } from "@titaniumnetwork-dev/ultraviolet";
import { dynamicPath } from "@nebula-services/dynamic"; import { dynamicPath } from "@nebula-services/dynamic";
import { epoxyPath } from "@mercuryworkshop/epoxy-transport";
import { baremuxPath } from "@mercuryworkshop/bare-mux";
import path from "path"; import path from "path";
const __dirname = path.resolve(); const __dirname = path.resolve();
console.log(dynamicPath);
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
viteStaticCopy({ viteStaticCopy({
targets: [ targets: [
{ {
// .replace fixes weird paths on Windows // .replace fixes weird paths on Windows
src: `${uvPath}/uv.*.js`.replace(/\\/g, "/"), src: `${uvPath}/**/*`.replace(/\\/g, "/"),
dest: "uv", dest: "uv",
overwrite: false overwrite: false
}, },
//{
// src: `${baremuxPath}/**/*`.replace(/\\/g, "/"),
// dest: "mux",
// overwrite: false
//},
{
//include ALL files types
src: `${epoxyPath}/**/*`,
dest: "epoxy",
overwrite: false
},
{ {
// .replace fixes weird paths on Windows // .replace fixes weird paths on Windows
src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"), src: `${dynamicPath}/dynamic.*.js`.replace(/\\/g, "/"),