@push.rocks/smartsocket
Version:
Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.
169 lines • 14.8 kB
JavaScript
import * as plugins from './smartsocket.plugins.js';
import * as pluginsTyped from './smartsocket.pluginstyped.js';
import * as interfaces from './interfaces/index.js';
// import classes
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
import { SocketFunction } from './smartsocket.classes.socketfunction.js';
import { SocketRequest } from './smartsocket.classes.socketrequest.js';
// socket.io
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
import { logger } from './smartsocket.logging.js';
// export classes
export let allSocketConnections = new plugins.lik.ObjectMap();
/**
* class SocketConnection represents a websocket connection
*/
export class SocketConnection {
constructor(optionsArg) {
this.authenticated = false;
this.eventSubject = new plugins.smartrx.rxjs.Subject();
this.eventStatus = 'new';
this.tagStore = {};
this.tagStoreObservable = new plugins.smartrx.rxjs.Subject();
this.remoteTagStoreObservable = new plugins.smartrx.rxjs.Subject();
this.alias = optionsArg.alias;
this.authenticated = optionsArg.authenticated;
this.side = optionsArg.side;
this.smartsocketRef = optionsArg.smartsocketHost;
this.socket = optionsArg.socket;
// standard behaviour that is always true
allSocketConnections.add(this);
// handle connection
this.socket.on('connect', async () => {
this.updateStatus('connected');
});
this.socket.on('disconnect', async () => {
logger.log('info', `SocketConnection with >alias ${this.alias} on >side ${this.side} disconnected`);
await this.disconnect();
allSocketConnections.remove(this);
this.eventSubject.next('disconnected');
});
}
/**
* adds a tag to a connection
*/
async addTag(tagArg) {
const done = plugins.smartpromise.defer();
this.tagStore[tagArg.id] = tagArg;
this.tagStoreObservable.next(this.tagStore);
const remoteSubscription = this.remoteTagStoreObservable.subscribe((remoteTagStore) => {
if (!remoteTagStore[tagArg.id]) {
return;
}
const localTagString = plugins.smartjson.stringify(tagArg);
const remoteTagString = plugins.smartjson.stringify(remoteTagStore[tagArg.id]);
if (localTagString === remoteTagString) {
remoteSubscription.unsubscribe();
done.resolve();
}
});
this.socket.emit('updateTagStore', this.tagStore);
await done.promise;
}
/**
* gets a tag by id
* @param tagIdArg
*/
async getTagById(tagIdArg) {
return this.tagStore[tagIdArg];
}
/**
* removes a tag from a connection
*/
async removeTagById(tagIdArg) {
delete this.tagStore[tagIdArg];
this.tagStoreObservable.next(this.tagStore);
this.socket.emit('updateTagStore', this.tagStore);
}
// authenticating --------------------------
/**
* authenticate the socket
*/
authenticate() {
const done = plugins.smartpromise.defer();
this.socket.on('dataAuth', async (dataArg) => {
logger.log('info', 'received authentication data...');
this.socket.removeAllListeners('dataAuth');
if (dataArg.alias) {
// TODO: authenticate password
this.alias = dataArg.alias;
this.authenticated = true;
this.socket.emit('authenticated');
logger.log('ok', `socket with >>alias ${this.alias} is authenticated!`);
done.resolve(this);
}
else {
this.authenticated = false;
await this.disconnect();
done.reject('a socket tried to connect, but could not authenticated.');
}
});
const requestAuthPayload = {
serverAlias: this.smartsocketRef.alias,
};
this.socket.emit('requestAuth', requestAuthPayload);
return done.promise;
}
// listening -------------------------------
/**
* listen to function requests
*/
listenToFunctionRequests() {
const done = plugins.smartpromise.defer();
if (this.authenticated) {
this.socket.on('function', (dataArg) => {
// check if requested function is available to the socket's scope
// logger.log('info', 'function request received');
const referencedFunction = this.smartsocketRef.socketFunctions.findSync((socketFunctionArg) => {
return socketFunctionArg.name === dataArg.funcCallData.funcName;
});
if (referencedFunction) {
// logger.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 {
logger.log('warn', 'function not existent or out of access scope');
}
});
this.socket.on('functionResponse', (dataArg) => {
// logger.log('info', `received response for request with id ${dataArg.shortId}`);
const targetSocketRequest = SocketRequest.getSocketRequestById(this.smartsocketRef, dataArg.shortId);
targetSocketRequest.handleResponse(dataArg);
});
this.socket.on('updateTagStore', async (tagStoreArg) => {
if (!plugins.smartjson.deepEqualObjects(this.tagStore, tagStoreArg)) {
this.tagStore = tagStoreArg;
this.socket.emit('updateTagStore', this.tagStore);
this.tagStoreObservable.next(this.tagStore);
}
this.remoteTagStoreObservable.next(tagStoreArg);
});
logger.log('info', `now listening to function requests for ${this.alias} on side ${this.side}`);
done.resolve(this);
}
else {
const errMessage = 'socket needs to be authenticated first';
logger.log('error', errMessage);
done.reject(errMessage);
}
return done.promise;
}
// disconnecting ----------------------
async disconnect() {
this.socket.disconnect(true);
this.updateStatus('disconnected');
}
updateStatus(statusArg) {
if (this.eventStatus !== statusArg) {
this.eventSubject.next(statusArg);
}
this.eventStatus = statusArg;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRjb25uZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRjb25uZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMEJBQTBCLENBQUM7QUFDcEQsT0FBTyxLQUFLLFlBQVksTUFBTSwrQkFBK0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssVUFBVSxNQUFNLHVCQUF1QixDQUFDO0FBRXBELGlCQUFpQjtBQUNqQixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDbkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQWlDLE1BQU0sd0NBQXdDLENBQUM7QUFFdEcsWUFBWTtBQUNaLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQTJCbEQsaUJBQWlCO0FBQ2pCLE1BQU0sQ0FBQyxJQUFJLG9CQUFvQixHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQW9CLENBQUM7QUFFaEY7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBYzNCLFlBQVksVUFBK0M7UUFYcEQsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFJL0IsaUJBQVksR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBZ0MsQ0FBQztRQUNoRixnQkFBVyxHQUFpQyxLQUFLLENBQUM7UUFFakQsYUFBUSxHQUF5QixFQUFFLENBQUM7UUFDckMsdUJBQWtCLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQXdCLENBQUM7UUFDOUUsNkJBQXdCLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQXdCLENBQUM7UUFHekYsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQzlCLElBQUksQ0FBQyxhQUFhLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FBQztRQUM5QyxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDNUIsSUFBSSxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQUMsZUFBZSxDQUFDO1FBQ2pELElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztRQUVoQyx5Q0FBeUM7UUFDekMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRS9CLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxLQUFLLElBQUksRUFBRTtZQUN0QyxNQUFNLENBQUMsR0FBRyxDQUNSLE1BQU0sRUFDTixnQ0FBZ0MsSUFBSSxDQUFDLEtBQUssYUFBYSxJQUFJLENBQUMsSUFBSSxlQUFlLENBQ2hGLENBQUM7WUFDRixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN4QixvQkFBb0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQXVCO1FBQ3pDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFNBQVMsQ0FBQyxDQUFDLGNBQWMsRUFBRSxFQUFFO1lBQ3BGLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQy9CLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxjQUFjLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0QsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQy9FLElBQUksY0FBYyxLQUFLLGVBQWUsRUFBRSxDQUFDO2dCQUN2QyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRCxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBK0I7UUFDckQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBK0I7UUFDeEQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsNENBQTRDO0lBRTVDOztPQUVHO0lBQ0ksWUFBWTtRQUNqQixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsT0FBOEMsRUFBRSxFQUFFO1lBQ2xGLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGlDQUFpQyxDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMzQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDbEIsOEJBQThCO2dCQUM5QixJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO2dCQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDbEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLElBQUksQ0FBQyxLQUFLLG9CQUFvQixDQUFDLENBQUM7Z0JBQ3hFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO2dCQUMzQixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO1lBQ3pFLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sa0JBQWtCLEdBQW1DO1lBQ3pELFdBQVcsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUs7U0FDdkMsQ0FBQztRQUNGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBRUQsNENBQTRDO0lBRTVDOztPQUVHO0lBQ0ksd0JBQXdCO1FBQzdCLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDMUMsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUMsT0FBc0MsRUFBRSxFQUFFO2dCQUNwRSxpRUFBaUU7Z0JBQ2pFLG1EQUFtRDtnQkFDbkQsTUFBTSxrQkFBa0IsR0FDdEIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUMsaUJBQWlCLEVBQUUsRUFBRTtvQkFDakUsT0FBTyxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7Z0JBQ2xFLENBQUMsQ0FBQyxDQUFDO2dCQUNMLElBQUksa0JBQWtCLEVBQUUsQ0FBQztvQkFDdkIsZ0RBQWdEO29CQUNoRCxNQUFNLGtCQUFrQixHQUFHLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7d0JBQ2hFLElBQUksRUFBRSxZQUFZO3dCQUNsQixzQkFBc0IsRUFBRSxJQUFJO3dCQUM1QixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87d0JBQ3hCLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtxQkFDbkMsQ0FBQyxDQUFDO29CQUNILGtCQUFrQixDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsc0RBQXNEO2dCQUM3RixDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsOENBQThDLENBQUMsQ0FBQztnQkFDckUsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxPQUFzQyxFQUFFLEVBQUU7Z0JBQzVFLGtGQUFrRjtnQkFDbEYsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUMsb0JBQW9CLENBQzVELElBQUksQ0FBQyxjQUFjLEVBQ25CLE9BQU8sQ0FBQyxPQUFPLENBQ2hCLENBQUM7Z0JBQ0YsbUJBQW1CLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlDLENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLFdBQWlDLEVBQUUsRUFBRTtnQkFDM0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDO29CQUNwRSxJQUFJLENBQUMsUUFBUSxHQUFHLFdBQVcsQ0FBQztvQkFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUNsRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDOUMsQ0FBQztnQkFDRCxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2xELENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxDQUFDLEdBQUcsQ0FDUixNQUFNLEVBQ04sMENBQTBDLElBQUksQ0FBQyxLQUFLLFlBQVksSUFBSSxDQUFDLElBQUksRUFBRSxDQUM1RSxDQUFDO1lBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sVUFBVSxHQUFHLHdDQUF3QyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUIsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBRUQsdUNBQXVDO0lBQ2hDLEtBQUssQ0FBQyxVQUFVO1FBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVPLFlBQVksQ0FBQyxTQUF1QztRQUMxRCxJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDO0lBQy9CLENBQUM7Q0FDRiJ9