/
var
/
www
/
greso.tech
/
server
/
nsm
/
node_modules
/
@grpc
/
grpc-js
/
src
/
/var/www/greso.tech/server/nsm/node_modules/@grpc/grpc-js/src
mkdir
upload
Name
Size
Mode
Actions
generated/
-
0755
rm
admin.ts
1345
0644
edit
dl
rm
backoff-timeout.ts
4719
0644
edit
dl
rm
call-credentials.ts
6555
0644
edit
dl
rm
call-interface.ts
4982
0644
edit
dl
rm
call-number.ts
694
0644
edit
dl
rm
call.ts
5447
0644
edit
dl
rm
channel-credentials.ts
8753
0644
edit
dl
rm
channel-options.ts
4100
0644
edit
dl
rm
channel.ts
5547
0644
edit
dl
rm
channelz.ts
26226
0644
edit
dl
rm
client-interceptors.ts
17901
0644
edit
dl
rm
client.ts
24828
0644
edit
dl
rm
compression-algorithms.ts
682
0644
edit
dl
rm
compression-filter.ts
10167
0644
edit
dl
rm
connectivity-state.ts
699
0644
edit
dl
rm
constants.ts
1651
0644
edit
dl
rm
control-plane-status.ts
1222
0644
edit
dl
rm
deadline.ts
2935
0644
edit
dl
rm
duration.ts
1096
0644
edit
dl
rm
error.ts
1062
0644
edit
dl
rm
events.ts
1108
0644
edit
dl
rm
experimental.ts
1352
0644
edit
dl
rm
filter-stack.ts
2674
0644
edit
dl
rm
filter.ts
1887
0644
edit
dl
rm
http_proxy.ts
8827
0644
edit
dl
rm
index.ts
7918
0644
edit
dl
rm
internal-channel.ts
21831
0644
edit
dl
rm
load-balancer-child-handler.ts
4868
0644
edit
dl
rm
load-balancer-outlier-detection.ts
25014
0644
edit
dl
rm
load-balancer-pick-first.ts
16073
0644
edit
dl
rm
load-balancer-round-robin.ts
7573
0644
edit
dl
rm
load-balancer.ts
7483
0644
edit
dl
rm
load-balancing-call.ts
10585
0644
edit
dl
rm
logging.ts
3407
0644
edit
dl
rm
make-client.ts
7201
0644
edit
dl
rm
max-message-size-filter.ts
3049
0644
edit
dl
rm
metadata.ts
8988
0644
edit
dl
rm
object-stream.ts
2214
0644
edit
dl
rm
picker.ts
4328
0644
edit
dl
rm
resolver-dns.ts
13169
0644
edit
dl
rm
resolver-ip.ts
3559
0644
edit
dl
rm
resolver-uds.ts
1611
0644
edit
dl
rm
resolver.ts
5805
0644
edit
dl
rm
resolving-call.ts
9856
0644
edit
dl
rm
resolving-load-balancer.ts
11508
0644
edit
dl
rm
retrying-call.ts
23079
0644
edit
dl
rm
server-call.ts
27256
0644
edit
dl
rm
server-credentials.ts
2822
0644
edit
dl
rm
server.ts
37334
0644
edit
dl
rm
service-config.ts
15852
0644
edit
dl
rm
status-builder.ts
1783
0644
edit
dl
rm
stream-decoder.ts
3501
0644
edit
dl
rm
subchannel-address.ts
2307
0644
edit
dl
rm
subchannel-call.ts
18197
0644
edit
dl
rm
subchannel-interface.ts
2831
0644
edit
dl
rm
subchannel-pool.ts
5490
0644
edit
dl
rm
subchannel.ts
13755
0644
edit
dl
rm
tls-helpers.ts
1088
0644
edit
dl
rm
transport.ts
25264
0644
edit
dl
rm
uri-parser.ts
2814
0644
edit
dl
rm
Edit:
/var/www/greso.tech/server/nsm/node_modules/@grpc/grpc-js/src/transport.ts
(25264B)
/* * Copyright 2023 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import * as http2 from 'http2'; import { checkServerIdentity, CipherNameAndProtocol, ConnectionOptions, PeerCertificate, TLSSocket } from 'tls'; import { StatusObject } from './call-interface'; import { ChannelCredentials } from './channel-credentials'; import { ChannelOptions } from './channel-options'; import { ChannelzCallTracker, registerChannelzSocket, SocketInfo, SocketRef, TlsInfo, unregisterChannelzRef } from './channelz'; import { LogVerbosity } from './constants'; import { getProxiedConnection, ProxyConnectionResult } from './http_proxy'; import * as logging from './logging'; import { getDefaultAuthority } from './resolver'; import { stringToSubchannelAddress, SubchannelAddress, subchannelAddressToString } from './subchannel-address'; import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; import * as net from 'net'; import { Http2SubchannelCall, SubchannelCall, SubchannelCallInterceptingListener } from './subchannel-call'; import { Metadata } from './metadata'; import { getNextCallNumber } from './call-number'; const TRACER_NAME = 'transport'; const FLOW_CONTROL_TRACER_NAME = 'transport_flowctrl'; const clientVersion = require('../../package.json').version; const { HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_TE, HTTP2_HEADER_USER_AGENT, } = http2.constants; /* setInterval and setTimeout only accept signed 32 bit integers. JS doesn't * have a constant for the max signed 32 bit integer, so this is a simple way * to calculate it */ const KEEPALIVE_MAX_TIME_MS = ~(1 << 31); const KEEPALIVE_TIMEOUT_MS = 20000; export interface CallEventTracker { addMessageSent(): void; addMessageReceived(): void; onCallEnd(status: StatusObject): void; onStreamEnd(success: boolean): void; } export interface TransportDisconnectListener { (tooManyPings: boolean): void; } export interface Transport { getChannelzRef(): SocketRef; getPeerName(): string; createCall(metadata: Metadata, host: string, method: string, listener: SubchannelCallInterceptingListener, subchannelCallStatsTracker: Partial<CallEventTracker>): SubchannelCall; addDisconnectListener(listener: TransportDisconnectListener): void; shutdown(): void; } const tooManyPingsData: Buffer = Buffer.from('too_many_pings', 'ascii'); class Http2Transport implements Transport { /** * The amount of time in between sending pings */ private keepaliveTimeMs: number = -1; /** * The amount of time to wait for an acknowledgement after sending a ping */ private keepaliveTimeoutMs: number = KEEPALIVE_TIMEOUT_MS; /** * Timer reference for timeout that indicates when to send the next ping */ private keepaliveIntervalId: NodeJS.Timer; /** * Timer reference tracking when the most recent ping will be considered lost */ private keepaliveTimeoutId: NodeJS.Timer | null = null; /** * Indicates whether keepalive pings should be sent without any active calls */ private keepaliveWithoutCalls = false; private userAgent: string; private activeCalls: Set<Http2SubchannelCall> = new Set(); private subchannelAddressString: string; private disconnectListeners: TransportDisconnectListener[] = []; private disconnectHandled = false; // Channelz info private channelzRef: SocketRef; private readonly channelzEnabled: boolean = true; /** * Name of the remote server, if it is not the same as the subchannel * address, i.e. if connecting through an HTTP CONNECT proxy. */ private remoteName: string | null = null; private streamTracker = new ChannelzCallTracker(); private keepalivesSent = 0; private messagesSent = 0; private messagesReceived = 0; private lastMessageSentTimestamp: Date | null = null; private lastMessageReceivedTimestamp: Date | null = null; constructor( private session: http2.ClientHttp2Session, subchannelAddress: SubchannelAddress, options: ChannelOptions ) { // Build user-agent string. this.userAgent = [ options['grpc.primary_user_agent'], `grpc-node-js/${clientVersion}`, options['grpc.secondary_user_agent'], ] .filter((e) => e) .join(' '); // remove falsey values first if ('grpc.keepalive_time_ms' in options) { this.keepaliveTimeMs = options['grpc.keepalive_time_ms']!; } if ('grpc.keepalive_timeout_ms' in options) { this.keepaliveTimeoutMs = options['grpc.keepalive_timeout_ms']!; } if ('grpc.keepalive_permit_without_calls' in options) { this.keepaliveWithoutCalls = options['grpc.keepalive_permit_without_calls'] === 1; } else { this.keepaliveWithoutCalls = false; } this.keepaliveIntervalId = setTimeout(() => {}, 0); clearTimeout(this.keepaliveIntervalId); if (this.keepaliveWithoutCalls) { this.startKeepalivePings(); } this.subchannelAddressString = subchannelAddressToString(subchannelAddress); if (options['grpc.enable_channelz'] === 0) { this.channelzEnabled = false; } this.channelzRef = registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzInfo(), this.channelzEnabled); session.once('close', () => { this.trace('session closed'); this.stopKeepalivePings(); this.handleDisconnect(); }); session.once('goaway', (errorCode: number, lastStreamID: number, opaqueData: Buffer) => { let tooManyPings = false; /* See the last paragraph of * https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md#basic-keepalive */ if ( errorCode === http2.constants.NGHTTP2_ENHANCE_YOUR_CALM && opaqueData.equals(tooManyPingsData) ) { tooManyPings = true; } this.trace( 'connection closed by GOAWAY with code ' + errorCode ); this.reportDisconnectToOwner(tooManyPings); }); session.once('error', error => { /* Do nothing here. Any error should also trigger a close event, which is * where we want to handle that. */ this.trace( 'connection closed with error ' + (error as Error).message ); }); if (logging.isTracerEnabled(TRACER_NAME)) { session.on('remoteSettings', (settings: http2.Settings) => { this.trace( 'new settings received' + (this.session !== session ? ' on the old connection' : '') + ': ' + JSON.stringify(settings) ); }); session.on('localSettings', (settings: http2.Settings) => { this.trace( 'local settings acknowledged by remote' + (this.session !== session ? ' on the old connection' : '') + ': ' + JSON.stringify(settings) ); }); } } private getChannelzInfo(): SocketInfo { const sessionSocket = this.session.socket; const remoteAddress = sessionSocket.remoteAddress ? stringToSubchannelAddress(sessionSocket.remoteAddress, sessionSocket.remotePort) : null; const localAddress = sessionSocket.localAddress ? stringToSubchannelAddress(sessionSocket.localAddress, sessionSocket.localPort) : null; let tlsInfo: TlsInfo | null; if (this.session.encrypted) { const tlsSocket: TLSSocket = sessionSocket as TLSSocket; const cipherInfo: CipherNameAndProtocol & {standardName?: string} = tlsSocket.getCipher(); const certificate = tlsSocket.getCertificate(); const peerCertificate = tlsSocket.getPeerCertificate(); tlsInfo = { cipherSuiteStandardName: cipherInfo.standardName ?? null, cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name, localCertificate: (certificate && 'raw' in certificate) ? certificate.raw : null, remoteCertificate: (peerCertificate && 'raw' in peerCertificate) ? peerCertificate.raw : null }; } else { tlsInfo = null; } const socketInfo: SocketInfo = { remoteAddress: remoteAddress, localAddress: localAddress, security: tlsInfo, remoteName: this.remoteName, streamsStarted: this.streamTracker.callsStarted, streamsSucceeded: this.streamTracker.callsSucceeded, streamsFailed: this.streamTracker.callsFailed, messagesSent: this.messagesSent, messagesReceived: this.messagesReceived, keepAlivesSent: this.keepalivesSent, lastLocalStreamCreatedTimestamp: this.streamTracker.lastCallStartedTimestamp, lastRemoteStreamCreatedTimestamp: null, lastMessageSentTimestamp: this.lastMessageSentTimestamp, lastMessageReceivedTimestamp: this.lastMessageReceivedTimestamp, localFlowControlWindow: this.session.state.localWindowSize ?? null, remoteFlowControlWindow: this.session.state.remoteWindowSize ?? null }; return socketInfo; } private trace(text: string): void { logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } private keepaliveTrace(text: string): void { logging.trace(LogVerbosity.DEBUG, 'keepalive', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } private flowControlTrace(text: string): void { logging.trace(LogVerbosity.DEBUG, FLOW_CONTROL_TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } private internalsTrace(text: string): void { logging.trace(LogVerbosity.DEBUG, 'transport_internals', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text); } /** * Indicate to the owner of this object that this transport should no longer * be used. That happens if the connection drops, or if the server sends a * GOAWAY. * @param tooManyPings If true, this was triggered by a GOAWAY with data * indicating that the session was closed becaues the client sent too many * pings. * @returns */ private reportDisconnectToOwner(tooManyPings: boolean) { if (this.disconnectHandled) { return; } this.disconnectHandled = true; this.disconnectListeners.forEach(listener => listener(tooManyPings)); } /** * Handle connection drops, but not GOAWAYs. */ private handleDisconnect() { this.reportDisconnectToOwner(false); /* Give calls an event loop cycle to finish naturally before reporting the * disconnnection to them. */ setImmediate(() => { for (const call of this.activeCalls) { call.onDisconnect(); } }); } addDisconnectListener(listener: TransportDisconnectListener): void { this.disconnectListeners.push(listener); } private clearKeepaliveTimeout() { if (!this.keepaliveTimeoutId) { return; } clearTimeout(this.keepaliveTimeoutId); this.keepaliveTimeoutId = null; } private sendPing() { if (this.channelzEnabled) { this.keepalivesSent += 1; } this.keepaliveTrace('Sending ping with timeout ' + this.keepaliveTimeoutMs + 'ms'); if (!this.keepaliveTimeoutId) { this.keepaliveTimeoutId = setTimeout(() => { this.keepaliveTrace('Ping timeout passed without response'); this.handleDisconnect(); }, this.keepaliveTimeoutMs); this.keepaliveTimeoutId.unref?.(); } try { this.session!.ping( (err: Error | null, duration: number, payload: Buffer) => { this.keepaliveTrace('Received ping response'); this.clearKeepaliveTimeout(); } ); } catch (e) { /* If we fail to send a ping, the connection is no longer functional, so * we should discard it. */ this.handleDisconnect(); } } private startKeepalivePings() { if (this.keepaliveTimeMs < 0) { return; } this.keepaliveIntervalId = setInterval(() => { this.sendPing(); }, this.keepaliveTimeMs); this.keepaliveIntervalId.unref?.(); /* Don't send a ping immediately because whatever caused us to start * sending pings should also involve some network activity. */ } /** * Stop keepalive pings when terminating a connection. This discards the * outstanding ping timeout, so it should not be called if the same * connection will still be used. */ private stopKeepalivePings() { clearInterval(this.keepaliveIntervalId); this.clearKeepaliveTimeout(); } private removeActiveCall(call: Http2SubchannelCall) { this.activeCalls.delete(call); if (this.activeCalls.size === 0) { this.session.unref(); if (!this.keepaliveWithoutCalls) { this.stopKeepalivePings(); } } } private addActiveCall(call: Http2SubchannelCall) { if (this.activeCalls.size === 0) { this.session.ref(); if (!this.keepaliveWithoutCalls) { this.startKeepalivePings(); } } this.activeCalls.add(call); } createCall(metadata: Metadata, host: string, method: string, listener: SubchannelCallInterceptingListener, subchannelCallStatsTracker: Partial<CallEventTracker>): Http2SubchannelCall { const headers = metadata.toHttp2Headers(); headers[HTTP2_HEADER_AUTHORITY] = host; headers[HTTP2_HEADER_USER_AGENT] = this.userAgent; headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc'; headers[HTTP2_HEADER_METHOD] = 'POST'; headers[HTTP2_HEADER_PATH] = method; headers[HTTP2_HEADER_TE] = 'trailers'; let http2Stream: http2.ClientHttp2Stream; /* In theory, if an error is thrown by session.request because session has * become unusable (e.g. because it has received a goaway), this subchannel * should soon see the corresponding close or goaway event anyway and leave * READY. But we have seen reports that this does not happen * (https://github.com/googleapis/nodejs-firestore/issues/1023#issuecomment-653204096) * so for defense in depth, we just discard the session when we see an * error here. */ try { http2Stream = this.session!.request(headers); } catch (e) { this.handleDisconnect(); throw e; } this.flowControlTrace( 'local window size: ' + this.session.state.localWindowSize + ' remote window size: ' + this.session.state.remoteWindowSize ); this.internalsTrace( 'session.closed=' + this.session.closed + ' session.destroyed=' + this.session.destroyed + ' session.socket.destroyed=' + this.session.socket.destroyed); let eventTracker: CallEventTracker; let call: Http2SubchannelCall; if (this.channelzEnabled) { this.streamTracker.addCallStarted(); eventTracker = { addMessageSent: () => { this.messagesSent += 1; this.lastMessageSentTimestamp = new Date(); subchannelCallStatsTracker.addMessageSent?.(); }, addMessageReceived: () => { this.messagesReceived += 1; this.lastMessageReceivedTimestamp = new Date(); subchannelCallStatsTracker.addMessageReceived?.(); }, onCallEnd: status => { subchannelCallStatsTracker.onCallEnd?.(status); this.removeActiveCall(call); }, onStreamEnd: success => { if (success) { this.streamTracker.addCallSucceeded(); } else { this.streamTracker.addCallFailed(); } subchannelCallStatsTracker.onStreamEnd?.(success); } } } else { eventTracker = { addMessageSent: () => { subchannelCallStatsTracker.addMessageSent?.(); }, addMessageReceived: () => { subchannelCallStatsTracker.addMessageReceived?.(); }, onCallEnd: (status) => { subchannelCallStatsTracker.onCallEnd?.(status); this.removeActiveCall(call); }, onStreamEnd: (success) => { subchannelCallStatsTracker.onStreamEnd?.(success); } } } call = new Http2SubchannelCall(http2Stream, eventTracker, listener, this, getNextCallNumber()); this.addActiveCall(call); return call; } getChannelzRef(): SocketRef { return this.channelzRef; } getPeerName() { return this.subchannelAddressString; } shutdown() { this.session.close(); unregisterChannelzRef(this.channelzRef); } } export interface SubchannelConnector { connect(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions): Promise<Transport>; shutdown(): void; } export class Http2SubchannelConnector implements SubchannelConnector { private session: http2.ClientHttp2Session | null = null; private isShutdown = false; constructor(private channelTarget: GrpcUri) {} private trace(text: string) { } private createSession(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions, proxyConnectionResult: ProxyConnectionResult): Promise<Http2Transport> { if (this.isShutdown) { return Promise.reject(); } return new Promise<Http2Transport>((resolve, reject) => { let remoteName: string | null; if (proxyConnectionResult.realTarget) { remoteName = uriToString(proxyConnectionResult.realTarget); this.trace('creating HTTP/2 session through proxy to ' + uriToString(proxyConnectionResult.realTarget)); } else { remoteName = null; this.trace('creating HTTP/2 session to ' + subchannelAddressToString(address)); } const targetAuthority = getDefaultAuthority( proxyConnectionResult.realTarget ?? this.channelTarget ); let connectionOptions: http2.SecureClientSessionOptions = credentials._getConnectionOptions() || {}; connectionOptions.maxSendHeaderBlockLength = Number.MAX_SAFE_INTEGER; if ('grpc-node.max_session_memory' in options) { connectionOptions.maxSessionMemory = options[ 'grpc-node.max_session_memory' ]; } else { /* By default, set a very large max session memory limit, to effectively * disable enforcement of the limit. Some testing indicates that Node's * behavior degrades badly when this limit is reached, so we solve that * by disabling the check entirely. */ connectionOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER; } let addressScheme = 'http://'; if ('secureContext' in connectionOptions) { addressScheme = 'https://'; // If provided, the value of grpc.ssl_target_name_override should be used // to override the target hostname when checking server identity. // This option is used for testing only. if (options['grpc.ssl_target_name_override']) { const sslTargetNameOverride = options[ 'grpc.ssl_target_name_override' ]!; connectionOptions.checkServerIdentity = ( host: string, cert: PeerCertificate ): Error | undefined => { return checkServerIdentity(sslTargetNameOverride, cert); }; connectionOptions.servername = sslTargetNameOverride; } else { const authorityHostname = splitHostPort(targetAuthority)?.host ?? 'localhost'; // We want to always set servername to support SNI connectionOptions.servername = authorityHostname; } if (proxyConnectionResult.socket) { /* This is part of the workaround for * https://github.com/nodejs/node/issues/32922. Without that bug, * proxyConnectionResult.socket would always be a plaintext socket and * this would say * connectionOptions.socket = proxyConnectionResult.socket; */ connectionOptions.createConnection = (authority, option) => { return proxyConnectionResult.socket!; }; } } else { /* In all but the most recent versions of Node, http2.connect does not use * the options when establishing plaintext connections, so we need to * establish that connection explicitly. */ connectionOptions.createConnection = (authority, option) => { if (proxyConnectionResult.socket) { return proxyConnectionResult.socket; } else { /* net.NetConnectOpts is declared in a way that is more restrictive * than what net.connect will actually accept, so we use the type * assertion to work around that. */ return net.connect(address); } }; } connectionOptions = { ...connectionOptions, ...address, }; /* http2.connect uses the options here: * https://github.com/nodejs/node/blob/70c32a6d190e2b5d7b9ff9d5b6a459d14e8b7d59/lib/internal/http2/core.js#L3028-L3036 * The spread operator overides earlier values with later ones, so any port * or host values in the options will be used rather than any values extracted * from the first argument. In addition, the path overrides the host and port, * as documented for plaintext connections here: * https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener * and for TLS connections here: * https://nodejs.org/api/tls.html#tls_tls_connect_options_callback. In * earlier versions of Node, http2.connect passes these options to * tls.connect but not net.connect, so in the insecure case we still need * to set the createConnection option above to create the connection * explicitly. We cannot do that in the TLS case because http2.connect * passes necessary additional options to tls.connect. * The first argument just needs to be parseable as a URL and the scheme * determines whether the connection will be established over TLS or not. */ const session = http2.connect( addressScheme + targetAuthority, connectionOptions ); this.session = session; session.unref(); session.once('connect', () => { session.removeAllListeners(); resolve(new Http2Transport(session, address, options)); this.session = null; }); session.once('close', () => { this.session = null; reject(); }); session.once('error', error => { this.trace('connection failed with error ' + (error as Error).message) }); }); } connect(address: SubchannelAddress, credentials: ChannelCredentials, options: ChannelOptions): Promise<Http2Transport> { if (this.isShutdown) { return Promise.reject(); } /* Pass connection options through to the proxy so that it's able to * upgrade it's connection to support tls if needed. * This is a workaround for https://github.com/nodejs/node/issues/32922 * See https://github.com/grpc/grpc-node/pull/1369 for more info. */ const connectionOptions: ConnectionOptions = credentials._getConnectionOptions() || {}; if ('secureContext' in connectionOptions) { connectionOptions.ALPNProtocols = ['h2']; // If provided, the value of grpc.ssl_target_name_override should be used // to override the target hostname when checking server identity. // This option is used for testing only. if (options['grpc.ssl_target_name_override']) { const sslTargetNameOverride = options[ 'grpc.ssl_target_name_override' ]!; connectionOptions.checkServerIdentity = ( host: string, cert: PeerCertificate ): Error | undefined => { return checkServerIdentity(sslTargetNameOverride, cert); }; connectionOptions.servername = sslTargetNameOverride; } else { if ('grpc.http_connect_target' in options) { /* This is more or less how servername will be set in createSession * if a connection is successfully established through the proxy. * If the proxy is not used, these connectionOptions are discarded * anyway */ const targetPath = getDefaultAuthority( parseUri(options['grpc.http_connect_target'] as string) ?? { path: 'localhost', } ); const hostPort = splitHostPort(targetPath); connectionOptions.servername = hostPort?.host ?? targetPath; } } } return getProxiedConnection( address, options, connectionOptions ).then( result => this.createSession(address, credentials, options, result) ); } shutdown(): void { this.isShutdown = true; this.session?.close(); this.session = null; } }
Save
cmd:
run