Merge pull request #1090 from ProgrammerIn-wonderland/main

TLS Support through rustls-wasm
This commit is contained in:
Nariman Jelveh
2025-01-14 21:01:29 -08:00
committed by GitHub
5 changed files with 130 additions and 14 deletions
+5 -1
View File
@@ -20,6 +20,7 @@ import { XDIncomingService } from './services/XDIncoming.js';
import { NoPuterYetService } from './services/NoPuterYet.js';
import { Debug } from './modules/Debug.js';
import { PSocket, wispInfo } from './modules/networking/PSocket.js';
import { PTLSSocket } from "./modules/networking/PTLS.js"
import { PWispHandler } from './modules/networking/PWispHandler.js';
// TODO: This is for a safe-guard below; we should check if we can
@@ -330,7 +331,10 @@ window.puter = (function() {
})).json())["token"];
wispInfo.handler = new PWispHandler(wispInfo.server, wispToken);
this.net = {
Socket: PSocket
Socket: PSocket,
tls: {
TLSSocket: PTLSSocket
}
}
})();
+17 -11
View File
@@ -1,6 +1,6 @@
import EventListener from "../../lib/EventListener.js";
import {PWispHandler} from "./PWispHandler.js"
import { errors } from "./parsers.js";
const texten = new TextEncoder();
export let wispInfo = {
server: "wss://puter.cafe/",
@@ -11,34 +11,40 @@ export class PSocket extends EventListener {
_events = new Map();
_streamID;
constructor(host, port) {
super(["data", "drain", "open", "close"]);
super(["data", "drain", "open", "error", "close", "tlsdata", "tlsopen"]);
const callbacks = {
dataCallBack: (data) => {
this.emit("data", data);
},
closeCallBack: (reason) => {
this.emit("close", false); // TODO, report errors
},
openCallBack: () => {
this.emit("open");
if (reason !== 0x02) {
this.emit("error", new Error(errors[reason]));
this.emit("close", true);
return;
}
this.emit("close", false);
}
}
this._streamID = wispInfo.handler.register(host, port, callbacks);
setTimeout(() => {this.emit("open", undefined)}, 0);
}
addListener(...args) {
this.on(...args);
}
write(data, callback) {
if (data.buffer) { // typedArray
if (data.buffer) { // TypedArray
wispInfo.handler.write(this._streamID, data);
if (callback) callback();
} else if (data.resize) {
} else if (data.resize) { // ArrayBuffer
data.write(this._streamID, new Uint8Array(data));
if (callback) callback();
} else if (data.arrayBuffer) { // Oh No, a blob, I need to handle this later, maybe with https://gist.github.com/jimmywarting/65c358f878cac8e7f39cfb7d43931f62?
} else if (typeof(data) === "string") {
wispInfo.handler.write(this._streamID, texten.encode(data))
if (callback) callback();
} else {
throw new Error("Invalid data type (not TypedArray, ArrayBuffer or String!!)");
}
}
close() {
@@ -0,0 +1,98 @@
/**
* This file uses https://github.com/MercuryWorkshop/rustls-wasm authored by GitHub:@r58Playz under the MIT License
*/
import { PSocket } from "./PSocket";
let rustls = undefined;
export class PTLSSocket extends PSocket {
constructor(...args) {
super(...args);
(async() => {
if (!rustls) {
rustls = (await import( /* webpackIgnore: true */ "https://puter-net.b-cdn.net/rustls.js"))
await rustls.default("https://puter-net.b-cdn.net/rustls.wasm")
}
let cancelled = false;
const readable = new ReadableStream({
/**
*
* @param {ReadableStreamDefaultController} controller
*/
start: (controller) => {
super.on("data", (data) => {
controller.enqueue(data.buffer)
})
super.on("close", () => {
if (!cancelled)
controller.close()
})
},
pull: (controller) => {
},
cancel: () => {
cancelled = true;
}
})
const writable = new WritableStream({
write: (chunk) => { super.write(chunk); },
abort: () => { console.log("hello"); super.close(); },
close: () => { super.close(); },
})
let read, write;
try {
const TLSConnnection = await rustls.connect_tls(readable, writable, args[0])
read = TLSConnnection.read;
write = TLSConnnection.write;
} catch (e) {
this.emit("error", new Error("TLS Handshake failed: " + e));
return;
}
this.writer = write.getWriter();
// writer.write("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n");
let reader = read.getReader();
let done = false;
this.emit("tlsopen", undefined);
while (!done) {
try {
const {done: readerDone, value} = await reader.read();
done = readerDone;
if (!done) {
this.emit("tlsdata", value);
}
} catch (e) {
this.emit("error", e)
}
}
})();
}
on(event, callback) {
if (event === "data" || event === "open") {
return super.on("tls" + event, callback)
} else {
return super.on(event, callback);
}
}
write(data, callback) {
if (data.buffer) { // TypedArray
this.writer.write(data.slice(0).buffer).then(callback);
} else if (data.resize) { // ArrayBuffer
this.writer.write(data).then(callback);
} else if (typeof(data) === "string"){
this.writer.write(data).then(callback);
} else {
throw new Error("Invalid data type (not TypedArray, ArrayBuffer or String!!)");
}
}
}
@@ -43,7 +43,7 @@ export class PWispHandler {
}
register(host, port, callbacks) {
const streamID = this._nextStreamID++;
this.streamMap.set(streamID, {queue: [], streamID, buffer: this._bufferMax, dataCallBack: callbacks.dataCallBack, closeCallBack: callbacks.closeCallBack, openCallBack: callbacks.openCallBack});
this.streamMap.set(streamID, {queue: [], streamID, buffer: this._bufferMax, dataCallBack: callbacks.dataCallBack, closeCallBack: callbacks.closeCallBack});
this._ws.send(createWispPacket({
packetType: CONNECT,
streamType: TCP,
@@ -51,7 +51,6 @@ export class PWispHandler {
hostname: host,
port: port
}))
return streamID;
}
@@ -14,6 +14,15 @@ export const UDP = 0x02;
// Frequently used objects
export const textde = new TextDecoder();
const texten = new TextEncoder();
export const errors = {
0x41: "Stream creation failed due to invalid information. This could be sent if the destination was a reserved address or the port is invalid."
,0x42: "Stream creation failed due to an unreachable destination host. This could be sent if the destination is an domain which does not resolve to anything."
,0x43: "Stream creation timed out due to the destination server not responding."
,0x44: "Stream creation failed due to the destination server refusing the connection."
,0x47: "TCP data transfer timed out."
,0x48: "Stream destination address/domain is intentionally blocked by the proxy server."
,0x49: "Connection throttled by the server."
}
/**
* @typedef {{packetType: number, streamID: number, streamType?: number, port?: number, hostname?: string, payload?: Uint8Array, reason?: number, remainingBuffer?: number}} ParsedWispPacket