import * as net from "net" ; import { callbackify } from "util" ; import { ClientProxy , ClientServerProxy } from "../common/proxy" ; import { NetModuleProxy , NetServerProxy , NetSocketProxy } from "../server/net" ; import { Duplex } from "./stream" ; interface ClientNetSocketProxy extends NetSocketProxy , ClientServerProxy < net . Socket > { } export class Socket extends Duplex < ClientNetSocketProxy > implements net . Socket { private _connecting = false ; private _destroyed = false ; public constructor ( proxyPromise , connecting ? ) { super ( proxyPromise ) ; if ( connecting ) { this . _connecting = connecting ; } this . on ( "close" , ( ) => { this . _destroyed = true ; this . _connecting = false ; } ) ; this . on ( "connect" , ( ) => ( this . _connecting = false ) ) ; } public connect ( options , host ? , callback ? ) { if ( typeof host === "function" ) { callback = host ; host = undefined ; } this . _connecting = true ; if ( callback ) { this . on ( "connect" , callback as ( ) => void ) ; } return this . catch ( this . proxy . connect ( options , host ) ) ; } public end ( data ? , encoding ? , callback ? ) { if ( typeof encoding === "function" ) { callback = encoding ; encoding = undefined ; } callbackify ( this . proxy . end ) ( data , encoding , ( ) => { if ( callback ) { callback ( ) ; } } ) ; } public write ( data , encoding ? , fd ? ) { let callback ; if ( typeof encoding === "function" ) { callback = encoding ; encoding = undefined ; } if ( typeof fd === "function" ) { callback = fd ; fd = undefined ; } if ( typeof fd !== "undefined" ) { throw new Error ( "fd argument not supported" ) ; } callbackify ( this . proxy . write ) ( data , encoding , ( ) => { if ( callback ) { callback ( ) ; } } ) ; return true ; } public get connecting ( ) : boolean { return this . _connecting ; } public get destroyed ( ) : boolean { return this . _destroyed ; } public get bufferSize ( ) : number { throw new Error ( "not implemented" ) ; } public get bytesRead ( ) : number { throw new Error ( "not implemented" ) ; } public get bytesWritten ( ) : number { throw new Error ( "not implemented" ) ; } public get localAddress ( ) : string { throw new Error ( "not implemented" ) ; } public get localPort ( ) : number { throw new Error ( "not implemented" ) ; } public address ( ) { throw new Error ( "not implemented" ) ; } public setTimeout ( ) { throw new Error ( "not implemented" ) ; } public setNoDelay ( ) { throw new Error ( "not implemented" ) ; } public setKeepAlive ( ) { throw new Error ( "not implemented" ) ; } public unref ( ) { this . catch ( this . proxy . unref ( ) ) ; } public ref ( ) { this . catch ( this . proxy . ref ( ) ) ; } } interface ClientNetServerProxy extends NetServerProxy , ClientServerProxy < net . Server > { onConnection ( cb ) : Promise < void > ; } export class Server extends ClientProxy < ClientNetServerProxy > implements net . Server { private socketId = 0 ; private readonly sockets = new Map < number , net . Socket > ( ) ; private _listening = false ; public constructor ( proxyPromise ) { super ( proxyPromise ) ; this . catch ( this . proxy . onConnection ( ( socketProxy ) => { const socket = new Socket ( socketProxy ) ; const socketId = this . socketId ++ ; this . sockets . set ( socketId , socket ) ; socket . onInternalError ( ( ) => this . sockets . delete ( socketId ) ) ; socket . on ( "close" , ( ) => this . sockets . delete ( socketId ) ) ; this . emit ( "connection" , socket ) ; } ) ) ; this . on ( "listening" , ( ) => ( this . _listening = true ) ) ; this . onInternalError ( ( ) => ( this . _listening = false ) ) ; this . on ( "close" , ( ) => ( this . _listening = false ) ) ; } public listen ( handle ? , hostname ? , backlog ? , callback ? ) { if ( typeof hostname === "function" ) { callback = hostname ; hostname = undefined ; } if ( typeof backlog === "function" ) { callback = backlog ; backlog = undefined ; } if ( callback ) { this . on ( "listening" , callback as ( ) => void ) ; } return this . catch ( this . proxy . listen ( handle , hostname , backlog ) ) ; } public get connections ( ) : number { return this . sockets . size ; } public get listening ( ) : boolean { return this . _listening ; } public get maxConnections ( ) : number { throw new Error ( "not implemented" ) ; } public address ( ) { throw new Error ( "not implemented" ) ; } public close ( callback ? ) { this . _listening = false ; if ( callback ) { this . on ( "close" , callback ) ; } return this . catch ( this . proxy . close ( ) ) ; } public ref ( ) { return this . catch ( this . proxy . ref ( ) ) ; } public unref ( ) { return this . catch ( this . proxy . unref ( ) ) ; } public getConnections ( cb ) { cb ( null , this . sockets . size ) ; } protected handleDisconnect ( ) { this . emit ( "close" ) ; } } type NodeNet = typeof net ; interface ClientNetModuleProxy extends NetModuleProxy , ClientServerProxy { createSocket ( options ? ) : Promise < ClientNetSocketProxy > ; createConnection ( target , host ? ) : Promise < ClientNetSocketProxy > ; createServer ( options ? ) : Promise < ClientNetServerProxy > ; } export class NetModule implements NodeNet { public readonly Socket : typeof net . Socket ; public readonly Server : typeof net . Server ; public constructor ( private readonly proxy ) { this . Socket = class extends Socket { public constructor ( options ? ) { super ( proxy . createSocket ( options ) ) ; } } ; this . Server = class extends Server { public constructor ( options ? , listener ? ) { super ( proxy . createServer ( typeof options !== "function" ? options : undefined ) ) ; if ( typeof options === "function" ) { listener = options ; } if ( listener ) { this . on ( "connection" , listener ) ; } } } ; } public createConnection = ( target , host ? , callback ? ) : net . Socket => { if ( typeof host === "function" ) { callback = host ; host = undefined ; } const socket = new Socket ( this . proxy . createConnection ( target , host ) , true ) ; if ( callback ) { socket . on ( "connect" , callback as ( ) => void ) ; } return socket ; } ; public createServer = ( options ? , callback ? ) : net . Server => { if ( typeof options === "function" ) { callback = options ; options = undefined ; } const server = new Server ( this . proxy . createServer ( options ) ) ; if ( callback ) { server . on ( "connection" , callback ) ; } return server ; } ; public connect = ( ) : net . Socket => { throw new Error ( "not implemented" ) ; } ; public isIP = ( ) : number => { throw new Error ( "not implemented" ) ; } ; public isIPv4 = ( ) : boolean => { throw new Error ( "not implemented" ) ; } ; public isIPv6 = ( ) : boolean => { throw new Error ( "not implemented" ) ; } ; }