Compare commits

..

105 Commits

Author SHA1 Message Date
fb99848df1 1.1.41 2019-08-12 22:45:58 +02:00
1bd39d0755 fix(core): update 2019-08-12 22:45:58 +02:00
d24c5f628c 1.1.40 2019-08-12 22:31:41 +02:00
33fbabdd72 fix(core): update 2019-08-12 22:31:40 +02:00
9d26fff986 1.1.39 2019-08-12 18:16:26 +02:00
41151e5436 fix(core): update 2019-08-12 18:16:25 +02:00
109c5197f3 1.1.38 2019-06-07 08:40:24 +02:00
c3d47c1f50 fix(core): update 2019-06-07 08:40:24 +02:00
1b45fb45e9 1.1.37 2019-06-06 23:11:03 +02:00
c22adc9b57 fix(core): update 2019-06-06 23:11:03 +02:00
35e87306dd 1.1.36 2019-05-02 11:46:36 +02:00
1b20aa5992 fix(core): update 2019-05-02 11:46:36 +02:00
a63f14da47 1.1.35 2019-04-26 17:35:15 +02:00
86cf94c5dc fix(core): update 2019-04-26 17:35:15 +02:00
0d39d6f237 1.1.34 2019-04-24 18:30:57 +02:00
1856ad5cfc fix(core): update 2019-04-24 18:30:56 +02:00
b5dab810e8 1.1.33 2019-04-24 17:57:17 +02:00
f145b85b1c fix(core): update 2019-04-24 17:57:16 +02:00
a8c647c5c7 1.1.32 2019-04-24 17:17:36 +02:00
22472e0adf fix(core): update 2019-04-24 17:17:36 +02:00
333ddb4d9c 1.1.31 2019-04-24 17:10:52 +02:00
126f020bf8 fix(core): update 2019-04-24 17:10:51 +02:00
7677b1bb48 1.1.30 2019-04-24 16:09:01 +02:00
114379c5b3 fix(core): update 2019-04-24 16:09:01 +02:00
79ae7d2039 1.1.29 2019-04-24 15:47:29 +02:00
d2cb6a3045 fix(core): update 2019-04-24 15:47:28 +02:00
963619b2ed 1.1.28 2019-04-23 17:28:46 +02:00
976abaaed7 fix(core): update 2019-04-23 17:28:46 +02:00
ef322c32ac 1.1.27 2019-01-31 02:32:52 +01:00
475911a968 fix(build): now building with tsbuild 2019-01-31 02:32:52 +01:00
5530e29da4 1.1.26 2019-01-31 00:54:40 +01:00
5f1d2c83c6 fix(core): update 2019-01-31 00:54:39 +01:00
b84dd36885 1.1.25 2019-01-31 00:46:42 +01:00
c2d64ba39a fix(readme): update 2019-01-31 00:46:42 +01:00
85a5d7cdaf 1.1.24 2019-01-30 10:55:52 +01:00
69380a2dbc fix(npmextra): adjust access level 2019-01-30 10:55:51 +01:00
fc292d83b9 1.1.23 2019-01-30 10:55:17 +01:00
b29961df95 fix(scope): switch to @pushrocks 2019-01-30 10:55:16 +01:00
f774a82ad5 1.1.22 2019-01-30 03:21:15 +01:00
5a45f4750b fix(package.json): private setting 2019-01-30 03:21:14 +01:00
fc6227ef96 1.1.21 2019-01-30 03:15:22 +01:00
873aba3e0b fix(snyk): add .snyk file 2019-01-30 03:15:21 +01:00
f9bed9da8a 1.1.20 2019-01-30 03:14:03 +01:00
d296064bfa fix(structure): update to latest standards 2019-01-30 03:14:02 +01:00
1b0922759a 1.1.19 2018-03-19 10:00:14 +01:00
aef4f9c591 now working as expected 2018-03-19 10:00:11 +01:00
abf546eec3 1.1.18 2018-03-18 17:50:39 +01:00
483cb38175 start transitioning to better SocketFunction handling 2018-03-18 17:50:37 +01:00
b2bd66a6a6 1.1.17 2018-03-18 16:40:42 +01:00
cfc3e8788d add @types/node 2018-03-18 16:40:40 +01:00
23c14c032c 1.1.16 2018-03-17 17:52:36 +01:00
c92dae809f format README 2018-03-17 17:52:31 +01:00
7200464e4b 1.1.15 2018-03-17 17:52:07 +01:00
eaa97f0598 update readme 2018-03-17 17:52:01 +01:00
cde8270313 1.1.14 2018-03-17 17:18:59 +01:00
1b073ac8f6 update readme 2018-03-17 17:18:53 +01:00
3f3857df1e 1.1.13 2018-03-15 02:29:44 +01:00
02e17a52c3 update to latest standards 2018-03-15 02:29:40 +01:00
287c2a73c5 1.1.12 2017-10-09 16:46:24 +02:00
dea3746bb0 allow setting of specific server 2017-10-09 10:40:59 +02:00
fc2a55bb0d fix not ending error correctly 2017-10-09 10:28:18 +02:00
99eca912d3 1.1.11 2017-10-09 03:06:14 +02:00
0b6929af8f update to newest version 2017-10-09 03:06:09 +02:00
0aa073f2a7 1.1.10 2017-07-15 23:16:26 +02:00
7170e58457 update smartsocket class to use standard class method definition 2017-07-15 23:16:22 +02:00
cccee35f2c 1.1.9 2017-07-07 22:38:14 +02:00
118ec84ec5 update docs 2017-07-07 22:38:10 +02:00
dd31eea263 update tests 2017-07-07 22:10:03 +02:00
477429143d 1.1.8 2017-07-07 22:03:22 +02:00
ea6fa14133 remove taskbuffer 2017-07-07 22:03:18 +02:00
02065e36a6 update to latest standards 2017-07-07 22:02:19 +02:00
f34358db81 update README 2016-09-26 16:59:06 +02:00
fddf54b2b1 1.1.7 2016-09-26 00:28:45 +02:00
e1dbdc1a15 improve README 2016-09-26 00:28:39 +02:00
f3031a1d4e 1.1.6 2016-09-26 00:23:28 +02:00
47ca497d48 improve README 2016-09-26 00:23:17 +02:00
c7e3c4537b 1.1.5 2016-09-05 00:34:13 +02:00
62b36ab859 fix scoping of socket roles 2016-09-05 00:34:09 +02:00
4563aade16 small syntax fix 2016-09-04 22:20:33 +02:00
47596bfa59 1.1.4 2016-09-03 16:21:00 +02:00
6543d60019 added docs 2016-09-03 16:03:57 +02:00
f0aba45cec 1.1.3 2016-09-03 00:41:52 +02:00
f327fa2784 updated dependencies and exported socketConnection 2016-09-03 00:41:49 +02:00
983b4672fd 1.1.2 2016-08-16 04:48:47 +02:00
c81a41b365 now authenticating sockets by checking the password hash 2016-08-16 04:48:42 +02:00
abe4d22226 1.1.1 2016-08-15 03:47:36 +02:00
87cc238345 update README 2016-08-15 03:47:32 +02:00
475cd12904 1.1.0 2016-08-15 02:36:24 +02:00
84f33fa447 now working in both directions so mesh setups work. 2016-08-15 02:36:17 +02:00
180ae23c9a 1.0.7 2016-08-15 01:38:38 +02:00
7f0fff0bf4 updated tests. Data now flows correctly between socket endpoints 2016-08-15 01:38:28 +02:00
24310b6709 1.0.6 2016-08-14 22:18:09 +02:00
bd8697ac6e reconnect is now working 2016-08-14 22:17:55 +02:00
7b2b2bd151 updated structure 2016-08-14 03:25:26 +02:00
8dfc39be75 update tests 2016-08-12 05:57:32 +02:00
ab2196fd5f update tests:
starting with updating tests to use both server and client side to mimic operation
2016-08-12 05:56:40 +02:00
3afede95fc now handling responses 2016-08-12 05:17:13 +02:00
da510eb87a more structure updates 2016-08-12 03:22:36 +02:00
cb3d7f4d7b update structure 2016-08-12 01:32:57 +02:00
19a883c641 structure update 2016-08-09 23:37:25 +02:00
1f8e1fc7cb some heavy internal refactoring 2016-08-09 18:22:30 +02:00
5109964247 some more logic
request/response abstraction to make transparent function calls happen
2016-08-09 16:33:56 +02:00
f670cae1f8 1.0.5 2016-08-09 11:42:27 +02:00
fee54dfb95 add some more logic 2016-08-09 11:42:21 +02:00
8d58e0b2f3 update structure 2016-08-08 18:20:00 +02:00
38 changed files with 4529 additions and 485 deletions

