@lakam99/socks
Advanced tools
Comparing version 0.3.6 to 0.3.7
@@ -86,2 +86,3 @@ import { JaxonSSLConfig } from '../jax.on/src/jax.on'; | ||
export type SockErrorMessage = {type: SockMessageType.ERROR, data: {message: string}}; | ||
export type SockSesh = {ip: string, pages: InstantiatedSockPageReference[], currentPage: InstantiatedSockPageReference}; | ||
@@ -94,8 +95,2 @@ /** | ||
/** | ||
* Designates that the following page can only be accessed if the following prop is set | ||
* @param key the property name to check for | ||
*/ | ||
export function pageRequire(key: string): Function; | ||
export declare class SocksServer { | ||
@@ -131,2 +126,7 @@ /** | ||
protected _publicProps: string[]; | ||
/** | ||
* The session this page belongs to | ||
* @public | ||
*/ | ||
public sesh: SockSesh; | ||
@@ -133,0 +133,0 @@ /** |
@@ -6,3 +6,3 @@ { | ||
"main": "socks.js", | ||
"version": "0.3.6", | ||
"version": "0.3.7", | ||
"devDependencies": { | ||
@@ -23,5 +23,5 @@ "@types/cookie-parser": "^1.4.3", | ||
"dependencies": { | ||
"@lakam99/jax.on": "^0.3.2", | ||
"@lakam99/jax.on": "^0.3.4", | ||
"ts-node": "^10.9.1" | ||
} | ||
} |
141
socks.js
@@ -31,4 +31,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SocksServer = exports.SockPage = exports.pageRequire = exports.monitor_prop = exports.SockMessageType = void 0; | ||
const express_1 = require("express"); | ||
exports.SocksServer = exports.SockPage = exports.monitor_prop = exports.SockMessageType = void 0; | ||
const fs_1 = require("fs"); | ||
@@ -66,8 +65,2 @@ const ws_1 = require("ws"); | ||
exports.monitor_prop = monitor_prop; | ||
function pageRequire(key) { | ||
return function (target) { | ||
return !!target[key]; | ||
}; | ||
} | ||
exports.pageRequire = pageRequire; | ||
function parseHtml(html, context) { | ||
@@ -82,25 +75,36 @@ let result = ''; | ||
} | ||
function getRequesterIp(req) { | ||
return req?.client?.remoteAddress; | ||
} | ||
function getSocketIp(socket) { | ||
return socket._socket.remoteAddress; | ||
} | ||
class SockPage { | ||
constructor(socket = undefined, socks) { | ||
this.onInitialized = []; | ||
this.socks = socks; | ||
this._socket = socket; | ||
this.onInitialized.forEach(f => f()); | ||
this._socketListener = (message) => { | ||
try { | ||
const parsed = JSON.parse(message); | ||
switch (parsed.type) { | ||
case SockMessageType.INVOKE: | ||
this.invoke(parsed); | ||
break; | ||
case SockMessageType.VARCHANGE: | ||
this.setVar(parsed); | ||
break; | ||
case SockMessageType.ERROR: | ||
console.error(parsed.data.data.message); | ||
break; | ||
} | ||
} | ||
catch (e) { | ||
this.send({ type: SockMessageType.ERROR, data: { message: 'Unexpected message format received.' } }); | ||
console.warn(e); | ||
} | ||
}; | ||
this.listen_to_sock(); | ||
} | ||
listen_to_sock() { | ||
this._socket?.on('message', (message) => { | ||
const parsed = JSON.parse(message); | ||
switch (parsed.type) { | ||
case SockMessageType.INVOKE: | ||
this.invoke(parsed); | ||
break; | ||
case SockMessageType.VARCHANGE: | ||
this.setVar(parsed); | ||
break; | ||
case SockMessageType.ERROR: | ||
console.error(parsed.data.data.message); | ||
break; | ||
} | ||
}); | ||
this._socket?.on('message', this._socketListener); | ||
} | ||
@@ -111,2 +115,3 @@ getConnectionIP() { | ||
setSock(socket) { | ||
this._socket?.off('message', this._socketListener); | ||
this._socket = socket; | ||
@@ -122,5 +127,8 @@ this.listen_to_sock(); | ||
else { | ||
console.warn(`Cannot reconnect with session IP ${socket._socket.remoteAddress} to ${this.getConnectionIP()}`); | ||
console.warn(`Cannot reconnect with session IP ${getSocketIp(socket)} to ${this.getConnectionIP()}`); | ||
} | ||
} | ||
setSesh(sesh) { | ||
this.sesh = sesh; | ||
} | ||
setVar(message) { | ||
@@ -160,8 +168,2 @@ const messageData = message.data; | ||
} | ||
/** | ||
* @override | ||
* @param data data being transferred from the previous page / the webserver | ||
*/ | ||
accept_redirect(data = undefined) { | ||
} | ||
} | ||
@@ -178,8 +180,10 @@ exports.SockPage = SockPage; | ||
this.source_code_path = source_code_path; | ||
this.getTheServer().use(express_1.static(':/name/pages/:pageNum/client')); | ||
this.wss.on('connection', (socket) => { | ||
const existingSesh = this.get_sesh(socket._socket.remoteAddress); | ||
existingSesh?.pages.find(page => page.isCurrent)?.page.connect(socket); | ||
const existingSesh = this.get_sesh(getSocketIp(socket)); | ||
existingSesh?.currentPage.page.connect(socket); | ||
socket.on('close', () => { | ||
// this.get_sesh(existingSesh?.page.getConnectionIP()); | ||
const sesh = this.get_sesh(getSocketIp(socket)); | ||
if (sesh) { | ||
//this.sessions.splice(this.sessions.indexOf(sesh), 1); | ||
} | ||
}); | ||
@@ -193,36 +197,23 @@ }); | ||
const basePath = path.resolve(`${this.source_code_path}/pages/${pageName}`); | ||
const html = fs_1.readFileSync(`${basePath}/client/${pageName}.client.html`, 'utf8'); | ||
const pageClass = require(`${basePath}/server/${pageName}.server.ts`).default; | ||
this.getTheServer().get(`/${pageName}/${pageName}.client.css`, (req, res) => res.sendFile(`${basePath}/client/${pageName}.client.css`)); | ||
this.getTheServer().get(`/${pageName}/${pageName}.client.js`, (req, res) => res.sendFile(`${basePath}/client/${pageName}.client.js`)); | ||
this.getTheServer().get(`/${pageName}`, (req, res) => { | ||
const html = fs_1.readFileSync(`${basePath}/client/${pageName}.client.html`, 'utf8'); | ||
const pageClass = require(`${basePath}/server/${pageName}.server.ts`).default; | ||
const webpage = node_html_parser_1.parse(html); | ||
const head = webpage.querySelector('head'); | ||
const body = webpage.querySelector('body'); | ||
if (!head || !body) | ||
throw "Invalid HTML for page " + pageName; | ||
head.innerHTML += ` | ||
<link type='stylesheet' href='/${pageName}/${pageName}.client.css'> | ||
<script type='text/javascript' src='/${pageName}/${pageName}.client.js'> | ||
`; | ||
var thisPage; | ||
var sesh = this.get_sesh(req.client.remoteAddress); | ||
if (sesh) { | ||
const instanceOfThisPage = sesh.pages.find((page) => page.name === pageName); | ||
if (instanceOfThisPage) { | ||
thisPage = instanceOfThisPage.page; | ||
var ip = getRequesterIp(req); | ||
var sesh = this.get_sesh(ip); | ||
if (!sesh) { | ||
sesh = this.new_sesh(ip, pageName, new pageClass(undefined, this.getTheServer.bind(this))); | ||
} | ||
else { | ||
const thisPage = sesh.pages.find(page => page.name === pageName); | ||
if (thisPage) { | ||
sesh.currentPage = thisPage; | ||
} | ||
else { | ||
thisPage = new pageClass(undefined, this.getTheServer); | ||
sesh.pages.push({ name: pageName, page: thisPage, isCurrent: true }); | ||
this.set_current_page_to_new_page(ip, pageClass, pageName); | ||
} | ||
} | ||
else { | ||
thisPage = new pageClass(undefined, this.getTheServer); | ||
this.sessions.push({ ip: req.client.remoteAddress, pages: [{ name: pageName, page: thisPage, isCurrent: true }] }); | ||
sesh = this.get_sesh(req.client.remoteAddress); | ||
} | ||
sesh?.pages.filter((page) => page.name !== pageName).forEach((page) => page.isCurrent = false); | ||
const renderedHtml = parseHtml(html, thisPage); | ||
const renderedPage = node_html_parser_1.parse(renderedHtml); | ||
const renderedHtml = parseHtml(html, sesh.currentPage); | ||
var renderedPage = node_html_parser_1.parse(renderedHtml); | ||
renderedPage.querySelector('body').innerHTML += `<script>${clientScript}</script>`; | ||
@@ -233,2 +224,21 @@ res.send(renderedPage.toString()); | ||
} | ||
new_sesh(ip, currentPageName, currentPage) { | ||
const page = { page: currentPage, name: currentPageName }; | ||
const sesh = { ip, currentPage: page, pages: [page] }; | ||
this.sessions.push(sesh); | ||
currentPage.setSesh(sesh); | ||
return sesh; | ||
} | ||
set_current_page_to_new_page(ip, pageClass, pageName) { | ||
const page = new pageClass(undefined, this.getTheServer.bind(this)); | ||
const pageReference = { page, name: pageName }; | ||
const sesh = this.get_sesh(ip); | ||
if (sesh) { | ||
sesh.pages.push(pageReference); | ||
sesh.currentPage = pageReference; | ||
} | ||
else { | ||
throw 'No sesh matching ip ' + ip; | ||
} | ||
} | ||
getTheServer() { | ||
@@ -240,8 +250,5 @@ return this.constructor.server; | ||
} | ||
redirect_to_page(page) { | ||
page.accept_redirect(); | ||
} | ||
get_current_page(req) { | ||
const sesh = this.get_sesh(req.client.remoteAddress); | ||
return sesh?.pages.find(session => session.isCurrent); | ||
const sesh = this.get_sesh(getRequesterIp(req)); | ||
return sesh?.currentPage; | ||
} | ||
@@ -248,0 +255,0 @@ }; |
165
src/socks.ts
@@ -9,4 +9,6 @@ import {Application, static as _static} from 'express'; | ||
export type SockCurrentPage = {name: string, page: SockPage, isCurrent: boolean}; | ||
export type SockSesh = {ip: string, pages: SockCurrentPage[], expired?: {value: boolean, timeRemainingMS: number}}; | ||
export type InstantiatedSockPageReference = {name: string, page: SockPage}; | ||
export type SockSesh = {ip: string, pages: InstantiatedSockPageReference[], currentPage: InstantiatedSockPageReference}; | ||
export type SockPageConstructor<T = {}> = new (socket: WebSocket | undefined, socks: (() => Application)) => T; | ||
type InstantiatedSockPage = SockPageConstructor<SockPage> & { prototype: SockPage }; | ||
@@ -52,8 +54,2 @@ export type SockInvoke = {name: string, data: any[]}; | ||
export function pageRequire(key: string) { | ||
return function(target: any) { | ||
return !!target[key]; | ||
} | ||
} | ||
function parseHtml(html: string, context: any): string { | ||
@@ -71,12 +67,39 @@ let result:string = ''; | ||
return result; | ||
} | ||
} | ||
function getRequesterIp(req: any): string { | ||
return req?.client?.remoteAddress; | ||
} | ||
function getSocketIp(socket: WebSocket): string { | ||
return (socket as any)._socket.remoteAddress; | ||
} | ||
export abstract class SockPage { | ||
private _socket: WebSocket | undefined; | ||
protected socks: SocksServer; | ||
protected onInitialized : Function[] = []; | ||
constructor(socket: WebSocket | undefined = undefined, socks: SocksServer) { | ||
private _socketListener: (message: string) => void; | ||
protected socks: SocksServer | (() => Application); | ||
public sesh!: SockSesh; | ||
constructor(socket: WebSocket | undefined = undefined, socks: (() => Application)) { | ||
this.socks = socks; | ||
this._socket = socket; | ||
this.onInitialized.forEach(f => f()); | ||
this._socketListener = (message: string) => { | ||
try { | ||
const parsed = JSON.parse(message) as SockMessage; | ||
switch (parsed.type) { | ||
case SockMessageType.INVOKE: | ||
this.invoke(parsed as SockInvokeMessage); | ||
break; | ||
case SockMessageType.VARCHANGE: | ||
this.setVar(parsed as SockVarChangeMessage); | ||
break; | ||
case SockMessageType.ERROR: | ||
console.error((parsed.data as SockErrorMessage).data.message); | ||
break; | ||
} | ||
} catch (e) { | ||
this.send({type: SockMessageType.ERROR, data: {message: 'Unexpected message format received.'}}); | ||
console.warn(e); | ||
} | ||
}; | ||
this.listen_to_sock(); | ||
@@ -86,16 +109,3 @@ } | ||
private listen_to_sock():void { | ||
this._socket?.on('message', (message: string) => { | ||
const parsed = JSON.parse(message) as SockMessage; | ||
switch (parsed.type) { | ||
case SockMessageType.INVOKE: | ||
this.invoke(parsed as SockInvokeMessage); | ||
break; | ||
case SockMessageType.VARCHANGE: | ||
this.setVar(parsed as SockVarChangeMessage); | ||
break; | ||
case SockMessageType.ERROR: | ||
console.error((parsed.data as SockErrorMessage).data.message); | ||
break; | ||
} | ||
}); | ||
this._socket?.on('message', this._socketListener); | ||
} | ||
@@ -108,2 +118,3 @@ | ||
private setSock(socket: WebSocket) { | ||
this._socket?.off('message', this._socketListener); | ||
this._socket = socket; | ||
@@ -119,5 +130,9 @@ this.listen_to_sock(); | ||
} else { | ||
console.warn(`Cannot reconnect with session IP ${(socket as any)._socket.remoteAddress} to ${this.getConnectionIP()}`); | ||
console.warn(`Cannot reconnect with session IP ${getSocketIp(socket)} to ${this.getConnectionIP()}`); | ||
} | ||
} | ||
public setSesh(sesh: SockSesh) { | ||
this.sesh = sesh; | ||
} | ||
@@ -165,10 +180,2 @@ private setVar(message: SockVarChangeMessage) { | ||
} | ||
/** | ||
* @override | ||
* @param data data being transferred from the previous page / the webserver | ||
*/ | ||
public accept_redirect(data: any = undefined): void { | ||
} | ||
} | ||
@@ -188,46 +195,52 @@ | ||
const basePath = path.resolve(`${this.source_code_path}/pages/${pageName}`); | ||
const html = readFileSync(`${basePath}/client/${pageName}.client.html`, 'utf8'); | ||
const pageClass: InstantiatedSockPage = require(`${basePath}/server/${pageName}.server.ts`).default; | ||
this.getTheServer().get(`/${pageName}/${pageName}.client.css`, (req: any, res: any) => res.sendFile(`${basePath}/client/${pageName}.client.css`)); | ||
this.getTheServer().get(`/${pageName}/${pageName}.client.js`, (req: any, res: any) => res.sendFile(`${basePath}/client/${pageName}.client.js`)); | ||
this.getTheServer().get(`/${pageName}`, (req: any, res: any) => { | ||
const html = readFileSync(`${basePath}/client/${pageName}.client.html`, 'utf8'); | ||
const pageClass = require(`${basePath}/server/${pageName}.server.ts`).default; | ||
var ip = getRequesterIp(req); | ||
var sesh = this.get_sesh(ip); | ||
const webpage = parse(html); | ||
const head = webpage.querySelector('head'); | ||
const body = webpage.querySelector('body'); | ||
if (!head || !body) throw "Invalid HTML for page " + pageName; | ||
head.innerHTML += ` | ||
<link type='stylesheet' href='/${pageName}/${pageName}.client.css'> | ||
<script type='text/javascript' src='/${pageName}/${pageName}.client.js'> | ||
`; | ||
var thisPage; | ||
var sesh = this.get_sesh(req.client.remoteAddress); | ||
if (sesh) { | ||
const instanceOfThisPage = sesh.pages.find((page: SockCurrentPage) => page.name === pageName); | ||
if (instanceOfThisPage) { | ||
thisPage = instanceOfThisPage.page; | ||
if (!sesh) { | ||
sesh = this.new_sesh(ip, pageName, new pageClass(undefined, this.getTheServer.bind(this))); | ||
} else { | ||
const thisPage = sesh.pages.find(page => page.name === pageName); | ||
if (thisPage) { | ||
sesh.currentPage = thisPage; | ||
} else { | ||
thisPage = new pageClass(undefined, this.getTheServer); | ||
sesh.pages.push({name: pageName, page: thisPage, isCurrent: true}); | ||
this.set_current_page_to_new_page(ip, pageClass, pageName); | ||
} | ||
} else { | ||
thisPage = new pageClass(undefined, this.getTheServer); | ||
this.sessions.push({ip: req.client.remoteAddress, pages: [{name: pageName, page: thisPage, isCurrent: true}]}); | ||
sesh = this.get_sesh(req.client.remoteAddress); | ||
} | ||
sesh?.pages.filter((page: SockCurrentPage) => page.name !== pageName).forEach((page: SockCurrentPage) => page.isCurrent = false); | ||
const renderedHtml = parseHtml(html, sesh.currentPage); | ||
var renderedPage = parse(renderedHtml); | ||
const renderedHtml = parseHtml(html, thisPage); | ||
const renderedPage = parse(renderedHtml); | ||
(renderedPage.querySelector('body') as any).innerHTML += `<script>${clientScript}</script>`; | ||
res.send(renderedPage.toString()); | ||
}) | ||
}) | ||
}); | ||
}); | ||
} | ||
new_sesh(ip: string, currentPageName: string, currentPage: SockPage): SockSesh { | ||
const page: InstantiatedSockPageReference = {page: currentPage, name: currentPageName}; | ||
const sesh = {ip, currentPage: page, pages: [page]}; | ||
this.sessions.push(sesh); | ||
currentPage.setSesh(sesh); | ||
return sesh; | ||
} | ||
set_current_page_to_new_page(ip: string, pageClass: InstantiatedSockPage, pageName: string) { | ||
const page = new pageClass(undefined, this.getTheServer.bind(this)); | ||
const pageReference = {page, name: pageName}; | ||
const sesh = this.get_sesh(ip); | ||
if (sesh) { | ||
sesh.pages.push(pageReference); | ||
sesh.currentPage = pageReference; | ||
} else { | ||
throw 'No sesh matching ip ' + ip; | ||
} | ||
} | ||
private getTheServer(): Application { | ||
@@ -245,9 +258,11 @@ return (this.constructor as any).server as Application; | ||
this.getTheServer().use(_static(':/name/pages/:pageNum/client')); | ||
this.wss.on('connection', (socket: WebSocket) => { | ||
const existingSesh = this.get_sesh((socket as any)._socket.remoteAddress); | ||
existingSesh?.pages.find(page => page.isCurrent)?.page.connect(socket); | ||
const existingSesh = this.get_sesh(getSocketIp(socket)); | ||
existingSesh?.currentPage.page.connect(socket); | ||
socket.on('close', () => { | ||
// this.get_sesh(existingSesh?.page.getConnectionIP()); | ||
const sesh = this.get_sesh(getSocketIp(socket)); | ||
if (sesh) { | ||
this.sessions.splice(this.sessions.indexOf(sesh), 1); | ||
} | ||
}); | ||
@@ -264,10 +279,6 @@ } | ||
redirect_to_page(page: SockPage) { | ||
page.accept_redirect() | ||
protected get_current_page(req: any): InstantiatedSockPageReference | undefined { | ||
const sesh = this.get_sesh(getRequesterIp(req)); | ||
return sesh?.currentPage; | ||
} | ||
protected get_current_page(req: any): SockCurrentPage | undefined { | ||
const sesh = this.get_sesh(req.client.remoteAddress); | ||
return sesh?.pages.find(session => session.isCurrent); | ||
} | ||
} |
38487
795
Updated@lakam99/jax.on@^0.3.4