1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
19 | exports.Http2SubchannelConnector = void 0;
|
20 | const http2 = require("http2");
|
21 | const tls_1 = require("tls");
|
22 | const channelz_1 = require("./channelz");
|
23 | const constants_1 = require("./constants");
|
24 | const http_proxy_1 = require("./http_proxy");
|
25 | const logging = require("./logging");
|
26 | const resolver_1 = require("./resolver");
|
27 | const subchannel_address_1 = require("./subchannel-address");
|
28 | const uri_parser_1 = require("./uri-parser");
|
29 | const net = require("net");
|
30 | const subchannel_call_1 = require("./subchannel-call");
|
31 | const call_number_1 = require("./call-number");
|
32 | const TRACER_NAME = 'transport';
|
33 | const FLOW_CONTROL_TRACER_NAME = 'transport_flowctrl';
|
34 | const clientVersion = require('../../package.json').version;
|
35 | const { HTTP2_HEADER_AUTHORITY, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_TE, HTTP2_HEADER_USER_AGENT, } = http2.constants;
|
36 | const KEEPALIVE_TIMEOUT_MS = 20000;
|
37 | const tooManyPingsData = Buffer.from('too_many_pings', 'ascii');
|
38 | class Http2Transport {
|
39 | constructor(session, subchannelAddress, options,
|
40 | /**
|
41 | * Name of the remote server, if it is not the same as the subchannel
|
42 | * address, i.e. if connecting through an HTTP CONNECT proxy.
|
43 | */
|
44 | remoteName) {
|
45 | this.session = session;
|
46 | this.remoteName = remoteName;
|
47 | |
48 |
|
49 |
|
50 | this.keepaliveTimeMs = -1;
|
51 | |
52 |
|
53 |
|
54 | this.keepaliveTimeoutMs = KEEPALIVE_TIMEOUT_MS;
|
55 | |
56 |
|
57 |
|
58 | this.keepaliveTimerId = null;
|
59 | |
60 |
|
61 |
|
62 |
|
63 | this.pendingSendKeepalivePing = false;
|
64 | |
65 |
|
66 |
|
67 | this.keepaliveTimeoutId = null;
|
68 | |
69 |
|
70 |
|
71 | this.keepaliveWithoutCalls = false;
|
72 | this.activeCalls = new Set();
|
73 | this.disconnectListeners = [];
|
74 | this.disconnectHandled = false;
|
75 | this.channelzEnabled = true;
|
76 | this.streamTracker = new channelz_1.ChannelzCallTracker();
|
77 | this.keepalivesSent = 0;
|
78 | this.messagesSent = 0;
|
79 | this.messagesReceived = 0;
|
80 | this.lastMessageSentTimestamp = null;
|
81 | this.lastMessageReceivedTimestamp = null;
|
82 | |
83 |
|
84 | this.subchannelAddressString = (0, subchannel_address_1.subchannelAddressToString)(subchannelAddress);
|
85 | if (options['grpc.enable_channelz'] === 0) {
|
86 | this.channelzEnabled = false;
|
87 | }
|
88 | this.channelzRef = (0, channelz_1.registerChannelzSocket)(this.subchannelAddressString, () => this.getChannelzInfo(), this.channelzEnabled);
|
89 |
|
90 | this.userAgent = [
|
91 | options['grpc.primary_user_agent'],
|
92 | `grpc-node-js/${clientVersion}`,
|
93 | options['grpc.secondary_user_agent'],
|
94 | ]
|
95 | .filter(e => e)
|
96 | .join(' ');
|
97 | if ('grpc.keepalive_time_ms' in options) {
|
98 | this.keepaliveTimeMs = options['grpc.keepalive_time_ms'];
|
99 | }
|
100 | if ('grpc.keepalive_timeout_ms' in options) {
|
101 | this.keepaliveTimeoutMs = options['grpc.keepalive_timeout_ms'];
|
102 | }
|
103 | if ('grpc.keepalive_permit_without_calls' in options) {
|
104 | this.keepaliveWithoutCalls =
|
105 | options['grpc.keepalive_permit_without_calls'] === 1;
|
106 | }
|
107 | else {
|
108 | this.keepaliveWithoutCalls = false;
|
109 | }
|
110 | session.once('close', () => {
|
111 | this.trace('session closed');
|
112 | this.stopKeepalivePings();
|
113 | this.handleDisconnect();
|
114 | });
|
115 | session.once('goaway', (errorCode, lastStreamID, opaqueData) => {
|
116 | let tooManyPings = false;
|
117 | |
118 |
|
119 | if (errorCode === http2.constants.NGHTTP2_ENHANCE_YOUR_CALM &&
|
120 | opaqueData.equals(tooManyPingsData)) {
|
121 | tooManyPings = true;
|
122 | }
|
123 | this.trace('connection closed by GOAWAY with code ' + errorCode);
|
124 | this.reportDisconnectToOwner(tooManyPings);
|
125 | });
|
126 | session.once('error', error => {
|
127 | |
128 |
|
129 | this.trace('connection closed with error ' + error.message);
|
130 | });
|
131 | if (logging.isTracerEnabled(TRACER_NAME)) {
|
132 | session.on('remoteSettings', (settings) => {
|
133 | this.trace('new settings received' +
|
134 | (this.session !== session ? ' on the old connection' : '') +
|
135 | ': ' +
|
136 | JSON.stringify(settings));
|
137 | });
|
138 | session.on('localSettings', (settings) => {
|
139 | this.trace('local settings acknowledged by remote' +
|
140 | (this.session !== session ? ' on the old connection' : '') +
|
141 | ': ' +
|
142 | JSON.stringify(settings));
|
143 | });
|
144 | }
|
145 | |
146 |
|
147 | if (this.keepaliveWithoutCalls) {
|
148 | this.maybeStartKeepalivePingTimer();
|
149 | }
|
150 | }
|
151 | getChannelzInfo() {
|
152 | var _a, _b, _c;
|
153 | const sessionSocket = this.session.socket;
|
154 | const remoteAddress = sessionSocket.remoteAddress
|
155 | ? (0, subchannel_address_1.stringToSubchannelAddress)(sessionSocket.remoteAddress, sessionSocket.remotePort)
|
156 | : null;
|
157 | const localAddress = sessionSocket.localAddress
|
158 | ? (0, subchannel_address_1.stringToSubchannelAddress)(sessionSocket.localAddress, sessionSocket.localPort)
|
159 | : null;
|
160 | let tlsInfo;
|
161 | if (this.session.encrypted) {
|
162 | const tlsSocket = sessionSocket;
|
163 | const cipherInfo = tlsSocket.getCipher();
|
164 | const certificate = tlsSocket.getCertificate();
|
165 | const peerCertificate = tlsSocket.getPeerCertificate();
|
166 | tlsInfo = {
|
167 | cipherSuiteStandardName: (_a = cipherInfo.standardName) !== null && _a !== void 0 ? _a : null,
|
168 | cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name,
|
169 | localCertificate: certificate && 'raw' in certificate ? certificate.raw : null,
|
170 | remoteCertificate: peerCertificate && 'raw' in peerCertificate
|
171 | ? peerCertificate.raw
|
172 | : null,
|
173 | };
|
174 | }
|
175 | else {
|
176 | tlsInfo = null;
|
177 | }
|
178 | const socketInfo = {
|
179 | remoteAddress: remoteAddress,
|
180 | localAddress: localAddress,
|
181 | security: tlsInfo,
|
182 | remoteName: this.remoteName,
|
183 | streamsStarted: this.streamTracker.callsStarted,
|
184 | streamsSucceeded: this.streamTracker.callsSucceeded,
|
185 | streamsFailed: this.streamTracker.callsFailed,
|
186 | messagesSent: this.messagesSent,
|
187 | messagesReceived: this.messagesReceived,
|
188 | keepAlivesSent: this.keepalivesSent,
|
189 | lastLocalStreamCreatedTimestamp: this.streamTracker.lastCallStartedTimestamp,
|
190 | lastRemoteStreamCreatedTimestamp: null,
|
191 | lastMessageSentTimestamp: this.lastMessageSentTimestamp,
|
192 | lastMessageReceivedTimestamp: this.lastMessageReceivedTimestamp,
|
193 | localFlowControlWindow: (_b = this.session.state.localWindowSize) !== null && _b !== void 0 ? _b : null,
|
194 | remoteFlowControlWindow: (_c = this.session.state.remoteWindowSize) !== null && _c !== void 0 ? _c : null,
|
195 | };
|
196 | return socketInfo;
|
197 | }
|
198 | trace(text) {
|
199 | logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, '(' +
|
200 | this.channelzRef.id +
|
201 | ') ' +
|
202 | this.subchannelAddressString +
|
203 | ' ' +
|
204 | text);
|
205 | }
|
206 | keepaliveTrace(text) {
|
207 | logging.trace(constants_1.LogVerbosity.DEBUG, 'keepalive', '(' +
|
208 | this.channelzRef.id +
|
209 | ') ' +
|
210 | this.subchannelAddressString +
|
211 | ' ' +
|
212 | text);
|
213 | }
|
214 | flowControlTrace(text) {
|
215 | logging.trace(constants_1.LogVerbosity.DEBUG, FLOW_CONTROL_TRACER_NAME, '(' +
|
216 | this.channelzRef.id +
|
217 | ') ' +
|
218 | this.subchannelAddressString +
|
219 | ' ' +
|
220 | text);
|
221 | }
|
222 | internalsTrace(text) {
|
223 | logging.trace(constants_1.LogVerbosity.DEBUG, 'transport_internals', '(' +
|
224 | this.channelzRef.id +
|
225 | ') ' +
|
226 | this.subchannelAddressString +
|
227 | ' ' +
|
228 | text);
|
229 | }
|
230 | |
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 | reportDisconnectToOwner(tooManyPings) {
|
240 | if (this.disconnectHandled) {
|
241 | return;
|
242 | }
|
243 | this.disconnectHandled = true;
|
244 | this.disconnectListeners.forEach(listener => listener(tooManyPings));
|
245 | }
|
246 | |
247 |
|
248 |
|
249 | handleDisconnect() {
|
250 | this.reportDisconnectToOwner(false);
|
251 | |
252 |
|
253 | setImmediate(() => {
|
254 | for (const call of this.activeCalls) {
|
255 | call.onDisconnect();
|
256 | }
|
257 | });
|
258 | }
|
259 | addDisconnectListener(listener) {
|
260 | this.disconnectListeners.push(listener);
|
261 | }
|
262 | clearKeepaliveTimer() {
|
263 | if (!this.keepaliveTimerId) {
|
264 | return;
|
265 | }
|
266 | clearTimeout(this.keepaliveTimerId);
|
267 | this.keepaliveTimerId = null;
|
268 | }
|
269 | clearKeepaliveTimeout() {
|
270 | if (!this.keepaliveTimeoutId) {
|
271 | return;
|
272 | }
|
273 | clearTimeout(this.keepaliveTimeoutId);
|
274 | this.keepaliveTimeoutId = null;
|
275 | }
|
276 | canSendPing() {
|
277 | return (this.keepaliveTimeMs > 0 &&
|
278 | (this.keepaliveWithoutCalls || this.activeCalls.size > 0));
|
279 | }
|
280 | maybeSendPing() {
|
281 | var _a, _b;
|
282 | this.clearKeepaliveTimer();
|
283 | if (!this.canSendPing()) {
|
284 | this.pendingSendKeepalivePing = true;
|
285 | return;
|
286 | }
|
287 | if (this.channelzEnabled) {
|
288 | this.keepalivesSent += 1;
|
289 | }
|
290 | this.keepaliveTrace('Sending ping with timeout ' + this.keepaliveTimeoutMs + 'ms');
|
291 | if (!this.keepaliveTimeoutId) {
|
292 | this.keepaliveTimeoutId = setTimeout(() => {
|
293 | this.keepaliveTrace('Ping timeout passed without response');
|
294 | this.handleDisconnect();
|
295 | }, this.keepaliveTimeoutMs);
|
296 | (_b = (_a = this.keepaliveTimeoutId).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
297 | }
|
298 | try {
|
299 | this.session.ping((err, duration, payload) => {
|
300 | if (err) {
|
301 | this.keepaliveTrace('Ping failed with error ' + err.message);
|
302 | this.handleDisconnect();
|
303 | }
|
304 | this.keepaliveTrace('Received ping response');
|
305 | this.clearKeepaliveTimeout();
|
306 | this.maybeStartKeepalivePingTimer();
|
307 | });
|
308 | }
|
309 | catch (e) {
|
310 | |
311 |
|
312 | this.handleDisconnect();
|
313 | }
|
314 | }
|
315 | |
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 | maybeStartKeepalivePingTimer() {
|
322 | var _a, _b;
|
323 | if (!this.canSendPing()) {
|
324 | return;
|
325 | }
|
326 | if (this.pendingSendKeepalivePing) {
|
327 | this.pendingSendKeepalivePing = false;
|
328 | this.maybeSendPing();
|
329 | }
|
330 | else if (!this.keepaliveTimerId && !this.keepaliveTimeoutId) {
|
331 | this.keepaliveTrace('Starting keepalive timer for ' + this.keepaliveTimeMs + 'ms');
|
332 | this.keepaliveTimerId = (_b = (_a = setTimeout(() => {
|
333 | this.maybeSendPing();
|
334 | }, this.keepaliveTimeMs)).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
335 | }
|
336 | |
337 |
|
338 | }
|
339 | stopKeepalivePings() {
|
340 | if (this.keepaliveTimerId) {
|
341 | clearTimeout(this.keepaliveTimerId);
|
342 | this.keepaliveTimerId = null;
|
343 | }
|
344 | this.clearKeepaliveTimeout();
|
345 | }
|
346 | removeActiveCall(call) {
|
347 | this.activeCalls.delete(call);
|
348 | if (this.activeCalls.size === 0) {
|
349 | this.session.unref();
|
350 | }
|
351 | }
|
352 | addActiveCall(call) {
|
353 | this.activeCalls.add(call);
|
354 | if (this.activeCalls.size === 1) {
|
355 | this.session.ref();
|
356 | if (!this.keepaliveWithoutCalls) {
|
357 | this.maybeStartKeepalivePingTimer();
|
358 | }
|
359 | }
|
360 | }
|
361 | createCall(metadata, host, method, listener, subchannelCallStatsTracker) {
|
362 | const headers = metadata.toHttp2Headers();
|
363 | headers[HTTP2_HEADER_AUTHORITY] = host;
|
364 | headers[HTTP2_HEADER_USER_AGENT] = this.userAgent;
|
365 | headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc';
|
366 | headers[HTTP2_HEADER_METHOD] = 'POST';
|
367 | headers[HTTP2_HEADER_PATH] = method;
|
368 | headers[HTTP2_HEADER_TE] = 'trailers';
|
369 | let http2Stream;
|
370 | |
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 |
|
378 | try {
|
379 | http2Stream = this.session.request(headers);
|
380 | }
|
381 | catch (e) {
|
382 | this.handleDisconnect();
|
383 | throw e;
|
384 | }
|
385 | this.flowControlTrace('local window size: ' +
|
386 | this.session.state.localWindowSize +
|
387 | ' remote window size: ' +
|
388 | this.session.state.remoteWindowSize);
|
389 | this.internalsTrace('session.closed=' +
|
390 | this.session.closed +
|
391 | ' session.destroyed=' +
|
392 | this.session.destroyed +
|
393 | ' session.socket.destroyed=' +
|
394 | this.session.socket.destroyed);
|
395 | let eventTracker;
|
396 |
|
397 | let call;
|
398 | if (this.channelzEnabled) {
|
399 | this.streamTracker.addCallStarted();
|
400 | eventTracker = {
|
401 | addMessageSent: () => {
|
402 | var _a;
|
403 | this.messagesSent += 1;
|
404 | this.lastMessageSentTimestamp = new Date();
|
405 | (_a = subchannelCallStatsTracker.addMessageSent) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker);
|
406 | },
|
407 | addMessageReceived: () => {
|
408 | var _a;
|
409 | this.messagesReceived += 1;
|
410 | this.lastMessageReceivedTimestamp = new Date();
|
411 | (_a = subchannelCallStatsTracker.addMessageReceived) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker);
|
412 | },
|
413 | onCallEnd: status => {
|
414 | var _a;
|
415 | (_a = subchannelCallStatsTracker.onCallEnd) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker, status);
|
416 | this.removeActiveCall(call);
|
417 | },
|
418 | onStreamEnd: success => {
|
419 | var _a;
|
420 | if (success) {
|
421 | this.streamTracker.addCallSucceeded();
|
422 | }
|
423 | else {
|
424 | this.streamTracker.addCallFailed();
|
425 | }
|
426 | (_a = subchannelCallStatsTracker.onStreamEnd) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker, success);
|
427 | },
|
428 | };
|
429 | }
|
430 | else {
|
431 | eventTracker = {
|
432 | addMessageSent: () => {
|
433 | var _a;
|
434 | (_a = subchannelCallStatsTracker.addMessageSent) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker);
|
435 | },
|
436 | addMessageReceived: () => {
|
437 | var _a;
|
438 | (_a = subchannelCallStatsTracker.addMessageReceived) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker);
|
439 | },
|
440 | onCallEnd: status => {
|
441 | var _a;
|
442 | (_a = subchannelCallStatsTracker.onCallEnd) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker, status);
|
443 | this.removeActiveCall(call);
|
444 | },
|
445 | onStreamEnd: success => {
|
446 | var _a;
|
447 | (_a = subchannelCallStatsTracker.onStreamEnd) === null || _a === void 0 ? void 0 : _a.call(subchannelCallStatsTracker, success);
|
448 | },
|
449 | };
|
450 | }
|
451 | call = new subchannel_call_1.Http2SubchannelCall(http2Stream, eventTracker, listener, this, (0, call_number_1.getNextCallNumber)());
|
452 | this.addActiveCall(call);
|
453 | return call;
|
454 | }
|
455 | getChannelzRef() {
|
456 | return this.channelzRef;
|
457 | }
|
458 | getPeerName() {
|
459 | return this.subchannelAddressString;
|
460 | }
|
461 | shutdown() {
|
462 | this.session.close();
|
463 | (0, channelz_1.unregisterChannelzRef)(this.channelzRef);
|
464 | }
|
465 | }
|
466 | class Http2SubchannelConnector {
|
467 | constructor(channelTarget) {
|
468 | this.channelTarget = channelTarget;
|
469 | this.session = null;
|
470 | this.isShutdown = false;
|
471 | }
|
472 | trace(text) {
|
473 | logging.trace(constants_1.LogVerbosity.DEBUG, TRACER_NAME, (0, uri_parser_1.uriToString)(this.channelTarget) + ' ' + text);
|
474 | }
|
475 | createSession(address, credentials, options, proxyConnectionResult) {
|
476 | if (this.isShutdown) {
|
477 | return Promise.reject();
|
478 | }
|
479 | return new Promise((resolve, reject) => {
|
480 | var _a, _b, _c;
|
481 | let remoteName;
|
482 | if (proxyConnectionResult.realTarget) {
|
483 | remoteName = (0, uri_parser_1.uriToString)(proxyConnectionResult.realTarget);
|
484 | this.trace('creating HTTP/2 session through proxy to ' +
|
485 | (0, uri_parser_1.uriToString)(proxyConnectionResult.realTarget));
|
486 | }
|
487 | else {
|
488 | remoteName = null;
|
489 | this.trace('creating HTTP/2 session to ' + (0, subchannel_address_1.subchannelAddressToString)(address));
|
490 | }
|
491 | const targetAuthority = (0, resolver_1.getDefaultAuthority)((_a = proxyConnectionResult.realTarget) !== null && _a !== void 0 ? _a : this.channelTarget);
|
492 | let connectionOptions = credentials._getConnectionOptions() || {};
|
493 | connectionOptions.maxSendHeaderBlockLength = Number.MAX_SAFE_INTEGER;
|
494 | if ('grpc-node.max_session_memory' in options) {
|
495 | connectionOptions.maxSessionMemory =
|
496 | options['grpc-node.max_session_memory'];
|
497 | }
|
498 | else {
|
499 | |
500 |
|
501 |
|
502 |
|
503 | connectionOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER;
|
504 | }
|
505 | let addressScheme = 'http://';
|
506 | if ('secureContext' in connectionOptions) {
|
507 | addressScheme = 'https://';
|
508 |
|
509 |
|
510 |
|
511 | if (options['grpc.ssl_target_name_override']) {
|
512 | const sslTargetNameOverride = options['grpc.ssl_target_name_override'];
|
513 | connectionOptions.checkServerIdentity = (host, cert) => {
|
514 | return (0, tls_1.checkServerIdentity)(sslTargetNameOverride, cert);
|
515 | };
|
516 | connectionOptions.servername = sslTargetNameOverride;
|
517 | }
|
518 | else {
|
519 | const authorityHostname = (_c = (_b = (0, uri_parser_1.splitHostPort)(targetAuthority)) === null || _b === void 0 ? void 0 : _b.host) !== null && _c !== void 0 ? _c : 'localhost';
|
520 |
|
521 | connectionOptions.servername = authorityHostname;
|
522 | }
|
523 | if (proxyConnectionResult.socket) {
|
524 | |
525 |
|
526 |
|
527 |
|
528 |
|
529 | connectionOptions.createConnection = (authority, option) => {
|
530 | return proxyConnectionResult.socket;
|
531 | };
|
532 | }
|
533 | }
|
534 | else {
|
535 | |
536 |
|
537 |
|
538 | connectionOptions.createConnection = (authority, option) => {
|
539 | if (proxyConnectionResult.socket) {
|
540 | return proxyConnectionResult.socket;
|
541 | }
|
542 | else {
|
543 | |
544 |
|
545 |
|
546 | return net.connect(address);
|
547 | }
|
548 | };
|
549 | }
|
550 | connectionOptions = Object.assign(Object.assign(Object.assign({}, connectionOptions), address), { enableTrace: options['grpc-node.tls_enable_trace'] === 1 });
|
551 | |
552 |
|
553 |
|
554 |
|
555 |
|
556 |
|
557 |
|
558 |
|
559 |
|
560 |
|
561 |
|
562 |
|
563 |
|
564 |
|
565 |
|
566 |
|
567 |
|
568 | const session = http2.connect(addressScheme + targetAuthority, connectionOptions);
|
569 | this.session = session;
|
570 | session.unref();
|
571 | session.once('connect', () => {
|
572 | session.removeAllListeners();
|
573 | resolve(new Http2Transport(session, address, options, remoteName));
|
574 | this.session = null;
|
575 | });
|
576 | session.once('close', () => {
|
577 | this.session = null;
|
578 | reject();
|
579 | });
|
580 | session.once('error', error => {
|
581 | this.trace('connection failed with error ' + error.message);
|
582 | });
|
583 | });
|
584 | }
|
585 | connect(address, credentials, options) {
|
586 | var _a, _b;
|
587 | if (this.isShutdown) {
|
588 | return Promise.reject();
|
589 | }
|
590 | |
591 |
|
592 |
|
593 |
|
594 | const connectionOptions = credentials._getConnectionOptions() || {};
|
595 | if ('secureContext' in connectionOptions) {
|
596 | connectionOptions.ALPNProtocols = ['h2'];
|
597 |
|
598 |
|
599 |
|
600 | if (options['grpc.ssl_target_name_override']) {
|
601 | const sslTargetNameOverride = options['grpc.ssl_target_name_override'];
|
602 | connectionOptions.checkServerIdentity = (host, cert) => {
|
603 | return (0, tls_1.checkServerIdentity)(sslTargetNameOverride, cert);
|
604 | };
|
605 | connectionOptions.servername = sslTargetNameOverride;
|
606 | }
|
607 | else {
|
608 | if ('grpc.http_connect_target' in options) {
|
609 | |
610 |
|
611 |
|
612 |
|
613 | const targetPath = (0, resolver_1.getDefaultAuthority)((_a = (0, uri_parser_1.parseUri)(options['grpc.http_connect_target'])) !== null && _a !== void 0 ? _a : {
|
614 | path: 'localhost',
|
615 | });
|
616 | const hostPort = (0, uri_parser_1.splitHostPort)(targetPath);
|
617 | connectionOptions.servername = (_b = hostPort === null || hostPort === void 0 ? void 0 : hostPort.host) !== null && _b !== void 0 ? _b : targetPath;
|
618 | }
|
619 | }
|
620 | if (options['grpc-node.tls_enable_trace']) {
|
621 | connectionOptions.enableTrace = true;
|
622 | }
|
623 | }
|
624 | return (0, http_proxy_1.getProxiedConnection)(address, options, connectionOptions).then(result => this.createSession(address, credentials, options, result));
|
625 | }
|
626 | shutdown() {
|
627 | var _a;
|
628 | this.isShutdown = true;
|
629 | (_a = this.session) === null || _a === void 0 ? void 0 : _a.close();
|
630 | this.session = null;
|
631 | }
|
632 | }
|
633 | exports.Http2SubchannelConnector = Http2SubchannelConnector;
|
634 |
|
\ | No newline at end of file |