23
.gitignore vendored
View File

@ -1,3 +1,22 @@
node_modules/ .nogit/
# artifacts
coverage/ coverage/
docs/ public/
pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_web/
dist_serve/
dist_ts_web/
# custom

View File

@ -1,36 +1,119 @@
image: hosttoday/ht-docker-node:npmts # gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: "$CI_BUILD_STAGE"
stages: stages:
- security
- test - test
- release - release
- metadata
testLEGACY: # ====================
stage: test # security stage
# ====================
mirror:
stage: security
script: script:
- npmci test legacy - npmci git mirror
tags: tags:
- docker - docker
- notpriv
snyk:
stage: security
script:
- npmci npm prepare
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags:
- docker
- notpriv
# ====================
# test stage
# ====================
testLTS: testLTS:
stage: test stage: test
script: script:
- npmci test lts - npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
testSTABLE: testBuild:
stage: test stage: test
script: script:
- npmci test stable - npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
release: release:
stage: release stage: release
environment: npmjs-com_registry
script: script:
- npmci publish - npmci node install lts
- npmci npm publish
only: only:
- tags - tags
tags: tags:
- docker - docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
allow_failure: true
script:
- npmci command npm install -g tslint typescript
- npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags:
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- docker
- notpriv
pages:
image: hosttoday/ht-docker-dbase:npmci
services:
- docker:18-dind
stage: metadata
script:
- npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command tsdoc
tags:
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public
allow_failure: true

13
.snyk Normal file
View File

@ -0,0 +1,13 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.13.5
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-JSYAML-173999:
- '@pushrocks/smartexpress > @pushrocks/smartfile > js-yaml':
reason: None given
expires: '2019-05-24T15:16:11.291Z'
SNYK-JS-JSYAML-174129:
- '@pushrocks/smartexpress > @pushrocks/smartfile > js-yaml':
reason: None given
expires: '2019-05-24T15:16:11.291Z'
patch: {}

29
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,29 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "current file",
"type": "node",
"request": "launch",
"args": [
"${relativeFile}"
],
"runtimeArgs": ["-r", "@gitzone/tsrun"],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "test.ts",
"type": "node",
"request": "launch",
"args": [
"test/test.ts"
],
"runtimeArgs": ["-r", "@gitzone/tsrun"],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"internalConsoleOptions": "openOnSessionStart"
}
]
}

118
README.md
View File

