UNPKG

@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
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRjb25uZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRjb25uZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMEJBQTBCLENBQUM7QUFDcEQsT0FBTyxLQUFLLFlBQVksTUFBTSwrQkFBK0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssVUFBVSxNQUFNLHVCQUF1QixDQUFDO0FBRXBELGlCQUFpQjtBQUNqQixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFDbkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQWlDLE1BQU0sd0NBQXdDLENBQUM7QUFFdEcsWUFBWTtBQUNaLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQTJCbEQsaUJBQWlCO0FBQ2pCLE1BQU0sQ0FBQyxJQUFJLG9CQUFvQixHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQW9CLENBQUM7QUFFaEY7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBYzNCLFlBQVksVUFBK0M7UUFYcEQsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFJL0IsaUJBQVksR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBZ0MsQ0FBQztRQUNoRixnQkFBVyxHQUFpQyxLQUFLLENBQUM7UUFFakQsYUFBUSxHQUF5QixFQUFFLENBQUM7UUFDckMsdUJBQWtCLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQXdCLENBQUM7UUFDOUUsNkJBQXdCLEdBQUcsSUFBSSxPQUFP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