@@ -83,6 +83,21 @@ export class DevicePortForwarder extends EventEmitter {
8383 this . activeSockets . add ( localSocket ) ;
8484 this . emit ( 'clientConnected' , localSocket ) ;
8585
86+ const upstreamSocket = await this . openUpstreamForClient ( localSocket ) ;
87+ if ( ! upstreamSocket ) {
88+ return ;
89+ }
90+
91+ this . activeSockets . add ( upstreamSocket ) ;
92+ this . emit ( 'upstreamConnected' , upstreamSocket ) ;
93+ this . bridgeSockets ( localSocket , upstreamSocket ) ;
94+ }
95+
96+ /**
97+ * Opens the upstream socket while watching for the client going away.
98+ * Returns undefined after cleanup if the connect fails or the client disconnected meanwhile.
99+ */
100+ private async openUpstreamForClient ( localSocket : Socket ) : Promise < Socket | undefined > {
86101 let clientError : Error | undefined ;
87102 let clientClosed = false ;
88103 const onEarlyError = ( err : Error ) : void => {
@@ -94,15 +109,15 @@ export class DevicePortForwarder extends EventEmitter {
94109 localSocket . once ( 'error' , onEarlyError ) ;
95110 localSocket . once ( 'close' , onEarlyClose ) ;
96111
97- let upstreamSocket : Socket | undefined ;
112+ let upstreamSocket : Socket ;
98113 try {
99114 upstreamSocket = await this . openUpstreamSocket ( ) ;
100115 } catch ( err ) {
101116 this . activeSockets . delete ( localSocket ) ;
102117 this . emit ( 'upstreamConnectError' , err ) ;
103118 this . emit ( 'clientDisconnected' , localSocket , err ) ;
104119 localSocket . destroy ( ) ;
105- return ;
120+ return undefined ;
106121 } finally {
107122 localSocket . off ( 'error' , onEarlyError ) ;
108123 localSocket . off ( 'close' , onEarlyClose ) ;
@@ -113,12 +128,16 @@ export class DevicePortForwarder extends EventEmitter {
113128 this . emit ( 'clientDisconnected' , localSocket , clientError ) ;
114129 localSocket . destroy ( ) ;
115130 upstreamSocket . destroy ( ) ;
116- return ;
131+ return undefined ;
117132 }
118133
119- this . activeSockets . add ( upstreamSocket ) ;
120- this . emit ( 'upstreamConnected' , upstreamSocket ) ;
134+ return upstreamSocket ;
135+ }
121136
137+ /**
138+ * Pipes the two sockets together and tears both down when either side closes or errors.
139+ */
140+ private bridgeSockets ( localSocket : Socket , upstreamSocket : Socket ) : void {
122141 let cleanedUp = false ;
123142 const teardown = ( ) : void => {
124143 this . activeSockets . delete ( localSocket ) ;
@@ -135,6 +154,7 @@ export class DevicePortForwarder extends EventEmitter {
135154 upstreamSocket . destroy ( ) ;
136155 } ;
137156
157+ let clientError : Error | undefined ;
138158 localSocket . once ( 'error' , ( err ) => {
139159 clientError = err ;
140160 teardown ( ) ;
0 commit comments