@ -1,67 +1,111 @@
# smartsocket # @pushrocks/smartsocket
easy and secure websocket communication, Typescript ready easy and secure websocket communication
## Status ## Availabililty and Links
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartsocket)
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartsocket)
* [github.com (source mirror)](https://github.com/pushrocks/smartsocket)
* [docs (typedoc)](https://pushrocks.gitlab.io/smartsocket/)
## Status for master
[![build status](https://gitlab.com/pushrocks/smartsocket/badges/master/build.svg)](https://gitlab.com/pushrocks/smartsocket/commits/master) [![build status](https://gitlab.com/pushrocks/smartsocket/badges/master/build.svg)](https://gitlab.com/pushrocks/smartsocket/commits/master)
[![coverage report](https://gitlab.com/pushrocks/smartsocket/badges/master/coverage.svg)](https://gitlab.com/pushrocks/smartsocket/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@pushrocks/smartsocket.svg)](https://www.npmjs.com/package/@pushrocks/smartsocket)
[![Known Vulnerabilities](https://snyk.io/test/npm/@pushrocks/smartsocket/badge.svg)](https://snyk.io/test/npm/@pushrocks/smartsocket)
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
## Usage ## Usage
We recommend the use of typescript.
Use TypeScript for best in class instellisense.
Under the hood we use socket.io and shortid for managed data exchange. Under the hood we use socket.io and shortid for managed data exchange.
### Serverside ### Serverside
```typescript
import * as smartsocket from "smartsocket";
```typescript
import * as smartsocket from 'smartsocket';
import * as q from q; // q is a promise library
// The "Smartsocket" listens on a port and can receive new "SocketConnection" requests.
let mySmartsocket = new smartsocket.Smartsocket({ let mySmartsocket = new smartsocket.Smartsocket({
port: 3000 // the port smartsocket will listen on port: 3000 // the port smartsocket will listen on
}); });
// optional:
// run this with anothoer existing server like express
declare var someExpressServer; // read the express docs about how express actually works
mySmartsocket.setServer(someExpressServer);
// A "SocketRole" can be referenced by "SocketFunction"s.
// All "SocketRequest"s carry authentication data for a specific "SocketRole".
// "SocketFunction"s know which "SocketRole"s are allowed to execute them
let mySocketRole = new smartsocket.SocketRole({ let mySocketRole = new smartsocket.SocketRole({
name: "someRoleName", name: 'someRoleName',
passwordHash: "someHashedString" passwordHash: 'someHashedString'
}); });
let mySocketFunction = new smartsocket.SocketFunction({ // A "SocketFunction" executes a referenced function and passes in any data of the corresponding "SocketRequest".
name:"newService", // The referenced function must return a promise and resolve with data of type any.
func:(data) => { // Any "SocketRequest" carries a unique identifier. If the referenced function's promise resolved any passed on argument will be returned to the requesting party
let testSocketFunction1 = new smartsocket.SocketFunction({
}, the function to execute funcName: 'testSocketFunction1',
roles:[mySocketRole] // all roles that have access to a specific function funcDef: data => {
console.log('testSocketFunction1 executed successfully!');
},
allowedRoles: [mySocketRole] // all roles that have access to a specific function
}); });
mySmartsocket.registerRole(mySocketRole); // A "Smartsocket" exposes a .clientCall() that gets
mySmartsocket.clientCall.select("client1","restart",data) // 1. the name of the "SocketFunction" on the client side
.then((responseData) => { // 2. the data to pass in
// 3. And a target "SocketConnection" (there can be multiple connections at once)
}); // any unique id association is done internally
mySmartsocket.clientCall('restart', data, someTargetConnection).then(responseData => {});
``` ```
#### Client side #### Client side
```typescript ```typescript
import * as smartsocket from "smartsocket"; import * as smartsocket from 'smartsocket';
let mySmartsocketClient = new smartsocket.SmartsocketClient({ // A "SmartsocketClient" is different from a "Smartsocket" in that it doesn't expose any public address.
url: "somedomain.com", // url, note: will only work over https, no http supported. // Thus any new "SocketConnection"s must be innitiated from a "SmartsocketClient".
port: 3000 let testSmartsocketClient = new smartsocket.SmartsocketClient({
role:"dockerhost", // some role, in this example a dockerhost vm, port: testConfig.port,
password:"somePassword", url: 'http://localhost',
alias:"client1" password: 'testPassword',
alias: 'testClient1',
role: 'testRole1'
}); });
let mySocketFunction2 = new smartsocket.SocketFunction({ // You can .connect() and .disconnect() from a "Smartsocket"
name:"restart", testSmartsocketClient.connect().then(() => {
func:(data) => {}, the function to execute done();
}); });
mySmartsocketClient.registerFunction(mySocketFunction2); // The client can also specify "SocketFunction"s. It can also specify "SocketRole"s in case a client connects to multiple servers at once
let testSocketFunction2 = new smartsocket.SocketFunction({
funcName: 'testSocketFunction2',
funcDef: data => {}, // the function to execute, has to return promise
allowedRoles: []
});
mySmartsocketClient.serverCall("newService",data) // A "SmartsocketClient" can call functions on the serverside using .serverCall() analog to the "Smartsocket"'s .clientCall method.
.then((responseData) => { mySmartsocketClient.serverCall('function', functionCallData).then(functionResponseData => {
// the functionResponseData comes from the server... awesome, right?
});; });
``` ```
> **NOTE:** > **NOTE:**
you can easily chain dependent requests on eiter the server or client side with promises. > you can easily chain dependent requests on either the server or client side with promises.
`data` is always a js object that you can design for your specific needs. > `data` is always a js object that you can design for your specific needs.
It supports buffers for large binary data network exchange. > It supports buffers for large binary data network exchange.
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

2
dist/index.d.ts vendored
View File

@ -1,2 +0,0 @@
export * from "./smartsocket.classes.smartsocket";
export * from "./smartsocket.classes.smartsocketclient";

7
dist/index.js vendored
View File

@ -1,7 +0,0 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require("./smartsocket.classes.smartsocket"));
__export(require("./smartsocket.classes.smartsocketclient"));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBRUEsaUJBQWMsbUNBQW1DLENBQUMsRUFBQTtBQUNsRCxpQkFBYyx5Q0FBeUMsQ0FBQyxFQUFBIn0=

View File

@ -1,29 +0,0 @@
/// <reference types="socket.io" />
import { Objectmap } from "lik";
import { SocketRole } from "./smartsocket.classes.socketrole";
export interface ISocketObject {
alias?: string;
authenticated: boolean;
role?: string;
socket: SocketIO.Socket;
}
export interface ISmartsocketConstructorOptions {
port: number;
}
export declare class Smartsocket {
options: ISmartsocketConstructorOptions;
io: SocketIO.Server;
openSockets: Objectmap;
registeredRoles: Objectmap;
constructor(optionsArg: ISmartsocketConstructorOptions);
/**
* the standard handler for new socket connections
*/
private _handleSocket(socket);
registerFunctions(socketRoleArg: SocketRole): void;
/**
* starts listening to incling sockets:
*/
startServer: () => void;
closeServer: () => void;
}

View File

@ -1,51 +0,0 @@
"use strict";
const plugins = require("./smartsocket.plugins");
const helpers = require("./smartsocket.helpers");
// classes
const lik_1 = require("lik");
;
;
class Smartsocket {
constructor(optionsArg) {
this.openSockets = new lik_1.Objectmap();
this.registeredRoles = new lik_1.Objectmap();
/**
* starts listening to incling sockets:
*/
this.startServer = () => {
this.io = plugins.socketIo(this.options.port);
this.io.on('connection', (socketArg) => {
this._handleSocket(socketArg);
});
};
this.closeServer = () => {
this.openSockets.forEach((socketObjectArg) => {
plugins.beautylog.log(`disconnect socket with >>alias ${socketObjectArg.alias}`);
socketObjectArg.socket.disconnect();
});
this.openSockets.wipe();
this.io.close();
};
this.options = optionsArg;
}
;
/**
* the standard handler for new socket connections
*/
_handleSocket(socket) {
let socketObject = {
socket: socket,
authenticated: false
};
plugins.beautylog.log("Socket connected. Trying to authenticate...");
this.openSockets.add(socketObject);
helpers.authenticateSocket(socketObject)
.then();
}
registerFunctions(socketRoleArg) {
this.registeredRoles.add(socketRoleArg);
}
;
}
exports.Smartsocket = Smartsocket;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zbWFydHNvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmNsYXNzZXMuc21hcnRzb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHVCQUF1QixDQUFDLENBQUE7QUFDakQsTUFBWSxPQUFPLFdBQU0sdUJBQXVCLENBQUMsQ0FBQTtBQUVqRCxVQUFVO0FBQ1Ysc0JBQTBCLEtBQUssQ0FBQyxDQUFBO0FBVS9CLENBQUM7QUFLRCxDQUFDO0FBRUY7SUFLSSxZQUFZLFVBQTBDO1FBRnRELGdCQUFXLEdBQUcsSUFBSSxlQUFTLEVBQUUsQ0FBQztRQUM5QixvQkFBZSxHQUFHLElBQUksZUFBUyxFQUFFLENBQUM7UUF3QmxDOztXQUVHO1FBRUgsZ0JBQVcsR0FBRztZQUNWLElBQUksQ0FBQyxFQUFFLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDLFNBQVM7Z0JBQy9CLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDbEMsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUE7UUFDRCxnQkFBVyxHQUFHO1lBQ1YsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxlQUE4QjtnQkFDcEQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsa0NBQWtDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNqRixlQUFlLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3hDLENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQTtRQXZDRyxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztJQUM5QixDQUFDOztJQUVEOztPQUVHO0lBQ0ssYUFBYSxDQUFDLE1BQU07UUFDeEIsSUFBSSxZQUFZLEdBQWtCO1lBQzlCLE1BQU0sRUFBRSxNQUFNO1lBQ2QsYUFBYSxFQUFFLEtBQUs7U0FDdkIsQ0FBQztRQUNGLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLDZDQUE2QyxDQUFDLENBQUE7UUFDcEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbkMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQzthQUNuQyxJQUFJLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRUQsaUJBQWlCLENBQUMsYUFBd0I7UUFDdEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDNUMsQ0FBQzs7QUFxQkwsQ0FBQztBQTlDWSxtQkFBVyxjQThDdkIsQ0FBQSJ9

View File

@ -1,10 +0,0 @@
/**
* interface for class SmartsocketClient
*/
export interface ISmartsocketClientOptions {
port: number;
url: string;
}
export declare class SmartsocketClient {
constructor();
}

View File

@ -1,7 +0,0 @@
"use strict";
class SmartsocketClient {
constructor() {
}
}
exports.SmartsocketClient = SmartsocketClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zbWFydHNvY2tldGNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmNsYXNzZXMuc21hcnRzb2NrZXRjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQVVBO0lBQ0k7SUFFQSxDQUFDO0FBQ0wsQ0FBQztBQUpZLHlCQUFpQixvQkFJN0IsQ0FBQSJ9

View File

@ -1,12 +0,0 @@
import { SocketRole } from "./smartsocket.classes.socketrole";
export interface SocketFunctionOptions {
name: string;
func: any;
roles: SocketRole[];
}
export declare class SocketFunction {
name: string;
func: any;
roles: SocketRole[];
constructor(optionsArg: SocketFunctionOptions);
}

View File

@ -1,12 +0,0 @@
"use strict";
;
class SocketFunction {
constructor(optionsArg) {
this.name = optionsArg.name;
this.func = optionsArg.func;
this.roles = optionsArg.roles;
}
;
}
exports.SocketFunction = SocketFunction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRmdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmNsYXNzZXMuc29ja2V0ZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQVlDLENBQUM7QUFFRjtJQUlJLFlBQVksVUFBaUM7UUFDekMsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQztRQUM1QixJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7SUFDbEMsQ0FBQzs7QUFDTCxDQUFDO0FBVFksc0JBQWMsaUJBUzFCLENBQUEifQ==

View File

@ -1,15 +0,0 @@
/**
* interface for class SocketRole
*/
export interface SocketRoleOptions {
name: string;
passwordHash: string;
}
/**
* A socketrole defines access to certain routines.
*/
export declare class SocketRole {
name: string;
passwordHash: string;
constructor(optionsArg: SocketRoleOptions);
}

View File

@ -1,12 +0,0 @@
"use strict";
/**
* A socketrole defines access to certain routines.
*/
class SocketRole {
constructor(optionsArg) {
this.name = optionsArg.name;
this.passwordHash = optionsArg.passwordHash;
}
}
exports.SocketRole = SocketRole;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyb2xlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFjQTs7R0FFRztBQUNIO0lBR0ksWUFBWSxVQUE0QjtRQUNwQyxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDNUIsSUFBSSxDQUFDLFlBQVksR0FBRyxVQUFVLENBQUMsWUFBWSxDQUFDO0lBQ2hELENBQUM7QUFDTCxDQUFDO0FBUFksa0JBQVUsYUFPdEIsQ0FBQSJ9

View File

@ -1,7 +0,0 @@
/// <reference types="q" />
import * as plugins from "./smartsocket.plugins";
import { ISocketObject } from "./smartsocket.classes.smartsocket";
/**
* authenticate a socket
*/
export declare let authenticateSocket: (socketObjectArg: ISocketObject) => plugins.q.Promise<{}>;

View File

@ -1,28 +0,0 @@
"use strict";
const plugins = require("./smartsocket.plugins");
/**
* authenticate a socket
*/
exports.authenticateSocket = (socketObjectArg) => {
let done = plugins.q.defer();
socketObjectArg.socket.on("dataAuth", dataArg => {
plugins.beautylog.log("received authentication data. now hashing and comparing...");
socketObjectArg.socket.removeListener("dataAuth", () => { });
if ((true)) {
socketObjectArg.alias = dataArg.alias;
socketObjectArg.authenticated = true;
socketObjectArg.role = dataArg.role;
socketObjectArg.socket.emit("authenticated");
plugins.beautylog.ok(`socket with >>alias ${socketObjectArg.alias} >>role ${socketObjectArg.role} is authenticated!`);
done.resolve(socketObjectArg);
}
else {
socketObjectArg.socket.disconnect();
done.reject("not authenticated");
}
;
});
socketObjectArg.socket.emit("requestAuth");
return done.promise;
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHVCQUF1QixDQUFDLENBQUE7QUFRakQ7O0dBRUc7QUFDUSwwQkFBa0IsR0FBRyxDQUFDLGVBQThCO0lBQzNELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDN0IsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLE9BQU87UUFDekMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsNERBQTRELENBQUMsQ0FBQztRQUNwRixlQUFlLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUM3RCxFQUFFLENBQUEsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUEsQ0FBQztZQUNQLGVBQWUsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQTtZQUNyQyxlQUFlLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztZQUNyQyxlQUFlLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDcEMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDN0MsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsdUJBQXVCLGVBQWUsQ0FBQyxLQUFLLFdBQVcsZUFBZSxDQUFDLElBQUksb0JBQW9CLENBQUMsQ0FBQTtZQUNySCxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ2xDLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNKLGVBQWUsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFBQSxDQUFDO0lBQ04sQ0FBQyxDQUFDLENBQUM7SUFDSCxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMzQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztBQUN4QixDQUFDLENBQUMifQ==

View File

@ -1,7 +0,0 @@
import "typings-global";
export import beautylog = require("beautylog");
export import lik = require("lik");
export import q = require("q");
export import socketIo = require("socket.io");
export import socketIoClient = require("socket.io-client");
export import taskbuffer = require("taskbuffer");

View File

@ -1,9 +0,0 @@
"use strict";
require("typings-global");
exports.beautylog = require("beautylog");
exports.lik = require("lik");
exports.q = require("q");
exports.socketIo = require("socket.io");
exports.socketIoClient = require("socket.io-client");
exports.taskbuffer = require("taskbuffer");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sZ0JBQWdCLENBQUMsQ0FBQTtBQUNWLGlCQUFTLFdBQVcsV0FBVyxDQUFDLENBQUM7QUFDakMsV0FBRyxXQUFZLEtBQUssQ0FBQyxDQUFDO0FBQ3RCLFNBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztBQUNqQixnQkFBUSxXQUFXLFdBQVcsQ0FBQyxDQUFDO0FBQ2hDLHNCQUFjLFdBQVcsa0JBQWtCLENBQUMsQ0FBQztBQUM3QyxrQkFBVSxXQUFXLFlBQVksQ0FBQyxDQUFDIn0=

17
npmextra.json Normal file
View File

@ -0,0 +1,17 @@
{
"gitzone": {
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"gitrepo": "smartsocket",
"shortDescription": "easy and secure websocket communication",
"npmPackagename": "@pushrocks/smartsocket",
"license": "MIT",
"projectDomain": "push.rocks"
}
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public"
}
}

3290
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
{ {
"name": "smartsocket", "name": "@pushrocks/smartsocket",
"version": "1.0.4", "version": "1.1.41",
"description": "easy and secure websocket communication, Typescript ready", "description": "easy and secure websocket communication",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"scripts": { "scripts": {
"test": "(npmts)" "test": "tstest test/",
"build": "tsbuild"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -18,19 +19,38 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartsocket#README", "homepage": "https://gitlab.com/pushrocks/smartsocket#README",
"dependencies": { "dependencies": {
"@types/q": "0.x.x", "@pushrocks/lik": "^3.0.10",
"@types/socket.io": "^1.4.26", "@pushrocks/smartdelay": "^2.0.3",
"@types/socket.io-client": "^1.4.26", "@pushrocks/smartexpress": "^3.0.38",
"beautylog": "^5.0.20", "@pushrocks/smarthash": "^2.0.6",
"lik": "^1.0.10", "@pushrocks/smartlog": "^2.0.19",
"q": "^1.4.1", "@pushrocks/smartpromise": "^3.0.2",
"socket.io": "^1.4.8", "@types/shortid": "0.0.29",
"socket.io-client": "^1.4.8", "@types/socket.io": "^2.1.2",
"taskbuffer": "^1.0.7" "@types/socket.io-client": "^1.4.32",
"shortid": "^2.2.14",
"socket.io": "^2.2.0",
"socket.io-client": "^2.2.0"
}, },
"devDependencies": { "devDependencies": {
"npmts-g": "^5.2.8", "@gitzone/tsbuild": "^2.1.11",
"should": "^10.0.0", "@gitzone/tsrun": "^1.2.8",
"typings-test": "^1.0.1" "@gitzone/tstest": "^1.0.24",
} "@pushrocks/tapbundle": "^3.0.11",
"@types/node": "^12.7.1",
"tslint": "^5.18.0",
"tslint-config-prettier": "^1.18.0"
},
"private": false,
"files": [
"ts/*",
"ts_web/*",
"dist/*",
"dist_web/*",
"dist_ts_web/*",
"assets/*",
"cli.js",
"npmextra.json",
"readme.md"
]
} }

1
test/common/test.ts Normal file
View File

@ -0,0 +1 @@
console.log('TODO');

2
test/test.d.ts vendored
View File

@ -1,2 +0,0 @@
import "typings-test";
import "should";

106
test/test.expressserver.ts Normal file
View File

@ -0,0 +1,106 @@
// tslint:disable-next-line:no-implicit-dependencies
import { expect, tap } from '@pushrocks/tapbundle';
import * as smarthash from '@pushrocks/smarthash';
import * as smartpromise from '@pushrocks/smartpromise';
import * as smartexpress from '@pushrocks/smartexpress';
import socketIoClient = require('socket.io-client');
import smartsocket = require('../ts/index');
let testSmartsocket: smartsocket.Smartsocket;
let testSmartsocketClient: smartsocket.SmartsocketClient;
let testSocketRole1: smartsocket.SocketRole;
let testSocketFunction1: smartsocket.SocketFunction;
let myseServer: smartexpress.Server;
const testConfig = {
port: 3000
};
// class smartsocket
tap.test('should create a new smartsocket', async () => {
testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
expect(testSmartsocket).be.instanceOf(smartsocket.Smartsocket);
});
tap.test('Should accept an smartExpressServer as server', async () => {
myseServer = new smartexpress.Server({
cors: true,
forceSsl: false,
port: testConfig.port
});
testSmartsocket.setExternalServer('smartexpress', myseServer);
await myseServer.start();
});
// class socketrole
tap.test('should add a socketrole', async () => {
testSocketRole1 = new smartsocket.SocketRole({
name: 'testRole1',
passwordHash: smarthash.sha256FromStringSync('testPassword')
});
testSmartsocket.addSocketRoles([testSocketRole1]);
});
// class SocketFunction
tap.test('should register a new Function', async () => {
testSocketFunction1 = new smartsocket.SocketFunction({
allowedRoles: [testSocketRole1],
funcDef: async (dataArg, socketConnectionArg) => {
return dataArg;
},
funcName: 'testFunction1'
});
testSmartsocket.addSocketFunction(testSocketFunction1);
console.log(testSmartsocket.socketFunctions);
});
tap.test('should start listening when .started is called', async () => {
await testSmartsocket.start();
});
// class SmartsocketClient
tap.test('should react to a new websocket connection from client', async () => {
testSmartsocketClient = new smartsocket.SmartsocketClient({
port: testConfig.port,
url: 'http://localhost',
password: 'testPassword',
alias: 'testClient1',
role: 'testRole1'
});
testSmartsocketClient.addSocketFunction(testSocketFunction1);
console.log(testSmartsocketClient.socketFunctions);
await testSmartsocketClient.connect();
});
tap.test('client should disconnect and reconnect', async tools => {
await testSmartsocketClient.disconnect();
await tools.delayFor(100);
await testSmartsocketClient.connect();
});
tap.test('2 clients should connect in parallel', async () => {
// TODO: implement parallel test
});
tap.test('should be able to make a functionCall from client to server', async () => {
const response = await testSmartsocketClient.serverCall('testFunction1', {
value1: 'hello'
});
console.log(response);
});
tap.test('should be able to make a functionCall from server to client', async () => {
});
// terminate
tap.test('should close the server', async () => {
await testSmartsocket.stop();
await myseServer.stop();
});
tap.start();

View File

@ -1,37 +0,0 @@
"use strict";
require("typings-test");
require("should");
const socketIoClient = require("socket.io-client");
const smartsocket = require("../dist/index");
let testSmartsocket;
describe("smartsocket", function () {
it("should create a new smartsocket", function () {
testSmartsocket = new smartsocket.Smartsocket({ port: 3000 });
testSmartsocket.should.be.instanceOf(smartsocket.Smartsocket);
});
it("should register a new Function", function () {
});
it("should start listening when .started is called", function () {
testSmartsocket.startServer();
});
it("should react to a new websocket connection", function (done) {
this.timeout(10000);
let socket = socketIoClient("http://localhost:3000", {});
socket.on("requestAuth", function () {
console.log("server requested authentication");
socket.emit("dataAuth", {
role: "coreflowContainer",
password: "somePassword",
alias: "coreflow1"
});
socket.on("authenticated", () => {
console.log("client is authenticated");
done();
});
});
});
it("should close the server", function () {
testSmartsocket.closeServer();
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQixNQUFPLGNBQWMsV0FBVyxrQkFBa0IsQ0FBQyxDQUFDO0FBQ3BELE1BQU8sV0FBVyxXQUFXLGVBQWUsQ0FBQyxDQUFDO0FBRTlDLElBQUksZUFBd0MsQ0FBQztBQUU3QyxRQUFRLENBQUMsYUFBYSxFQUFFO0lBQ3BCLEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRTtRQUNsQyxlQUFlLEdBQUcsSUFBSSxXQUFXLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUQsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNsRSxDQUFDLENBQUMsQ0FBQztJQUNILEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBQztJQUVwQyxDQUFDLENBQUMsQ0FBQTtJQUNGLEVBQUUsQ0FBQyxnREFBZ0QsRUFBQztRQUNoRCxlQUFlLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUE7SUFDRixFQUFFLENBQUMsNENBQTRDLEVBQUUsVUFBVSxJQUFJO1FBQzNELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEIsSUFBSSxNQUFNLEdBQUcsY0FBYyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFO1lBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUNBQWlDLENBQUMsQ0FBQztZQUMvQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDcEIsSUFBSSxFQUFFLG1CQUFtQjtnQkFDekIsUUFBUSxFQUFFLGNBQWM7Z0JBQ3hCLEtBQUssRUFBRSxXQUFXO2FBQ3JCLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFDO2dCQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLENBQUM7Z0JBQ3ZDLElBQUksRUFBRSxDQUFDO1lBQ1gsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUFDO0lBQ0gsRUFBRSxDQUFDLHlCQUF5QixFQUFDO1FBQ3pCLGVBQWUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNsQyxDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQyxDQUFDIn0=

View File

@ -1,38 +1,94 @@
import "typings-test"; // tslint:disable-next-line:no-implicit-dependencies
import "should"; import { expect, tap } from '@pushrocks/tapbundle';
import socketIoClient = require("socket.io-client");
import smartsocket = require("../dist/index"); import * as smarthash from '@pushrocks/smarthash';
import * as smartpromise from '@pushrocks/smartpromise';
import socketIoClient = require('socket.io-client');
import smartsocket = require('../ts/index');
let testSmartsocket: smartsocket.Smartsocket; let testSmartsocket: smartsocket.Smartsocket;
let testSmartsocketClient: smartsocket.SmartsocketClient;
let testSocketRole1: smartsocket.SocketRole;
let testSocketFunction1: smartsocket.SocketFunction;
describe("smartsocket", function () { const testConfig = {
it("should create a new smartsocket", function () { port: 3000
testSmartsocket = new smartsocket.Smartsocket({ port: 3000 }); };
testSmartsocket.should.be.instanceOf(smartsocket.Smartsocket);
});
it("should register a new Function",function(){
}) // class smartsocket
it("should start listening when .started is called",function(){ tap.test('should create a new smartsocket', async () => {
testSmartsocket.startServer(); testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
}) expect(testSmartsocket).be.instanceOf(smartsocket.Smartsocket);
it("should react to a new websocket connection", function (done) {
this.timeout(10000);
let socket = socketIoClient("http://localhost:3000", {});
socket.on("requestAuth", function () {
console.log("server requested authentication");
socket.emit("dataAuth", {
role: "coreflowContainer",
password: "somePassword",
alias: "coreflow1"
}); });
socket.on("authenticated",() => {
console.log("client is authenticated"); // class socketrole
done(); tap.test('should add a socketrole', async () => {
testSocketRole1 = new smartsocket.SocketRole({
name: 'testRole1',
passwordHash: smarthash.sha256FromStringSync('testPassword')
}); });
testSmartsocket.addSocketRoles([testSocketRole1]);
}); });
// class SocketFunction
tap.test('should register a new Function', async () => {
testSocketFunction1 = new smartsocket.SocketFunction({
allowedRoles: [testSocketRole1],
funcDef: async (dataArg, socketConnectionArg) => {
return dataArg;
},
funcName: 'testFunction1'
}); });
it("should close the server",function(){ testSmartsocket.addSocketFunction(testSocketFunction1);
testSmartsocket.closeServer(); console.log(testSmartsocket.socketFunctions);
})
}); });
tap.test('should start listening when .started is called', async () => {
await testSmartsocket.start();
});
// class SmartsocketClient
tap.test('should react to a new websocket connection from client', async () => {
testSmartsocketClient = new smartsocket.SmartsocketClient({
port: testConfig.port,
url: 'http://localhost',
password: 'testPassword',
alias: 'testClient1',
role: 'testRole1'
});
testSmartsocketClient.addSocketFunction(testSocketFunction1);
console.log(testSmartsocketClient.socketFunctions);
await testSmartsocketClient.connect();
});
tap.test('client should disconnect and reconnect', async tools => {
await testSmartsocketClient.disconnect();
await tools.delayFor(100);
await testSmartsocketClient.connect();
});
tap.test('2 clients should connect in parallel', async () => {
// TODO: implement parallel test
});
tap.test('should be able to make a functionCall from client to server', async () => {
const response = await testSmartsocketClient.serverCall('testFunction1', {
value1: 'hello'
});
console.log(response);
});
tap.test('should be able to make a functionCall from server to client', async () => {
const response = await testSmartsocketClient.serverCall('testFunction1', {
hi: 'hi there from client'
});
console.log(response);
});
// terminate
tap.test('should close the server', async () => {
await testSmartsocket.stop();
});
tap.start();

View File

@ -1,4 +1,10 @@
import * as plugins from "./smartsocket.plugins"; import * as plugins from './smartsocket.plugins';
export * from "./smartsocket.classes.smartsocket"; // export main classes
export * from "./smartsocket.classes.smartsocketclient"; export * from './smartsocket.classes.smartsocket';
export * from './smartsocket.classes.smartsocketclient';
// export further classes and objects
export * from './smartsocket.classes.socketfunction';
export * from './smartsocket.classes.socketrole';
export * from './smartsocket.classes.socketconnection';

View File

@ -1,68 +1,131 @@
import * as plugins from "./smartsocket.plugins"; import * as plugins from './smartsocket.plugins';
import * as helpers from "./smartsocket.helpers";
// classes // classes
import { Objectmap } from "lik"; import { Objectmap } from '@pushrocks/lik';
import {SocketRole} from "./smartsocket.classes.socketrole"; import { SocketConnection } from './smartsocket.classes.socketconnection';
import {SocketFunction} from "./smartsocket.classes.socketfunction"; import { ISocketFunctionCall, SocketFunction } from './smartsocket.classes.socketfunction';
import { SocketRequest } from './smartsocket.classes.socketrequest';
import { SocketRole } from './smartsocket.classes.socketrole';
import { SocketServer } from './smartsocket.classes.socketserver';
// socket.io
export interface ISocketObject { import * as SocketIO from 'socket.io';
alias?:string;
authenticated: boolean
role?:string,
socket: SocketIO.Socket,
};
export interface ISmartsocketConstructorOptions { export interface ISmartsocketConstructorOptions {
port: number; port?: number;
}
};
export class Smartsocket { export class Smartsocket {
options:ISmartsocketConstructorOptions public options: ISmartsocketConstructorOptions;
io: SocketIO.Server; public io: SocketIO.Server;
openSockets = new Objectmap(); public openSockets = new Objectmap<SocketConnection>();
registeredRoles = new Objectmap(); public socketRoles = new Objectmap<SocketRole>();
public socketFunctions = new Objectmap<SocketFunction>();
public socketRequests = new Objectmap<SocketRequest>();
private socketServer = new SocketServer(this);
constructor(optionsArg: ISmartsocketConstructorOptions) { constructor(optionsArg: ISmartsocketConstructorOptions) {
this.options = optionsArg; this.options = optionsArg;
};
/**
* the standard handler for new socket connections
*/
private _handleSocket(socket) {
let socketObject: ISocketObject = {
socket: socket,
authenticated: false
};
plugins.beautylog.log("Socket connected. Trying to authenticate...")
this.openSockets.add(socketObject);
helpers.authenticateSocket(socketObject)
.then();
} }
registerFunctions(socketRoleArg:SocketRole){ // tslint:disable-next-line:member-ordering
this.registeredRoles.add(socketRoleArg); public async setExternalServer(serverType: 'smartexpress', serverArg: any) {
}; await this.socketServer.setExternalServer(serverType, serverArg);
}
/** /**
* starts listening to incling sockets: * starts smartsocket
*/ */
public async start() {
startServer = () => { this.io = plugins.socketIo(this.socketServer.getServerForSocketIo());
this.io = plugins.socketIo(this.options.port); await this.socketServer.start();
this.io.on('connection', (socketArg) => { this.io.on('connection', socketArg => {
this._handleSocket(socketArg); this._handleSocketConnection(socketArg);
}); });
} }
closeServer = () => {
this.openSockets.forEach((socketObjectArg: ISocketObject) => { /**
plugins.beautylog.log(`disconnect socket with >>alias ${socketObjectArg.alias}`); * stops smartsocket
*/
public async stop() {
await plugins.smartdelay.delayFor(1000);
this.openSockets.forEach((socketObjectArg: SocketConnection) => {
plugins.smartlog.defaultLogger.log(
'info',
`disconnect socket with >>alias ${socketObjectArg.alias}`
);
socketObjectArg.socket.disconnect(); socketObjectArg.socket.disconnect();
}); });
this.openSockets.wipe(); this.openSockets.wipe();
this.io.close(); this.io.close();
// stop the corresponging server
this.socketServer.stop();
}
// communication
/**
* allows call to specific client.
*/
public async clientCall(
functionNameArg: string,
dataArg: any,
targetSocketConnectionArg: SocketConnection
) {
const done = plugins.smartpromise.defer();
const socketRequest = new SocketRequest(this, {
funcCallData: {
funcDataArg: dataArg,
funcName: functionNameArg
},
originSocketConnection: targetSocketConnectionArg,
shortId: plugins.shortid.generate(),
side: 'requesting'
});
socketRequest.dispatch().then((dataArg2: ISocketFunctionCall) => {
done.resolve(dataArg2.funcDataArg);
});
const result = await done.promise;
return result;
}
/**
* adds socketRoles
*/
public addSocketRoles(socketRolesArray: SocketRole[]): void {
for (const socketRole of socketRolesArray) {
this.socketRoles.add(socketRole);
}
return;
}
public addSocketFunction(socketFunction: SocketFunction) {
this.socketFunctions.add(socketFunction);
}
/**
* the standard handler for new socket connections
*/
private _handleSocketConnection(socketArg) {
const socketConnection: SocketConnection = new SocketConnection({
alias: undefined,
authenticated: false,
role: undefined,
side: 'server',
smartsocketHost: this,
socket: socketArg
});
plugins.smartlog.defaultLogger.log('info', 'Socket connected. Trying to authenticate...');
this.openSockets.add(socketConnection);
socketConnection
.authenticate()
.then(() => {
return socketConnection.listenToFunctionRequests();
})
.catch(err => {
console.log(err);
});
} }
} }

View File

@ -1,4 +1,9 @@
import * as plugins from "./smartsocket.plugins" import * as plugins from './smartsocket.plugins';
import { SocketConnection } from './smartsocket.classes.socketconnection';
import { ISocketFunctionCall, SocketFunction } from './smartsocket.classes.socketfunction';
import { ISocketRequestDataObject, SocketRequest } from './smartsocket.classes.socketrequest';
import { SocketRole } from './smartsocket.classes.socketrole';
/** /**
* interface for class SmartsocketClient * interface for class SmartsocketClient
@ -6,10 +11,90 @@ import * as plugins from "./smartsocket.plugins"
export interface ISmartsocketClientOptions { export interface ISmartsocketClientOptions {
port: number; port: number;
url: string; url: string;
alias: string; // an alias makes it easier to identify this client in a multo client environment
role: string;
password: string; // by setting a password access to functions can be limited
} }
export class SmartsocketClient { export class SmartsocketClient {
constructor(){ public alias: string;
public role: string;
public socketConnection: SocketConnection;
public serverUrl: string;
public serverPort: number;
public serverPassword: string;
public socketFunctions = new plugins.lik.Objectmap<SocketFunction>();
public socketRequests = new plugins.lik.Objectmap<SocketRequest>();
public socketRoles = new plugins.lik.Objectmap<SocketRole>();
constructor(optionsArg: ISmartsocketClientOptions) {
this.alias = optionsArg.alias;
this.role = optionsArg.role;
this.serverUrl = optionsArg.url;
this.serverPort = optionsArg.port;
this.serverPassword = optionsArg.password;
}
public addSocketFunction(socketFunction: SocketFunction) {
this.socketFunctions.add(socketFunction);
}
/**
* connect the client to the server
*/
public connect() {
const done = plugins.smartpromise.defer();
plugins.smartlog.defaultLogger.log('info', 'trying to connect...');
const socketUrl = `${this.serverUrl}:${this.serverPort}`;
this.socketConnection = new SocketConnection({
alias: this.alias,
authenticated: false,
role: undefined,
side: 'client',
smartsocketHost: this,
socket: plugins.socketIoClient(socketUrl, { multiplex: false })
});
this.socketConnection.socket.on('requestAuth', () => {
console.log('server requested authentication');
this.socketConnection.socket.emit('dataAuth', {
role: this.role,
password: this.serverPassword,
alias: this.alias
});
this.socketConnection.socket.on('authenticated', () => {
console.log('client is authenticated');
this.socketConnection.authenticated = true;
this.socketConnection.listenToFunctionRequests();
done.resolve();
});
});
return done.promise;
}
public disconnect() {
const done = plugins.smartpromise.defer();
this.socketConnection.socket.disconnect();
this.socketConnection = undefined;
plugins.smartlog.defaultLogger.log('ok', 'disconnected!');
done.resolve();
return done.promise;
}
public serverCall(functionNameArg: string, dataArg: any) {
const done = plugins.smartpromise.defer();
const socketRequest = new SocketRequest(this, {
side: 'requesting',
originSocketConnection: this.socketConnection,
shortId: plugins.shortid.generate(),
funcCallData: {
funcName: functionNameArg,
funcDataArg: dataArg
}
});
socketRequest.dispatch().then((dataArg2: ISocketFunctionCall) => {
done.resolve(dataArg2.funcDataArg);
});
return done.promise;
} }
} }

View File

@ -0,0 +1,167 @@
import * as plugins from './smartsocket.plugins';
import { Objectmap } from '@pushrocks/lik';
// import classes
import { Smartsocket } from './smartsocket.classes.smartsocket';
import { SocketFunction } from './smartsocket.classes.socketfunction';
import {
SocketRequest,
ISocketRequestDataObject,
} from './smartsocket.classes.socketrequest';
import { SocketRole } from './smartsocket.classes.socketrole';
// socket.io
import * as SocketIO from 'socket.io';
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
// export interfaces
/**
* defines is a SocketConnection is server or client side. Important for mesh setups.
*/
export type TSocketConnectionSide = 'server' | 'client';
/**
* interface for constructor of class SocketConnection
*/
export interface ISocketConnectionConstructorOptions {
alias: string;
authenticated: boolean;
role: SocketRole;
side: TSocketConnectionSide;
smartsocketHost: Smartsocket | SmartsocketClient;
socket: SocketIO.Socket | SocketIOClient.Socket;
}
/**
* interface for authentication data
*/
export interface ISocketConnectionAuthenticationObject {
role: 'coreflowContainer';
password: 'somePassword';
alias: 'coreflow1';
}
// export classes
export let allSocketConnections = new Objectmap<SocketConnection>();
/**
* class SocketConnection represents a websocket connection
*/
export class SocketConnection {
public alias: string;
public side: TSocketConnectionSide;
public authenticated: boolean = false;
public role: SocketRole;
public smartsocketRef: Smartsocket | SmartsocketClient;
public socket: SocketIO.Socket | SocketIOClient.Socket;
constructor(optionsArg: ISocketConnectionConstructorOptions) {
this.alias = optionsArg.alias;
this.authenticated = optionsArg.authenticated;
this.role = optionsArg.role;
this.side = optionsArg.side;
this.smartsocketRef = optionsArg.smartsocketHost;
this.socket = optionsArg.socket;
// standard behaviour that is always true
allSocketConnections.add(this);
this.socket.on('disconnect', () => {
plugins.smartlog.defaultLogger.log(
'info',
`SocketConnection with >alias ${this.alias} on >side ${this.side} disconnected`
);
this.socket.disconnect();
allSocketConnections.remove(this);
});
}
// authenticating --------------------------
/**
* authenticate the socket
*/
public authenticate() {
const done = plugins.smartpromise.defer();
this.socket.on('dataAuth', (dataArg: ISocketConnectionAuthenticationObject) => {
plugins.smartlog.defaultLogger.log(
'info',
'received authentication data. now hashing and comparing...'
);
this.socket.removeListener('dataAuth', () => {});
if (SocketRole.checkPasswordForRole(dataArg, this.smartsocketRef)) {
// TODO: authenticate password
this.alias = dataArg.alias;
this.authenticated = true;
this.role = SocketRole.getSocketRoleByName(this.smartsocketRef, dataArg.role);
this.socket.emit('authenticated');
plugins.smartlog.defaultLogger.log(
'ok',
`socket with >>alias ${this.alias} >>role ${this.role} is authenticated!`
);
done.resolve(this);
} else {
this.authenticated = false;
this.socket.disconnect();
done.reject('not authenticated');
}
});
this.socket.emit('requestAuth');
return done.promise;
}
// listening -------------------------------
/**
* listen to function requests
*/
public listenToFunctionRequests() {
const done = plugins.smartpromise.defer();
if (this.authenticated) {
this.socket.on('function', (dataArg: ISocketRequestDataObject) => {
// check if requested function is available to the socket's scope
plugins.smartlog.defaultLogger.log('info', 'function request received');
const referencedFunction: SocketFunction = this.role.allowedFunctions.find(
socketFunctionArg => {
return socketFunctionArg.name === dataArg.funcCallData.funcName;
}
);
if (referencedFunction !== undefined) {
plugins.smartlog.defaultLogger.log('ok', 'function in access scope');
const localSocketRequest = new SocketRequest(this.smartsocketRef, {
side: 'responding',
originSocketConnection: this,
shortId: dataArg.shortId,
funcCallData: dataArg.funcCallData
});
localSocketRequest.createResponse(); // takes care of creating response and sending it back
} else {
plugins.smartlog.defaultLogger.log(
'warn',
'function not existent or out of access scope'
);
}
});
this.socket.on('functionResponse', (dataArg: ISocketRequestDataObject) => {
plugins.smartlog.defaultLogger.log(
'info',
`received response for request with id ${dataArg.shortId}`
);
const targetSocketRequest = SocketRequest.getSocketRequestById(this.smartsocketRef, dataArg.shortId);
targetSocketRequest.handleResponse(dataArg);
});
plugins.smartlog.defaultLogger.log(
'info',
`now listening to function requests for ${this.alias}`
);
done.resolve(this);
} else {
const errMessage = 'socket needs to be authenticated first';
plugins.smartlog.defaultLogger.log('error', errMessage);
done.reject(errMessage);
}
return done.promise;
}
// sending ----------------------
}

View File

@ -1,24 +1,90 @@
import * as plugins from "./smartsocket.plugins"; import * as plugins from './smartsocket.plugins';
// import classes // import classes
import { Stringmap } from "lik"; import { Objectmap } from '@pushrocks/lik';
import { SocketRole } from "./smartsocket.classes.socketrole"; import { SocketRole } from './smartsocket.classes.socketrole';
import { SocketConnection } from './smartsocket.classes.socketconnection';
import { Smartsocket } from './smartsocket.classes.smartsocket';
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
// export interfaces
/**
export interface SocketFunctionOptions { * interface of the contructor options of class SocketFunction
name: string; */
func: any; export interface ISocketFunctionConstructorOptions {
roles: SocketRole[]; // all roles that are allowed to execute a SocketFunction funcName: string;
}; funcDef: TFuncDef;
allowedRoles: SocketRole[]; // all roles that are allowed to execute a SocketFunction
export class SocketFunction { }
name: string;
func: any; /**
roles: SocketRole[]; * interface of the Socket Function call, in other words the object that routes a call to a function
constructor(optionsArg: SocketFunctionOptions) { */
this.name = optionsArg.name; export interface ISocketFunctionCall {
this.func = optionsArg.func; funcName: string;
this.roles = optionsArg.roles; funcDataArg: any;
}; }
/**
* interface for function definition of SocketFunction
*/
export type TFuncDef = (dataArg: any, connectionArg: SocketConnection) => PromiseLike<any>;
// export classes
/**
* class that respresents a function that can be transparently called using a SocketConnection
*/
export class SocketFunction {
// STATIC
public static getSocketFunctionByName (smartsocketRefArg: Smartsocket | SmartsocketClient, functionNameArg: string): SocketFunction {
console.log(smartsocketRefArg.socketFunctions);
return smartsocketRefArg.socketFunctions.find(socketFunctionArg => {
return socketFunctionArg.name === functionNameArg;
});
}
// INSTANCE
public name: string;
public funcDef: TFuncDef;
public roles: SocketRole[];
/**
* the constructor for SocketFunction
*/
constructor(optionsArg: ISocketFunctionConstructorOptions) {
this.name = optionsArg.funcName;
this.funcDef = optionsArg.funcDef;
this.roles = optionsArg.allowedRoles;
for (const socketRoleArg of this.roles) {
this._notifyRole(socketRoleArg);
}
}
/**
* invokes the function of this SocketFunction
*/
public invoke(dataArg: ISocketFunctionCall, socketConnectionArg: SocketConnection): Promise<any> {
const done = plugins.smartpromise.defer();
if (dataArg.funcName === this.name) {
this.funcDef(dataArg.funcDataArg, socketConnectionArg).then((resultData: any) => {
const funcResponseData: ISocketFunctionCall = {
funcName: this.name,
funcDataArg: resultData
};
done.resolve(funcResponseData);
});
} else {
throw new Error("SocketFunction.name does not match the data argument's .name!");
}
return done.promise;
}
/**
* notifies a role about access to this SocketFunction
*/
private _notifyRole(socketRoleArg: SocketRole) {
socketRoleArg.addSocketFunction(this);
}
} }

View File

@ -0,0 +1,121 @@
import * as plugins from './smartsocket.plugins';
// import interfaces
import { SocketFunction, ISocketFunctionCall } from './smartsocket.classes.socketfunction';
// import classes
import { Objectmap } from '@pushrocks/lik';
import { SocketConnection } from './smartsocket.classes.socketconnection';
import { defaultLogger } from '@pushrocks/smartlog';
import { Smartsocket } from './smartsocket.classes.smartsocket';
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
// export interfaces
export type TSocketRequestStatus = 'new' | 'pending' | 'finished';
export type TSocketRequestSide = 'requesting' | 'responding';
/**
* interface of constructor of class SocketRequest
*/
export interface SocketRequestConstructorOptions {
side: TSocketRequestSide;
originSocketConnection: SocketConnection;
shortId: string;
funcCallData?: ISocketFunctionCall;
}
/**
* request object that is sent initially and may or may not receive a response
*/
export interface ISocketRequestDataObject {
funcCallData: ISocketFunctionCall;
shortId: string;
responseTimeout?: number;
}
// export classes
export class SocketRequest {
// STATIC
public static getSocketRequestById(
smartsocketRef: Smartsocket | SmartsocketClient,
shortIdArg: string
): SocketRequest {
return smartsocketRef.socketRequests.find(socketRequestArg => {
return socketRequestArg.shortid === shortIdArg;
});
}
// INSTANCE
public status: TSocketRequestStatus = 'new';
public side: TSocketRequestSide;
public shortid: string;
public originSocketConnection: SocketConnection;
public funcCallData: ISocketFunctionCall;
public done = plugins.smartpromise.defer();
public smartsocketRef: Smartsocket | SmartsocketClient;
constructor(smartsocketRefArg: Smartsocket | SmartsocketClient, optionsArg: SocketRequestConstructorOptions) {
this.smartsocketRef = smartsocketRefArg;
this.side = optionsArg.side;
this.shortid = optionsArg.shortId;
this.funcCallData = optionsArg.funcCallData;
this.originSocketConnection = optionsArg.originSocketConnection;
this.smartsocketRef.socketRequests.add(this);
}
// requesting --------------------------
/**
* dispatches a socketrequest from the requesting to the receiving side
*/
public dispatch() {
const requestData: ISocketRequestDataObject = {
funcCallData: this.funcCallData,
shortId: this.shortid
};
this.originSocketConnection.socket.emit('function', requestData);
return this.done.promise;
}
/**
* handles the response that is received by the requesting side
*/
public handleResponse(responseDataArg: ISocketRequestDataObject) {
plugins.smartlog.defaultLogger.log('info', 'handling response!');
this.done.resolve(responseDataArg.funcCallData);
this.smartsocketRef.socketRequests.remove(this);
}
// responding --------------------------
/**
* creates the response on the responding side
*/
public async createResponse(): Promise<void> {
const targetSocketFunction: SocketFunction = SocketFunction.getSocketFunctionByName(
this.smartsocketRef,
this.funcCallData.funcName
);
if (!targetSocketFunction) {
defaultLogger.log(
'warn',
`There is no SocketFunction defined for ${this.funcCallData.funcName}`
);
defaultLogger.log('warn', `So now response is being sent.`);
return;
}
plugins.smartlog.defaultLogger.log('info', `invoking ${targetSocketFunction.name}`);
targetSocketFunction.invoke(this.funcCallData, this.originSocketConnection).then(resultData => {
plugins.smartlog.defaultLogger.log('info', 'got resultData. Sending it to requesting party.');
const requestData: ISocketRequestDataObject = {
funcCallData: resultData,
shortId: this.shortid
};
this.originSocketConnection.socket.emit('functionResponse', requestData);
this.smartsocketRef.socketRequests.remove(this);
});
}
}

View File

@ -1,7 +1,12 @@
import * as plugins from "./smartsocket.plugins"; import * as plugins from './smartsocket.plugins';
// import classes // import classes
import { Stringmap } from "lik"; import { Objectmap } from '@pushrocks/lik';
import { SocketFunction } from './smartsocket.classes.socketfunction';
import { Smartsocket } from './smartsocket.classes.smartsocket';
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
import { ISocketConnectionAuthenticationObject } from './smartsocket.classes.socketconnection';
/** /**
* interface for class SocketRole * interface for class SocketRole
@ -11,15 +16,38 @@ export interface SocketRoleOptions {
passwordHash: string; passwordHash: string;
} }
/** /**
* A socketrole defines access to certain routines. * A socketrole defines access to certain routines.
*/ */
export class SocketRole { export class SocketRole {
name:string; // STATIC
passwordHash:string; public static getSocketRoleByName(
referenceSmartsocket: Smartsocket | SmartsocketClient,
socketRoleNameArg: string,
): SocketRole{
return referenceSmartsocket.socketRoles.find(socketRoleArg => {
return socketRoleArg.name === socketRoleNameArg;
});
}
public static checkPasswordForRole (
dataArg: ISocketConnectionAuthenticationObject,
referenceSmartsocket: Smartsocket | SmartsocketClient
): boolean {
const targetPasswordHash = SocketRole.getSocketRoleByName(referenceSmartsocket, dataArg.role).passwordHash;
const computedCompareHash = plugins.smarthash.sha256FromStringSync(dataArg.password);
return targetPasswordHash === computedCompareHash;
}
// INSTANCE
public name: string;
public passwordHash: string;
public allowedFunctions = new Objectmap<SocketFunction>();
constructor(optionsArg: SocketRoleOptions) { constructor(optionsArg: SocketRoleOptions) {
this.name = optionsArg.name; this.name = optionsArg.name;
this.passwordHash = optionsArg.passwordHash; this.passwordHash = optionsArg.passwordHash;
} }
public addSocketFunction(socketFunctionArg: SocketFunction) {
this.allowedFunctions.add(socketFunctionArg);
}
} }

View File

@ -0,0 +1,77 @@
import * as plugins from './smartsocket.plugins';
// used in case no other server is supplied
import * as http from 'http';
import { Smartsocket } from './smartsocket.classes.smartsocket';
/**
* class socketServer
* handles the attachment of socketIo to whatever server is in play
*/
export class SocketServer {
private smartsocket: Smartsocket;
private httpServer: http.Server;
// wether httpServer is standalone
private standaloneServer = false;
private expressServer: any;
constructor(smartSocketInstance: Smartsocket) {
this.smartsocket = smartSocketInstance;
}
/**
* starts the server with another server
* also works with an express style server
*/
public async setExternalServer(
serverType: 'smartexpress',
serverArg: plugins.smartexpress.Server
) {
await serverArg.startedPromise;
this.httpServer = serverArg.httpServer;
}
/**
* gets the server for socket.io
*/
public getServerForSocketIo() {
if (this.httpServer) {
return this.httpServer;
} else {
this.httpServer = new http.Server();
this.standaloneServer = true;
return this.httpServer;
}
}
/**
* starts listening to incoming sockets:
*/
public async start() {
const done = plugins.smartpromise.defer();
// handle http servers
// in case an external server has been set "this.standaloneServer" should be false
if (this.httpServer && this.standaloneServer) {
if (!this.smartsocket.options.port) {
console.log('there should be a port specifed for smartsocket!');
throw new Error('there should be a port specified for smartsocket');
}
this.httpServer.listen(this.smartsocket.options.port, () => {
console.log(`Server started in standalone mode on ${this.smartsocket.options.port}`);
done.resolve();
});
} else {
done.resolve();
}
// nothing else to do if express server is set
await done.promise;
return;
}
/**
* closes the server
*/
public async stop() {}
}

View File

@ -1,31 +0,0 @@
import * as plugins from "./smartsocket.plugins";
// interfaces
import {ISocketObject} from "./smartsocket.classes.smartsocket";
/**
* authenticate a socket
*/
export let authenticateSocket = (socketObjectArg: ISocketObject) => {
let done = plugins.q.defer();
socketObjectArg.socket.on("dataAuth", dataArg => {
plugins.beautylog.log("received authentication data. now hashing and comparing...");
socketObjectArg.socket.removeListener("dataAuth", () => { });
if((true)){ // TODO: authenticate password
socketObjectArg.alias = dataArg.alias
socketObjectArg.authenticated = true;
socketObjectArg.role = dataArg.role;
socketObjectArg.socket.emit("authenticated");
plugins.beautylog.ok(`socket with >>alias ${socketObjectArg.alias} >>role ${socketObjectArg.role} is authenticated!`)
done.resolve(socketObjectArg);
} else {
socketObjectArg.socket.disconnect();
done.reject("not authenticated");
};
});
socketObjectArg.socket.emit("requestAuth");
return done.promise;
};

View File

@ -1,7 +1,21 @@
import "typings-global"; import * as lik from '@pushrocks/lik';
export import beautylog = require("beautylog"); import * as smartlog from '@pushrocks/smartlog';
export import lik = require("lik"); import * as smarthash from '@pushrocks/smarthash';
export import q = require("q"); import * as smartdelay from '@pushrocks/smartdelay';
export import socketIo = require("socket.io"); import * as smartexpress from '@pushrocks/smartexpress';
export import socketIoClient = require("socket.io-client"); import * as smartpromise from '@pushrocks/smartpromise';
export import taskbuffer = require("taskbuffer"); import * as shortid from 'shortid';
import socketIo from 'socket.io';
import socketIoClient from 'socket.io-client';
export {
lik,
smartlog,
smarthash,
smartdelay,
smartexpress,
smartpromise,
shortid,
socketIo,
socketIoClient
};

17
tslint.json Normal file
View File

@ -0,0 +1,17 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}