import { EventEmitter } from 'events' ; import Queue from 'promise-queue' ; import type Client from '../client' ; import TcpSocket from './tcp-socket' ; import UdpSocket from './udp-socket' ; import type { Logger } from '../logger' ; hidden export default abstract class TplinkConnection extends EventEmitter { abstract readonly socketType : string ; private queue = new Queue ( 1 , Infinity ) ; constructor ( public host , public port , readonly log , readonly client ) { super ( ) ; this . on ( 'timeout' , ( ) => { this . log . debug ( `TplinkConnection(${ this . description }): timeout()` , this . host , this . port ) ; this . queue . add ( async ( ) => { this . close ( ) ; } ) ; } ) ; } protected get description ( ) : string { return `${ this . socketType } ${ this . host }:${ this . port }` ; } protected abstract getSocket ( useSharedSocket ? ) ; async send ( payload , port , host , { timeout , useSharedSocket , sharedSocketTimeout , } ) { this . log . debug ( `TplinkConnection(${ this . description }).send(%j)` , { payload , timeout , useSharedSocket , sharedSocketTimeout , } ) ; this . port = port ; this . host = host ; let socket ; return this . queue . add ( async ( ) => { try { socket = await this . getSocket ( useSharedSocket ) ; const response = await socket . send ( payload , this . port , this . host , { timeout , } ) ; if ( ! useSharedSocket ) { socket . close ( ) ; } return response ; } catch ( err ) { this . log . error ( `${ this . description } %s` , err ) ; if ( socket && socket . isBound ) socket . close ( ) ; throw err ; } } ) ; } close ( ) { this . log . debug ( `TplinkConnection(${ this . description }).close()` ) ; } }