|
@@ -1,10 +1,23 @@
|
|
|
-import {dumpIP} from "./tun/tailscale_tun.js"
|
|
|
+// import {getDumpIP} from "./tun/tailscale_tun_auto.js"
|
|
|
|
|
|
export class DirectNetwork {
|
|
|
constructor() {}
|
|
|
tcpSocket(ip, port, options) {
|
|
|
- return new TCPSocket(ip, port, options)
|
|
|
+ return new TCPSocketClient(ip, port, options);
|
|
|
}
|
|
|
+ // directServerSocket(localAddress, options) {
|
|
|
+ // return new DirectTCPServer(localAddress, options);
|
|
|
+ // }
|
|
|
+}
|
|
|
+
|
|
|
+function uint32ToIp(uint32) {
|
|
|
+ // backwards from what I thought?
|
|
|
+ const a = uint32 & 0xFF; // First byte
|
|
|
+ const b = (uint32 >>> 8) & 0xFF; // Second byte
|
|
|
+ const c = (uint32 >>> 16) & 0xFF; // Third byte
|
|
|
+ const d = (uint32 >>> 24) & 0xFF; // Fourth byte
|
|
|
+
|
|
|
+ return `${a}.${b}.${c}.${d}`;
|
|
|
}
|
|
|
|
|
|
export class TCPSocketClient {
|
|
@@ -18,9 +31,10 @@ export class TCPSocketClient {
|
|
|
this.readable = null;
|
|
|
this.writable = null;
|
|
|
|
|
|
- const formatted_ip = dumpIP(ip);
|
|
|
- this.socket = new TCPSocket(formatted_ip, port, options);
|
|
|
- console.log(`Created new TCPSocket: ip=[${ip}], port=[${port}], options=[${options}]`);
|
|
|
+ let ip_string = uint32ToIp(ip);
|
|
|
+
|
|
|
+ this.socket = new TCPSocket(ip_string, port, options);
|
|
|
+ console.log(`Created new TCPSocket: ip=[${ip_string}], port=[${port}], options=[${options}]`);
|
|
|
}
|
|
|
async connect() {
|
|
|
try {
|
|
@@ -40,275 +54,84 @@ export class TCPSocketClient {
|
|
|
}
|
|
|
}
|
|
|
async send(data) {
|
|
|
- const writer = this.writable.getWriter();
|
|
|
- await writer.write(data);
|
|
|
- writer.releaseLock();
|
|
|
+ try {
|
|
|
+ console.log("WEBVM: SEND");
|
|
|
+ const writer = this.writable.getWriter();
|
|
|
+ await writer.write(data);
|
|
|
+ writer.releaseLock();
|
|
|
+ return 0
|
|
|
+ } catch (e) {
|
|
|
+ console.log("Error sending: ", e);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
async recv() {
|
|
|
- const reader = this.readable.getReader();
|
|
|
- while (true) {
|
|
|
- const {value, done} = await reader.read();
|
|
|
- if (done) {
|
|
|
- break;
|
|
|
+ try {
|
|
|
+ console.log("WEBVM: RECV");
|
|
|
+ const reader = this.readable.getReader();
|
|
|
+ while (true) {
|
|
|
+ const {value, done} = await reader.read();
|
|
|
+ if (done) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ console.log("value in recv(): ", value);
|
|
|
+ reader.releaseLock();
|
|
|
+ return value;
|
|
|
}
|
|
|
- console.log("value in recv(): ", value);
|
|
|
+ reader.releaseLock();
|
|
|
+ } catch (e) {
|
|
|
+ console.log("Error Receiving: ", e);
|
|
|
+ return null;
|
|
|
}
|
|
|
- reader.releaseLock();
|
|
|
+ return null;
|
|
|
}
|
|
|
- // being xtra xtra safe but I think it'll cause issues to get reader and writer here again
|
|
|
async close() {
|
|
|
- const writer = this.writable.getWriter();
|
|
|
- const reader = this.readable.getReader();
|
|
|
-
|
|
|
- await writer.close();
|
|
|
- await reader.close();
|
|
|
- await this.socket.close();
|
|
|
+ try {
|
|
|
+ console.log("WEBVM: CLOSE");
|
|
|
+ await this.socket.close();
|
|
|
+ console.log("WEBVM: CLOSED");
|
|
|
+ return 0
|
|
|
+ } catch (e) {
|
|
|
+ console.log("Error closing: ", e);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
- // async connect(timeoutMs = 5000) {
|
|
|
- // try {
|
|
|
- // let timeoutID;
|
|
|
- // // added timeout cause it seems to be standard
|
|
|
- // const timeoutPromise = new Promise((_, reject) => {
|
|
|
- // timeoutID = setTimeout(() => {
|
|
|
- // console.log(`Connection to ${this.remoteAddress}:${this.remotePort} timed out after ${timeoutMs}ms`);
|
|
|
- // reject(new Error("Connection timeout"));
|
|
|
- // }, timeoutMs);
|
|
|
- // });
|
|
|
-
|
|
|
- // this.socket = new TCPSocket(this.remoteAddress, this.remotePort, this.options);
|
|
|
- // // race between socket.opened and timeout
|
|
|
- // const openInfo = await Promise.race([this.socket.opened, timeoutPromise]);
|
|
|
- // clearTimeout(timeoutID);
|
|
|
-
|
|
|
- // this._readable = openInfo.readable;
|
|
|
- // this._writable = openInfo.writable;
|
|
|
-
|
|
|
- // if (this.onData) {
|
|
|
- // this._startReading();
|
|
|
- // }
|
|
|
- // if (this.onOpen) {
|
|
|
- // this.onOpen(openInfo);
|
|
|
- // }
|
|
|
-
|
|
|
- // this._resolveOpened(openInfo);
|
|
|
- // return openInfo;
|
|
|
- // } catch (e) {
|
|
|
- // this._rejectOpened(e);
|
|
|
- // this._rejectClosed(e);
|
|
|
-
|
|
|
- // if (this.onError) {
|
|
|
- // this.onError(e);
|
|
|
- // }
|
|
|
-
|
|
|
- // throw e;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // constructor(remoteAddress, remotePort, options = {}) {
|
|
|
- // this.socket = null;
|
|
|
- // this.remoteAddress = remoteAddress;
|
|
|
- // this.remotePort = remotePort;
|
|
|
- // this.options = options;
|
|
|
-
|
|
|
- // // internals
|
|
|
- // this._readable = null;
|
|
|
- // this._writable = null;
|
|
|
- // this._reader = null;
|
|
|
- // this._writer;
|
|
|
-
|
|
|
- // // open and closed promise as fields
|
|
|
- // this._isOpenedSettled = false;
|
|
|
- // this._isClosedSettled = false;
|
|
|
- // this._openedPromise = new Promise((resolve, reject) => {
|
|
|
- // this._resolveOpened = (value) => {
|
|
|
- // this._isOpenedSettled = true;
|
|
|
- // resolve(value);
|
|
|
- // };
|
|
|
-
|
|
|
- // this._rejectOpened = (reason) => {
|
|
|
- // this._isOpenedSettled = true;
|
|
|
- // reject(reason);
|
|
|
- // };
|
|
|
- // });
|
|
|
- // this._closedPromise = new Promise((resolve, reject) => {
|
|
|
- // this._resolveClosed = (value) => {
|
|
|
- // this._isClosedSettled = true;
|
|
|
- // resolve(value);
|
|
|
- // };
|
|
|
- // this._rejectClosed = (reason) => {
|
|
|
- // this._isClosedSettled = true;
|
|
|
- // reject(reason);
|
|
|
- // };
|
|
|
- // });
|
|
|
-
|
|
|
- // // event callbacks
|
|
|
- // this.onOpen = null;
|
|
|
- // this.onData = null;
|
|
|
- // this.onClose = null;
|
|
|
- // this.onError = null;
|
|
|
- // }
|
|
|
-
|
|
|
- // get opened() {
|
|
|
- // return this._openedPromise;
|
|
|
- // }
|
|
|
-
|
|
|
- // get closed() {
|
|
|
- // return this._closedPromise;
|
|
|
- // }
|
|
|
-
|
|
|
- // async connect(timeoutMs = 5000) {
|
|
|
- // try {
|
|
|
- // let timeoutID;
|
|
|
- // // added timeout cause it seems to be standard
|
|
|
- // const timeoutPromise = new Promise((_, reject) => {
|
|
|
- // timeoutID = setTimeout(() => {
|
|
|
- // console.log(`Connection to ${this.remoteAddress}:${this.remotePort} timed out after ${timeoutMs}ms`);
|
|
|
- // reject(new Error("Connection timeout"));
|
|
|
- // }, timeoutMs);
|
|
|
- // });
|
|
|
-
|
|
|
- // this.socket = new TCPSocket(this.remoteAddress, this.remotePort, this.options);
|
|
|
- // // race between socket.opened and timeout
|
|
|
- // const openInfo = await Promise.race([this.socket.opened, timeoutPromise]);
|
|
|
- // clearTimeout(timeoutID);
|
|
|
-
|
|
|
- // this._readable = openInfo.readable;
|
|
|
- // this._writable = openInfo.writable;
|
|
|
-
|
|
|
- // if (this.onData) {
|
|
|
- // this._startReading();
|
|
|
- // }
|
|
|
- // if (this.onOpen) {
|
|
|
- // this.onOpen(openInfo);
|
|
|
- // }
|
|
|
-
|
|
|
- // this._resolveOpened(openInfo);
|
|
|
- // return openInfo;
|
|
|
- // } catch (e) {
|
|
|
- // this._rejectOpened(e);
|
|
|
- // this._rejectClosed(e);
|
|
|
-
|
|
|
- // if (this.onError) {
|
|
|
- // this.onError(e);
|
|
|
- // }
|
|
|
-
|
|
|
- // throw e;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // async _startReading() {
|
|
|
- // try {
|
|
|
- // this._reader = this._readable.getReader();
|
|
|
- // while (true) {
|
|
|
- // const {value, done} = await this._reader.read();
|
|
|
-
|
|
|
- // if (done) {
|
|
|
- // // releaseLock() here
|
|
|
- // this._reader.releaseLock();
|
|
|
- // this._reader = null;
|
|
|
- // if (this.onClose) {
|
|
|
- // this.onClose();
|
|
|
- // }
|
|
|
- // break;
|
|
|
- // }
|
|
|
- // if (value && value.byteLength > 0) {
|
|
|
- // if (this.onData) {
|
|
|
- // this.onData(value);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
- // } catch (e) {
|
|
|
- // if (this._reader) {
|
|
|
- // this._reader.releaseLock();
|
|
|
- // this._reader = null;
|
|
|
- // }
|
|
|
- // if (this.onClose) {
|
|
|
- // this.onClose();
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // async send(data) {
|
|
|
- // if (!this._writable) {
|
|
|
- // throw new Error(`Socket is not connected`);
|
|
|
- // }
|
|
|
-
|
|
|
- // try {
|
|
|
- // this._writer = this._writable.getWriter();
|
|
|
- // let buffer = data;
|
|
|
- // // old: for text exchange test, can probably be removed
|
|
|
- // if (typeof data === `string`) {
|
|
|
- // const encoder = new TextEncoder();
|
|
|
- // buffer = encoder.encode(data);
|
|
|
- // }
|
|
|
-
|
|
|
- // await this._writer.write(buffer);
|
|
|
-
|
|
|
- // await this._writer.releaseLock();
|
|
|
- // this._writer = null;
|
|
|
- // return true;
|
|
|
- // } catch (e) {
|
|
|
- // if (this.onError) {
|
|
|
- // this.onError(e);
|
|
|
- // }
|
|
|
- // throw e;
|
|
|
- // }
|
|
|
- // }
|
|
|
+}
|
|
|
|
|
|
- // async close() {
|
|
|
- // if (!this.socket) {
|
|
|
- // throw new Error(`Socket is not connected`);
|
|
|
- // }
|
|
|
|
|
|
+export async function autoConfSockets() {
|
|
|
+ console.log(`AutoConfSockets running`);
|
|
|
+ return {tcpSocket: TCPSocketClient}
|
|
|
+}
|
|
|
|
|
|
- // try {
|
|
|
- // // try to handle leftover locks if necessary, tho should have been handled in startReading's loop and send()
|
|
|
- // if (this._reader) {
|
|
|
- // this._reader.releaseLock();
|
|
|
- // this._reader = null;
|
|
|
- // }
|
|
|
- // if (this._writer) {
|
|
|
- // this._writer.releaseLock();
|
|
|
- // this._writer = null;
|
|
|
- // }
|
|
|
|
|
|
- // // returning this before trying to handle leftover locks errs because close before releaseLock(). I thought I had made it so it'd take care of that but guess not
|
|
|
- // // just try to release before fixes it
|
|
|
- // if (this._isClosedSettled) {
|
|
|
- // return this._closedPromise;
|
|
|
- // }
|
|
|
+export class DirectTCPServer {
|
|
|
+ constructor(localAddress, options) {
|
|
|
+ this.server = null;
|
|
|
+ this.localAddress = localAddress;
|
|
|
+ this.readable = null;
|
|
|
|
|
|
+ let str =uint32ToIp(localAddress);
|
|
|
+ this.server = new TCPServerSocket(localAddress, options);
|
|
|
+ console.log(`Created new ServerSocket: localAddress = [${localAddress}], options = [${options}]`);
|
|
|
+ }
|
|
|
|
|
|
- // await this.socket.closed;
|
|
|
- // if (this.onClose) {
|
|
|
- // this.onClose();
|
|
|
- // }
|
|
|
+ async bind() {
|
|
|
+ this.readable = await this.server.opened;
|
|
|
+ const reader = this.readable.getReader();
|
|
|
|
|
|
- // this._resolveClosed();
|
|
|
- // return this._closedPromise;
|
|
|
- // } catch (e) {
|
|
|
- // this._rejectClosed(e);
|
|
|
- // if (this.onError) {
|
|
|
- // this.onError(e);
|
|
|
- // }
|
|
|
-
|
|
|
- // throw e;
|
|
|
- // }
|
|
|
- // }
|
|
|
-}
|
|
|
+ while (true) {
|
|
|
+ const {value: acceptedSocket, done} = await reader.read();
|
|
|
+ if (done) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ console.log(`New Socket connected to server: `, value);
|
|
|
+ }
|
|
|
|
|
|
+ reader.releaseLock();
|
|
|
+ }
|
|
|
|
|
|
-export async function autoConfSockets() {
|
|
|
- console.log(`AutoConfSockets running`);
|
|
|
- return {tcpSocket: TCPSocketClient}
|
|
|
+ close() {
|
|
|
+ this.server.close();
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
-// export async function autoConfSockets({host, port, options}) {
|
|
|
-// // console.log(`Creating new socket with: `, host, port, options);
|
|
|
-// console.log("called autoConfSockets");
|
|
|
-// // return new TCPSocketClient()
|
|
|
-// }
|
|
|
-
|
|
|
-// export async function connect() {
|
|
|
- // return await sock.connect()
|
|
|
-// }
|