@@ -4,7 +4,13 @@ import stream = require('stream');
44import { V1Status } from './api' ;
55import { KubeConfig } from './config' ;
66
7- const protocols = [ 'v4.channel.k8s.io' , 'v3.channel.k8s.io' , 'v2.channel.k8s.io' , 'channel.k8s.io' ] ;
7+ const protocols = [
8+ 'v5.channel.k8s.io' ,
9+ 'v4.channel.k8s.io' ,
10+ 'v3.channel.k8s.io' ,
11+ 'v2.channel.k8s.io' ,
12+ 'channel.k8s.io' ,
13+ ] ;
814
915export type TextHandler = ( text : string ) => boolean ;
1016export type BinaryHandler = ( stream : number , buff : Buffer ) => boolean ;
@@ -17,12 +23,37 @@ export interface WebSocketInterface {
1723 ) : Promise < WebSocket . WebSocket > ;
1824}
1925
26+ export interface StreamInterface {
27+ stdin : stream . Readable ;
28+ stdout : stream . Writable ;
29+ stderr : stream . Writable ;
30+ }
31+
2032export class WebSocketHandler implements WebSocketInterface {
2133 public static readonly StdinStream : number = 0 ;
2234 public static readonly StdoutStream : number = 1 ;
2335 public static readonly StderrStream : number = 2 ;
2436 public static readonly StatusStream : number = 3 ;
2537 public static readonly ResizeStream : number = 4 ;
38+ public static readonly CloseStream : number = 255 ;
39+
40+ public static supportsClose ( protocol : string ) : boolean {
41+ return protocol === 'v5.channel.k8s.io' ;
42+ }
43+
44+ public static closeStream ( streamNum : number , streams : StreamInterface ) : void {
45+ switch ( streamNum ) {
46+ case WebSocketHandler . StdinStream :
47+ streams . stdin . pause ( ) ;
48+ break ;
49+ case WebSocketHandler . StdoutStream :
50+ streams . stdout . end ( ) ;
51+ break ;
52+ case WebSocketHandler . StderrStream :
53+ streams . stderr . end ( ) ;
54+ break ;
55+ }
56+ }
2657
2758 public static handleStandardStreams (
2859 streamNum : number ,
@@ -39,6 +70,7 @@ export class WebSocketHandler implements WebSocketInterface {
3970 stderr . write ( buff ) ;
4071 } else if ( streamNum === WebSocketHandler . StatusStream ) {
4172 // stream closing.
73+ // Hacky, change tests to use the stream interface
4274 if ( stdout && stdout !== process . stdout ) {
4375 stdout . end ( ) ;
4476 }
@@ -69,6 +101,12 @@ export class WebSocketHandler implements WebSocketInterface {
69101 } ) ;
70102
71103 stdin . on ( 'end' , ( ) => {
104+ if ( WebSocketHandler . supportsClose ( ws . protocol ) ) {
105+ const buff = Buffer . alloc ( 2 ) ;
106+ buff . writeUint8 ( this . CloseStream , 0 ) ;
107+ buff . writeUint8 ( this . StdinStream , 1 ) ;
108+ ws . send ( buff ) ;
109+ }
72110 ws . close ( ) ;
73111 } ) ;
74112 // Keep the stream open
@@ -141,7 +179,16 @@ export class WebSocketHandler implements WebSocketInterface {
141179 // factory is really just for test injection
142180 public constructor (
143181 readonly config : KubeConfig ,
144- readonly socketFactory ?: ( uri : string , opts : WebSocket . ClientOptions ) => WebSocket . WebSocket ,
182+ readonly socketFactory ?: (
183+ uri : string ,
184+ protocols : string [ ] ,
185+ opts : WebSocket . ClientOptions ,
186+ ) => WebSocket . WebSocket ,
187+ readonly streams : StreamInterface = {
188+ stdin : process . stdin ,
189+ stdout : process . stdout ,
190+ stderr : process . stderr ,
191+ } ,
145192 ) { }
146193
147194 /**
@@ -173,7 +220,7 @@ export class WebSocketHandler implements WebSocketInterface {
173220
174221 return await new Promise < WebSocket . WebSocket > ( ( resolve , reject ) => {
175222 const client = this . socketFactory
176- ? this . socketFactory ( uri , opts )
223+ ? this . socketFactory ( uri , protocols , opts )
177224 : new WebSocket ( uri , protocols , opts ) ;
178225 let resolved = false ;
179226
@@ -191,11 +238,17 @@ export class WebSocketHandler implements WebSocketInterface {
191238 client . onmessage = ( { data } : { data : WebSocket . Data } ) => {
192239 // TODO: support ArrayBuffer and Buffer[] data types?
193240 if ( typeof data === 'string' ) {
241+ if ( data . charCodeAt ( 0 ) === WebSocketHandler . CloseStream ) {
242+ WebSocketHandler . closeStream ( data . charCodeAt ( 1 ) , this . streams ) ;
243+ }
194244 if ( textHandler && ! textHandler ( data ) ) {
195245 client . close ( ) ;
196246 }
197247 } else if ( data instanceof Buffer ) {
198- const streamNum = data . readInt8 ( 0 ) ;
248+ const streamNum = data . readUint8 ( 0 ) ;
249+ if ( streamNum === WebSocketHandler . CloseStream ) {
250+ WebSocketHandler . closeStream ( data . readInt8 ( 1 ) , this . streams ) ;
251+ }
199252 if ( binaryHandler && ! binaryHandler ( streamNum , data . subarray ( 1 ) ) ) {
200253 client . close ( ) ;
201254 }
0 commit comments