WSJS / WebSocket Integrity
This commit is contained in:
parent
0a0dcdf764
commit
08e8c59d59
|
@ -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;
|
|
@ -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;
|
|
@ -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'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
let {addListener} = require("../WebSocket.js");
|
||||||
|
|
||||||
|
addListener('connect',(global, client)=>{
|
||||||
|
client.send([{
|
||||||
|
type: 'id',
|
||||||
|
value: client.id
|
||||||
|
},'id'])
|
||||||
|
});
|
|
@ -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;
|
|
@ -0,0 +1,5 @@
|
||||||
|
require("./HTTPServer.js");
|
||||||
|
require("./WebSocket.js");
|
||||||
|
|
||||||
|
require("./Services/YourID.js");
|
||||||
|
require("./Services/Auth.js");
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue