WSJS / WebSocket Integrity

This commit is contained in:
Abdussamed ULUTAŞ 2022-11-17 00:17:55 +03:00
parent 0a0dcdf764
commit 08e8c59d59
10 changed files with 2964 additions and 0 deletions

23
Source/Client.js Normal file
View File

@ -0,0 +1,23 @@
function Client()
{
/**
* @type {string}
*/
this.id = null;
/**
* @type {import("websocket").connection}
*/
this.socket = null;
/**
* @type {Date}
*/
this.created_at = null;
this.store = new Map();
};
Client.prototype.send = function(obj){
this.socket.sendUTF(JSON.stringify(obj));
};
exports.Client = Client;

8
Source/HTTPServer.js Normal file
View File

@ -0,0 +1,8 @@
"use strict";
let http = require("http");
let server = http.createServer();
server.listen(8282,'0.0.0.0',() => {
console.log("HTTP Service Running...");
});
exports.http = server;

47
Source/Services/Auth.js Normal file
View File

@ -0,0 +1,47 @@
let {addService} = require("../WebSocket.js");
addService(({
global,
client,
message,
end,
next,
response
})=>{
let {type,username,password} = message;
if(type === 'auth/check')
{
let auth = client.store.has('user');
return end({
value: auth
})
};
if(type === 'auth/login')
{
if(username == 'admin' && password == '123456Kc')
{
return end({
status: 'success'
})
}else{
return end({
status: 'fail'
})
}
};
if(type === 'auth/logout')
{
let auth = client.store.has('user');
if(auth)
{
client.store.delete('user');
return end({
status: 'success'
})
}else{
return end({
status: 'fail'
})
}
};
});

View File

@ -0,0 +1,8 @@
let {addListener} = require("../WebSocket.js");
addListener('connect',(global, client)=>{
client.send([{
type: 'id',
value: client.id
},'id'])
});

117
Source/WebSocket.js Normal file
View File

@ -0,0 +1,117 @@
"use strict";
let websocket = require("websocket");
let {http} = require("./HTTPServer");
let {randomUUID} = require("crypto");
const { Client } = require("./Client.js");
let wsServer = new websocket.server({
httpServer: http,
autoAcceptConnections: true
});
let global = new Map();
let clients = new Map();
wsServer.addListener("connect",(socket) => {
let local = new Client();
let id = randomUUID();
socket.id = id;
local.id = id;
local.socket = socket;
local.created_at = new Date();
clients.set(id, local);
emit("connect", global, local);
socket.addListener("close",()=>{
emit("disconnect", global, local);
clients.delete(id);
});
socket.addListener("message",({type,utf8Data}) => {
if(type == "utf8")
{
let json;
try{
json = JSON.parse(utf8Data);
emit('services', global, local, json);
let [payload, id, action] = json;
if(typeof id === "string")
{
action = id;
}
emitService(global, local, id, payload, action);
}catch{
emit("messageError", global, local, utf8Data);
}
}
});
});
/**
* @type {Map<string, Function[]>}
*/
let events = new Map();
/**
* @type {Map<string, Function[]>}
*/
let services = []
/**
*
* @param {string} event
* @param {(global:Map<string, any>, client:Client, data:any) => any} func
*/
exports.addListener = (event, func) => {
if(!events.has(event))
{
events.set(event,[]);
};
events.get(event).push(func);
};
/**
*
* @param {string} event
* @param {(data:{global:Map<string, any>, client:Client, message:any,response:Function,end:Function,next:Function}) => any} func
*/
exports.addService = (func) => {
services.push(func);
};
function emit(event,...args)
{
if(events.has(event))
{
for (const callback of events.get(event)) {
callback(...args);
}
};
};
/**
*
* @param {Map} global
* @param {Client} local
* @param {number} id
* @param {{[key:string]:any}} payload
* @param {"R"|"S"} action
*/
async function emitService(global, client, id, payload, action)
{
let willContinue = false;
for (const callback of services) {
await callback({
message: payload,
action,
client,
global,
response:(obj)=>{
client.send([obj, id, 'C']) // continue
},
end:(obj)=>{
client.send([obj, id, 'E']) // stopped data stream (this channel)
},
next:function(){
willContinue = true;
}
});
if(willContinue === false) break;
}
};
exports.websocket = wsServer;

5
Source/index.js Normal file
View File

