const uuid = require('uuid').v4 const { Message } = require('../shared') const { Injectable } = require('flitter-di') class Socket extends Injectable { static get services() { return [...super.services, 'app', 'output'] } messages = [] constructor(socket) { super() this.socket = socket this.uuid = uuid() this.session = {} this.socket.on('message', msg => this.on_message(msg)) } ping() { this.send(Message.route('meta.ping').expect_response()) } send(message) { this.output.debug(message) if ( typeof message === 'string' ) { this.socket.send(message) return } if ( message.needs_response ) { this.messages.push(message) } const serial = message.serialize() this.socket.send(serial) } async on_message(msg) { this.output.debug(msg) const message = new Message(msg) const response = new Message() message.socket = this if ( message.is_response() ) { // Try to find the message that sent the request const request = this.messages.find(x => x.uuid() === message.response_to()) if ( request ) { await request._response_callback(message) request.has_response = true; } else { this.send( response.response_to(message.uuid()) .error(Errors.InvalidReplyUUID) ) } this.messages = this.messages.filter(x => !x.has_response) } else { if ( this.needs_auth(message.route()) && !this.session.is_auth ) { return this.send(response.error(Errors.NodePermissionFail)) } let handler; try { handler = require(`./routes/${message.route()}`) } catch (e) {} if ( !handler ) { return this.send(response.error(Errors.InvalidMessageRoute)) } await handler(message, this.app.di().container.proxy()) } } needs_auth(route) { return route.startsWith('fs.') || route.startsWith('stream.') } } module.exports = exports = Socket