11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { ERR_CHILD_CLOSED_BEFORE_REPLY } = require('internal/errors').codes; 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst EventEmitter = require('events'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci// This object keeps track of the sockets that are sent 81cb0ef41Sopenharmony_ciclass SocketListSend extends EventEmitter { 91cb0ef41Sopenharmony_ci constructor(child, key) { 101cb0ef41Sopenharmony_ci super(); 111cb0ef41Sopenharmony_ci this.key = key; 121cb0ef41Sopenharmony_ci this.child = child; 131cb0ef41Sopenharmony_ci child.once('exit', () => this.emit('exit', this)); 141cb0ef41Sopenharmony_ci } 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci _request(msg, cmd, swallowErrors, callback) { 171cb0ef41Sopenharmony_ci const self = this; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci if (!this.child.connected) return onclose(); 201cb0ef41Sopenharmony_ci this.child._send(msg, undefined, swallowErrors); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci function onclose() { 231cb0ef41Sopenharmony_ci self.child.removeListener('internalMessage', onreply); 241cb0ef41Sopenharmony_ci callback(new ERR_CHILD_CLOSED_BEFORE_REPLY()); 251cb0ef41Sopenharmony_ci } 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci function onreply(msg) { 281cb0ef41Sopenharmony_ci if (!(msg.cmd === cmd && msg.key === self.key)) return; 291cb0ef41Sopenharmony_ci self.child.removeListener('disconnect', onclose); 301cb0ef41Sopenharmony_ci self.child.removeListener('internalMessage', onreply); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci callback(null, msg); 331cb0ef41Sopenharmony_ci } 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci this.child.once('disconnect', onclose); 361cb0ef41Sopenharmony_ci this.child.on('internalMessage', onreply); 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci close(callback) { 401cb0ef41Sopenharmony_ci this._request({ 411cb0ef41Sopenharmony_ci cmd: 'NODE_SOCKET_NOTIFY_CLOSE', 421cb0ef41Sopenharmony_ci key: this.key, 431cb0ef41Sopenharmony_ci }, 'NODE_SOCKET_ALL_CLOSED', true, callback); 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci getConnections(callback) { 471cb0ef41Sopenharmony_ci this._request({ 481cb0ef41Sopenharmony_ci cmd: 'NODE_SOCKET_GET_COUNT', 491cb0ef41Sopenharmony_ci key: this.key, 501cb0ef41Sopenharmony_ci }, 'NODE_SOCKET_COUNT', false, (err, msg) => { 511cb0ef41Sopenharmony_ci if (err) return callback(err); 521cb0ef41Sopenharmony_ci callback(null, msg.count); 531cb0ef41Sopenharmony_ci }); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci// This object keeps track of the sockets that are received 591cb0ef41Sopenharmony_ciclass SocketListReceive extends EventEmitter { 601cb0ef41Sopenharmony_ci constructor(child, key) { 611cb0ef41Sopenharmony_ci super(); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci this.connections = 0; 641cb0ef41Sopenharmony_ci this.key = key; 651cb0ef41Sopenharmony_ci this.child = child; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci function onempty(self) { 681cb0ef41Sopenharmony_ci if (!self.child.connected) return; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci self.child._send({ 711cb0ef41Sopenharmony_ci cmd: 'NODE_SOCKET_ALL_CLOSED', 721cb0ef41Sopenharmony_ci key: self.key, 731cb0ef41Sopenharmony_ci }, undefined, true); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci this.child.on('internalMessage', (msg) => { 771cb0ef41Sopenharmony_ci if (msg.key !== this.key) return; 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci if (msg.cmd === 'NODE_SOCKET_NOTIFY_CLOSE') { 801cb0ef41Sopenharmony_ci // Already empty 811cb0ef41Sopenharmony_ci if (this.connections === 0) return onempty(this); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci // Wait for sockets to get closed 841cb0ef41Sopenharmony_ci this.once('empty', onempty); 851cb0ef41Sopenharmony_ci } else if (msg.cmd === 'NODE_SOCKET_GET_COUNT') { 861cb0ef41Sopenharmony_ci if (!this.child.connected) return; 871cb0ef41Sopenharmony_ci this.child._send({ 881cb0ef41Sopenharmony_ci cmd: 'NODE_SOCKET_COUNT', 891cb0ef41Sopenharmony_ci key: this.key, 901cb0ef41Sopenharmony_ci count: this.connections, 911cb0ef41Sopenharmony_ci }); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci }); 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci add(obj) { 971cb0ef41Sopenharmony_ci this.connections++; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci // Notify the previous owner of the socket about its state change 1001cb0ef41Sopenharmony_ci obj.socket.once('close', () => { 1011cb0ef41Sopenharmony_ci this.connections--; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci if (this.connections === 0) this.emit('empty', this); 1041cb0ef41Sopenharmony_ci }); 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_cimodule.exports = { SocketListSend, SocketListReceive }; 109