@ -0,0 +1,5 @@
require("./HTTPServer.js");
require("./WebSocket.js");
require("./Services/YourID.js");
require("./Services/Auth.js");

2574
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

26
package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "mwse",
"version": "0.1.0",
"description": "Mikro WebSocket Engine",
"main": "Source/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "http://git.saqut.com/saqut/MWSE"
},
"keywords": [
"WebSocket",
"server",
"microservice",
"ws"
],
"author": "Abdussamed ULUTAŞ <abdussamedulutas@yandex.com.tr>",
"license": "MIT",
"dependencies": {
"knex": "^2.3.0",
"sqlite3": "^5.1.2",
"websocket": "^1.0.34"
}
}

23
test.html Normal file
View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./wsjs.js"></script>
<script>
let ws = new WSJS();
ws.connect('ws://localhost:8282');
ws.scope(()=>{
console.log("Connected ws")
ws.authWith("admin","123456Kc");
});
ws.signal('id',(data)=>{
console.log("Your id is ", data.value)
});
</script>
</body>
</html>

133
wsjs.js Normal file
View File

@ -0,0 +1,133 @@
function WSJS()
{
this.isActive = false;
this.ws = null;
this.endpoint = null;
};
WSJS.prototype.connect = function(url){
this.ws = new WebSocket(url);
this.addListeners();
}
WSJS.prototype.addListeners = function(url){
this.ws.addEventListener("close", this.closedEvent.bind(this));
this.ws.addEventListener("message", this.messageEvent.bind(this));
this.ws.addEventListener("open", this.openMessage.bind(this));
}
WSJS.prototype.closedEvent = function(){
this.isActive = false;
this.ws = null;
this.events.dispatchEvent(new Event("close"));
}
WSJS.prototype.openMessage = function(){
this.isActive = true;
this.events.dispatchEvent(new Event("open"));
}
WSJS.prototype.messageEvent = function({data}){
let [payload, id, action] = JSON.parse(data);
if(typeof id === 'number')
{
if(this.requests.has(id))
{
this.requests.get(id)(payload, action);
switch(action)
{
case 'E':{
this.requests.delete(id);
break;
}
case 'S':
default:{
break;
}
}
}else console.warn("Missing event sended from server");
}else{
if(this.signals.has(id))
{
for (const callback of this.signals.get(id)) {
callback(payload);
}
}else console.warn("Missing event sended from server");
}
}
WSJS.prototype.events = new EventTarget();
WSJS.prototype.scope = function(func){
if(this.isActive)
{
func();
}else this.events.addEventListener("open", func);
}
WSJS.prototype.sendOnly = function(obj){
if(this.isActive)
{
this.sendRaw([obj,'R']);
}else throw new Error(`socket could be a active`);
}
WSJS.prototype.requests = new Map();
WSJS.prototype.requestCount = 0;
WSJS.prototype.request = async function(obj){
if(this.isActive)
{
return await new Promise(ok => {
let id = ++this.requestCount;
this.sendRaw([obj,id,'R']);
this.requests.set(id,data => {
ok(data);
});
})
}else throw new Error(`socket could be a active`);
}
WSJS.prototype.stream = async function(obj,callback){
if(this.isActive)
{
let id = ++this.requestCount;
this.sendRaw([obj, id, 'S']);
this.requests.set(id,data => {
callback(data);
});
}else throw new Error(`socket could be a active`);
}
WSJS.prototype.signals = new Map();
WSJS.prototype.signal = async function(name, callback){
if(!this.signals.has(name))
{
this.signals.set(name, [callback]);
}else{
this.signals.get(name).push(callback);
}
}
WSJS.prototype.slot = async function(name, obj){
if(this.isActive)
{
if(typeof name == "string")
{
this.sendOnly([obj,name]);
}else{
throw new Error(`name could be a string, gived ${typeof name}`);
}
}else throw new Error(`socket could be a active`);
}
WSJS.prototype.sendRaw = function(obj){
if(this.isActive)
{
this.ws.send(JSON.stringify(obj))
};
}
WSJS.prototype.checkAuth = async function(username, password){
let {value:isAuth} = await this.request({
type: 'auth/check'
});
return isAuth;
};
WSJS.prototype.authWith = async function(username, password){
if(!await this.checkAuth())
{
let requets = await this.request({
type: 'auth/login',
username,
password
});
debugger;
}
};