@reptilestyle/grpc-js 1.9.14-compression.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +79 -0
- package/build/src/admin.d.ts +11 -0
- package/build/src/admin.js +30 -0
- package/build/src/admin.js.map +1 -0
- package/build/src/backoff-timeout.d.ts +90 -0
- package/build/src/backoff-timeout.js +174 -0
- package/build/src/backoff-timeout.js.map +1 -0
- package/build/src/call-credentials.d.ts +56 -0
- package/build/src/call-credentials.js +153 -0
- package/build/src/call-credentials.js.map +1 -0
- package/build/src/call-interface.d.ts +85 -0
- package/build/src/call-interface.js +84 -0
- package/build/src/call-interface.js.map +1 -0
- package/build/src/call-number.d.ts +1 -0
- package/build/src/call-number.js +24 -0
- package/build/src/call-number.js.map +1 -0
- package/build/src/call.d.ts +80 -0
- package/build/src/call.js +136 -0
- package/build/src/call.js.map +1 -0
- package/build/src/channel-credentials.d.ts +81 -0
- package/build/src/channel-credentials.js +177 -0
- package/build/src/channel-credentials.js.map +1 -0
- package/build/src/channel-options.d.ts +72 -0
- package/build/src/channel-options.js +69 -0
- package/build/src/channel-options.js.map +1 -0
- package/build/src/channel.d.ts +76 -0
- package/build/src/channel.js +68 -0
- package/build/src/channel.js.map +1 -0
- package/build/src/channelz.d.ts +108 -0
- package/build/src/channelz.js +637 -0
- package/build/src/channelz.js.map +1 -0
- package/build/src/client-interceptors.d.ts +120 -0
- package/build/src/client-interceptors.js +428 -0
- package/build/src/client-interceptors.js.map +1 -0
- package/build/src/client.d.ts +74 -0
- package/build/src/client.js +431 -0
- package/build/src/client.js.map +1 -0
- package/build/src/compression-algorithms.d.ts +5 -0
- package/build/src/compression-algorithms.js +26 -0
- package/build/src/compression-algorithms.js.map +1 -0
- package/build/src/compression-filter.d.ts +26 -0
- package/build/src/compression-filter.js +257 -0
- package/build/src/compression-filter.js.map +1 -0
- package/build/src/connectivity-state.d.ts +7 -0
- package/build/src/connectivity-state.js +28 -0
- package/build/src/connectivity-state.js.map +1 -0
- package/build/src/constants.d.ts +38 -0
- package/build/src/constants.js +64 -0
- package/build/src/constants.js.map +1 -0
- package/build/src/control-plane-status.d.ts +5 -0
- package/build/src/control-plane-status.js +42 -0
- package/build/src/control-plane-status.js.map +1 -0
- package/build/src/deadline.d.ts +14 -0
- package/build/src/deadline.js +97 -0
- package/build/src/deadline.js.map +1 -0
- package/build/src/duration.d.ts +7 -0
- package/build/src/duration.js +34 -0
- package/build/src/duration.js.map +1 -0
- package/build/src/error.d.ts +2 -0
- package/build/src/error.js +40 -0
- package/build/src/error.js.map +1 -0
- package/build/src/events.d.ts +9 -0
- package/build/src/events.js +19 -0
- package/build/src/events.js.map +1 -0
- package/build/src/experimental.d.ts +16 -0
- package/build/src/experimental.js +39 -0
- package/build/src/experimental.js.map +1 -0
- package/build/src/filter-stack.d.ts +21 -0
- package/build/src/filter-stack.js +82 -0
- package/build/src/filter-stack.js.map +1 -0
- package/build/src/filter.d.ts +25 -0
- package/build/src/filter.js +38 -0
- package/build/src/filter.js.map +1 -0
- package/build/src/generated/channelz.d.ts +72 -0
- package/build/src/generated/channelz.js +3 -0
- package/build/src/generated/channelz.js.map +1 -0
- package/build/src/generated/google/protobuf/Any.d.ts +9 -0
- package/build/src/generated/google/protobuf/Any.js +4 -0
- package/build/src/generated/google/protobuf/Any.js.map +1 -0
- package/build/src/generated/google/protobuf/BoolValue.d.ts +6 -0
- package/build/src/generated/google/protobuf/BoolValue.js +4 -0
- package/build/src/generated/google/protobuf/BoolValue.js.map +1 -0
- package/build/src/generated/google/protobuf/BytesValue.d.ts +6 -0
- package/build/src/generated/google/protobuf/BytesValue.js +4 -0
- package/build/src/generated/google/protobuf/BytesValue.js.map +1 -0
- package/build/src/generated/google/protobuf/DoubleValue.d.ts +6 -0
- package/build/src/generated/google/protobuf/DoubleValue.js +4 -0
- package/build/src/generated/google/protobuf/DoubleValue.js.map +1 -0
- package/build/src/generated/google/protobuf/Duration.d.ts +9 -0
- package/build/src/generated/google/protobuf/Duration.js +4 -0
- package/build/src/generated/google/protobuf/Duration.js.map +1 -0
- package/build/src/generated/google/protobuf/FloatValue.d.ts +6 -0
- package/build/src/generated/google/protobuf/FloatValue.js +4 -0
- package/build/src/generated/google/protobuf/FloatValue.js.map +1 -0
- package/build/src/generated/google/protobuf/Int32Value.d.ts +6 -0
- package/build/src/generated/google/protobuf/Int32Value.js +4 -0
- package/build/src/generated/google/protobuf/Int32Value.js.map +1 -0
- package/build/src/generated/google/protobuf/Int64Value.d.ts +7 -0
- package/build/src/generated/google/protobuf/Int64Value.js +4 -0
- package/build/src/generated/google/protobuf/Int64Value.js.map +1 -0
- package/build/src/generated/google/protobuf/StringValue.d.ts +6 -0
- package/build/src/generated/google/protobuf/StringValue.js +4 -0
- package/build/src/generated/google/protobuf/StringValue.js.map +1 -0
- package/build/src/generated/google/protobuf/Timestamp.d.ts +9 -0
- package/build/src/generated/google/protobuf/Timestamp.js +4 -0
- package/build/src/generated/google/protobuf/Timestamp.js.map +1 -0
- package/build/src/generated/google/protobuf/UInt32Value.d.ts +6 -0
- package/build/src/generated/google/protobuf/UInt32Value.js +4 -0
- package/build/src/generated/google/protobuf/UInt32Value.js.map +1 -0
- package/build/src/generated/google/protobuf/UInt64Value.d.ts +7 -0
- package/build/src/generated/google/protobuf/UInt64Value.js +4 -0
- package/build/src/generated/google/protobuf/UInt64Value.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Address.d.ts +79 -0
- package/build/src/generated/grpc/channelz/v1/Address.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Address.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Channel.d.ts +64 -0
- package/build/src/generated/grpc/channelz/v1/Channel.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Channel.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ChannelConnectivityState.d.ts +24 -0
- package/build/src/generated/grpc/channelz/v1/ChannelConnectivityState.js +14 -0
- package/build/src/generated/grpc/channelz/v1/ChannelConnectivityState.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ChannelData.d.ts +72 -0
- package/build/src/generated/grpc/channelz/v1/ChannelData.js +4 -0
- package/build/src/generated/grpc/channelz/v1/ChannelData.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ChannelRef.d.ts +27 -0
- package/build/src/generated/grpc/channelz/v1/ChannelRef.js +4 -0
- package/build/src/generated/grpc/channelz/v1/ChannelRef.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTrace.d.ts +41 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTrace.js +4 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTrace.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTraceEvent.d.ts +74 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTraceEvent.js +15 -0
- package/build/src/generated/grpc/channelz/v1/ChannelTraceEvent.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Channelz.d.ts +159 -0
- package/build/src/generated/grpc/channelz/v1/Channelz.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Channelz.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelRequest.d.ts +13 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelResponse.d.ts +15 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetChannelResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServerRequest.d.ts +13 -0
- package/build/src/generated/grpc/channelz/v1/GetServerRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServerRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServerResponse.d.ts +15 -0
- package/build/src/generated/grpc/channelz/v1/GetServerResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServerResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsRequest.d.ts +35 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsResponse.d.ts +29 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServerSocketsResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServersRequest.d.ts +33 -0
- package/build/src/generated/grpc/channelz/v1/GetServersRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServersRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetServersResponse.d.ts +29 -0
- package/build/src/generated/grpc/channelz/v1/GetServersResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetServersResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketRequest.d.ts +25 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketResponse.d.ts +15 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetSocketResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelRequest.d.ts +13 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelResponse.d.ts +15 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetSubchannelResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsRequest.d.ts +33 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsRequest.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsRequest.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsResponse.d.ts +29 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsResponse.js +4 -0
- package/build/src/generated/grpc/channelz/v1/GetTopChannelsResponse.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Security.d.ts +79 -0
- package/build/src/generated/grpc/channelz/v1/Security.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Security.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Server.d.ts +41 -0
- package/build/src/generated/grpc/channelz/v1/Server.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Server.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ServerData.d.ts +53 -0
- package/build/src/generated/grpc/channelz/v1/ServerData.js +4 -0
- package/build/src/generated/grpc/channelz/v1/ServerData.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/ServerRef.d.ts +27 -0
- package/build/src/generated/grpc/channelz/v1/ServerRef.js +4 -0
- package/build/src/generated/grpc/channelz/v1/ServerRef.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Socket.d.ts +66 -0
- package/build/src/generated/grpc/channelz/v1/Socket.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Socket.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketData.d.ts +146 -0
- package/build/src/generated/grpc/channelz/v1/SocketData.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketData.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketOption.d.ts +43 -0
- package/build/src/generated/grpc/channelz/v1/SocketOption.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketOption.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionLinger.d.ts +29 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionLinger.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionLinger.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.d.ts +70 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTimeout.d.ts +15 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTimeout.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketOptionTimeout.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SocketRef.d.ts +27 -0
- package/build/src/generated/grpc/channelz/v1/SocketRef.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SocketRef.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/Subchannel.d.ts +66 -0
- package/build/src/generated/grpc/channelz/v1/Subchannel.js +4 -0
- package/build/src/generated/grpc/channelz/v1/Subchannel.js.map +1 -0
- package/build/src/generated/grpc/channelz/v1/SubchannelRef.d.ts +27 -0
- package/build/src/generated/grpc/channelz/v1/SubchannelRef.js +4 -0
- package/build/src/generated/grpc/channelz/v1/SubchannelRef.js.map +1 -0
- package/build/src/http_proxy.d.ts +15 -0
- package/build/src/http_proxy.js +259 -0
- package/build/src/http_proxy.js.map +1 -0
- package/build/src/index.d.ts +76 -0
- package/build/src/index.js +140 -0
- package/build/src/index.js.map +1 -0
- package/build/src/internal-channel.d.ts +118 -0
- package/build/src/internal-channel.js +535 -0
- package/build/src/internal-channel.js.map +1 -0
- package/build/src/load-balancer-child-handler.d.ts +24 -0
- package/build/src/load-balancer-child-handler.js +151 -0
- package/build/src/load-balancer-child-handler.js.map +1 -0
- package/build/src/load-balancer-outlier-detection.d.ts +61 -0
- package/build/src/load-balancer-outlier-detection.js +608 -0
- package/build/src/load-balancer-outlier-detection.js.map +1 -0
- package/build/src/load-balancer-pick-first.d.ts +97 -0
- package/build/src/load-balancer-pick-first.js +393 -0
- package/build/src/load-balancer-pick-first.js.map +1 -0
- package/build/src/load-balancer-round-robin.d.ts +21 -0
- package/build/src/load-balancer-round-robin.js +174 -0
- package/build/src/load-balancer-round-robin.js.map +1 -0
- package/build/src/load-balancer.d.ts +97 -0
- package/build/src/load-balancer.js +102 -0
- package/build/src/load-balancer.js.map +1 -0
- package/build/src/load-balancing-call.d.ts +44 -0
- package/build/src/load-balancing-call.js +269 -0
- package/build/src/load-balancing-call.js.map +1 -0
- package/build/src/logging.d.ts +7 -0
- package/build/src/logging.js +114 -0
- package/build/src/logging.js.map +1 -0
- package/build/src/make-client.d.ts +71 -0
- package/build/src/make-client.js +143 -0
- package/build/src/make-client.js.map +1 -0
- package/build/src/max-message-size-filter.d.ts +15 -0
- package/build/src/max-message-size-filter.js +86 -0
- package/build/src/max-message-size-filter.js.map +1 -0
- package/build/src/metadata.d.ts +84 -0
- package/build/src/metadata.js +249 -0
- package/build/src/metadata.js.map +1 -0
- package/build/src/object-stream.d.ts +27 -0
- package/build/src/object-stream.js +19 -0
- package/build/src/object-stream.js.map +1 -0
- package/build/src/picker.d.ts +91 -0
- package/build/src/picker.js +78 -0
- package/build/src/picker.js.map +1 -0
- package/build/src/resolver-dns.d.ts +13 -0
- package/build/src/resolver-dns.js +328 -0
- package/build/src/resolver-dns.js.map +1 -0
- package/build/src/resolver-ip.d.ts +1 -0
- package/build/src/resolver-ip.js +104 -0
- package/build/src/resolver-ip.js.map +1 -0
- package/build/src/resolver-uds.d.ts +1 -0
- package/build/src/resolver-uds.js +50 -0
- package/build/src/resolver-uds.js.map +1 -0
- package/build/src/resolver.d.ts +105 -0
- package/build/src/resolver.js +87 -0
- package/build/src/resolver.js.map +1 -0
- package/build/src/resolving-call.d.ts +44 -0
- package/build/src/resolving-call.js +273 -0
- package/build/src/resolving-call.js.map +1 -0
- package/build/src/resolving-load-balancer.d.ts +67 -0
- package/build/src/resolving-load-balancer.js +304 -0
- package/build/src/resolving-load-balancer.js.map +1 -0
- package/build/src/retrying-call.d.ts +94 -0
- package/build/src/retrying-call.js +639 -0
- package/build/src/retrying-call.js.map +1 -0
- package/build/src/server-call.d.ts +159 -0
- package/build/src/server-call.js +700 -0
- package/build/src/server-call.js.map +1 -0
- package/build/src/server-credentials.d.ts +11 -0
- package/build/src/server-credentials.js +81 -0
- package/build/src/server-credentials.js.map +1 -0
- package/build/src/server.d.ts +56 -0
- package/build/src/server.js +892 -0
- package/build/src/server.js.map +1 -0
- package/build/src/service-config.d.ts +56 -0
- package/build/src/service-config.js +416 -0
- package/build/src/service-config.js.map +1 -0
- package/build/src/status-builder.d.ts +28 -0
- package/build/src/status-builder.js +68 -0
- package/build/src/status-builder.js.map +1 -0
- package/build/src/stream-decoder.d.ts +10 -0
- package/build/src/stream-decoder.js +96 -0
- package/build/src/stream-decoder.js.map +1 -0
- package/build/src/subchannel-address.d.ts +18 -0
- package/build/src/subchannel-address.js +65 -0
- package/build/src/subchannel-address.js.map +1 -0
- package/build/src/subchannel-call.d.ts +61 -0
- package/build/src/subchannel-call.js +461 -0
- package/build/src/subchannel-call.js.map +1 -0
- package/build/src/subchannel-interface.d.ts +49 -0
- package/build/src/subchannel-interface.js +59 -0
- package/build/src/subchannel-interface.js.map +1 -0
- package/build/src/subchannel-pool.d.ts +40 -0
- package/build/src/subchannel-pool.js +137 -0
- package/build/src/subchannel-pool.js.map +1 -0
- package/build/src/subchannel.d.ts +119 -0
- package/build/src/subchannel.js +353 -0
- package/build/src/subchannel.js.map +1 -0
- package/build/src/tls-helpers.d.ts +2 -0
- package/build/src/tls-helpers.js +34 -0
- package/build/src/tls-helpers.js.map +1 -0
- package/build/src/transport.d.ts +130 -0
- package/build/src/transport.js +640 -0
- package/build/src/transport.js.map +1 -0
- package/build/src/uri-parser.d.ts +12 -0
- package/build/src/uri-parser.js +110 -0
- package/build/src/uri-parser.js.map +1 -0
- package/package.json +85 -0
- package/proto/channelz.proto +564 -0
- package/src/admin.ts +45 -0
- package/src/backoff-timeout.ts +196 -0
- package/src/call-credentials.ts +226 -0
- package/src/call-interface.ts +173 -0
- package/src/call-number.ts +22 -0
- package/src/call.ts +200 -0
- package/src/channel-credentials.ts +267 -0
- package/src/channel-options.ts +119 -0
- package/src/channel.ts +174 -0
- package/src/channelz.ts +886 -0
- package/src/client-interceptors.ts +577 -0
- package/src/client.ts +715 -0
- package/src/compression-algorithms.ts +22 -0
- package/src/compression-filter.ts +315 -0
- package/src/connectivity-state.ts +24 -0
- package/src/constants.ts +66 -0
- package/src/control-plane-status.ts +43 -0
- package/src/deadline.ts +95 -0
- package/src/duration.ts +36 -0
- package/src/error.ts +37 -0
- package/src/events.ts +26 -0
- package/src/experimental.ts +48 -0
- package/src/filter-stack.ts +100 -0
- package/src/filter.ts +63 -0
- package/src/generated/channelz.ts +73 -0
- package/src/generated/google/protobuf/Any.ts +13 -0
- package/src/generated/google/protobuf/BoolValue.ts +10 -0
- package/src/generated/google/protobuf/BytesValue.ts +10 -0
- package/src/generated/google/protobuf/DoubleValue.ts +10 -0
- package/src/generated/google/protobuf/Duration.ts +13 -0
- package/src/generated/google/protobuf/FloatValue.ts +10 -0
- package/src/generated/google/protobuf/Int32Value.ts +10 -0
- package/src/generated/google/protobuf/Int64Value.ts +11 -0
- package/src/generated/google/protobuf/StringValue.ts +10 -0
- package/src/generated/google/protobuf/Timestamp.ts +13 -0
- package/src/generated/google/protobuf/UInt32Value.ts +10 -0
- package/src/generated/google/protobuf/UInt64Value.ts +11 -0
- package/src/generated/grpc/channelz/v1/Address.ts +89 -0
- package/src/generated/grpc/channelz/v1/Channel.ts +68 -0
- package/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts +45 -0
- package/src/generated/grpc/channelz/v1/ChannelData.ts +76 -0
- package/src/generated/grpc/channelz/v1/ChannelRef.ts +31 -0
- package/src/generated/grpc/channelz/v1/ChannelTrace.ts +45 -0
- package/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts +91 -0
- package/src/generated/grpc/channelz/v1/Channelz.ts +178 -0
- package/src/generated/grpc/channelz/v1/GetChannelRequest.ts +17 -0
- package/src/generated/grpc/channelz/v1/GetChannelResponse.ts +19 -0
- package/src/generated/grpc/channelz/v1/GetServerRequest.ts +17 -0
- package/src/generated/grpc/channelz/v1/GetServerResponse.ts +19 -0
- package/src/generated/grpc/channelz/v1/GetServerSocketsRequest.ts +39 -0
- package/src/generated/grpc/channelz/v1/GetServerSocketsResponse.ts +33 -0
- package/src/generated/grpc/channelz/v1/GetServersRequest.ts +37 -0
- package/src/generated/grpc/channelz/v1/GetServersResponse.ts +33 -0
- package/src/generated/grpc/channelz/v1/GetSocketRequest.ts +29 -0
- package/src/generated/grpc/channelz/v1/GetSocketResponse.ts +19 -0
- package/src/generated/grpc/channelz/v1/GetSubchannelRequest.ts +17 -0
- package/src/generated/grpc/channelz/v1/GetSubchannelResponse.ts +19 -0
- package/src/generated/grpc/channelz/v1/GetTopChannelsRequest.ts +37 -0
- package/src/generated/grpc/channelz/v1/GetTopChannelsResponse.ts +33 -0
- package/src/generated/grpc/channelz/v1/Security.ts +87 -0
- package/src/generated/grpc/channelz/v1/Server.ts +45 -0
- package/src/generated/grpc/channelz/v1/ServerData.ts +57 -0
- package/src/generated/grpc/channelz/v1/ServerRef.ts +31 -0
- package/src/generated/grpc/channelz/v1/Socket.ts +70 -0
- package/src/generated/grpc/channelz/v1/SocketData.ts +150 -0
- package/src/generated/grpc/channelz/v1/SocketOption.ts +47 -0
- package/src/generated/grpc/channelz/v1/SocketOptionLinger.ts +33 -0
- package/src/generated/grpc/channelz/v1/SocketOptionTcpInfo.ts +74 -0
- package/src/generated/grpc/channelz/v1/SocketOptionTimeout.ts +19 -0
- package/src/generated/grpc/channelz/v1/SocketRef.ts +31 -0
- package/src/generated/grpc/channelz/v1/Subchannel.ts +70 -0
- package/src/generated/grpc/channelz/v1/SubchannelRef.ts +31 -0
- package/src/http_proxy.ts +311 -0
- package/src/index.ts +284 -0
- package/src/internal-channel.ts +832 -0
- package/src/load-balancer-child-handler.ts +169 -0
- package/src/load-balancer-outlier-detection.ts +882 -0
- package/src/load-balancer-pick-first.ts +487 -0
- package/src/load-balancer-round-robin.ts +249 -0
- package/src/load-balancer.ts +230 -0
- package/src/load-balancing-call.ts +351 -0
- package/src/logging.ts +123 -0
- package/src/make-client.ts +238 -0
- package/src/max-message-size-filter.ts +88 -0
- package/src/metadata.ts +298 -0
- package/src/object-stream.ts +66 -0
- package/src/picker.ts +146 -0
- package/src/resolver-dns.ts +412 -0
- package/src/resolver-ip.ts +120 -0
- package/src/resolver-uds.ts +63 -0
- package/src/resolver.ts +180 -0
- package/src/resolving-call.ts +331 -0
- package/src/resolving-load-balancer.ts +403 -0
- package/src/retrying-call.ts +821 -0
- package/src/server-call.ts +1033 -0
- package/src/server-credentials.ts +108 -0
- package/src/server.ts +1300 -0
- package/src/service-config.ts +542 -0
- package/src/status-builder.ts +80 -0
- package/src/stream-decoder.ts +105 -0
- package/src/subchannel-address.ts +88 -0
- package/src/subchannel-call.ts +539 -0
- package/src/subchannel-interface.ts +97 -0
- package/src/subchannel-pool.ts +176 -0
- package/src/subchannel.ts +482 -0
- package/src/tls-helpers.ts +35 -0
- package/src/transport.ts +824 -0
- package/src/uri-parser.ts +114 -0
package/src/server.ts
ADDED
|
@@ -0,0 +1,1300 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2019 gRPC authors.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as http2 from 'http2';
|
|
19
|
+
import { AddressInfo } from 'net';
|
|
20
|
+
|
|
21
|
+
import { ServiceError } from './call';
|
|
22
|
+
import { Status, LogVerbosity } from './constants';
|
|
23
|
+
import { Deserialize, Serialize, ServiceDefinition } from './make-client';
|
|
24
|
+
import { Metadata } from './metadata';
|
|
25
|
+
import {
|
|
26
|
+
BidiStreamingHandler,
|
|
27
|
+
ClientStreamingHandler,
|
|
28
|
+
HandleCall,
|
|
29
|
+
Handler,
|
|
30
|
+
HandlerType,
|
|
31
|
+
Http2ServerCallStream,
|
|
32
|
+
sendUnaryData,
|
|
33
|
+
ServerDuplexStream,
|
|
34
|
+
ServerDuplexStreamImpl,
|
|
35
|
+
ServerReadableStream,
|
|
36
|
+
ServerReadableStreamImpl,
|
|
37
|
+
ServerStreamingHandler,
|
|
38
|
+
ServerUnaryCall,
|
|
39
|
+
ServerUnaryCallImpl,
|
|
40
|
+
ServerWritableStream,
|
|
41
|
+
ServerWritableStreamImpl,
|
|
42
|
+
UnaryHandler,
|
|
43
|
+
ServerErrorResponse,
|
|
44
|
+
ServerStatusResponse,
|
|
45
|
+
} from './server-call';
|
|
46
|
+
import { ServerCredentials } from './server-credentials';
|
|
47
|
+
import { ChannelOptions } from './channel-options';
|
|
48
|
+
import {
|
|
49
|
+
createResolver,
|
|
50
|
+
ResolverListener,
|
|
51
|
+
mapUriDefaultScheme,
|
|
52
|
+
} from './resolver';
|
|
53
|
+
import * as logging from './logging';
|
|
54
|
+
import {
|
|
55
|
+
SubchannelAddress,
|
|
56
|
+
TcpSubchannelAddress,
|
|
57
|
+
isTcpSubchannelAddress,
|
|
58
|
+
subchannelAddressToString,
|
|
59
|
+
stringToSubchannelAddress,
|
|
60
|
+
} from './subchannel-address';
|
|
61
|
+
import { parseUri } from './uri-parser';
|
|
62
|
+
import {
|
|
63
|
+
ChannelzCallTracker,
|
|
64
|
+
ChannelzChildrenTracker,
|
|
65
|
+
ChannelzTrace,
|
|
66
|
+
registerChannelzServer,
|
|
67
|
+
registerChannelzSocket,
|
|
68
|
+
ServerInfo,
|
|
69
|
+
ServerRef,
|
|
70
|
+
SocketInfo,
|
|
71
|
+
SocketRef,
|
|
72
|
+
TlsInfo,
|
|
73
|
+
unregisterChannelzRef,
|
|
74
|
+
} from './channelz';
|
|
75
|
+
import { CipherNameAndProtocol, TLSSocket } from 'tls';
|
|
76
|
+
|
|
77
|
+
const UNLIMITED_CONNECTION_AGE_MS = ~(1 << 31);
|
|
78
|
+
const KEEPALIVE_MAX_TIME_MS = ~(1 << 31);
|
|
79
|
+
const KEEPALIVE_TIMEOUT_MS = 20000;
|
|
80
|
+
|
|
81
|
+
const { HTTP2_HEADER_PATH } = http2.constants;
|
|
82
|
+
|
|
83
|
+
const TRACER_NAME = 'server';
|
|
84
|
+
|
|
85
|
+
interface BindResult {
|
|
86
|
+
port: number;
|
|
87
|
+
count: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function noop(): void {}
|
|
91
|
+
|
|
92
|
+
function getUnimplementedStatusResponse(
|
|
93
|
+
methodName: string
|
|
94
|
+
): Partial<ServiceError> {
|
|
95
|
+
return {
|
|
96
|
+
code: Status.UNIMPLEMENTED,
|
|
97
|
+
details: `The server does not implement the method ${methodName}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
102
|
+
type UntypedUnaryHandler = UnaryHandler<any, any>;
|
|
103
|
+
type UntypedClientStreamingHandler = ClientStreamingHandler<any, any>;
|
|
104
|
+
type UntypedServerStreamingHandler = ServerStreamingHandler<any, any>;
|
|
105
|
+
type UntypedBidiStreamingHandler = BidiStreamingHandler<any, any>;
|
|
106
|
+
export type UntypedHandleCall = HandleCall<any, any>;
|
|
107
|
+
type UntypedHandler = Handler<any, any>;
|
|
108
|
+
export interface UntypedServiceImplementation {
|
|
109
|
+
[name: string]: UntypedHandleCall;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function getDefaultHandler(handlerType: HandlerType, methodName: string) {
|
|
113
|
+
const unimplementedStatusResponse =
|
|
114
|
+
getUnimplementedStatusResponse(methodName);
|
|
115
|
+
switch (handlerType) {
|
|
116
|
+
case 'unary':
|
|
117
|
+
return (
|
|
118
|
+
call: ServerUnaryCall<any, any>,
|
|
119
|
+
callback: sendUnaryData<any>
|
|
120
|
+
) => {
|
|
121
|
+
callback(unimplementedStatusResponse as ServiceError, null);
|
|
122
|
+
};
|
|
123
|
+
case 'clientStream':
|
|
124
|
+
return (
|
|
125
|
+
call: ServerReadableStream<any, any>,
|
|
126
|
+
callback: sendUnaryData<any>
|
|
127
|
+
) => {
|
|
128
|
+
callback(unimplementedStatusResponse as ServiceError, null);
|
|
129
|
+
};
|
|
130
|
+
case 'serverStream':
|
|
131
|
+
return (call: ServerWritableStream<any, any>) => {
|
|
132
|
+
call.emit('error', unimplementedStatusResponse);
|
|
133
|
+
};
|
|
134
|
+
case 'bidi':
|
|
135
|
+
return (call: ServerDuplexStream<any, any>) => {
|
|
136
|
+
call.emit('error', unimplementedStatusResponse);
|
|
137
|
+
};
|
|
138
|
+
default:
|
|
139
|
+
throw new Error(`Invalid handlerType ${handlerType}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface ChannelzSessionInfo {
|
|
144
|
+
ref: SocketRef;
|
|
145
|
+
streamTracker: ChannelzCallTracker;
|
|
146
|
+
messagesSent: number;
|
|
147
|
+
messagesReceived: number;
|
|
148
|
+
lastMessageSentTimestamp: Date | null;
|
|
149
|
+
lastMessageReceivedTimestamp: Date | null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export class Server {
|
|
153
|
+
private http2ServerList: {
|
|
154
|
+
server: http2.Http2Server | http2.Http2SecureServer;
|
|
155
|
+
channelzRef: SocketRef;
|
|
156
|
+
}[] = [];
|
|
157
|
+
|
|
158
|
+
private handlers: Map<string, UntypedHandler> = new Map<
|
|
159
|
+
string,
|
|
160
|
+
UntypedHandler
|
|
161
|
+
>();
|
|
162
|
+
private sessions = new Map<http2.ServerHttp2Session, ChannelzSessionInfo>();
|
|
163
|
+
private started = false;
|
|
164
|
+
private shutdown = false;
|
|
165
|
+
private options: ChannelOptions;
|
|
166
|
+
private serverAddressString = 'null';
|
|
167
|
+
|
|
168
|
+
// Channelz Info
|
|
169
|
+
private readonly channelzEnabled: boolean = true;
|
|
170
|
+
private channelzRef: ServerRef;
|
|
171
|
+
private channelzTrace = new ChannelzTrace();
|
|
172
|
+
private callTracker = new ChannelzCallTracker();
|
|
173
|
+
private listenerChildrenTracker = new ChannelzChildrenTracker();
|
|
174
|
+
private sessionChildrenTracker = new ChannelzChildrenTracker();
|
|
175
|
+
|
|
176
|
+
private readonly maxConnectionAgeMs: number;
|
|
177
|
+
private readonly maxConnectionAgeGraceMs: number;
|
|
178
|
+
|
|
179
|
+
private readonly keepaliveTimeMs: number;
|
|
180
|
+
private readonly keepaliveTimeoutMs: number;
|
|
181
|
+
|
|
182
|
+
constructor(options?: ChannelOptions) {
|
|
183
|
+
this.options = options ?? {};
|
|
184
|
+
if (this.options['grpc.enable_channelz'] === 0) {
|
|
185
|
+
this.channelzEnabled = false;
|
|
186
|
+
}
|
|
187
|
+
this.channelzRef = registerChannelzServer(
|
|
188
|
+
() => this.getChannelzInfo(),
|
|
189
|
+
this.channelzEnabled
|
|
190
|
+
);
|
|
191
|
+
if (this.channelzEnabled) {
|
|
192
|
+
this.channelzTrace.addTrace('CT_INFO', 'Server created');
|
|
193
|
+
}
|
|
194
|
+
this.maxConnectionAgeMs =
|
|
195
|
+
this.options['grpc.max_connection_age_ms'] ?? UNLIMITED_CONNECTION_AGE_MS;
|
|
196
|
+
this.maxConnectionAgeGraceMs =
|
|
197
|
+
this.options['grpc.max_connection_age_grace_ms'] ??
|
|
198
|
+
UNLIMITED_CONNECTION_AGE_MS;
|
|
199
|
+
this.keepaliveTimeMs =
|
|
200
|
+
this.options['grpc.keepalive_time_ms'] ?? KEEPALIVE_MAX_TIME_MS;
|
|
201
|
+
this.keepaliveTimeoutMs =
|
|
202
|
+
this.options['grpc.keepalive_timeout_ms'] ?? KEEPALIVE_TIMEOUT_MS;
|
|
203
|
+
this.trace('Server constructed');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private getChannelzInfo(): ServerInfo {
|
|
207
|
+
return {
|
|
208
|
+
trace: this.channelzTrace,
|
|
209
|
+
callTracker: this.callTracker,
|
|
210
|
+
listenerChildren: this.listenerChildrenTracker.getChildLists(),
|
|
211
|
+
sessionChildren: this.sessionChildrenTracker.getChildLists(),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private getChannelzSessionInfoGetter(
|
|
216
|
+
session: http2.ServerHttp2Session
|
|
217
|
+
): () => SocketInfo {
|
|
218
|
+
return () => {
|
|
219
|
+
const sessionInfo = this.sessions.get(session)!;
|
|
220
|
+
const sessionSocket = session.socket;
|
|
221
|
+
const remoteAddress = sessionSocket.remoteAddress
|
|
222
|
+
? stringToSubchannelAddress(
|
|
223
|
+
sessionSocket.remoteAddress,
|
|
224
|
+
sessionSocket.remotePort
|
|
225
|
+
)
|
|
226
|
+
: null;
|
|
227
|
+
const localAddress = sessionSocket.localAddress
|
|
228
|
+
? stringToSubchannelAddress(
|
|
229
|
+
sessionSocket.localAddress!,
|
|
230
|
+
sessionSocket.localPort
|
|
231
|
+
)
|
|
232
|
+
: null;
|
|
233
|
+
let tlsInfo: TlsInfo | null;
|
|
234
|
+
if (session.encrypted) {
|
|
235
|
+
const tlsSocket: TLSSocket = sessionSocket as TLSSocket;
|
|
236
|
+
const cipherInfo: CipherNameAndProtocol & { standardName?: string } =
|
|
237
|
+
tlsSocket.getCipher();
|
|
238
|
+
const certificate = tlsSocket.getCertificate();
|
|
239
|
+
const peerCertificate = tlsSocket.getPeerCertificate();
|
|
240
|
+
tlsInfo = {
|
|
241
|
+
cipherSuiteStandardName: cipherInfo.standardName ?? null,
|
|
242
|
+
cipherSuiteOtherName: cipherInfo.standardName
|
|
243
|
+
? null
|
|
244
|
+
: cipherInfo.name,
|
|
245
|
+
localCertificate:
|
|
246
|
+
certificate && 'raw' in certificate ? certificate.raw : null,
|
|
247
|
+
remoteCertificate:
|
|
248
|
+
peerCertificate && 'raw' in peerCertificate
|
|
249
|
+
? peerCertificate.raw
|
|
250
|
+
: null,
|
|
251
|
+
};
|
|
252
|
+
} else {
|
|
253
|
+
tlsInfo = null;
|
|
254
|
+
}
|
|
255
|
+
const socketInfo: SocketInfo = {
|
|
256
|
+
remoteAddress: remoteAddress,
|
|
257
|
+
localAddress: localAddress,
|
|
258
|
+
security: tlsInfo,
|
|
259
|
+
remoteName: null,
|
|
260
|
+
streamsStarted: sessionInfo.streamTracker.callsStarted,
|
|
261
|
+
streamsSucceeded: sessionInfo.streamTracker.callsSucceeded,
|
|
262
|
+
streamsFailed: sessionInfo.streamTracker.callsFailed,
|
|
263
|
+
messagesSent: sessionInfo.messagesSent,
|
|
264
|
+
messagesReceived: sessionInfo.messagesReceived,
|
|
265
|
+
keepAlivesSent: 0,
|
|
266
|
+
lastLocalStreamCreatedTimestamp: null,
|
|
267
|
+
lastRemoteStreamCreatedTimestamp:
|
|
268
|
+
sessionInfo.streamTracker.lastCallStartedTimestamp,
|
|
269
|
+
lastMessageSentTimestamp: sessionInfo.lastMessageSentTimestamp,
|
|
270
|
+
lastMessageReceivedTimestamp: sessionInfo.lastMessageReceivedTimestamp,
|
|
271
|
+
localFlowControlWindow: session.state.localWindowSize ?? null,
|
|
272
|
+
remoteFlowControlWindow: session.state.remoteWindowSize ?? null,
|
|
273
|
+
};
|
|
274
|
+
return socketInfo;
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private trace(text: string): void {
|
|
279
|
+
logging.trace(
|
|
280
|
+
LogVerbosity.DEBUG,
|
|
281
|
+
TRACER_NAME,
|
|
282
|
+
'(' + this.channelzRef.id + ') ' + text
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
addProtoService(): never {
|
|
287
|
+
throw new Error('Not implemented. Use addService() instead');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
addService(
|
|
291
|
+
service: ServiceDefinition,
|
|
292
|
+
implementation: UntypedServiceImplementation
|
|
293
|
+
): void {
|
|
294
|
+
if (
|
|
295
|
+
service === null ||
|
|
296
|
+
typeof service !== 'object' ||
|
|
297
|
+
implementation === null ||
|
|
298
|
+
typeof implementation !== 'object'
|
|
299
|
+
) {
|
|
300
|
+
throw new Error('addService() requires two objects as arguments');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const serviceKeys = Object.keys(service);
|
|
304
|
+
|
|
305
|
+
if (serviceKeys.length === 0) {
|
|
306
|
+
throw new Error('Cannot add an empty service to a server');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
serviceKeys.forEach(name => {
|
|
310
|
+
const attrs = service[name];
|
|
311
|
+
let methodType: HandlerType;
|
|
312
|
+
|
|
313
|
+
if (attrs.requestStream) {
|
|
314
|
+
if (attrs.responseStream) {
|
|
315
|
+
methodType = 'bidi';
|
|
316
|
+
} else {
|
|
317
|
+
methodType = 'clientStream';
|
|
318
|
+
}
|
|
319
|
+
} else {
|
|
320
|
+
if (attrs.responseStream) {
|
|
321
|
+
methodType = 'serverStream';
|
|
322
|
+
} else {
|
|
323
|
+
methodType = 'unary';
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let implFn = implementation[name];
|
|
328
|
+
let impl;
|
|
329
|
+
|
|
330
|
+
if (implFn === undefined && typeof attrs.originalName === 'string') {
|
|
331
|
+
implFn = implementation[attrs.originalName];
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (implFn !== undefined) {
|
|
335
|
+
impl = implFn.bind(implementation);
|
|
336
|
+
} else {
|
|
337
|
+
impl = getDefaultHandler(methodType, name);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const success = this.register(
|
|
341
|
+
attrs.path,
|
|
342
|
+
impl as UntypedHandleCall,
|
|
343
|
+
attrs.responseSerialize,
|
|
344
|
+
attrs.requestDeserialize,
|
|
345
|
+
methodType
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
if (success === false) {
|
|
349
|
+
throw new Error(`Method handler for ${attrs.path} already provided.`);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
removeService(service: ServiceDefinition): void {
|
|
355
|
+
if (service === null || typeof service !== 'object') {
|
|
356
|
+
throw new Error('removeService() requires object as argument');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const serviceKeys = Object.keys(service);
|
|
360
|
+
serviceKeys.forEach(name => {
|
|
361
|
+
const attrs = service[name];
|
|
362
|
+
this.unregister(attrs.path);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
bind(port: string, creds: ServerCredentials): never {
|
|
367
|
+
throw new Error('Not implemented. Use bindAsync() instead');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
bindAsync(
|
|
371
|
+
port: string,
|
|
372
|
+
creds: ServerCredentials,
|
|
373
|
+
callback: (error: Error | null, port: number) => void
|
|
374
|
+
): void {
|
|
375
|
+
if (this.started === true) {
|
|
376
|
+
throw new Error('server is already started');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (this.shutdown) {
|
|
380
|
+
throw new Error('bindAsync called after shutdown');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (typeof port !== 'string') {
|
|
384
|
+
throw new TypeError('port must be a string');
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (creds === null || !(creds instanceof ServerCredentials)) {
|
|
388
|
+
throw new TypeError('creds must be a ServerCredentials object');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (typeof callback !== 'function') {
|
|
392
|
+
throw new TypeError('callback must be a function');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const initialPortUri = parseUri(port);
|
|
396
|
+
if (initialPortUri === null) {
|
|
397
|
+
throw new Error(`Could not parse port "${port}"`);
|
|
398
|
+
}
|
|
399
|
+
const portUri = mapUriDefaultScheme(initialPortUri);
|
|
400
|
+
if (portUri === null) {
|
|
401
|
+
throw new Error(`Could not get a default scheme for port "${port}"`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const serverOptions: http2.ServerOptions = {
|
|
405
|
+
maxSendHeaderBlockLength: Number.MAX_SAFE_INTEGER,
|
|
406
|
+
};
|
|
407
|
+
if ('grpc-node.max_session_memory' in this.options) {
|
|
408
|
+
serverOptions.maxSessionMemory =
|
|
409
|
+
this.options['grpc-node.max_session_memory'];
|
|
410
|
+
} else {
|
|
411
|
+
/* By default, set a very large max session memory limit, to effectively
|
|
412
|
+
* disable enforcement of the limit. Some testing indicates that Node's
|
|
413
|
+
* behavior degrades badly when this limit is reached, so we solve that
|
|
414
|
+
* by disabling the check entirely. */
|
|
415
|
+
serverOptions.maxSessionMemory = Number.MAX_SAFE_INTEGER;
|
|
416
|
+
}
|
|
417
|
+
if ('grpc.max_concurrent_streams' in this.options) {
|
|
418
|
+
serverOptions.settings = {
|
|
419
|
+
maxConcurrentStreams: this.options['grpc.max_concurrent_streams'],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const deferredCallback = (error: Error | null, port: number) => {
|
|
424
|
+
process.nextTick(() => callback(error, port));
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const setupServer = (): http2.Http2Server | http2.Http2SecureServer => {
|
|
428
|
+
let http2Server: http2.Http2Server | http2.Http2SecureServer;
|
|
429
|
+
if (creds._isSecure()) {
|
|
430
|
+
const secureServerOptions = Object.assign(
|
|
431
|
+
serverOptions,
|
|
432
|
+
creds._getSettings()!
|
|
433
|
+
);
|
|
434
|
+
secureServerOptions.enableTrace =
|
|
435
|
+
this.options['grpc-node.tls_enable_trace'] === 1;
|
|
436
|
+
http2Server = http2.createSecureServer(secureServerOptions);
|
|
437
|
+
http2Server.on('secureConnection', (socket: TLSSocket) => {
|
|
438
|
+
/* These errors need to be handled by the user of Http2SecureServer,
|
|
439
|
+
* according to https://github.com/nodejs/node/issues/35824 */
|
|
440
|
+
socket.on('error', (e: Error) => {
|
|
441
|
+
this.trace(
|
|
442
|
+
'An incoming TLS connection closed with error: ' + e.message
|
|
443
|
+
);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
} else {
|
|
447
|
+
http2Server = http2.createServer(serverOptions);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
http2Server.setTimeout(0, noop);
|
|
451
|
+
this._setupHandlers(http2Server);
|
|
452
|
+
return http2Server;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const bindSpecificPort = (
|
|
456
|
+
addressList: SubchannelAddress[],
|
|
457
|
+
portNum: number,
|
|
458
|
+
previousCount: number
|
|
459
|
+
): Promise<BindResult> => {
|
|
460
|
+
if (addressList.length === 0) {
|
|
461
|
+
return Promise.resolve({ port: portNum, count: previousCount });
|
|
462
|
+
}
|
|
463
|
+
return Promise.all(
|
|
464
|
+
addressList.map(address => {
|
|
465
|
+
this.trace(
|
|
466
|
+
'Attempting to bind ' + subchannelAddressToString(address)
|
|
467
|
+
);
|
|
468
|
+
let addr: SubchannelAddress;
|
|
469
|
+
if (isTcpSubchannelAddress(address)) {
|
|
470
|
+
addr = {
|
|
471
|
+
host: (address as TcpSubchannelAddress).host,
|
|
472
|
+
port: portNum,
|
|
473
|
+
};
|
|
474
|
+
} else {
|
|
475
|
+
addr = address;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const http2Server = setupServer();
|
|
479
|
+
return new Promise<number | Error>((resolve, reject) => {
|
|
480
|
+
const onError = (err: Error) => {
|
|
481
|
+
this.trace(
|
|
482
|
+
'Failed to bind ' +
|
|
483
|
+
subchannelAddressToString(address) +
|
|
484
|
+
' with error ' +
|
|
485
|
+
err.message
|
|
486
|
+
);
|
|
487
|
+
resolve(err);
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
http2Server.once('error', onError);
|
|
491
|
+
|
|
492
|
+
http2Server.listen(addr, () => {
|
|
493
|
+
if (this.shutdown) {
|
|
494
|
+
http2Server.close();
|
|
495
|
+
resolve(new Error('bindAsync failed because server is shutdown'));
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const boundAddress = http2Server.address()!;
|
|
499
|
+
let boundSubchannelAddress: SubchannelAddress;
|
|
500
|
+
if (typeof boundAddress === 'string') {
|
|
501
|
+
boundSubchannelAddress = {
|
|
502
|
+
path: boundAddress,
|
|
503
|
+
};
|
|
504
|
+
} else {
|
|
505
|
+
boundSubchannelAddress = {
|
|
506
|
+
host: boundAddress.address,
|
|
507
|
+
port: boundAddress.port,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const channelzRef = registerChannelzSocket(
|
|
512
|
+
subchannelAddressToString(boundSubchannelAddress),
|
|
513
|
+
() => {
|
|
514
|
+
return {
|
|
515
|
+
localAddress: boundSubchannelAddress,
|
|
516
|
+
remoteAddress: null,
|
|
517
|
+
security: null,
|
|
518
|
+
remoteName: null,
|
|
519
|
+
streamsStarted: 0,
|
|
520
|
+
streamsSucceeded: 0,
|
|
521
|
+
streamsFailed: 0,
|
|
522
|
+
messagesSent: 0,
|
|
523
|
+
messagesReceived: 0,
|
|
524
|
+
keepAlivesSent: 0,
|
|
525
|
+
lastLocalStreamCreatedTimestamp: null,
|
|
526
|
+
lastRemoteStreamCreatedTimestamp: null,
|
|
527
|
+
lastMessageSentTimestamp: null,
|
|
528
|
+
lastMessageReceivedTimestamp: null,
|
|
529
|
+
localFlowControlWindow: null,
|
|
530
|
+
remoteFlowControlWindow: null,
|
|
531
|
+
};
|
|
532
|
+
},
|
|
533
|
+
this.channelzEnabled
|
|
534
|
+
);
|
|
535
|
+
if (this.channelzEnabled) {
|
|
536
|
+
this.listenerChildrenTracker.refChild(channelzRef);
|
|
537
|
+
}
|
|
538
|
+
this.http2ServerList.push({
|
|
539
|
+
server: http2Server,
|
|
540
|
+
channelzRef: channelzRef,
|
|
541
|
+
});
|
|
542
|
+
this.trace(
|
|
543
|
+
'Successfully bound ' +
|
|
544
|
+
subchannelAddressToString(boundSubchannelAddress)
|
|
545
|
+
);
|
|
546
|
+
resolve(
|
|
547
|
+
'port' in boundSubchannelAddress
|
|
548
|
+
? boundSubchannelAddress.port
|
|
549
|
+
: portNum
|
|
550
|
+
);
|
|
551
|
+
http2Server.removeListener('error', onError);
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
})
|
|
555
|
+
).then(results => {
|
|
556
|
+
let count = 0;
|
|
557
|
+
for (const result of results) {
|
|
558
|
+
if (typeof result === 'number') {
|
|
559
|
+
count += 1;
|
|
560
|
+
if (result !== portNum) {
|
|
561
|
+
throw new Error(
|
|
562
|
+
'Invalid state: multiple port numbers added from single address'
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
port: portNum,
|
|
569
|
+
count: count + previousCount,
|
|
570
|
+
};
|
|
571
|
+
});
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
const bindWildcardPort = (
|
|
575
|
+
addressList: SubchannelAddress[]
|
|
576
|
+
): Promise<BindResult> => {
|
|
577
|
+
if (addressList.length === 0) {
|
|
578
|
+
return Promise.resolve<BindResult>({ port: 0, count: 0 });
|
|
579
|
+
}
|
|
580
|
+
const address = addressList[0];
|
|
581
|
+
const http2Server = setupServer();
|
|
582
|
+
return new Promise<BindResult>((resolve, reject) => {
|
|
583
|
+
const onError = (err: Error) => {
|
|
584
|
+
this.trace(
|
|
585
|
+
'Failed to bind ' +
|
|
586
|
+
subchannelAddressToString(address) +
|
|
587
|
+
' with error ' +
|
|
588
|
+
err.message
|
|
589
|
+
);
|
|
590
|
+
resolve(bindWildcardPort(addressList.slice(1)));
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
http2Server.once('error', onError);
|
|
594
|
+
|
|
595
|
+
http2Server.listen(address, () => {
|
|
596
|
+
if (this.shutdown) {
|
|
597
|
+
http2Server.close();
|
|
598
|
+
resolve({port: 0, count: 0});
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const boundAddress = http2Server.address() as AddressInfo;
|
|
602
|
+
const boundSubchannelAddress: SubchannelAddress = {
|
|
603
|
+
host: boundAddress.address,
|
|
604
|
+
port: boundAddress.port,
|
|
605
|
+
};
|
|
606
|
+
const channelzRef = registerChannelzSocket(
|
|
607
|
+
subchannelAddressToString(boundSubchannelAddress),
|
|
608
|
+
() => {
|
|
609
|
+
return {
|
|
610
|
+
localAddress: boundSubchannelAddress,
|
|
611
|
+
remoteAddress: null,
|
|
612
|
+
security: null,
|
|
613
|
+
remoteName: null,
|
|
614
|
+
streamsStarted: 0,
|
|
615
|
+
streamsSucceeded: 0,
|
|
616
|
+
streamsFailed: 0,
|
|
617
|
+
messagesSent: 0,
|
|
618
|
+
messagesReceived: 0,
|
|
619
|
+
keepAlivesSent: 0,
|
|
620
|
+
lastLocalStreamCreatedTimestamp: null,
|
|
621
|
+
lastRemoteStreamCreatedTimestamp: null,
|
|
622
|
+
lastMessageSentTimestamp: null,
|
|
623
|
+
lastMessageReceivedTimestamp: null,
|
|
624
|
+
localFlowControlWindow: null,
|
|
625
|
+
remoteFlowControlWindow: null,
|
|
626
|
+
};
|
|
627
|
+
},
|
|
628
|
+
this.channelzEnabled
|
|
629
|
+
);
|
|
630
|
+
if (this.channelzEnabled) {
|
|
631
|
+
this.listenerChildrenTracker.refChild(channelzRef);
|
|
632
|
+
}
|
|
633
|
+
this.http2ServerList.push({
|
|
634
|
+
server: http2Server,
|
|
635
|
+
channelzRef: channelzRef,
|
|
636
|
+
});
|
|
637
|
+
this.trace(
|
|
638
|
+
'Successfully bound ' +
|
|
639
|
+
subchannelAddressToString(boundSubchannelAddress)
|
|
640
|
+
);
|
|
641
|
+
resolve(bindSpecificPort(addressList.slice(1), boundAddress.port, 1));
|
|
642
|
+
http2Server.removeListener('error', onError);
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
const resolverListener: ResolverListener = {
|
|
648
|
+
onSuccessfulResolution: (
|
|
649
|
+
addressList,
|
|
650
|
+
serviceConfig,
|
|
651
|
+
serviceConfigError
|
|
652
|
+
) => {
|
|
653
|
+
// We only want one resolution result. Discard all future results
|
|
654
|
+
resolverListener.onSuccessfulResolution = () => {};
|
|
655
|
+
if (this.shutdown) {
|
|
656
|
+
deferredCallback(
|
|
657
|
+
new Error(`bindAsync failed because server is shutdown`),
|
|
658
|
+
0
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
if (addressList.length === 0) {
|
|
662
|
+
deferredCallback(
|
|
663
|
+
new Error(`No addresses resolved for port ${port}`),
|
|
664
|
+
0
|
|
665
|
+
);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
let bindResultPromise: Promise<BindResult>;
|
|
669
|
+
if (isTcpSubchannelAddress(addressList[0])) {
|
|
670
|
+
if (addressList[0].port === 0) {
|
|
671
|
+
bindResultPromise = bindWildcardPort(addressList);
|
|
672
|
+
} else {
|
|
673
|
+
bindResultPromise = bindSpecificPort(
|
|
674
|
+
addressList,
|
|
675
|
+
addressList[0].port,
|
|
676
|
+
0
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
// Use an arbitrary non-zero port for non-TCP addresses
|
|
681
|
+
bindResultPromise = bindSpecificPort(addressList, 1, 0);
|
|
682
|
+
}
|
|
683
|
+
bindResultPromise.then(
|
|
684
|
+
bindResult => {
|
|
685
|
+
if (bindResult.count === 0) {
|
|
686
|
+
const errorString = `No address added out of total ${addressList.length} resolved`;
|
|
687
|
+
logging.log(LogVerbosity.ERROR, errorString);
|
|
688
|
+
deferredCallback(new Error(errorString), 0);
|
|
689
|
+
} else {
|
|
690
|
+
if (bindResult.count < addressList.length) {
|
|
691
|
+
logging.log(
|
|
692
|
+
LogVerbosity.INFO,
|
|
693
|
+
`WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved`
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
deferredCallback(null, bindResult.port);
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
error => {
|
|
700
|
+
const errorString = `No address added out of total ${addressList.length} resolved`;
|
|
701
|
+
logging.log(LogVerbosity.ERROR, errorString);
|
|
702
|
+
deferredCallback(new Error(errorString), 0);
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
},
|
|
706
|
+
onError: error => {
|
|
707
|
+
deferredCallback(new Error(error.details), 0);
|
|
708
|
+
},
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
const resolver = createResolver(portUri, resolverListener, this.options);
|
|
712
|
+
resolver.updateResolution();
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
forceShutdown(): void {
|
|
716
|
+
// Close the server if it is still running.
|
|
717
|
+
|
|
718
|
+
for (const { server: http2Server, channelzRef: ref } of this
|
|
719
|
+
.http2ServerList) {
|
|
720
|
+
if (http2Server.listening) {
|
|
721
|
+
http2Server.close(() => {
|
|
722
|
+
if (this.channelzEnabled) {
|
|
723
|
+
this.listenerChildrenTracker.unrefChild(ref);
|
|
724
|
+
unregisterChannelzRef(ref);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
this.started = false;
|
|
731
|
+
this.shutdown = true;
|
|
732
|
+
|
|
733
|
+
// Always destroy any available sessions. It's possible that one or more
|
|
734
|
+
// tryShutdown() calls are in progress. Don't wait on them to finish.
|
|
735
|
+
this.sessions.forEach((channelzInfo, session) => {
|
|
736
|
+
// Cast NGHTTP2_CANCEL to any because TypeScript doesn't seem to
|
|
737
|
+
// recognize destroy(code) as a valid signature.
|
|
738
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
739
|
+
session.destroy(http2.constants.NGHTTP2_CANCEL as any);
|
|
740
|
+
});
|
|
741
|
+
this.sessions.clear();
|
|
742
|
+
if (this.channelzEnabled) {
|
|
743
|
+
unregisterChannelzRef(this.channelzRef);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
register<RequestType, ResponseType>(
|
|
748
|
+
name: string,
|
|
749
|
+
handler: HandleCall<RequestType, ResponseType>,
|
|
750
|
+
serialize: Serialize<ResponseType>,
|
|
751
|
+
deserialize: Deserialize<RequestType>,
|
|
752
|
+
type: string
|
|
753
|
+
): boolean {
|
|
754
|
+
if (this.handlers.has(name)) {
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
this.handlers.set(name, {
|
|
759
|
+
func: handler,
|
|
760
|
+
serialize,
|
|
761
|
+
deserialize,
|
|
762
|
+
type,
|
|
763
|
+
path: name,
|
|
764
|
+
} as UntypedHandler);
|
|
765
|
+
return true;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
unregister(name: string): boolean {
|
|
769
|
+
return this.handlers.delete(name);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
start(): void {
|
|
773
|
+
if (
|
|
774
|
+
this.http2ServerList.length === 0 ||
|
|
775
|
+
this.http2ServerList.every(
|
|
776
|
+
({ server: http2Server }) => http2Server.listening !== true
|
|
777
|
+
)
|
|
778
|
+
) {
|
|
779
|
+
throw new Error('server must be bound in order to start');
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
if (this.started === true) {
|
|
783
|
+
throw new Error('server is already started');
|
|
784
|
+
}
|
|
785
|
+
if (this.channelzEnabled) {
|
|
786
|
+
this.channelzTrace.addTrace('CT_INFO', 'Starting');
|
|
787
|
+
}
|
|
788
|
+
this.started = true;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
tryShutdown(callback: (error?: Error) => void): void {
|
|
792
|
+
const wrappedCallback = (error?: Error) => {
|
|
793
|
+
if (this.channelzEnabled) {
|
|
794
|
+
unregisterChannelzRef(this.channelzRef);
|
|
795
|
+
}
|
|
796
|
+
callback(error);
|
|
797
|
+
};
|
|
798
|
+
let pendingChecks = 0;
|
|
799
|
+
|
|
800
|
+
function maybeCallback(): void {
|
|
801
|
+
pendingChecks--;
|
|
802
|
+
|
|
803
|
+
if (pendingChecks === 0) {
|
|
804
|
+
wrappedCallback();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Close the server if necessary.
|
|
809
|
+
this.started = false;
|
|
810
|
+
this.shutdown = true;
|
|
811
|
+
|
|
812
|
+
for (const { server: http2Server, channelzRef: ref } of this
|
|
813
|
+
.http2ServerList) {
|
|
814
|
+
if (http2Server.listening) {
|
|
815
|
+
pendingChecks++;
|
|
816
|
+
http2Server.close(() => {
|
|
817
|
+
if (this.channelzEnabled) {
|
|
818
|
+
this.listenerChildrenTracker.unrefChild(ref);
|
|
819
|
+
unregisterChannelzRef(ref);
|
|
820
|
+
}
|
|
821
|
+
maybeCallback();
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
this.sessions.forEach((channelzInfo, session) => {
|
|
827
|
+
if (!session.closed) {
|
|
828
|
+
pendingChecks += 1;
|
|
829
|
+
session.close(maybeCallback);
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
if (pendingChecks === 0) {
|
|
833
|
+
wrappedCallback();
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
addHttp2Port(): never {
|
|
838
|
+
throw new Error('Not yet implemented');
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Get the channelz reference object for this server. The returned value is
|
|
843
|
+
* garbage if channelz is disabled for this server.
|
|
844
|
+
* @returns
|
|
845
|
+
*/
|
|
846
|
+
getChannelzRef() {
|
|
847
|
+
return this.channelzRef;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
private _verifyContentType(
|
|
851
|
+
stream: http2.ServerHttp2Stream,
|
|
852
|
+
headers: http2.IncomingHttpHeaders
|
|
853
|
+
): boolean {
|
|
854
|
+
const contentType = headers[http2.constants.HTTP2_HEADER_CONTENT_TYPE];
|
|
855
|
+
|
|
856
|
+
if (
|
|
857
|
+
typeof contentType !== 'string' ||
|
|
858
|
+
!contentType.startsWith('application/grpc')
|
|
859
|
+
) {
|
|
860
|
+
stream.respond(
|
|
861
|
+
{
|
|
862
|
+
[http2.constants.HTTP2_HEADER_STATUS]:
|
|
863
|
+
http2.constants.HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE,
|
|
864
|
+
},
|
|
865
|
+
{ endStream: true }
|
|
866
|
+
);
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
private _retrieveHandler(path: string): Handler<any, any> | null {
|
|
874
|
+
this.trace(
|
|
875
|
+
'Received call to method ' +
|
|
876
|
+
path +
|
|
877
|
+
' at address ' +
|
|
878
|
+
this.serverAddressString
|
|
879
|
+
);
|
|
880
|
+
|
|
881
|
+
const handler = this.handlers.get(path);
|
|
882
|
+
|
|
883
|
+
if (handler === undefined) {
|
|
884
|
+
this.trace(
|
|
885
|
+
'No handler registered for method ' +
|
|
886
|
+
path +
|
|
887
|
+
'. Sending UNIMPLEMENTED status.'
|
|
888
|
+
);
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return handler;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
private _respondWithError<T extends Partial<ServiceError>>(
|
|
896
|
+
err: T,
|
|
897
|
+
stream: http2.ServerHttp2Stream,
|
|
898
|
+
channelzSessionInfo: ChannelzSessionInfo | null = null
|
|
899
|
+
) {
|
|
900
|
+
const call = new Http2ServerCallStream(stream, null!, this.options);
|
|
901
|
+
|
|
902
|
+
if (err.code === undefined) {
|
|
903
|
+
err.code = Status.INTERNAL;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
if (this.channelzEnabled) {
|
|
907
|
+
this.callTracker.addCallFailed();
|
|
908
|
+
channelzSessionInfo?.streamTracker.addCallFailed();
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
call.sendError(err);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
private _channelzHandler(
|
|
915
|
+
stream: http2.ServerHttp2Stream,
|
|
916
|
+
headers: http2.IncomingHttpHeaders
|
|
917
|
+
) {
|
|
918
|
+
const channelzSessionInfo = this.sessions.get(
|
|
919
|
+
stream.session as http2.ServerHttp2Session
|
|
920
|
+
);
|
|
921
|
+
|
|
922
|
+
this.callTracker.addCallStarted();
|
|
923
|
+
channelzSessionInfo?.streamTracker.addCallStarted();
|
|
924
|
+
|
|
925
|
+
if (!this._verifyContentType(stream, headers)) {
|
|
926
|
+
this.callTracker.addCallFailed();
|
|
927
|
+
channelzSessionInfo?.streamTracker.addCallFailed();
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const path = headers[HTTP2_HEADER_PATH] as string;
|
|
932
|
+
|
|
933
|
+
const handler = this._retrieveHandler(path);
|
|
934
|
+
if (!handler) {
|
|
935
|
+
this._respondWithError(
|
|
936
|
+
getUnimplementedStatusResponse(path),
|
|
937
|
+
stream,
|
|
938
|
+
channelzSessionInfo
|
|
939
|
+
);
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
const call = new Http2ServerCallStream(stream, handler, this.options);
|
|
944
|
+
|
|
945
|
+
call.once('callEnd', (code: Status) => {
|
|
946
|
+
if (code === Status.OK) {
|
|
947
|
+
this.callTracker.addCallSucceeded();
|
|
948
|
+
} else {
|
|
949
|
+
this.callTracker.addCallFailed();
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
if (channelzSessionInfo) {
|
|
954
|
+
call.once('streamEnd', (success: boolean) => {
|
|
955
|
+
if (success) {
|
|
956
|
+
channelzSessionInfo.streamTracker.addCallSucceeded();
|
|
957
|
+
} else {
|
|
958
|
+
channelzSessionInfo.streamTracker.addCallFailed();
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
call.on('sendMessage', () => {
|
|
962
|
+
channelzSessionInfo.messagesSent += 1;
|
|
963
|
+
channelzSessionInfo.lastMessageSentTimestamp = new Date();
|
|
964
|
+
});
|
|
965
|
+
call.on('receiveMessage', () => {
|
|
966
|
+
channelzSessionInfo.messagesReceived += 1;
|
|
967
|
+
channelzSessionInfo.lastMessageReceivedTimestamp = new Date();
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
if (!this._runHandlerForCall(call, handler, headers)) {
|
|
972
|
+
this.callTracker.addCallFailed();
|
|
973
|
+
channelzSessionInfo?.streamTracker.addCallFailed();
|
|
974
|
+
|
|
975
|
+
call.sendError({
|
|
976
|
+
code: Status.INTERNAL,
|
|
977
|
+
details: `Unknown handler type: ${handler.type}`,
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
private _streamHandler(
|
|
983
|
+
stream: http2.ServerHttp2Stream,
|
|
984
|
+
headers: http2.IncomingHttpHeaders
|
|
985
|
+
) {
|
|
986
|
+
if (this._verifyContentType(stream, headers) !== true) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
const path = headers[HTTP2_HEADER_PATH] as string;
|
|
991
|
+
|
|
992
|
+
const handler = this._retrieveHandler(path);
|
|
993
|
+
if (!handler) {
|
|
994
|
+
this._respondWithError(
|
|
995
|
+
getUnimplementedStatusResponse(path),
|
|
996
|
+
stream,
|
|
997
|
+
null
|
|
998
|
+
);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
const call = new Http2ServerCallStream(stream, handler, this.options);
|
|
1003
|
+
if (!this._runHandlerForCall(call, handler, headers)) {
|
|
1004
|
+
call.sendError({
|
|
1005
|
+
code: Status.INTERNAL,
|
|
1006
|
+
details: `Unknown handler type: ${handler.type}`,
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
private _runHandlerForCall(
|
|
1012
|
+
call: Http2ServerCallStream<any, any>,
|
|
1013
|
+
handler: Handler<any, any>,
|
|
1014
|
+
headers: http2.IncomingHttpHeaders
|
|
1015
|
+
): boolean {
|
|
1016
|
+
const metadata = call.receiveMetadata(headers);
|
|
1017
|
+
const encoding =
|
|
1018
|
+
(metadata.get('grpc-encoding')[0] as string | undefined) ?? 'identity';
|
|
1019
|
+
metadata.remove('grpc-encoding');
|
|
1020
|
+
|
|
1021
|
+
const { type } = handler;
|
|
1022
|
+
if (type === 'unary') {
|
|
1023
|
+
handleUnary(call, handler as UntypedUnaryHandler, metadata, encoding);
|
|
1024
|
+
} else if (type === 'clientStream') {
|
|
1025
|
+
handleClientStreaming(
|
|
1026
|
+
call,
|
|
1027
|
+
handler as UntypedClientStreamingHandler,
|
|
1028
|
+
metadata,
|
|
1029
|
+
encoding
|
|
1030
|
+
);
|
|
1031
|
+
} else if (type === 'serverStream') {
|
|
1032
|
+
handleServerStreaming(
|
|
1033
|
+
call,
|
|
1034
|
+
handler as UntypedServerStreamingHandler,
|
|
1035
|
+
metadata,
|
|
1036
|
+
encoding
|
|
1037
|
+
);
|
|
1038
|
+
} else if (type === 'bidi') {
|
|
1039
|
+
handleBidiStreaming(
|
|
1040
|
+
call,
|
|
1041
|
+
handler as UntypedBidiStreamingHandler,
|
|
1042
|
+
metadata,
|
|
1043
|
+
encoding
|
|
1044
|
+
);
|
|
1045
|
+
} else {
|
|
1046
|
+
return false;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
return true;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
private _setupHandlers(
|
|
1053
|
+
http2Server: http2.Http2Server | http2.Http2SecureServer
|
|
1054
|
+
): void {
|
|
1055
|
+
if (http2Server === null) {
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
const serverAddress = http2Server.address();
|
|
1060
|
+
let serverAddressString = 'null';
|
|
1061
|
+
if (serverAddress) {
|
|
1062
|
+
if (typeof serverAddress === 'string') {
|
|
1063
|
+
serverAddressString = serverAddress;
|
|
1064
|
+
} else {
|
|
1065
|
+
serverAddressString = serverAddress.address + ':' + serverAddress.port;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
this.serverAddressString = serverAddressString;
|
|
1069
|
+
|
|
1070
|
+
const handler = this.channelzEnabled
|
|
1071
|
+
? this._channelzHandler
|
|
1072
|
+
: this._streamHandler;
|
|
1073
|
+
|
|
1074
|
+
http2Server.on('stream', handler.bind(this));
|
|
1075
|
+
http2Server.on('session', session => {
|
|
1076
|
+
if (!this.started) {
|
|
1077
|
+
session.destroy();
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const channelzRef = registerChannelzSocket(
|
|
1082
|
+
session.socket.remoteAddress ?? 'unknown',
|
|
1083
|
+
this.getChannelzSessionInfoGetter(session),
|
|
1084
|
+
this.channelzEnabled
|
|
1085
|
+
);
|
|
1086
|
+
|
|
1087
|
+
const channelzSessionInfo: ChannelzSessionInfo = {
|
|
1088
|
+
ref: channelzRef,
|
|
1089
|
+
streamTracker: new ChannelzCallTracker(),
|
|
1090
|
+
messagesSent: 0,
|
|
1091
|
+
messagesReceived: 0,
|
|
1092
|
+
lastMessageSentTimestamp: null,
|
|
1093
|
+
lastMessageReceivedTimestamp: null,
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
this.sessions.set(session, channelzSessionInfo);
|
|
1097
|
+
const clientAddress = session.socket.remoteAddress;
|
|
1098
|
+
if (this.channelzEnabled) {
|
|
1099
|
+
this.channelzTrace.addTrace(
|
|
1100
|
+
'CT_INFO',
|
|
1101
|
+
'Connection established by client ' + clientAddress
|
|
1102
|
+
);
|
|
1103
|
+
this.sessionChildrenTracker.refChild(channelzRef);
|
|
1104
|
+
}
|
|
1105
|
+
let connectionAgeTimer: NodeJS.Timeout | null = null;
|
|
1106
|
+
let connectionAgeGraceTimer: NodeJS.Timeout | null = null;
|
|
1107
|
+
let sessionClosedByServer = false;
|
|
1108
|
+
if (this.maxConnectionAgeMs !== UNLIMITED_CONNECTION_AGE_MS) {
|
|
1109
|
+
// Apply a random jitter within a +/-10% range
|
|
1110
|
+
const jitterMagnitude = this.maxConnectionAgeMs / 10;
|
|
1111
|
+
const jitter = Math.random() * jitterMagnitude * 2 - jitterMagnitude;
|
|
1112
|
+
connectionAgeTimer = setTimeout(() => {
|
|
1113
|
+
sessionClosedByServer = true;
|
|
1114
|
+
if (this.channelzEnabled) {
|
|
1115
|
+
this.channelzTrace.addTrace(
|
|
1116
|
+
'CT_INFO',
|
|
1117
|
+
'Connection dropped by max connection age from ' + clientAddress
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
try {
|
|
1121
|
+
session.goaway(
|
|
1122
|
+
http2.constants.NGHTTP2_NO_ERROR,
|
|
1123
|
+
~(1 << 31),
|
|
1124
|
+
Buffer.from('max_age')
|
|
1125
|
+
);
|
|
1126
|
+
} catch (e) {
|
|
1127
|
+
// The goaway can't be sent because the session is already closed
|
|
1128
|
+
session.destroy();
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
session.close();
|
|
1132
|
+
/* Allow a grace period after sending the GOAWAY before forcibly
|
|
1133
|
+
* closing the connection. */
|
|
1134
|
+
if (this.maxConnectionAgeGraceMs !== UNLIMITED_CONNECTION_AGE_MS) {
|
|
1135
|
+
connectionAgeGraceTimer = setTimeout(() => {
|
|
1136
|
+
session.destroy();
|
|
1137
|
+
}, this.maxConnectionAgeGraceMs).unref?.();
|
|
1138
|
+
}
|
|
1139
|
+
}, this.maxConnectionAgeMs + jitter).unref?.();
|
|
1140
|
+
}
|
|
1141
|
+
const keeapliveTimeTimer: NodeJS.Timeout | null = setInterval(() => {
|
|
1142
|
+
const timeoutTImer = setTimeout(() => {
|
|
1143
|
+
sessionClosedByServer = true;
|
|
1144
|
+
if (this.channelzEnabled) {
|
|
1145
|
+
this.channelzTrace.addTrace(
|
|
1146
|
+
'CT_INFO',
|
|
1147
|
+
'Connection dropped by keepalive timeout from ' + clientAddress
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
session.close();
|
|
1151
|
+
}, this.keepaliveTimeoutMs).unref?.();
|
|
1152
|
+
try {
|
|
1153
|
+
session.ping(
|
|
1154
|
+
(err: Error | null, duration: number, payload: Buffer) => {
|
|
1155
|
+
clearTimeout(timeoutTImer);
|
|
1156
|
+
}
|
|
1157
|
+
);
|
|
1158
|
+
} catch (e) {
|
|
1159
|
+
// The ping can't be sent because the session is already closed
|
|
1160
|
+
session.destroy();
|
|
1161
|
+
}
|
|
1162
|
+
}, this.keepaliveTimeMs).unref?.();
|
|
1163
|
+
session.on('close', () => {
|
|
1164
|
+
if (this.channelzEnabled) {
|
|
1165
|
+
if (!sessionClosedByServer) {
|
|
1166
|
+
this.channelzTrace.addTrace(
|
|
1167
|
+
'CT_INFO',
|
|
1168
|
+
'Connection dropped by client ' + clientAddress
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
this.sessionChildrenTracker.unrefChild(channelzRef);
|
|
1172
|
+
unregisterChannelzRef(channelzRef);
|
|
1173
|
+
}
|
|
1174
|
+
if (connectionAgeTimer) {
|
|
1175
|
+
clearTimeout(connectionAgeTimer);
|
|
1176
|
+
}
|
|
1177
|
+
if (connectionAgeGraceTimer) {
|
|
1178
|
+
clearTimeout(connectionAgeGraceTimer);
|
|
1179
|
+
}
|
|
1180
|
+
if (keeapliveTimeTimer) {
|
|
1181
|
+
clearTimeout(keeapliveTimeTimer);
|
|
1182
|
+
}
|
|
1183
|
+
this.sessions.delete(session);
|
|
1184
|
+
});
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
async function handleUnary<RequestType, ResponseType>(
|
|
1190
|
+
call: Http2ServerCallStream<RequestType, ResponseType>,
|
|
1191
|
+
handler: UnaryHandler<RequestType, ResponseType>,
|
|
1192
|
+
metadata: Metadata,
|
|
1193
|
+
encoding: string
|
|
1194
|
+
): Promise<void> {
|
|
1195
|
+
try {
|
|
1196
|
+
const request = await call.receiveUnaryMessage(encoding);
|
|
1197
|
+
|
|
1198
|
+
if (request === undefined || call.cancelled) {
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
const emitter = new ServerUnaryCallImpl<RequestType, ResponseType>(
|
|
1203
|
+
call,
|
|
1204
|
+
metadata,
|
|
1205
|
+
request
|
|
1206
|
+
);
|
|
1207
|
+
|
|
1208
|
+
handler.func(
|
|
1209
|
+
emitter,
|
|
1210
|
+
(
|
|
1211
|
+
err: ServerErrorResponse | ServerStatusResponse | null,
|
|
1212
|
+
value?: ResponseType | null,
|
|
1213
|
+
trailer?: Metadata,
|
|
1214
|
+
flags?: number
|
|
1215
|
+
) => {
|
|
1216
|
+
call.sendUnaryMessage(err, value, trailer, flags);
|
|
1217
|
+
}
|
|
1218
|
+
);
|
|
1219
|
+
} catch (err) {
|
|
1220
|
+
call.sendError(err as ServerErrorResponse);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
function handleClientStreaming<RequestType, ResponseType>(
|
|
1225
|
+
call: Http2ServerCallStream<RequestType, ResponseType>,
|
|
1226
|
+
handler: ClientStreamingHandler<RequestType, ResponseType>,
|
|
1227
|
+
metadata: Metadata,
|
|
1228
|
+
encoding: string
|
|
1229
|
+
): void {
|
|
1230
|
+
const stream = new ServerReadableStreamImpl<RequestType, ResponseType>(
|
|
1231
|
+
call,
|
|
1232
|
+
metadata,
|
|
1233
|
+
handler.deserialize,
|
|
1234
|
+
encoding
|
|
1235
|
+
);
|
|
1236
|
+
|
|
1237
|
+
function respond(
|
|
1238
|
+
err: ServerErrorResponse | ServerStatusResponse | null,
|
|
1239
|
+
value?: ResponseType | null,
|
|
1240
|
+
trailer?: Metadata,
|
|
1241
|
+
flags?: number
|
|
1242
|
+
) {
|
|
1243
|
+
stream.destroy();
|
|
1244
|
+
call.sendUnaryMessage(err, value, trailer, flags);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
if (call.cancelled) {
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
stream.on('error', respond);
|
|
1252
|
+
handler.func(stream, respond);
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
async function handleServerStreaming<RequestType, ResponseType>(
|
|
1256
|
+
call: Http2ServerCallStream<RequestType, ResponseType>,
|
|
1257
|
+
handler: ServerStreamingHandler<RequestType, ResponseType>,
|
|
1258
|
+
metadata: Metadata,
|
|
1259
|
+
encoding: string
|
|
1260
|
+
): Promise<void> {
|
|
1261
|
+
try {
|
|
1262
|
+
const request = await call.receiveUnaryMessage(encoding);
|
|
1263
|
+
|
|
1264
|
+
if (request === undefined || call.cancelled) {
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
const stream = new ServerWritableStreamImpl<RequestType, ResponseType>(
|
|
1269
|
+
call,
|
|
1270
|
+
metadata,
|
|
1271
|
+
handler.serialize,
|
|
1272
|
+
request
|
|
1273
|
+
);
|
|
1274
|
+
|
|
1275
|
+
handler.func(stream);
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
call.sendError(err as ServerErrorResponse);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
function handleBidiStreaming<RequestType, ResponseType>(
|
|
1282
|
+
call: Http2ServerCallStream<RequestType, ResponseType>,
|
|
1283
|
+
handler: BidiStreamingHandler<RequestType, ResponseType>,
|
|
1284
|
+
metadata: Metadata,
|
|
1285
|
+
encoding: string
|
|
1286
|
+
): void {
|
|
1287
|
+
const stream = new ServerDuplexStreamImpl<RequestType, ResponseType>(
|
|
1288
|
+
call,
|
|
1289
|
+
metadata,
|
|
1290
|
+
handler.serialize,
|
|
1291
|
+
handler.deserialize,
|
|
1292
|
+
encoding
|
|
1293
|
+
);
|
|
1294
|
+
|
|
1295
|
+
if (call.cancelled) {
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
handler.func(stream);
|
|
1300
|
+
}
|