diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index b02f8ac3d0..10a8f6ae03 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - version = '1.67.0-dev' + version = '1.68.0-dev' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' @@ -302,6 +302,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/compression_filter.h', @@ -1145,6 +1147,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/external/file_external_account_credentials.h', 'src/core/lib/security/credentials/external/url_external_account_credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', 'src/core/lib/security/credentials/iam/iam_credentials.h', 'src/core/lib/security/credentials/insecure/insecure_credentials.h', @@ -1327,6 +1330,7 @@ Pod::Spec.new do |s| 'src/core/util/json/json_util.h', 'src/core/util/json/json_writer.h', 'src/core/util/latent_see.h', + 'src/core/util/lru_cache.h', 'src/core/util/ring_buffer.h', 'src/core/util/spinlock.h', 'src/core/util/string.h', @@ -1353,6 +1357,7 @@ Pod::Spec.new do |s| 'src/core/xds/grpc/xds_http_fault_filter.h', 'src/core/xds/grpc/xds_http_filter.h', 'src/core/xds/grpc/xds_http_filter_registry.h', + 'src/core/xds/grpc/xds_http_gcp_authn_filter.h', 'src/core/xds/grpc/xds_http_rbac_filter.h', 'src/core/xds/grpc/xds_http_stateful_session_filter.h', 'src/core/xds/grpc/xds_lb_policy_registry.h', @@ -1612,6 +1617,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/compression_filter.h', @@ -2437,6 +2444,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/external/file_external_account_credentials.h', 'src/core/lib/security/credentials/external/url_external_account_credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', 'src/core/lib/security/credentials/iam/iam_credentials.h', 'src/core/lib/security/credentials/insecure/insecure_credentials.h', @@ -2619,6 +2627,7 @@ Pod::Spec.new do |s| 'src/core/util/json/json_util.h', 'src/core/util/json/json_writer.h', 'src/core/util/latent_see.h', + 'src/core/util/lru_cache.h', 'src/core/util/ring_buffer.h', 'src/core/util/spinlock.h', 'src/core/util/string.h', @@ -2645,6 +2654,7 @@ Pod::Spec.new do |s| 'src/core/xds/grpc/xds_http_fault_filter.h', 'src/core/xds/grpc/xds_http_filter.h', 'src/core/xds/grpc/xds_http_filter_registry.h', + 'src/core/xds/grpc/xds_http_gcp_authn_filter.h', 'src/core/xds/grpc/xds_http_rbac_filter.h', 'src/core/xds/grpc/xds_http_stateful_session_filter.h', 'src/core/xds/grpc/xds_lb_policy_registry.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 4948727543..3536ca8457 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.67.0-dev' + version = '1.68.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' @@ -199,7 +199,7 @@ Pod::Spec.new do |s| ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version ss.dependency "#{s.name}/Privacy", version - ss.dependency 'BoringSSL-GRPC', '0.0.36' + ss.dependency 'BoringSSL-GRPC', '0.0.37' ss.dependency 'abseil/algorithm/container', abseil_version ss.dependency 'abseil/base/base', abseil_version ss.dependency 'abseil/base/config', abseil_version @@ -297,6 +297,10 @@ Pod::Spec.new do |s| 'src/core/ext/filters/fault_injection/fault_injection_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.cc', 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.cc', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.cc', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.cc', @@ -1686,6 +1690,8 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/external/url_external_account_credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.cc', 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.cc', + 'src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h', 'src/core/lib/security/credentials/google_default/credentials_generic.cc', 'src/core/lib/security/credentials/google_default/google_default_credentials.cc', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', @@ -2056,6 +2062,7 @@ Pod::Spec.new do |s| 'src/core/util/latent_see.h', 'src/core/util/linux/cpu.cc', 'src/core/util/log.cc', + 'src/core/util/lru_cache.h', 'src/core/util/msys/tmpfile.cc', 'src/core/util/posix/cpu.cc', 'src/core/util/posix/string.cc', @@ -2114,6 +2121,8 @@ Pod::Spec.new do |s| 'src/core/xds/grpc/xds_http_filter.h', 'src/core/xds/grpc/xds_http_filter_registry.cc', 'src/core/xds/grpc/xds_http_filter_registry.h', + 'src/core/xds/grpc/xds_http_gcp_authn_filter.cc', + 'src/core/xds/grpc/xds_http_gcp_authn_filter.h', 'src/core/xds/grpc/xds_http_rbac_filter.cc', 'src/core/xds/grpc/xds_http_rbac_filter.h', 'src/core/xds/grpc/xds_http_stateful_session_filter.cc', @@ -2412,6 +2421,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_filter.h', 'src/core/ext/filters/fault_injection/fault_injection_service_config_parser.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h', + 'src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/compression_filter.h', @@ -3217,6 +3228,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/external/file_external_account_credentials.h', 'src/core/lib/security/credentials/external/url_external_account_credentials.h', 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h', 'src/core/lib/security/credentials/google_default/google_default_credentials.h', 'src/core/lib/security/credentials/iam/iam_credentials.h', 'src/core/lib/security/credentials/insecure/insecure_credentials.h', @@ -3399,6 +3411,7 @@ Pod::Spec.new do |s| 'src/core/util/json/json_util.h', 'src/core/util/json/json_writer.h', 'src/core/util/latent_see.h', + 'src/core/util/lru_cache.h', 'src/core/util/ring_buffer.h', 'src/core/util/spinlock.h', 'src/core/util/string.h', @@ -3424,6 +3437,7 @@ Pod::Spec.new do |s| 'src/core/xds/grpc/xds_http_fault_filter.h', 'src/core/xds/grpc/xds_http_filter.h', 'src/core/xds/grpc/xds_http_filter_registry.h', + 'src/core/xds/grpc/xds_http_gcp_authn_filter.h', 'src/core/xds/grpc/xds_http_rbac_filter.h', 'src/core/xds/grpc/xds_http_stateful_session_filter.h', 'src/core/xds/grpc/xds_lb_policy_registry.h', diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 5a19d7a554..291a494cd2 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.67.0-dev' + version = '1.68.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index d2ab0a8953..b79eacfc79 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.67.0-dev' + version = '1.68.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index ab3169b15a..2db370d71f 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.67.0-dev' + version = '1.68.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h index aa7f133177..92a41f0066 100644 --- a/include/grpc/support/log.h +++ b/include/grpc/support/log.h @@ -44,7 +44,10 @@ typedef enum gpr_log_severity { /** * EXPERIMENTAL. API stability not guaranteed. * Should only be used from gRPC PHP and RUBY. - * Equivalent to ABSL_LOG(severity) << message_str; + * This will be removed once Ruby and PHP can start using C++ APIs. + * We would replace this with calls to absl LOG functions. + * grpc_absl_log is equivalent to + * ABSL_LOG(severity) << message_str; * **/ GPRAPI void grpc_absl_log(const char* file, int line, gpr_log_severity severity, const char* message_str); @@ -52,7 +55,10 @@ GPRAPI void grpc_absl_log(const char* file, int line, gpr_log_severity severity, /** * EXPERIMENTAL. API stability not guaranteed. * Should only be used from gRPC PHP and RUBY. - * Equivalent to ABSL_LOG(severity) << message_str << num; + * This will be removed once Ruby and PHP can start using C++ APIs. + * We would replace this with calls to absl LOG functions. + * grpc_absl_log_int is equivalent to + * ABSL_LOG(severity) << message_str << num; * **/ GPRAPI void grpc_absl_log_int(const char* file, int line, gpr_log_severity severity, @@ -61,7 +67,10 @@ GPRAPI void grpc_absl_log_int(const char* file, int line, /** * EXPERIMENTAL. API stability not guaranteed. * Should only be used from gRPC PHP and RUBY. - * Equivalent to ABSL_LOG(severity) << message_str1 << message_str2; + * This will be removed once Ruby and PHP can start using C++ APIs. + * We would replace this with calls to absl LOG functions. + * grpc_absl_log_str is equivalent to + * ABSL_LOG(severity) << message_str1 << message_str2; * **/ GPRAPI void grpc_absl_log_str(const char* file, int line, gpr_log_severity severity, diff --git a/include/grpcpp/version_info.h b/include/grpcpp/version_info.h index f3785e640c..e9de5915e6 100644 --- a/include/grpcpp/version_info.h +++ b/include/grpcpp/version_info.h @@ -19,9 +19,9 @@ #define GRPCPP_VERSION_INFO_H #define GRPC_CPP_VERSION_MAJOR 1 -#define GRPC_CPP_VERSION_MINOR 67 +#define GRPC_CPP_VERSION_MINOR 68 #define GRPC_CPP_VERSION_PATCH 0 #define GRPC_CPP_VERSION_TAG "dev" -#define GRPC_CPP_VERSION_STRING "1.67.0-dev" +#define GRPC_CPP_VERSION_STRING "1.68.0-dev" #endif // GRPCPP_VERSION_INFO_H diff --git a/src/core/client_channel/client_channel.cc b/src/core/client_channel/client_channel.cc index 5e1e2ec8eb..f700b39463 100644 --- a/src/core/client_channel/client_channel.cc +++ b/src/core/client_channel/client_channel.cc @@ -1105,6 +1105,10 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { service_config = std::move(*result.service_config); config_selector = result.args.GetObjectRef(); } + // Remove the config selector from channel args so that we're not holding + // unnecessary refs that cause it to be destroyed somewhere other than in + // the WorkSerializer. + result.args = result.args.Remove(GRPC_ARG_CONFIG_SELECTOR); // Note: The only case in which service_config is null here is if the // resolver returned a service config error and we don't have a previous // service config to fall back to. @@ -1138,6 +1142,7 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { << "client_channel=" << this << ": service config not changed"; } // Create or update LB policy, as needed. + ChannelArgs new_args = result.args; resolver_result_status = CreateOrUpdateLbPolicyLocked( std::move(lb_policy_config), parsed_service_config->health_check_service_name(), std::move(result)); @@ -1146,7 +1151,7 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { // the ConfigSelector may need the LB policy to know about new // destinations before it can send RPCs to those destinations. if (service_config_changed || config_selector_changed) { - UpdateServiceConfigInDataPlaneLocked(); + UpdateServiceConfigInDataPlaneLocked(new_args); } } // Invoke resolver callback if needed. @@ -1196,10 +1201,7 @@ absl::Status ClientChannel::CreateOrUpdateLbPolicyLocked( } update_args.config = std::move(lb_policy_config); update_args.resolution_note = std::move(result.resolution_note); - // Remove the config selector from channel args so that we're not holding - // unnecessary refs that cause it to be destroyed somewhere other than in - // the WorkSerializer. - update_args.args = result.args.Remove(GRPC_ARG_CONFIG_SELECTOR); + update_args.args = std::move(result.args); // Add health check service name to channel args. if (health_check_service_name.has_value()) { update_args.args = update_args.args.Set(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME, @@ -1264,7 +1266,8 @@ void ClientChannel::UpdateServiceConfigInControlPlaneLocked( } } -void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { +void ClientChannel::UpdateServiceConfigInDataPlaneLocked( + const ChannelArgs& args) { GRPC_TRACE_LOG(client_channel, INFO) << "client_channel=" << this << ": switching to ConfigSelector " << saved_config_selector_.get(); @@ -1275,7 +1278,7 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { MakeRefCounted(saved_service_config_); } // Construct filter stack. - InterceptionChainBuilder builder(channel_args_.SetObject(this)); + InterceptionChainBuilder builder(args.SetObject(this)); if (idle_timeout_ != Duration::Zero()) { builder.AddOnServerTrailingMetadata([this](ServerMetadata&) { if (idle_state_.DecreaseCallCount()) StartIdleTimer(); diff --git a/src/core/client_channel/client_channel.h b/src/core/client_channel/client_channel.h index 13809c0447..7a73a2259d 100644 --- a/src/core/client_channel/client_channel.h +++ b/src/core/client_channel/client_channel.h @@ -149,7 +149,7 @@ class ClientChannel : public Channel { RefCountedPtr config_selector, std::string lb_policy_name) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); - void UpdateServiceConfigInDataPlaneLocked() + void UpdateServiceConfigInDataPlaneLocked(const ChannelArgs& args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); void UpdateStateLocked(grpc_connectivity_state state, diff --git a/src/core/client_channel/client_channel_filter.cc b/src/core/client_channel/client_channel_filter.cc index 0443002c52..70ef58f52c 100644 --- a/src/core/client_channel/client_channel_filter.cc +++ b/src/core/client_channel/client_channel_filter.cc @@ -1319,6 +1319,10 @@ void ClientChannelFilter::OnResolverResultChangedLocked( service_config = std::move(*result.service_config); config_selector = result.args.GetObjectRef(); } + // Remove the config selector from channel args so that we're not holding + // unnecessary refs that cause it to be destroyed somewhere other than in the + // WorkSerializer. + result.args = result.args.Remove(GRPC_ARG_CONFIG_SELECTOR); // Note: The only case in which service_config is null here is if the resolver // returned a service config error and we don't have a previous service // config to fall back to. @@ -1349,6 +1353,7 @@ void ClientChannelFilter::OnResolverResultChangedLocked( << "chand=" << this << ": service config not changed"; } // Create or update LB policy, as needed. + ChannelArgs new_args = result.args; resolver_result_status = CreateOrUpdateLbPolicyLocked( std::move(lb_policy_config), parsed_service_config->health_check_service_name(), std::move(result)); @@ -1357,7 +1362,7 @@ void ClientChannelFilter::OnResolverResultChangedLocked( // This needs to happen after the LB policy has been updated, since // the ConfigSelector may need the LB policy to know about new // destinations before it can send RPCs to those destinations. - UpdateServiceConfigInDataPlaneLocked(); + UpdateServiceConfigInDataPlaneLocked(new_args); // TODO(ncteisen): might be worth somehow including a snippet of the // config in the trace, at the risk of bloating the trace logs. trace_strings.push_back("Service config changed"); @@ -1413,10 +1418,7 @@ absl::Status ClientChannelFilter::CreateOrUpdateLbPolicyLocked( } update_args.config = std::move(lb_policy_config); update_args.resolution_note = std::move(result.resolution_note); - // Remove the config selector from channel args so that we're not holding - // unnecessary refs that cause it to be destroyed somewhere other than in the - // WorkSerializer. - update_args.args = result.args.Remove(GRPC_ARG_CONFIG_SELECTOR); + update_args.args = std::move(result.args); // Add health check service name to channel args. if (health_check_service_name.has_value()) { update_args.args = update_args.args.Set(GRPC_ARG_HEALTH_CHECK_SERVICE_NAME, @@ -1480,7 +1482,8 @@ void ClientChannelFilter::UpdateServiceConfigInControlPlaneLocked( << saved_config_selector_.get(); } -void ClientChannelFilter::UpdateServiceConfigInDataPlaneLocked() { +void ClientChannelFilter::UpdateServiceConfigInDataPlaneLocked( + const ChannelArgs& args) { // Grab ref to service config. RefCountedPtr service_config = saved_service_config_; // Grab ref to config selector. Use default if resolver didn't supply one. @@ -1492,8 +1495,7 @@ void ClientChannelFilter::UpdateServiceConfigInDataPlaneLocked() { config_selector = MakeRefCounted(saved_service_config_); } - ChannelArgs new_args = - channel_args_.SetObject(this).SetObject(service_config); + ChannelArgs new_args = args.SetObject(this).SetObject(service_config); bool enable_retries = !new_args.WantMinimalStack() && new_args.GetBool(GRPC_ARG_ENABLE_RETRIES).value_or(true); @@ -2516,16 +2518,17 @@ ClientChannelFilter::LoadBalancedCall::PickSubchannel(bool was_queued) { // updated before we queue it. // We need to unref pickers in the WorkSerializer. std::vector> pickers; - auto cleanup = absl::MakeCleanup([&]() { - if (IsWorkSerializerDispatchEnabled()) return; - chand_->work_serializer_->Run( - [pickers = std::move(pickers)]() mutable { - for (auto& picker : pickers) { - picker.reset(DEBUG_LOCATION, "PickSubchannel"); - } - }, - DEBUG_LOCATION); - }); + auto cleanup = absl::MakeCleanup( + [work_serializer = chand_->work_serializer_, &pickers]() { + if (IsWorkSerializerDispatchEnabled()) return; + work_serializer->Run( + [pickers = std::move(pickers)]() mutable { + for (auto& picker : pickers) { + picker.reset(DEBUG_LOCATION, "PickSubchannel"); + } + }, + DEBUG_LOCATION); + }); absl::AnyInvocable)> set_picker; if (!IsWorkSerializerDispatchEnabled()) { diff --git a/src/core/client_channel/client_channel_filter.h b/src/core/client_channel/client_channel_filter.h index 9b119b4e02..7ecf787ca7 100644 --- a/src/core/client_channel/client_channel_filter.h +++ b/src/core/client_channel/client_channel_filter.h @@ -247,7 +247,7 @@ class ClientChannelFilter final { RefCountedPtr config_selector, std::string lb_policy_name) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); - void UpdateServiceConfigInDataPlaneLocked() + void UpdateServiceConfigInDataPlaneLocked(const ChannelArgs& args) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); void CreateResolverLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_); diff --git a/src/core/client_channel/retry_filter_legacy_call_data.cc b/src/core/client_channel/retry_filter_legacy_call_data.cc index dd0267d7c5..4bb4bf3f9a 100644 --- a/src/core/client_channel/retry_filter_legacy_call_data.cc +++ b/src/core/client_channel/retry_filter_legacy_call_data.cc @@ -1890,7 +1890,7 @@ void RetryFilter::LegacyCallData::StartRetryTimer( next_attempt_timeout = *server_pushback; retry_backoff_.Reset(); } else { - next_attempt_timeout = retry_backoff_.NextAttemptTime() - Timestamp::Now(); + next_attempt_timeout = retry_backoff_.NextAttemptDelay(); } GRPC_TRACE_LOG(retry, INFO) << "chand=" << chand_ << " calld=" << this << ": retrying failed call in " diff --git a/src/core/client_channel/subchannel.cc b/src/core/client_channel/subchannel.cc index 35ec507c4d..298c7d7851 100644 --- a/src/core/client_channel/subchannel.cc +++ b/src/core/client_channel/subchannel.cc @@ -764,8 +764,9 @@ void Subchannel::OnRetryTimerLocked() { void Subchannel::StartConnectingLocked() { // Set next attempt time. - const Timestamp min_deadline = min_connect_timeout_ + Timestamp::Now(); - next_attempt_time_ = backoff_.NextAttemptTime(); + const Timestamp now = Timestamp::Now(); + const Timestamp min_deadline = now + min_connect_timeout_; + next_attempt_time_ = now + backoff_.NextAttemptDelay(); // Report CONNECTING. SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, absl::OkStatus()); // Start connection attempt. diff --git a/src/core/client_channel/subchannel_stream_client.cc b/src/core/client_channel/subchannel_stream_client.cc index d7f14b40cf..afdafe398e 100644 --- a/src/core/client_channel/subchannel_stream_client.cc +++ b/src/core/client_channel/subchannel_stream_client.cc @@ -130,7 +130,7 @@ void SubchannelStreamClient::StartRetryTimerLocked() { if (event_handler_ != nullptr) { event_handler_->OnRetryTimerStartLocked(this); } - const Duration timeout = retry_backoff_.NextAttemptTime() - Timestamp::Now(); + const Duration timeout = retry_backoff_.NextAttemptDelay(); if (GPR_UNLIKELY(tracer_ != nullptr)) { LOG(INFO) << tracer_ << " " << this << ": SubchannelStreamClient health check call lost..."; diff --git a/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc b/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc new file mode 100644 index 0000000000..c3a6ab3e71 --- /dev/null +++ b/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc @@ -0,0 +1,167 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h" + +#include +#include +#include + +#include "absl/log/check.h" +#include "absl/strings/str_cat.h" + +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/promise/context.h" +#include "src/core/lib/resource_quota/arena.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h" +#include "src/core/lib/transport/transport.h" +#include "src/core/resolver/xds/xds_resolver_attributes.h" +#include "src/core/service_config/service_config.h" +#include "src/core/service_config/service_config_call_data.h" + +namespace grpc_core { + +const NoInterceptor GcpAuthenticationFilter::Call::OnClientToServerMessage; +const NoInterceptor GcpAuthenticationFilter::Call::OnClientToServerHalfClose; +const NoInterceptor GcpAuthenticationFilter::Call::OnServerInitialMetadata; +const NoInterceptor GcpAuthenticationFilter::Call::OnServerToClientMessage; +const NoInterceptor GcpAuthenticationFilter::Call::OnServerTrailingMetadata; +const NoInterceptor GcpAuthenticationFilter::Call::OnFinalize; + +absl::Status GcpAuthenticationFilter::Call::OnClientInitialMetadata( + ClientMetadata& /*md*/, GcpAuthenticationFilter* filter) { + // Get the cluster name chosen for this RPC. + auto* service_config_call_data = GetContext(); + auto cluster_attribute = + service_config_call_data->GetCallAttribute(); + if (cluster_attribute == nullptr) { + // Can't happen, but be defensive. + return absl::InternalError( + "GCP authentication filter: call has no xDS cluster attribute"); + } + absl::string_view cluster_name = cluster_attribute->cluster(); + if (!absl::ConsumePrefix(&cluster_name, "cluster:")) { + return absl::OkStatus(); // Cluster specifier plugin. + } + // Look up the CDS resource for the cluster. + auto it = filter->xds_config_->clusters.find(cluster_name); + if (it == filter->xds_config_->clusters.end()) { + // Can't happen, but be defensive. + return absl::InternalError( + absl::StrCat("GCP authentication filter: xDS cluster ", cluster_name, + " not found in XdsConfig")); + } + if (!it->second.ok()) { + // Cluster resource had an error, so fail the call. + // Note: For wait_for_ready calls, this does the wrong thing by + // failing the call instead of queuing it, but there's no easy + // way to queue the call here until we get a valid CDS resource, + // because once that happens, a new instance of this filter will be + // swapped in for subsequent calls, but *this* call is already tied + // to this filter instance, which will never see the update. + return absl::UnavailableError( + absl::StrCat("GCP authentication filter: CDS resource unavailable for ", + cluster_name)); + } + if (it->second->cluster == nullptr) { + // Can't happen, but be defensive. + return absl::InternalError(absl::StrCat( + "GCP authentication filter: CDS resource not present for cluster ", + cluster_name)); + } + auto& metadata_map = it->second->cluster->metadata; + const XdsMetadataValue* metadata_value = + metadata_map.Find(filter->filter_config_->filter_instance_name); + // If no audience in the cluster, then no need to add call creds. + if (metadata_value == nullptr) return absl::OkStatus(); + // If the entry is present but the wrong type, fail the RPC. + if (metadata_value->type() != XdsGcpAuthnAudienceMetadataValue::Type()) { + return absl::UnavailableError(absl::StrCat( + "GCP authentication filter: audience metadata in wrong format for " + "cluster ", + cluster_name)); + } + // Get the call creds instance. + auto creds = filter->GetCallCredentials( + DownCast(metadata_value)->url()); + // Add the call creds instance to the call. + auto* arena = GetContext(); + auto* security_ctx = DownCast( + arena->GetContext()); + if (security_ctx == nullptr) { + security_ctx = arena->New(std::move(creds)); + arena->SetContext(security_ctx); + } else { + security_ctx->creds = std::move(creds); + } + return absl::OkStatus(); +} + +const grpc_channel_filter GcpAuthenticationFilter::kFilter = + MakePromiseBasedFilter(); + +absl::StatusOr> +GcpAuthenticationFilter::Create(const ChannelArgs& args, + ChannelFilter::Args filter_args) { + auto* service_config = args.GetObject(); + if (service_config == nullptr) { + return absl::InvalidArgumentError( + "gcp_auth: no service config in channel args"); + } + auto* config = static_cast( + service_config->GetGlobalParsedConfig( + GcpAuthenticationServiceConfigParser::ParserIndex())); + if (config == nullptr) { + return absl::InvalidArgumentError("gcp_auth: parsed config not found"); + } + auto* filter_config = config->GetConfig(filter_args.instance_id()); + if (filter_config == nullptr) { + return absl::InvalidArgumentError( + "gcp_auth: filter instance ID not found in filter config"); + } + auto xds_config = args.GetObjectRef(); + if (xds_config == nullptr) { + return absl::InvalidArgumentError( + "gcp_auth: xds config not found in channel args"); + } + return std::make_unique(filter_config, + std::move(xds_config)); +} + +GcpAuthenticationFilter::GcpAuthenticationFilter( + const GcpAuthenticationParsedConfig::Config* filter_config, + RefCountedPtr xds_config) + : filter_config_(filter_config), + xds_config_(std::move(xds_config)), + cache_(filter_config->cache_size) {} + +RefCountedPtr +GcpAuthenticationFilter::GetCallCredentials(const std::string& audience) { + MutexLock lock(&mu_); + return cache_.GetOrInsert(audience, [](const std::string& audience) { + return MakeRefCounted(audience); + }); +} + +void GcpAuthenticationFilterRegister(CoreConfiguration::Builder* builder) { + GcpAuthenticationServiceConfigParser::Register(builder); +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h b/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h new file mode 100644 index 0000000000..927e2de05e --- /dev/null +++ b/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h @@ -0,0 +1,82 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_FILTER_H +#define GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_FILTER_H + +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_fwd.h" +#include "src/core/lib/channel/promise_based_filter.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/transport/transport.h" +#include "src/core/resolver/xds/xds_config.h" +#include "src/core/util/lru_cache.h" + +namespace grpc_core { + +// xDS GCP Authentication filter. +// https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/gcp_authn_filter +class GcpAuthenticationFilter + : public ImplementChannelFilter { + public: + static const grpc_channel_filter kFilter; + + static absl::string_view TypeName() { return "gcp_authentication_filter"; } + + static absl::StatusOr> Create( + const ChannelArgs& args, ChannelFilter::Args filter_args); + + GcpAuthenticationFilter( + const GcpAuthenticationParsedConfig::Config* filter_config, + RefCountedPtr xds_config); + + class Call { + public: + absl::Status OnClientInitialMetadata(ClientMetadata& /*md*/, + GcpAuthenticationFilter* filter); + static const NoInterceptor OnClientToServerMessage; + static const NoInterceptor OnClientToServerHalfClose; + static const NoInterceptor OnServerInitialMetadata; + static const NoInterceptor OnServerToClientMessage; + static const NoInterceptor OnServerTrailingMetadata; + static const NoInterceptor OnFinalize; + }; + + private: + RefCountedPtr GetCallCredentials( + const std::string& audience); + + const GcpAuthenticationParsedConfig::Config* filter_config_; + const RefCountedPtr xds_config_; + + Mutex mu_; + LruCache> + cache_ ABSL_GUARDED_BY(&mu_); +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_FILTER_H diff --git a/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.cc b/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.cc new file mode 100644 index 0000000000..4af33e528f --- /dev/null +++ b/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.cc @@ -0,0 +1,81 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h" + +#include + +#include "absl/types/optional.h" + +#include "src/core/lib/channel/channel_args.h" + +namespace grpc_core { + +const JsonLoaderInterface* GcpAuthenticationParsedConfig::Config::JsonLoader( + const JsonArgs&) { + static const auto* loader = + JsonObjectLoader() + .Field("filter_instance_name", &Config::filter_instance_name) + .OptionalField("cache_size", &Config::cache_size) + .Finish(); + return loader; +} + +void GcpAuthenticationParsedConfig::Config::JsonPostLoad( + const Json&, const JsonArgs&, ValidationErrors* errors) { + if (cache_size == 0) { + ValidationErrors::ScopedField field(errors, ".cache_size"); + errors->AddError("must be non-zero"); + } +} + +const JsonLoaderInterface* GcpAuthenticationParsedConfig::JsonLoader( + const JsonArgs&) { + static const auto* loader = + JsonObjectLoader() + .OptionalField("gcp_authentication", + &GcpAuthenticationParsedConfig::configs_) + .Finish(); + return loader; +} + +std::unique_ptr +GcpAuthenticationServiceConfigParser::ParseGlobalParams( + const ChannelArgs& args, const Json& json, ValidationErrors* errors) { + // Only parse config if the following channel arg is enabled. + if (!args.GetBool(GRPC_ARG_PARSE_GCP_AUTHENTICATION_METHOD_CONFIG) + .value_or(false)) { + return nullptr; + } + // Parse config from json. + return LoadFromJson>( + json, JsonArgs(), errors); +} + +void GcpAuthenticationServiceConfigParser::Register( + CoreConfiguration::Builder* builder) { + builder->service_config_parser()->RegisterParser( + std::make_unique()); +} + +size_t GcpAuthenticationServiceConfigParser::ParserIndex() { + return CoreConfiguration::Get().service_config_parser().GetParserIndex( + parser_name()); +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h b/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h new file mode 100644 index 0000000000..97df008e96 --- /dev/null +++ b/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h @@ -0,0 +1,87 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_SERVICE_CONFIG_PARSER_H +#define GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_SERVICE_CONFIG_PARSER_H + +#include + +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/gprpp/validation_errors.h" +#include "src/core/service_config/service_config_parser.h" +#include "src/core/util/json/json.h" +#include "src/core/util/json/json_args.h" +#include "src/core/util/json/json_object_loader.h" + +// Channel arg key for enabling parsing fault injection via method config. +#define GRPC_ARG_PARSE_GCP_AUTHENTICATION_METHOD_CONFIG \ + "grpc.internal.parse_gcp_authentication_method_config" + +namespace grpc_core { + +class GcpAuthenticationParsedConfig : public ServiceConfigParser::ParsedConfig { + public: + struct Config { + std::string filter_instance_name; + uint64_t cache_size = 10; + + static const JsonLoaderInterface* JsonLoader(const JsonArgs&); + void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors); + }; + + // Returns the config at the specified index. There might be multiple + // GCP auth filters in the list of HTTP filters at the same time. + // The order of the list is stable, and an index is used to keep track of + // their relative positions. Each filter instance uses this method to + // access the appropriate parsed config for that instance. + const Config* GetConfig(size_t index) const { + if (index >= configs_.size()) return nullptr; + return &configs_[index]; + } + + static const JsonLoaderInterface* JsonLoader(const JsonArgs&); + + private: + std::vector configs_; +}; + +class GcpAuthenticationServiceConfigParser final + : public ServiceConfigParser::Parser { + public: + absl::string_view name() const override { return parser_name(); } + std::unique_ptr ParseGlobalParams( + const ChannelArgs& args, const Json& json, + ValidationErrors* errors) override; + // Returns the parser index for the parser. + static size_t ParserIndex(); + // Registers the parser. + static void Register(CoreConfiguration::Builder* builder); + + private: + static absl::string_view parser_name() { return "gcp_auth"; } +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_EXT_FILTERS_GCP_AUTHENTICATION_GCP_AUTHENTICATION_SERVICE_CONFIG_PARSER_H diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index e45a90de09..db0b4d514e 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -188,12 +188,12 @@ ClientMessageSizeFilter::Call::Call(ClientMessageSizeFilter* filter) if (config_from_call_context->max_send_size().has_value() && (!max_send_size.has_value() || *config_from_call_context->max_send_size() < *max_send_size)) { - max_send_size = *config_from_call_context->max_send_size(); + max_send_size = config_from_call_context->max_send_size(); } if (config_from_call_context->max_recv_size().has_value() && (!max_recv_size.has_value() || *config_from_call_context->max_recv_size() < *max_recv_size)) { - max_recv_size = *config_from_call_context->max_recv_size(); + max_recv_size = config_from_call_context->max_recv_size(); } limits_ = MessageSizeParsedConfig(max_send_size, max_recv_size); } diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.cc b/src/core/ext/transport/chttp2/server/chttp2_server.cc index f8f0c04f6a..50f165cd32 100644 --- a/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -207,7 +207,6 @@ class Chttp2ServerListener : public Server::ListenerInterface { ActiveConnection(grpc_pollset* accepting_pollset, AcceptorPtr acceptor, EventEngine* event_engine, const ChannelArgs& args, MemoryOwner memory_owner); - ~ActiveConnection() override; void Orphan() override; @@ -392,6 +391,10 @@ Chttp2ServerListener::ActiveConnection::HandshakingState::~HandshakingState() { grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_); } grpc_pollset_set_destroy(interested_parties_); + if (connection_->listener_ != nullptr && + connection_->listener_->tcp_server_ != nullptr) { + grpc_tcp_server_unref(connection_->listener_->tcp_server_); + } } void Chttp2ServerListener::ActiveConnection::HandshakingState::Orphan() { @@ -565,12 +568,6 @@ Chttp2ServerListener::ActiveConnection::ActiveConnection( grpc_schedule_on_exec_ctx); } -Chttp2ServerListener::ActiveConnection::~ActiveConnection() { - if (listener_ != nullptr && listener_->tcp_server_ != nullptr) { - grpc_tcp_server_unref(listener_->tcp_server_); - } -} - void Chttp2ServerListener::ActiveConnection::Orphan() { OrphanablePtr handshaking_state; { @@ -871,7 +868,8 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp, // Orphaned, so as to avoid heap-use-after-free issues where `Ref()` is // invoked when the listener is already shutdown. Note that the listener // holds a ref to the tcp_server but this ref is given away when the - // listener is orphaned (shutdown). + // listener is orphaned (shutdown). A connection needs the tcp_server to + // outlast the handshake since the acceptor needs it. if (self->tcp_server_ != nullptr) { grpc_tcp_server_ref(self->tcp_server_); } diff --git a/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb.h b/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb.h index 8336f7c2ff..3b87f262b9 100644 --- a/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb.h +++ b/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb.h @@ -186,6 +186,18 @@ UPB_INLINE bool google_api_expr_v1alpha1_CheckedExpr_has_source_info(const googl const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 65, 3, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_api_expr_v1alpha1_CheckedExpr_clear_expr_version(google_api_expr_v1alpha1_CheckedExpr* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 48), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_api_expr_v1alpha1_CheckedExpr_expr_version(const google_api_expr_v1alpha1_CheckedExpr* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {6, UPB_SIZE(28, 48), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} UPB_INLINE void google_api_expr_v1alpha1_CheckedExpr_reference_map_clear(google_api_expr_v1alpha1_CheckedExpr* msg) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; @@ -261,6 +273,10 @@ UPB_INLINE struct google_api_expr_v1alpha1_SourceInfo* google_api_expr_v1alpha1_ } return sub; } +UPB_INLINE void google_api_expr_v1alpha1_CheckedExpr_set_expr_version(google_api_expr_v1alpha1_CheckedExpr *msg, upb_StringView value) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 48), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} /* google.api.expr.v1alpha1.CheckedExpr.ReferenceMapEntry */ diff --git a/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c b/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c index 1ac713de42..a9296e36e9 100644 --- a/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c +++ b/src/core/ext/upb-gen/google/api/expr/v1alpha1/checked.upb_minitable.c @@ -22,20 +22,31 @@ static const upb_MiniTableSub google_api_expr_v1alpha1_CheckedExpr_submsgs[4] = {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__SourceInfo_msg_init}, }; -static const upb_MiniTableField google_api_expr_v1alpha1_CheckedExpr__fields[4] = { +static const upb_MiniTableField google_api_expr_v1alpha1_CheckedExpr__fields[5] = { {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {3, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {4, UPB_SIZE(20, 32), 64, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {5, UPB_SIZE(24, 40), 65, 3, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(28, 48), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, }; const upb_MiniTable google__api__expr__v1alpha1__CheckedExpr_msg_init = { &google_api_expr_v1alpha1_CheckedExpr_submsgs[0], &google_api_expr_v1alpha1_CheckedExpr__fields[0], - UPB_SIZE(32, 48), 4, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, + UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(56), 0, #ifdef UPB_TRACING_ENABLED "google.api.expr.v1alpha1.CheckedExpr", #endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f000032, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) }; static const upb_MiniTableSub google_api_expr_v1alpha1_CheckedExpr_ReferenceMapEntry_submsgs[1] = { diff --git a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb.h b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb.h index d11f020947..c7ff866228 100644 --- a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb.h +++ b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb.h @@ -34,12 +34,21 @@ typedef struct google_api_expr_v1alpha1_Expr_CreateStruct_Entry { upb_Message UP typedef struct google_api_expr_v1alpha1_Expr_Comprehension { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_Expr_Comprehension; typedef struct google_api_expr_v1alpha1_Constant { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_Constant; typedef struct google_api_expr_v1alpha1_SourceInfo { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourceInfo; +typedef struct google_api_expr_v1alpha1_SourceInfo_Extension { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourceInfo_Extension; +typedef struct google_api_expr_v1alpha1_SourceInfo_Extension_Version { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourceInfo_Extension_Version; typedef struct google_api_expr_v1alpha1_SourceInfo_PositionsEntry { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourceInfo_PositionsEntry; typedef struct google_api_expr_v1alpha1_SourceInfo_MacroCallsEntry { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourceInfo_MacroCallsEntry; typedef struct google_api_expr_v1alpha1_SourcePosition { upb_Message UPB_PRIVATE(base); } google_api_expr_v1alpha1_SourcePosition; struct google_protobuf_Duration; struct google_protobuf_Timestamp; +typedef enum { + google_api_expr_v1alpha1_SourceInfo_Extension_COMPONENT_UNSPECIFIED = 0, + google_api_expr_v1alpha1_SourceInfo_Extension_COMPONENT_PARSER = 1, + google_api_expr_v1alpha1_SourceInfo_Extension_COMPONENT_TYPE_CHECKER = 2, + google_api_expr_v1alpha1_SourceInfo_Extension_COMPONENT_RUNTIME = 3 +} google_api_expr_v1alpha1_SourceInfo_Extension_Component; + /* google.api.expr.v1alpha1.ParsedExpr */ @@ -765,6 +774,38 @@ UPB_INLINE upb_Array* _google_api_expr_v1alpha1_Expr_CreateList_elements_mutable } return arr; } +UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateList_clear_optional_indices(google_api_expr_v1alpha1_Expr_CreateList* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t const* google_api_expr_v1alpha1_Expr_CreateList_optional_indices(const google_api_expr_v1alpha1_Expr_CreateList* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_api_expr_v1alpha1_Expr_CreateList_optional_indices_upb_array(const google_api_expr_v1alpha1_Expr_CreateList* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_api_expr_v1alpha1_Expr_CreateList_optional_indices_mutable_upb_array(google_api_expr_v1alpha1_Expr_CreateList* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} UPB_INLINE google_api_expr_v1alpha1_Expr** google_api_expr_v1alpha1_Expr_CreateList_mutable_elements(google_api_expr_v1alpha1_Expr_CreateList* msg, size_t* size) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; @@ -796,6 +837,34 @@ UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_C (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } +UPB_INLINE int32_t* google_api_expr_v1alpha1_Expr_CreateList_mutable_optional_indices(google_api_expr_v1alpha1_Expr_CreateList* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE int32_t* google_api_expr_v1alpha1_Expr_CreateList_resize_optional_indices(google_api_expr_v1alpha1_Expr_CreateList* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_api_expr_v1alpha1_Expr_CreateList_add_optional_indices(google_api_expr_v1alpha1_Expr_CreateList* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} /* google.api.expr.v1alpha1.Expr.CreateStruct */ @@ -955,81 +1024,93 @@ typedef enum { google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_NOT_SET = 0 } google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_oneofcases; UPB_INLINE google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_oneofcases google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_case(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return (google_api_expr_v1alpha1_Expr_CreateStruct_Entry_key_kind_oneofcases)upb_Message_WhichOneofFieldNumber( UPB_UPCAST(msg), &field); } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_clear_id(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {1, 32, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(32, 40), 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE int64_t google_api_expr_v1alpha1_Expr_CreateStruct_Entry_id(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { int64_t default_val = (int64_t)0ll; int64_t ret; - const upb_MiniTableField field = {1, 32, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(32, 40), 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_clear_field_key(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE upb_StringView google_api_expr_v1alpha1_Expr_CreateStruct_Entry_field_key(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } UPB_INLINE bool google_api_expr_v1alpha1_Expr_CreateStruct_Entry_has_field_key(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_clear_map_key(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 16), -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {3, 24, -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE const google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_CreateStruct_Entry_map_key(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { const google_api_expr_v1alpha1_Expr* default_val = NULL; const google_api_expr_v1alpha1_Expr* ret; - const upb_MiniTableField field = {3, UPB_SIZE(20, 16), -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {3, 24, -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } UPB_INLINE bool google_api_expr_v1alpha1_Expr_CreateStruct_Entry_has_map_key(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 16), -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {3, 24, -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_clear_value(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 40), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {4, UPB_SIZE(16, 48), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE const google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_CreateStruct_Entry_value(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { const google_api_expr_v1alpha1_Expr* default_val = NULL; const google_api_expr_v1alpha1_Expr* ret; - const upb_MiniTableField field = {4, UPB_SIZE(16, 40), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {4, UPB_SIZE(16, 48), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } UPB_INLINE bool google_api_expr_v1alpha1_Expr_CreateStruct_Entry_has_value(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 40), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {4, UPB_SIZE(16, 48), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_clear_optional_entry(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 0, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_api_expr_v1alpha1_Expr_CreateStruct_Entry_optional_entry(const google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 0, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_set_id(google_api_expr_v1alpha1_Expr_CreateStruct_Entry *msg, int64_t value) { - const upb_MiniTableField field = {1, 32, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(32, 40), 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_set_field_key(google_api_expr_v1alpha1_Expr_CreateStruct_Entry *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_set_map_key(google_api_expr_v1alpha1_Expr_CreateStruct_Entry *msg, google_api_expr_v1alpha1_Expr* value) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 16), -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {3, 24, -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_CreateStruct_Entry_mutable_map_key(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg, upb_Arena* arena) { @@ -1041,7 +1122,7 @@ UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_C return sub; } UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_set_value(google_api_expr_v1alpha1_Expr_CreateStruct_Entry *msg, google_api_expr_v1alpha1_Expr* value) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 40), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {4, UPB_SIZE(16, 48), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_CreateStruct_Entry_mutable_value(google_api_expr_v1alpha1_Expr_CreateStruct_Entry* msg, upb_Arena* arena) { @@ -1052,6 +1133,10 @@ UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_C } return sub; } +UPB_INLINE void google_api_expr_v1alpha1_Expr_CreateStruct_Entry_set_optional_entry(google_api_expr_v1alpha1_Expr_CreateStruct_Entry *msg, bool value) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 0, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} /* google.api.expr.v1alpha1.Expr.Comprehension */ @@ -1193,6 +1278,18 @@ UPB_INLINE bool google_api_expr_v1alpha1_Expr_Comprehension_has_result(const goo const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 68, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_api_expr_v1alpha1_Expr_Comprehension_clear_iter_var2(google_api_expr_v1alpha1_Expr_Comprehension* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(48, 88), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_api_expr_v1alpha1_Expr_Comprehension_iter_var2(const google_api_expr_v1alpha1_Expr_Comprehension* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {8, UPB_SIZE(48, 88), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} UPB_INLINE void google_api_expr_v1alpha1_Expr_Comprehension_set_iter_var(google_api_expr_v1alpha1_Expr_Comprehension *msg, upb_StringView value) { const upb_MiniTableField field = {1, UPB_SIZE(32, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; @@ -1262,6 +1359,10 @@ UPB_INLINE struct google_api_expr_v1alpha1_Expr* google_api_expr_v1alpha1_Expr_C } return sub; } +UPB_INLINE void google_api_expr_v1alpha1_Expr_Comprehension_set_iter_var2(google_api_expr_v1alpha1_Expr_Comprehension *msg, upb_StringView value) { + const upb_MiniTableField field = {8, UPB_SIZE(48, 88), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} /* google.api.expr.v1alpha1.Constant */ @@ -1551,25 +1652,25 @@ UPB_INLINE char* google_api_expr_v1alpha1_SourceInfo_serialize_ex(const google_a return ptr; } UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_clear_syntax_version(google_api_expr_v1alpha1_SourceInfo* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(24, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE upb_StringView google_api_expr_v1alpha1_SourceInfo_syntax_version(const google_api_expr_v1alpha1_SourceInfo* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(24, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_clear_location(google_api_expr_v1alpha1_SourceInfo* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, UPB_SIZE(32, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE upb_StringView google_api_expr_v1alpha1_SourceInfo_location(const google_api_expr_v1alpha1_SourceInfo* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(28, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, UPB_SIZE(32, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -1664,13 +1765,45 @@ UPB_INLINE upb_Map* _google_api_expr_v1alpha1_SourceInfo_macro_calls_mutable_upb const upb_MiniTableField field = {5, UPB_SIZE(16, 56), 0, 1, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return _upb_Message_GetOrCreateMutableMap(UPB_UPCAST(msg), &field, sizeof(int64_t), sizeof(google_api_expr_v1alpha1_Expr*), a); } +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_clear_extensions(google_api_expr_v1alpha1_SourceInfo* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_api_expr_v1alpha1_SourceInfo_Extension* const* google_api_expr_v1alpha1_SourceInfo_extensions(const google_api_expr_v1alpha1_SourceInfo* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_api_expr_v1alpha1_SourceInfo_Extension* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_api_expr_v1alpha1_SourceInfo_extensions_upb_array(const google_api_expr_v1alpha1_SourceInfo* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_api_expr_v1alpha1_SourceInfo_extensions_mutable_upb_array(google_api_expr_v1alpha1_SourceInfo* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_set_syntax_version(google_api_expr_v1alpha1_SourceInfo *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(24, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_set_location(google_api_expr_v1alpha1_SourceInfo *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, UPB_SIZE(32, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE int32_t* google_api_expr_v1alpha1_SourceInfo_mutable_line_offsets(google_api_expr_v1alpha1_SourceInfo* msg, size_t* size) { @@ -1751,6 +1884,248 @@ UPB_INLINE google_api_expr_v1alpha1_SourceInfo_MacroCallsEntry* google_api_expr_ if (!map) return NULL; return (google_api_expr_v1alpha1_SourceInfo_MacroCallsEntry*)_upb_map_next(map, iter); } +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension** google_api_expr_v1alpha1_SourceInfo_mutable_extensions(google_api_expr_v1alpha1_SourceInfo* msg, size_t* size) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_api_expr_v1alpha1_SourceInfo_Extension**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension** google_api_expr_v1alpha1_SourceInfo_resize_extensions(google_api_expr_v1alpha1_SourceInfo* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_api_expr_v1alpha1_SourceInfo_Extension**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_api_expr_v1alpha1_SourceInfo_Extension* google_api_expr_v1alpha1_SourceInfo_add_extensions(google_api_expr_v1alpha1_SourceInfo* msg, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_api_expr_v1alpha1_SourceInfo_Extension* sub = (struct google_api_expr_v1alpha1_SourceInfo_Extension*)_upb_Message_New(&google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} + +/* google.api.expr.v1alpha1.SourceInfo.Extension */ + +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension* google_api_expr_v1alpha1_SourceInfo_Extension_new(upb_Arena* arena) { + return (google_api_expr_v1alpha1_SourceInfo_Extension*)_upb_Message_New(&google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, arena); +} +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension* google_api_expr_v1alpha1_SourceInfo_Extension_parse(const char* buf, size_t size, upb_Arena* arena) { + google_api_expr_v1alpha1_SourceInfo_Extension* ret = google_api_expr_v1alpha1_SourceInfo_Extension_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension* google_api_expr_v1alpha1_SourceInfo_Extension_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_api_expr_v1alpha1_SourceInfo_Extension* ret = google_api_expr_v1alpha1_SourceInfo_Extension_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_api_expr_v1alpha1_SourceInfo_Extension_serialize(const google_api_expr_v1alpha1_SourceInfo_Extension* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_api_expr_v1alpha1_SourceInfo_Extension_serialize_ex(const google_api_expr_v1alpha1_SourceInfo_Extension* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_clear_id(google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_api_expr_v1alpha1_SourceInfo_Extension_id(const google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_clear_affected_components(google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t const* google_api_expr_v1alpha1_SourceInfo_Extension_affected_components(const google_api_expr_v1alpha1_SourceInfo_Extension* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_api_expr_v1alpha1_SourceInfo_Extension_affected_components_upb_array(const google_api_expr_v1alpha1_SourceInfo_Extension* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_api_expr_v1alpha1_SourceInfo_Extension_affected_components_mutable_upb_array(google_api_expr_v1alpha1_SourceInfo_Extension* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_clear_version(google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_api_expr_v1alpha1_SourceInfo_Extension_Version* google_api_expr_v1alpha1_SourceInfo_Extension_version(const google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + const google_api_expr_v1alpha1_SourceInfo_Extension_Version* default_val = NULL; + const google_api_expr_v1alpha1_SourceInfo_Extension_Version* ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_api_expr_v1alpha1_SourceInfo_Extension_has_version(const google_api_expr_v1alpha1_SourceInfo_Extension* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_set_id(google_api_expr_v1alpha1_SourceInfo_Extension *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE int32_t* google_api_expr_v1alpha1_SourceInfo_Extension_mutable_affected_components(google_api_expr_v1alpha1_SourceInfo_Extension* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE int32_t* google_api_expr_v1alpha1_SourceInfo_Extension_resize_affected_components(google_api_expr_v1alpha1_SourceInfo_Extension* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_api_expr_v1alpha1_SourceInfo_Extension_add_affected_components(google_api_expr_v1alpha1_SourceInfo_Extension* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_set_version(google_api_expr_v1alpha1_SourceInfo_Extension *msg, google_api_expr_v1alpha1_SourceInfo_Extension_Version* value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_api_expr_v1alpha1_SourceInfo_Extension_Version* google_api_expr_v1alpha1_SourceInfo_Extension_mutable_version(google_api_expr_v1alpha1_SourceInfo_Extension* msg, upb_Arena* arena) { + struct google_api_expr_v1alpha1_SourceInfo_Extension_Version* sub = (struct google_api_expr_v1alpha1_SourceInfo_Extension_Version*)google_api_expr_v1alpha1_SourceInfo_Extension_version(msg); + if (sub == NULL) { + sub = (struct google_api_expr_v1alpha1_SourceInfo_Extension_Version*)_upb_Message_New(&google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, arena); + if (sub) google_api_expr_v1alpha1_SourceInfo_Extension_set_version(msg, sub); + } + return sub; +} + +/* google.api.expr.v1alpha1.SourceInfo.Extension.Version */ + +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension_Version* google_api_expr_v1alpha1_SourceInfo_Extension_Version_new(upb_Arena* arena) { + return (google_api_expr_v1alpha1_SourceInfo_Extension_Version*)_upb_Message_New(&google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, arena); +} +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension_Version* google_api_expr_v1alpha1_SourceInfo_Extension_Version_parse(const char* buf, size_t size, upb_Arena* arena) { + google_api_expr_v1alpha1_SourceInfo_Extension_Version* ret = google_api_expr_v1alpha1_SourceInfo_Extension_Version_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_api_expr_v1alpha1_SourceInfo_Extension_Version* google_api_expr_v1alpha1_SourceInfo_Extension_Version_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_api_expr_v1alpha1_SourceInfo_Extension_Version* ret = google_api_expr_v1alpha1_SourceInfo_Extension_Version_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_api_expr_v1alpha1_SourceInfo_Extension_Version_serialize(const google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_api_expr_v1alpha1_SourceInfo_Extension_Version_serialize_ex(const google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_Version_clear_major(google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg) { + const upb_MiniTableField field = {1, 8, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int64_t google_api_expr_v1alpha1_SourceInfo_Extension_Version_major(const google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg) { + int64_t default_val = (int64_t)0ll; + int64_t ret; + const upb_MiniTableField field = {1, 8, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_Version_clear_minor(google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg) { + const upb_MiniTableField field = {2, 16, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int64_t google_api_expr_v1alpha1_SourceInfo_Extension_Version_minor(const google_api_expr_v1alpha1_SourceInfo_Extension_Version* msg) { + int64_t default_val = (int64_t)0ll; + int64_t ret; + const upb_MiniTableField field = {2, 16, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} + +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_Version_set_major(google_api_expr_v1alpha1_SourceInfo_Extension_Version *msg, int64_t value) { + const upb_MiniTableField field = {1, 8, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_api_expr_v1alpha1_SourceInfo_Extension_Version_set_minor(google_api_expr_v1alpha1_SourceInfo_Extension_Version *msg, int64_t value) { + const upb_MiniTableField field = {2, 16, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} /* google.api.expr.v1alpha1.SourceInfo.PositionsEntry */ diff --git a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c index 09046cd120..86de1318a5 100644 --- a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c +++ b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.c @@ -154,20 +154,23 @@ static const upb_MiniTableSub google_api_expr_v1alpha1_Expr_CreateList_submsgs[1 {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__Expr_msg_init}, }; -static const upb_MiniTableField google_api_expr_v1alpha1_Expr_CreateList__fields[1] = { +static const upb_MiniTableField google_api_expr_v1alpha1_Expr_CreateList__fields[2] = { {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, }; const upb_MiniTable google__api__expr__v1alpha1__Expr__CreateList_msg_init = { &google_api_expr_v1alpha1_Expr_CreateList_submsgs[0], &google_api_expr_v1alpha1_Expr_CreateList__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, + UPB_SIZE(16, 24), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 0, #ifdef UPB_TRACING_ENABLED "google.api.expr.v1alpha1.Expr.CreateList", #endif UPB_FASTTABLE_INIT({ {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, {0x000800003f00000a, &upb_prm_1bt_max64b}, + {0x001000003f000012, &upb_ppv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, }) }; @@ -200,25 +203,30 @@ static const upb_MiniTableSub google_api_expr_v1alpha1_Expr_CreateStruct_Entry_s {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__Expr_msg_init}, }; -static const upb_MiniTableField google_api_expr_v1alpha1_Expr_CreateStruct_Entry__fields[4] = { - {1, 32, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(20, 16), -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(20, 16), -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(16, 40), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +static const upb_MiniTableField google_api_expr_v1alpha1_Expr_CreateStruct_Entry__fields[5] = { + {1, UPB_SIZE(32, 40), 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {2, 24, -13, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 24, -13, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 48), 64, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 16), 0, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, }; const upb_MiniTable google__api__expr__v1alpha1__Expr__CreateStruct__Entry_msg_init = { &google_api_expr_v1alpha1_Expr_CreateStruct_Entry_submsgs[0], &google_api_expr_v1alpha1_Expr_CreateStruct_Entry__fields[0], - UPB_SIZE(40, 48), 4, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(24), 0, + UPB_SIZE(40, 56), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, #ifdef UPB_TRACING_ENABLED "google.api.expr.v1alpha1.Expr.CreateStruct.Entry", #endif UPB_FASTTABLE_INIT({ {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000008, &upb_psv8_1bt}, - {0x0010000c02000012, &upb_pos_1bt}, - {0x0010000c0300001a, &upb_pom_1bt_max64b}, + {0x002800003f000008, &upb_psv8_1bt}, + {0x0018000c02000012, &upb_pos_1bt}, + {0x0018000c0300001a, &upb_pom_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f000028, &upb_psb1_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, }) }; @@ -230,7 +238,7 @@ static const upb_MiniTableSub google_api_expr_v1alpha1_Expr_Comprehension_submsg {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__Expr_msg_init}, }; -static const upb_MiniTableField google_api_expr_v1alpha1_Expr_Comprehension__fields[7] = { +static const upb_MiniTableField google_api_expr_v1alpha1_Expr_Comprehension__fields[8] = { {1, UPB_SIZE(32, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, {2, UPB_SIZE(12, 32), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {3, 40, 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, @@ -238,12 +246,13 @@ static const upb_MiniTableField google_api_expr_v1alpha1_Expr_Comprehension__fie {5, UPB_SIZE(20, 64), 66, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {6, UPB_SIZE(24, 72), 67, 3, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {7, UPB_SIZE(28, 80), 68, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(48, 88), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, }; const upb_MiniTable google__api__expr__v1alpha1__Expr__Comprehension_msg_init = { &google_api_expr_v1alpha1_Expr_Comprehension_submsgs[0], &google_api_expr_v1alpha1_Expr_Comprehension__fields[0], - UPB_SIZE(48, 88), 7, kUpb_ExtMode_NonExtendable, 7, UPB_FASTTABLE_MASK(24), 0, + UPB_SIZE(56, 104), 8, kUpb_ExtMode_NonExtendable, 8, UPB_FASTTABLE_MASK(120), 0, #ifdef UPB_TRACING_ENABLED "google.api.expr.v1alpha1.Expr.Comprehension", #endif @@ -252,6 +261,18 @@ const upb_MiniTable google__api__expr__v1alpha1__Expr__Comprehension_msg_init = {0x001000003f00000a, &upb_pss_1bt}, {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, {0x002800003f00001a, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x005800003f000042, &upb_pss_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, }) }; @@ -299,23 +320,25 @@ const upb_MiniTable google__api__expr__v1alpha1__Constant_msg_init = { }) }; -static const upb_MiniTableSub google_api_expr_v1alpha1_SourceInfo_submsgs[2] = { +static const upb_MiniTableSub google_api_expr_v1alpha1_SourceInfo_submsgs[3] = { {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__SourceInfo__PositionsEntry_msg_init}, {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__SourceInfo__MacroCallsEntry_msg_init}, + {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init}, }; -static const upb_MiniTableField google_api_expr_v1alpha1_SourceInfo__fields[5] = { - {1, UPB_SIZE(20, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(28, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +static const upb_MiniTableField google_api_expr_v1alpha1_SourceInfo__fields[6] = { + {1, UPB_SIZE(24, 8), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(32, 24), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, {3, UPB_SIZE(8, 40), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {4, UPB_SIZE(12, 48), 0, 0, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, {5, UPB_SIZE(16, 56), 0, 1, 11, (int)kUpb_FieldMode_Map | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(20, 64), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, }; const upb_MiniTable google__api__expr__v1alpha1__SourceInfo_msg_init = { &google_api_expr_v1alpha1_SourceInfo_submsgs[0], &google_api_expr_v1alpha1_SourceInfo__fields[0], - UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(24), 0, + UPB_SIZE(40, 72), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(56), 0, #ifdef UPB_TRACING_ENABLED "google.api.expr.v1alpha1.SourceInfo", #endif @@ -324,6 +347,55 @@ const upb_MiniTable google__api__expr__v1alpha1__SourceInfo_msg_init = { {0x000800003f00000a, &upb_pss_1bt}, {0x001800003f000012, &upb_pss_1bt}, {0x002800003f00001a, &upb_ppv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x004000003f020032, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableSub google_api_expr_v1alpha1_SourceInfo_Extension_submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init}, +}; + +static const upb_MiniTableField google_api_expr_v1alpha1_SourceInfo_Extension__fields[3] = { + {1, UPB_SIZE(20, 16), 0, kUpb_NoSub, 9, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__Extension_msg_init = { + &google_api_expr_v1alpha1_SourceInfo_Extension_submsgs[0], + &google_api_expr_v1alpha1_SourceInfo_Extension__fields[0], + UPB_SIZE(32, 48), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.api.expr.v1alpha1.SourceInfo.Extension", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f00000a, &upb_pss_1bt}, + {0x002000003f000012, &upb_ppv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +static const upb_MiniTableField google_api_expr_v1alpha1_SourceInfo_Extension_Version__fields[2] = { + {1, 8, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {2, 16, 0, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init = { + NULL, + &google_api_expr_v1alpha1_SourceInfo_Extension_Version__fields[0], + 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.api.expr.v1alpha1.SourceInfo.Extension.Version", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f000008, &upb_psv8_1bt}, + {0x001000003f000010, &upb_psv8_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, }) }; @@ -395,7 +467,7 @@ const upb_MiniTable google__api__expr__v1alpha1__SourcePosition_msg_init = { }) }; -static const upb_MiniTable *messages_layout[14] = { +static const upb_MiniTable *messages_layout[16] = { &google__api__expr__v1alpha1__ParsedExpr_msg_init, &google__api__expr__v1alpha1__Expr_msg_init, &google__api__expr__v1alpha1__Expr__Ident_msg_init, @@ -407,6 +479,8 @@ static const upb_MiniTable *messages_layout[14] = { &google__api__expr__v1alpha1__Expr__Comprehension_msg_init, &google__api__expr__v1alpha1__Constant_msg_init, &google__api__expr__v1alpha1__SourceInfo_msg_init, + &google__api__expr__v1alpha1__SourceInfo__Extension_msg_init, + &google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init, &google__api__expr__v1alpha1__SourceInfo__PositionsEntry_msg_init, &google__api__expr__v1alpha1__SourceInfo__MacroCallsEntry_msg_init, &google__api__expr__v1alpha1__SourcePosition_msg_init, @@ -416,7 +490,7 @@ const upb_MiniTableFile google_api_expr_v1alpha1_syntax_proto_upb_file_layout = messages_layout, NULL, NULL, - 14, + 16, 0, 0, }; diff --git a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.h b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.h index c0232345d2..269a82c1a3 100644 --- a/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.h +++ b/src/core/ext/upb-gen/google/api/expr/v1alpha1/syntax.upb_minitable.h @@ -28,6 +28,8 @@ extern const upb_MiniTable google__api__expr__v1alpha1__Expr__CreateStruct__Entr extern const upb_MiniTable google__api__expr__v1alpha1__Expr__Comprehension_msg_init; extern const upb_MiniTable google__api__expr__v1alpha1__Constant_msg_init; extern const upb_MiniTable google__api__expr__v1alpha1__SourceInfo_msg_init; +extern const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__Extension_msg_init; +extern const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__Extension__Version_msg_init; extern const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__PositionsEntry_msg_init; extern const upb_MiniTable google__api__expr__v1alpha1__SourceInfo__MacroCallsEntry_msg_init; extern const upb_MiniTable google__api__expr__v1alpha1__SourcePosition_msg_init; diff --git a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c index d664aa3531..a973925933 100644 --- a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c +++ b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/checked.upbdefs.c @@ -12,13 +12,13 @@ extern _upb_DefPool_Init google_api_expr_v1alpha1_syntax_proto_upbdefinit; extern _upb_DefPool_Init google_protobuf_empty_proto_upbdefinit; extern _upb_DefPool_Init google_protobuf_struct_proto_upbdefinit; -static const char descriptor[3089] = {'\n', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +static const char descriptor[3124] = {'\n', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\032', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 'o', '\032', '\033', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'e', 'm', 'p', 't', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\367', '\003', '\n', '\013', 'C', 'h', 'e', 'c', 'k', 'e', +'f', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\232', '\004', '\n', '\013', 'C', 'h', 'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', '\022', '\\', '\n', '\r', 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', '_', 'm', 'a', 'p', '\030', '\002', ' ', '\003', '(', '\013', '2', '7', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', '.', 'R', 'e', 'f', 'e', 'r', 'e', 'n', @@ -29,113 +29,114 @@ static const char descriptor[3089] = {'\n', '&', 'g', 'o', 'o', 'g', 'l', 'e', ' 'M', 'a', 'p', '\022', 'E', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\005', ' ', '\001', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\022', -'2', '\n', '\004', 'e', 'x', 'p', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', -'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'e', 'x', 'p', -'r', '\032', 'd', '\n', '\021', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', -'\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '9', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', -'\002', ' ', '\001', '(', '\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', -'1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', -'\002', '8', '\001', '\032', 'Z', '\n', '\014', 'T', 'y', 'p', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', -'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', -'(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', -'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '\310', '\013', '\n', '\004', -'T', 'y', 'p', 'e', '\022', '*', '\n', '\003', 'd', 'y', 'n', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'm', 'p', 't', 'y', 'H', '\000', 'R', '\003', 'd', 'y', 'n', '\022', '0', -'\n', '\004', 'n', 'u', 'l', 'l', '\030', '\002', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\004', 'n', 'u', 'l', 'l', '\022', 'L', -'\n', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', '\030', '\003', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', -'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', -'e', '\022', 'H', '\n', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', -'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', -'.', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', -'\022', 'M', '\n', '\n', 'w', 'e', 'l', 'l', '_', 'k', 'n', 'o', 'w', 'n', '\030', '\005', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', -'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', -'p', 'e', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\t', 'w', 'e', 'l', 'l', 'K', -'n', 'o', 'w', 'n', '\022', 'F', '\n', '\t', 'l', 'i', 's', 't', '_', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', '(', '\013', '2', '\'', +'!', '\n', '\014', 'e', 'x', 'p', 'r', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\013', 'e', 'x', +'p', 'r', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '2', '\n', '\004', 'e', 'x', 'p', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', -'.', 'T', 'y', 'p', 'e', '.', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\010', 'l', 'i', 's', 't', 'T', 'y', 'p', -'e', '\022', 'C', '\n', '\010', 'm', 'a', 'p', '_', 't', 'y', 'p', 'e', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', +'.', 'E', 'x', 'p', 'r', 'R', '\004', 'e', 'x', 'p', 'r', '\032', 'd', '\n', '\021', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'M', +'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', +'\022', '9', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'R', 'e', 'f', 'e', 'r', 'e', 'n', +'c', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\032', 'Z', '\n', '\014', 'T', 'y', 'p', 'e', 'M', 'a', 'p', 'E', +'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', +'\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\005', 'v', 'a', 'l', 'u', +'e', ':', '\002', '8', '\001', '\"', '\310', '\013', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '*', '\n', '\003', 'd', 'y', 'n', '\030', '\001', ' ', '\001', +'(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'm', 'p', 't', +'y', 'H', '\000', 'R', '\003', 'd', 'y', 'n', '\022', '0', '\n', '\004', 'n', 'u', 'l', 'l', '\030', '\002', ' ', '\001', '(', '\016', '2', '\032', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', +'H', '\000', 'R', '\004', 'n', 'u', 'l', 'l', '\022', 'L', '\n', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', '\030', '\003', ' ', '\001', +'(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', '\000', +'R', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', '\022', 'H', '\n', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', '\030', '\004', ' ', +'\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', +'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', +'\000', 'R', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', '\022', 'M', '\n', '\n', 'w', 'e', 'l', 'l', '_', 'k', 'n', 'o', 'w', 'n', '\030', +'\005', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', +'1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', +'e', 'H', '\000', 'R', '\t', 'w', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', '\022', 'F', '\n', '\t', 'l', 'i', 's', 't', '_', 't', 'y', +'p', 'e', '\030', '\006', ' ', '\001', '(', '\013', '2', '\'', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', +'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', 'H', +'\000', 'R', '\010', 'l', 'i', 's', 't', 'T', 'y', 'p', 'e', '\022', 'C', '\n', '\010', 'm', 'a', 'p', '_', 't', 'y', 'p', 'e', '\030', '\007', +' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'M', 'a', 'p', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\007', 'm', 'a', +'p', 'T', 'y', 'p', 'e', '\022', 'I', '\n', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\010', ' ', '\001', '(', '\013', '2', '+', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', +'.', 'T', 'y', 'p', 'e', '.', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\010', 'f', 'u', 'n', +'c', 't', 'i', 'o', 'n', '\022', '#', '\n', '\014', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\t', ' ', '\001', +'(', '\t', 'H', '\000', 'R', '\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\n', 't', 'y', 'p', 'e', +'_', 'p', 'a', 'r', 'a', 'm', '\030', '\n', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\t', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', +'\022', '4', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\013', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\004', +'t', 'y', 'p', 'e', '\022', '.', '\n', '\005', 'e', 'r', 'r', 'o', 'r', '\030', '\014', ' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'm', 'p', 't', 'y', 'H', '\000', 'R', '\005', 'e', 'r', 'r', +'o', 'r', '\022', 'R', '\n', '\r', 'a', 'b', 's', 't', 'r', 'a', 'c', 't', '_', 't', 'y', 'p', 'e', '\030', '\016', ' ', '\001', '(', '\013', +'2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', +'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'A', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\014', 'a', +'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', '\032', 'G', '\n', '\010', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', '\022', ';', +'\n', '\t', 'e', 'l', 'e', 'm', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', +'\010', 'e', 'l', 'e', 'm', 'T', 'y', 'p', 'e', '\032', '\203', '\001', '\n', '\007', 'M', 'a', 'p', 'T', 'y', 'p', 'e', '\022', '9', '\n', '\010', +'k', 'e', 'y', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\007', 'k', 'e', +'y', 'T', 'y', 'p', 'e', '\022', '=', '\n', '\n', 'v', 'a', 'l', 'u', 'e', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\013', +'2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', +'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\t', 'v', 'a', 'l', 'u', 'e', 'T', 'y', 'p', 'e', '\032', '\214', '\001', '\n', '\014', 'F', 'u', +'n', 'c', 't', 'i', 'o', 'n', 'T', 'y', 'p', 'e', '\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', 'e', +'\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', +'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', 'e', +'\022', ';', '\n', '\t', 'a', 'r', 'g', '_', 't', 'y', 'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', -'e', '.', 'M', 'a', 'p', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\007', 'm', 'a', 'p', 'T', 'y', 'p', 'e', '\022', 'I', '\n', '\010', 'f', -'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\010', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', -'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'F', 'u', 'n', 'c', -'t', 'i', 'o', 'n', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '#', '\n', '\014', 'm', -'e', 's', 's', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\t', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\013', 'm', 'e', 's', 's', -'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\n', 't', 'y', 'p', 'e', '_', 'p', 'a', 'r', 'a', 'm', '\030', '\n', ' ', '\001', -'(', '\t', 'H', '\000', 'R', '\t', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', '\022', '4', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\013', -' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', -'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\004', 't', 'y', 'p', 'e', '\022', '.', '\n', '\005', 'e', 'r', -'r', 'o', 'r', '\030', '\014', ' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', -'u', 'f', '.', 'E', 'm', 'p', 't', 'y', 'H', '\000', 'R', '\005', 'e', 'r', 'r', 'o', 'r', '\022', 'R', '\n', '\r', 'a', 'b', 's', 't', -'r', 'a', 'c', 't', '_', 't', 'y', 'p', 'e', '\030', '\016', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'A', 'b', -'s', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\014', 'a', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', -'e', '\032', 'G', '\n', '\010', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', '\022', ';', '\n', '\t', 'e', 'l', 'e', 'm', '_', 't', 'y', 'p', -'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', -'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\010', 'e', 'l', 'e', 'm', 'T', 'y', 'p', 'e', '\032', -'\203', '\001', '\n', '\007', 'M', 'a', 'p', 'T', 'y', 'p', 'e', '\022', '9', '\n', '\010', 'k', 'e', 'y', '_', 't', 'y', 'p', 'e', '\030', '\001', -' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', -'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\007', 'k', 'e', 'y', 'T', 'y', 'p', 'e', '\022', '=', '\n', '\n', 'v', -'a', 'l', 'u', 'e', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\t', 'v', -'a', 'l', 'u', 'e', 'T', 'y', 'p', 'e', '\032', '\214', '\001', '\n', '\014', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'T', 'y', 'p', 'e', -'\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', -'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', 'e', '\022', ';', '\n', '\t', 'a', 'r', 'g', '_', 't', 'y', -'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', -'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\010', 'a', 'r', 'g', 'T', 'y', 'p', 'e', -'s', '\032', 'k', '\n', '\014', 'A', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', -'\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'G', '\n', '\017', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', -'_', 't', 'y', 'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', -'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\016', 'p', 'a', 'r', 'a', -'m', 'e', 't', 'e', 'r', 'T', 'y', 'p', 'e', 's', '\"', 's', '\n', '\r', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', -'p', 'e', '\022', '\036', '\n', '\032', 'P', 'R', 'I', 'M', 'I', 'T', 'I', 'V', 'E', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'S', 'P', -'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\010', '\n', '\004', 'B', 'O', 'O', 'L', '\020', '\001', '\022', '\t', '\n', '\005', 'I', 'N', -'T', '6', '4', '\020', '\002', '\022', '\n', '\n', '\006', 'U', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\n', '\n', '\006', 'D', 'O', 'U', 'B', -'L', 'E', '\020', '\004', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\005', '\022', '\t', '\n', '\005', 'B', 'Y', 'T', 'E', 'S', -'\020', '\006', '\"', 'V', '\n', '\r', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\033', 'W', 'E', -'L', 'L', '_', 'K', 'N', 'O', 'W', 'N', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', -'\020', '\000', '\022', '\007', '\n', '\003', 'A', 'N', 'Y', '\020', '\001', '\022', '\r', '\n', '\t', 'T', 'I', 'M', 'E', 'S', 'T', 'A', 'M', 'P', '\020', -'\002', '\022', '\014', '\n', '\010', 'D', 'U', 'R', 'A', 'T', 'I', 'O', 'N', '\020', '\003', 'B', '\013', '\n', '\t', 't', 'y', 'p', 'e', '_', 'k', -'i', 'n', 'd', '\"', '\263', '\005', '\n', '\004', 'D', 'e', 'c', 'l', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', -'\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '@', '\n', '\005', 'i', 'd', 'e', 'n', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', -'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', -'D', 'e', 'c', 'l', '.', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', 'H', '\000', 'R', '\005', 'i', 'd', 'e', 'n', 't', '\022', 'I', -'\n', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', -'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', 'H', '\000', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\032', '\213', -'\001', '\n', '\t', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', '\022', '2', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', -'\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', -'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', '8', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', -' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', -'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '\020', '\n', -'\003', 'd', 'o', 'c', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', '\032', '\356', '\002', '\n', '\014', 'F', 'u', 'n', 'c', 't', -'i', 'o', 'n', 'D', 'e', 'c', 'l', '\022', 'R', '\n', '\t', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 's', '\030', '\001', ' ', '\003', '(', -'\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', -'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', '.', 'O', 'v', 'e', -'r', 'l', 'o', 'a', 'd', 'R', '\t', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 's', '\032', '\211', '\002', '\n', '\010', 'O', 'v', 'e', 'r', -'l', 'o', 'a', 'd', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '_', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', -'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '6', '\n', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\002', ' ', -'\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', -'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\022', '\037', '\n', '\013', 't', 'y', 'p', -'e', '_', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', -'s', '\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', +'e', 'R', '\010', 'a', 'r', 'g', 'T', 'y', 'p', 'e', 's', '\032', 'k', '\n', '\014', 'A', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', +'p', 'e', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'G', '\n', +'\017', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '_', 't', 'y', 'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', -'T', 'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', 'e', '\022', '0', '\n', '\024', 'i', 's', '_', 'i', 'n', -'s', 't', 'a', 'n', 'c', 'e', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\022', 'i', 's', -'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '\020', '\n', '\003', 'd', 'o', 'c', '\030', '\006', -' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', 'B', '\013', '\n', '\t', 'd', 'e', 'c', 'l', '_', 'k', 'i', 'n', 'd', '\"', 'z', '\n', -'\t', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', -'\004', 'n', 'a', 'm', 'e', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '_', 'i', 'd', '\030', '\003', ' ', '\003', '(', -'\t', 'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '8', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', -'\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', -'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', 'l', '\n', '\034', -'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', -'h', 'a', '1', 'B', '\t', 'D', 'e', 'c', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', -'e', 'a', 'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', -'x', 'p', 'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +'T', 'y', 'p', 'e', 'R', '\016', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'T', 'y', 'p', 'e', 's', '\"', 's', '\n', '\r', 'P', +'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', '\022', '\036', '\n', '\032', 'P', 'R', 'I', 'M', 'I', 'T', 'I', 'V', 'E', +'_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\010', '\n', '\004', 'B', 'O', +'O', 'L', '\020', '\001', '\022', '\t', '\n', '\005', 'I', 'N', 'T', '6', '4', '\020', '\002', '\022', '\n', '\n', '\006', 'U', 'I', 'N', 'T', '6', '4', +'\020', '\003', '\022', '\n', '\n', '\006', 'D', 'O', 'U', 'B', 'L', 'E', '\020', '\004', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', +'\005', '\022', '\t', '\n', '\005', 'B', 'Y', 'T', 'E', 'S', '\020', '\006', '\"', 'V', '\n', '\r', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', +'T', 'y', 'p', 'e', '\022', '\037', '\n', '\033', 'W', 'E', 'L', 'L', '_', 'K', 'N', 'O', 'W', 'N', '_', 'T', 'Y', 'P', 'E', '_', 'U', +'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\007', '\n', '\003', 'A', 'N', 'Y', '\020', '\001', '\022', '\r', '\n', '\t', +'T', 'I', 'M', 'E', 'S', 'T', 'A', 'M', 'P', '\020', '\002', '\022', '\014', '\n', '\010', 'D', 'U', 'R', 'A', 'T', 'I', 'O', 'N', '\020', '\003', +'B', '\013', '\n', '\t', 't', 'y', 'p', 'e', '_', 'k', 'i', 'n', 'd', '\"', '\263', '\005', '\n', '\004', 'D', 'e', 'c', 'l', '\022', '\022', '\n', +'\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '@', '\n', '\005', 'i', 'd', 'e', 'n', +'t', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', +'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', 'H', +'\000', 'R', '\005', 'i', 'd', 'e', 'n', 't', '\022', 'I', '\n', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', +'\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', 'H', '\000', 'R', '\010', +'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\032', '\213', '\001', '\n', '\t', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', '\022', '2', '\n', +'\004', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', +'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', +'8', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', +'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '\020', '\n', '\003', 'd', 'o', 'c', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', +'\032', '\356', '\002', '\n', '\014', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', '\022', 'R', '\n', '\t', 'o', 'v', 'e', 'r', +'l', 'o', 'a', 'd', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', +'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', 'u', 'n', 'c', 't', 'i', +'o', 'n', 'D', 'e', 'c', 'l', '.', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'R', '\t', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', +'s', '\032', '\211', '\002', '\n', '\010', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', 'a', +'d', '_', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '6', '\n', +'\006', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\006', 'p', 'a', 'r', +'a', 'm', 's', '\022', '\037', '\n', '\013', 't', 'y', 'p', 'e', '_', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\003', ' ', '\003', '(', '\t', 'R', +'\n', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', 's', '\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', +'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', +'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', +'e', '\022', '0', '\n', '\024', 'i', 's', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', +'\030', '\005', ' ', '\001', '(', '\010', 'R', '\022', 'i', 's', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'F', 'u', 'n', 'c', 't', 'i', 'o', +'n', '\022', '\020', '\n', '\003', 'd', 'o', 'c', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', 'B', '\013', '\n', '\t', 'd', 'e', +'c', 'l', '_', 'k', 'i', 'n', 'd', '\"', 'z', '\n', '\t', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', '\022', '\022', '\n', '\004', 'n', +'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', +'a', 'd', '_', 'i', 'd', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '8', +'\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'R', +'\005', 'v', 'a', 'l', 'u', 'e', 'B', 'l', '\n', '\034', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', +'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', '\t', 'D', 'e', 'c', 'l', 'P', 'r', 'o', 't', 'o', 'P', +'\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', +'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', 'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', +'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', 'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', }; static _upb_DefPool_Init *deps[4] = { @@ -149,5 +150,5 @@ _upb_DefPool_Init google_api_expr_v1alpha1_checked_proto_upbdefinit = { deps, &google_api_expr_v1alpha1_checked_proto_upb_file_layout, "google/api/expr/v1alpha1/checked.proto", - UPB_STRINGVIEW_INIT(descriptor, 3089) + UPB_STRINGVIEW_INIT(descriptor, 3124) }; diff --git a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c index 1bc7aafdd3..bdf128c4c3 100644 --- a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c +++ b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.c @@ -12,7 +12,7 @@ extern _upb_DefPool_Init google_protobuf_duration_proto_upbdefinit; extern _upb_DefPool_Init google_protobuf_struct_proto_upbdefinit; extern _upb_DefPool_Init google_protobuf_timestamp_proto_upbdefinit; -static const char descriptor[3059] = {'\n', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +static const char descriptor[3637] = {'\n', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g', @@ -23,8 +23,8 @@ static const char descriptor[3059] = {'\n', '%', 'g', 'o', 'o', 'g', 'l', 'e', ' 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'e', 'x', 'p', 'r', '\022', 'E', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\003', ' ', '\001', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', -'.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\"', '\334', -'\014', '\n', '\004', 'E', 'x', 'p', 'r', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\002', ' ', '\001', '(', '\003', 'R', '\002', 'i', 'd', '\022', 'C', +'.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\"', '\313', +'\r', '\n', '\004', 'E', 'x', 'p', 'r', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\002', ' ', '\001', '(', '\003', 'R', '\002', 'i', 'd', '\022', 'C', '\n', '\n', 'c', 'o', 'n', 's', 't', '_', 'e', 'x', 'p', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'H', '\000', 'R', '\t', 'c', 'o', 'n', 's', 't', 'E', 'x', 'p', 'r', '\022', 'E', '\n', '\n', 'i', 'd', 'e', 'n', @@ -57,84 +57,107 @@ static const char descriptor[3059] = {'\n', '%', 'g', 'o', 'o', 'g', 'l', 'e', ' 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\006', 't', 'a', 'r', 'g', 'e', 't', '\022', '\032', '\n', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '2', '\n', '\004', 'a', 'r', 'g', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', -'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'a', 'r', 'g', 's', '\032', 'H', '\n', +'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'a', 'r', 'g', 's', '\032', 's', '\n', '\n', 'C', 'r', 'e', 'a', 't', 'e', 'L', 'i', 's', 't', '\022', ':', '\n', '\010', 'e', 'l', 'e', 'm', 'e', 'n', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', -'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'e', 'l', 'e', 'm', 'e', 'n', 't', 's', '\032', '\264', '\002', '\n', -'\014', 'C', 'r', 'e', 'a', 't', 'e', 'S', 't', 'r', 'u', 'c', 't', '\022', '!', '\n', '\014', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', -'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '\022', 'K', -'\n', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '1', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'r', -'e', 'a', 't', 'e', 'S', 't', 'r', 'u', 'c', 't', '.', 'E', 'n', 't', 'r', 'y', 'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', -'\032', '\263', '\001', '\n', '\005', 'E', 'n', 't', 'r', 'y', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\002', 'i', -'d', '\022', '\035', '\n', '\t', 'f', 'i', 'e', 'l', 'd', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\010', 'f', -'i', 'e', 'l', 'd', 'K', 'e', 'y', '\022', '9', '\n', '\007', 'm', 'a', 'p', '_', 'k', 'e', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', +'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'e', 'l', 'e', 'm', 'e', 'n', 't', 's', '\022', ')', '\n', '\020', +'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '_', 'i', 'n', 'd', 'i', 'c', 'e', 's', '\030', '\002', ' ', '\003', '(', '\005', 'R', '\017', 'o', +'p', 't', 'i', 'o', 'n', 'a', 'l', 'I', 'n', 'd', 'i', 'c', 'e', 's', '\032', '\333', '\002', '\n', '\014', 'C', 'r', 'e', 'a', 't', 'e', +'S', 't', 'r', 'u', 'c', 't', '\022', '!', '\n', '\014', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', +'\001', '(', '\t', 'R', '\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '\022', 'K', '\n', '\007', 'e', 'n', 't', 'r', 'i', +'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '1', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', +'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'r', 'e', 'a', 't', 'e', 'S', 't', 'r', +'u', 'c', 't', '.', 'E', 'n', 't', 'r', 'y', 'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\032', '\332', '\001', '\n', '\005', 'E', 'n', +'t', 'r', 'y', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\002', 'i', 'd', '\022', '\035', '\n', '\t', 'f', 'i', +'e', 'l', 'd', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\010', 'f', 'i', 'e', 'l', 'd', 'K', 'e', 'y', +'\022', '9', '\n', '\007', 'm', 'a', 'p', '_', 'k', 'e', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'H', +'\000', 'R', '\006', 'm', 'a', 'p', 'K', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', -'1', '.', 'E', 'x', 'p', 'r', 'H', '\000', 'R', '\006', 'm', 'a', 'p', 'K', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', 'e', -'\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', -'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', '\n', '\n', '\010', 'k', -'e', 'y', '_', 'k', 'i', 'n', 'd', '\032', '\375', '\002', '\n', '\r', 'C', 'o', 'm', 'p', 'r', 'e', 'h', 'e', 'n', 's', 'i', 'o', 'n', -'\022', '\031', '\n', '\010', 'i', 't', 'e', 'r', '_', 'v', 'a', 'r', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 'i', 't', 'e', 'r', 'V', -'a', 'r', '\022', '=', '\n', '\n', 'i', 't', 'e', 'r', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', +'1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '%', '\n', '\016', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', +'_', 'e', 'n', 't', 'r', 'y', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\r', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', 'E', 'n', 't', +'r', 'y', 'B', '\n', '\n', '\010', 'k', 'e', 'y', '_', 'k', 'i', 'n', 'd', '\032', '\232', '\003', '\n', '\r', 'C', 'o', 'm', 'p', 'r', 'e', +'h', 'e', 'n', 's', 'i', 'o', 'n', '\022', '\031', '\n', '\010', 'i', 't', 'e', 'r', '_', 'v', 'a', 'r', '\030', '\001', ' ', '\001', '(', '\t', +'R', '\007', 'i', 't', 'e', 'r', 'V', 'a', 'r', '\022', '\033', '\n', '\t', 'i', 't', 'e', 'r', '_', 'v', 'a', 'r', '2', '\030', '\010', ' ', +'\001', '(', '\t', 'R', '\010', 'i', 't', 'e', 'r', 'V', 'a', 'r', '2', '\022', '=', '\n', '\n', 'i', 't', 'e', 'r', '_', 'r', 'a', 'n', +'g', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', +'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\t', 'i', 't', 'e', 'r', 'R', 'a', 'n', 'g', +'e', '\022', '\031', '\n', '\010', 'a', 'c', 'c', 'u', '_', 'v', 'a', 'r', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\007', 'a', 'c', 'c', 'u', +'V', 'a', 'r', '\022', ';', '\n', '\t', 'a', 'c', 'c', 'u', '_', 'i', 'n', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', -'E', 'x', 'p', 'r', 'R', '\t', 'i', 't', 'e', 'r', 'R', 'a', 'n', 'g', 'e', '\022', '\031', '\n', '\010', 'a', 'c', 'c', 'u', '_', 'v', -'a', 'r', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\007', 'a', 'c', 'c', 'u', 'V', 'a', 'r', '\022', ';', '\n', '\t', 'a', 'c', 'c', 'u', -'_', 'i', 'n', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', -'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'a', 'c', 'c', 'u', 'I', -'n', 'i', 't', '\022', 'E', '\n', '\016', 'l', 'o', 'o', 'p', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', -'(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', -'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\r', 'l', 'o', 'o', 'p', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', -';', '\n', '\t', 'l', 'o', 'o', 'p', '_', 's', 't', 'e', 'p', '\030', '\006', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', -'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', -'R', '\010', 'l', 'o', 'o', 'p', 'S', 't', 'e', 'p', '\022', '6', '\n', '\006', 'r', 'e', 's', 'u', 'l', 't', '\030', '\007', ' ', '\001', '(', -'\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', -'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\006', 'r', 'e', 's', 'u', 'l', 't', 'B', '\013', '\n', '\t', 'e', 'x', 'p', 'r', '_', -'k', 'i', 'n', 'd', '\"', '\301', '\003', '\n', '\010', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', '\022', ';', '\n', '\n', 'n', 'u', 'l', 'l', -'_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\t', 'n', 'u', 'l', 'l', 'V', 'a', -'l', 'u', 'e', '\022', '\037', '\n', '\n', 'b', 'o', 'o', 'l', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\010', 'H', '\000', -'R', '\t', 'b', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', -'e', '\030', '\003', ' ', '\001', '(', '\003', 'H', '\000', 'R', '\n', 'i', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', -'u', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'H', '\000', 'R', '\013', 'u', 'i', 'n', -'t', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', -'\005', ' ', '\001', '(', '\001', 'H', '\000', 'R', '\013', 'd', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 's', -'t', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', -'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', 'b', 'y', 't', 'e', 's', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', -'\001', '(', '\014', 'H', '\000', 'R', '\n', 'b', 'y', 't', 'e', 's', 'V', 'a', 'l', 'u', 'e', '\022', 'F', '\n', '\016', 'd', 'u', 'r', 'a', -'t', 'i', 'o', 'n', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\002', '\030', '\001', 'H', '\000', 'R', -'\r', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'V', 'a', 'l', 'u', 'e', '\022', 'I', '\n', '\017', 't', 'i', 'm', 'e', 's', 't', 'a', -'m', 'p', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\t', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'B', '\002', '\030', '\001', 'H', '\000', 'R', '\016', -'t', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'V', 'a', 'l', 'u', 'e', 'B', '\017', '\n', '\r', 'c', 'o', 'n', 's', 't', 'a', 'n', -'t', '_', 'k', 'i', 'n', 'd', '\"', '\271', '\003', '\n', '\n', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\022', '%', '\n', '\016', -'s', 'y', 'n', 't', 'a', 'x', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\r', 's', 'y', 'n', -'t', 'a', 'x', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '\032', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', -'\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '!', '\n', '\014', 'l', 'i', 'n', 'e', '_', 'o', 'f', 'f', -'s', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\005', 'R', '\013', 'l', 'i', 'n', 'e', 'O', 'f', 'f', 's', 'e', 't', 's', '\022', 'Q', -'\n', '\t', 'p', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '3', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', -'e', 'I', 'n', 'f', 'o', '.', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', 'R', '\t', 'p', 'o', 's', -'i', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\013', 'm', 'a', 'c', 'r', 'o', '_', 'c', 'a', 'l', 'l', 's', '\030', '\005', ' ', '\003', -'(', '\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', -'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '.', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', -'s', 'E', 'n', 't', 'r', 'y', 'R', '\n', 'm', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', '\032', '<', '\n', '\016', 'P', 'o', 's', -'i', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', -'\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\005', 'v', 'a', 'l', 'u', -'e', ':', '\002', '8', '\001', '\032', ']', '\n', '\017', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', 'E', 'n', 't', 'r', 'y', '\022', -'\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', -'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', -'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', -'\"', 'p', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', '\022', '\032', '\n', '\010', 'l', 'o', 'c', -'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\006', -'o', 'f', 'f', 's', 'e', 't', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'o', 'f', 'f', 's', 'e', 't', '\022', '\022', '\n', '\004', 'l', -'i', 'n', 'e', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\004', 'l', 'i', 'n', 'e', '\022', '\026', '\n', '\006', 'c', 'o', 'l', 'u', 'm', 'n', -'\030', '\004', ' ', '\001', '(', '\005', 'R', '\006', 'c', 'o', 'l', 'u', 'm', 'n', 'B', 'n', '\n', '\034', 'c', 'o', 'm', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', '\013', 'S', 'y', -'n', 't', 'a', 'x', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', -'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', 'p', 'i', 's', -'/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', 'r', '\370', '\001', -'\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +'E', 'x', 'p', 'r', 'R', '\010', 'a', 'c', 'c', 'u', 'I', 'n', 'i', 't', '\022', 'E', '\n', '\016', 'l', 'o', 'o', 'p', '_', 'c', 'o', +'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\r', 'l', 'o', 'o', +'p', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', ';', '\n', '\t', 'l', 'o', 'o', 'p', '_', 's', 't', 'e', 'p', '\030', '\006', +' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'l', 'o', 'o', 'p', 'S', 't', 'e', 'p', '\022', '6', '\n', '\006', +'r', 'e', 's', 'u', 'l', 't', '\030', '\007', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\006', 'r', 'e', 's', 'u', +'l', 't', 'B', '\013', '\n', '\t', 'e', 'x', 'p', 'r', '_', 'k', 'i', 'n', 'd', '\"', '\301', '\003', '\n', '\010', 'C', 'o', 'n', 's', 't', +'a', 'n', 't', '\022', ';', '\n', '\n', 'n', 'u', 'l', 'l', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\032', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', +'e', 'H', '\000', 'R', '\t', 'n', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\n', 'b', 'o', 'o', 'l', '_', 'v', 'a', +'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\t', 'b', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', +'\013', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\003', 'H', '\000', 'R', '\n', 'i', 'n', 't', +'6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 'u', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', +' ', '\001', '(', '\004', 'H', '\000', 'R', '\013', 'u', 'i', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 'd', 'o', +'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\001', 'H', '\000', 'R', '\013', 'd', 'o', 'u', 'b', 'l', +'e', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', +'\001', '(', '\t', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', 'b', 'y', 't', +'e', 's', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'H', '\000', 'R', '\n', 'b', 'y', 't', 'e', 's', 'V', 'a', +'l', 'u', 'e', '\022', 'F', '\n', '\016', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\001', +'(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', +'t', 'i', 'o', 'n', 'B', '\002', '\030', '\001', 'H', '\000', 'R', '\r', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'V', 'a', 'l', 'u', 'e', +'\022', 'I', '\n', '\017', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\t', ' ', '\001', '(', '\013', +'2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', +'a', 'm', 'p', 'B', '\002', '\030', '\001', 'H', '\000', 'R', '\016', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'V', 'a', 'l', 'u', 'e', +'B', '\017', '\n', '\r', 'c', 'o', 'n', 's', 't', 'a', 'n', 't', '_', 'k', 'i', 'n', 'd', '\"', '\214', '\007', '\n', '\n', 'S', 'o', 'u', +'r', 'c', 'e', 'I', 'n', 'f', 'o', '\022', '%', '\n', '\016', 's', 'y', 'n', 't', 'a', 'x', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', +'\030', '\001', ' ', '\001', '(', '\t', 'R', '\r', 's', 'y', 'n', 't', 'a', 'x', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '\032', '\n', '\010', +'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', +'!', '\n', '\014', 'l', 'i', 'n', 'e', '_', 'o', 'f', 'f', 's', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\005', 'R', '\013', 'l', 'i', +'n', 'e', 'O', 'f', 'f', 's', 'e', 't', 's', '\022', 'Q', '\n', '\t', 'p', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', +'\003', '(', '\013', '2', '3', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', +'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '.', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', +'s', 'E', 'n', 't', 'r', 'y', 'R', '\t', 'p', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\013', 'm', 'a', 'c', 'r', +'o', '_', 'c', 'a', 'l', 'l', 's', '\030', '\005', ' ', '\003', '(', '\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', +'o', '.', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', 'E', 'n', 't', 'r', 'y', 'R', '\n', 'm', 'a', 'c', 'r', 'o', 'C', +'a', 'l', 'l', 's', '\022', 'N', '\n', '\n', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', +'.', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', '\n', 'e', +'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '\032', '\200', '\003', '\n', '\t', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '\016', +'\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\002', 'i', 'd', '\022', 'i', '\n', '\023', 'a', 'f', 'f', 'e', 'c', 't', 'e', +'d', '_', 'c', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '\030', '\002', ' ', '\003', '(', '\016', '2', '8', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', +'c', 'e', 'I', 'n', 'f', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '.', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', +'t', 'R', '\022', 'a', 'f', 'f', 'e', 'c', 't', 'e', 'd', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '\022', 'P', '\n', '\007', +'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', +'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '.', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'R', '\007', 'v', 'e', 'r', 's', +'i', 'o', 'n', '\032', '5', '\n', '\007', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '\024', '\n', '\005', 'm', 'a', 'j', 'o', 'r', '\030', '\001', +' ', '\001', '(', '\003', 'R', '\005', 'm', 'a', 'j', 'o', 'r', '\022', '\024', '\n', '\005', 'm', 'i', 'n', 'o', 'r', '\030', '\002', ' ', '\001', '(', +'\003', 'R', '\005', 'm', 'i', 'n', 'o', 'r', '\"', 'o', '\n', '\t', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', '\022', '\031', '\n', '\025', +'C', 'O', 'M', 'P', 'O', 'N', 'E', 'N', 'T', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\024', +'\n', '\020', 'C', 'O', 'M', 'P', 'O', 'N', 'E', 'N', 'T', '_', 'P', 'A', 'R', 'S', 'E', 'R', '\020', '\001', '\022', '\032', '\n', '\026', 'C', +'O', 'M', 'P', 'O', 'N', 'E', 'N', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'C', 'H', 'E', 'C', 'K', 'E', 'R', '\020', '\002', '\022', '\025', +'\n', '\021', 'C', 'O', 'M', 'P', 'O', 'N', 'E', 'N', 'T', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\003', '\032', '<', '\n', '\016', +'P', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', +'(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\005', 'v', +'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\032', ']', '\n', '\017', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', 'E', 'n', 't', +'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', '\005', 'v', +'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', +'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', +'\002', '8', '\001', '\"', 'p', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', '\022', '\032', '\n', '\010', +'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', +'\026', '\n', '\006', 'o', 'f', 'f', 's', 'e', 't', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'o', 'f', 'f', 's', 'e', 't', '\022', '\022', +'\n', '\004', 'l', 'i', 'n', 'e', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\004', 'l', 'i', 'n', 'e', '\022', '\026', '\n', '\006', 'c', 'o', 'l', +'u', 'm', 'n', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\006', 'c', 'o', 'l', 'u', 'm', 'n', 'B', 'n', '\n', '\034', 'c', 'o', 'm', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', +'\013', 'S', 'y', 'n', 't', 'a', 'x', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', +'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', +'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', +'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', }; static _upb_DefPool_Init *deps[4] = { @@ -148,5 +171,5 @@ _upb_DefPool_Init google_api_expr_v1alpha1_syntax_proto_upbdefinit = { deps, &google_api_expr_v1alpha1_syntax_proto_upb_file_layout, "google/api/expr/v1alpha1/syntax.proto", - UPB_STRINGVIEW_INIT(descriptor, 3059) + UPB_STRINGVIEW_INIT(descriptor, 3637) }; diff --git a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.h b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.h index f176e5ef52..f2c9ce3912 100644 --- a/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.h +++ b/src/core/ext/upbdefs-gen/google/api/expr/v1alpha1/syntax.upbdefs.h @@ -73,6 +73,16 @@ UPB_INLINE const upb_MessageDef *google_api_expr_v1alpha1_SourceInfo_getmsgdef(u return upb_DefPool_FindMessageByName(s, "google.api.expr.v1alpha1.SourceInfo"); } +UPB_INLINE const upb_MessageDef *google_api_expr_v1alpha1_SourceInfo_Extension_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.api.expr.v1alpha1.SourceInfo.Extension"); +} + +UPB_INLINE const upb_MessageDef *google_api_expr_v1alpha1_SourceInfo_Extension_Version_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.api.expr.v1alpha1.SourceInfo.Extension.Version"); +} + UPB_INLINE const upb_MessageDef *google_api_expr_v1alpha1_SourceInfo_PositionsEntry_getmsgdef(upb_DefPool *s) { _upb_DefPool_LoadDefInit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); return upb_DefPool_FindMessageByName(s, "google.api.expr.v1alpha1.SourceInfo.PositionsEntry"); diff --git a/src/core/lib/backoff/backoff.cc b/src/core/lib/backoff/backoff.cc index b0d6a9fa1f..b4a520d13d 100644 --- a/src/core/lib/backoff/backoff.cc +++ b/src/core/lib/backoff/backoff.cc @@ -20,23 +20,20 @@ #include -#include - namespace grpc_core { BackOff::BackOff(const Options& options) : options_(options) { Reset(); } -Timestamp BackOff::NextAttemptTime() { +Duration BackOff::NextAttemptDelay() { if (initial_) { initial_ = false; - return current_backoff_ + Timestamp::Now(); + } else { + current_backoff_ = std::min(current_backoff_ * options_.multiplier(), + options_.max_backoff()); } - current_backoff_ = std::min(current_backoff_ * options_.multiplier(), - options_.max_backoff()); - const Duration jitter = Duration::FromSecondsAsDouble( - absl::Uniform(rand_gen_, -options_.jitter() * current_backoff_.seconds(), - options_.jitter() * current_backoff_.seconds())); - return Timestamp::Now() + current_backoff_ + jitter; + const double jitter = + absl::Uniform(rand_gen_, 1 - options_.jitter(), 1 + options_.jitter()); + return current_backoff_ * jitter; } void BackOff::Reset() { diff --git a/src/core/lib/backoff/backoff.h b/src/core/lib/backoff/backoff.h index 003335b6b7..75e87d3d44 100644 --- a/src/core/lib/backoff/backoff.h +++ b/src/core/lib/backoff/backoff.h @@ -21,8 +21,6 @@ #include "absl/random/random.h" -#include - #include "src/core/lib/gprpp/time.h" namespace grpc_core { @@ -36,11 +34,11 @@ class BackOff { /// Initialize backoff machinery - does not need to be destroyed explicit BackOff(const Options& options); - /// Returns the time at which the next attempt should start. - Timestamp NextAttemptTime(); + /// Returns the delay before the next attempt should start. + Duration NextAttemptDelay(); - /// Reset the backoff, so the next value returned by NextAttemptTime() - /// will be the time of the second attempt (rather than the Nth). + /// Reset the backoff, so the next value returned by NextAttemptDelay() + /// will be the delay for the second attempt (rather than the Nth). void Reset(); class Options { diff --git a/src/core/lib/event_engine/posix_engine/posix_endpoint.cc b/src/core/lib/event_engine/posix_engine/posix_endpoint.cc index 7634bb1334..c5708db02c 100644 --- a/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +++ b/src/core/lib/event_engine/posix_engine/posix_endpoint.cc @@ -236,7 +236,7 @@ msg_iovlen_type TcpZerocopySendRecord::PopulateIovs(size_t* unwind_slice_idx, iov_size++) { MutableSlice& slice = internal::SliceCast( buf_.MutableSliceAt(out_offset_.slice_idx)); - iov[iov_size].iov_base = slice.begin(); + iov[iov_size].iov_base = slice.begin() + out_offset_.byte_idx; iov[iov_size].iov_len = slice.length() - out_offset_.byte_idx; *sending_length += iov[iov_size].iov_len; ++(out_offset_.slice_idx); diff --git a/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc b/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc index 57c664f67b..dcb0aabaf7 100644 --- a/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +++ b/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc @@ -400,9 +400,7 @@ void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard:: if (pool_->IsQuiesced()) break; } else { lifeguard_should_shut_down_->WaitForNotificationWithTimeout( - absl::Milliseconds( - (backoff_.NextAttemptTime() - grpc_core::Timestamp::Now()) - .millis())); + absl::Milliseconds(backoff_.NextAttemptDelay().millis())); } MaybeStartNewThread(); } @@ -556,8 +554,8 @@ bool WorkStealingThreadPool::ThreadState::Step() { // No closures were retrieved from anywhere. // Quit the thread if the pool has been shut down. if (pool_->IsShutdown()) break; - bool timed_out = pool_->work_signal()->WaitWithTimeout( - backoff_.NextAttemptTime() - grpc_core::Timestamp::Now()); + bool timed_out = + pool_->work_signal()->WaitWithTimeout(backoff_.NextAttemptDelay()); if (pool_->IsForking() || pool_->IsShutdown()) break; // Quit a thread if the pool has more than it requires, and this thread // has been idle long enough. diff --git a/src/core/lib/experiments/config.cc b/src/core/lib/experiments/config.cc index ac1cf88386..5248321879 100644 --- a/src/core/lib/experiments/config.cc +++ b/src/core/lib/experiments/config.cc @@ -220,9 +220,6 @@ bool IsTestExperimentEnabled(size_t experiment_id) { return (*g_test_experiments)[experiment_id]; } -// This is VLOG(2) for Open Source gRPC because of a lot of log noise -// complaints. However, internally we want LOG(INFO) so that it is easier for us -// to debug prod issues. #define GRPC_EXPERIMENT_LOG VLOG(2) void PrintExperimentsList() { diff --git a/src/core/lib/experiments/experiments.cc b/src/core/lib/experiments/experiments.cc index 8a8b5a445e..96a2c73430 100644 --- a/src/core/lib/experiments/experiments.cc +++ b/src/core/lib/experiments/experiments.cc @@ -79,6 +79,10 @@ const char* const additional_constraints_tcp_frame_size_tuning = "{}"; const char* const description_tcp_rcv_lowat = "Use SO_RCVLOWAT to avoid wakeups on the read path."; const char* const additional_constraints_tcp_rcv_lowat = "{}"; +const char* const description_time_caching_in_party = + "Disable time caching in exec_ctx, and enable it only in a single party " + "execution."; +const char* const additional_constraints_time_caching_in_party = "{}"; const char* const description_trace_record_callops = "Enables tracing of call batch initiation and completion."; const char* const additional_constraints_trace_record_callops = "{}"; @@ -141,6 +145,8 @@ const ExperimentMetadata g_experiment_metadata[] = { additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true}, {"tcp_rcv_lowat", description_tcp_rcv_lowat, additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true}, + {"time_caching_in_party", description_time_caching_in_party, + additional_constraints_time_caching_in_party, nullptr, 0, true, true}, {"trace_record_callops", description_trace_record_callops, additional_constraints_trace_record_callops, nullptr, 0, true, true}, {"unconstrained_max_quota_buffer_size", @@ -216,6 +222,10 @@ const char* const additional_constraints_tcp_frame_size_tuning = "{}"; const char* const description_tcp_rcv_lowat = "Use SO_RCVLOWAT to avoid wakeups on the read path."; const char* const additional_constraints_tcp_rcv_lowat = "{}"; +const char* const description_time_caching_in_party = + "Disable time caching in exec_ctx, and enable it only in a single party " + "execution."; +const char* const additional_constraints_time_caching_in_party = "{}"; const char* const description_trace_record_callops = "Enables tracing of call batch initiation and completion."; const char* const additional_constraints_trace_record_callops = "{}"; @@ -278,6 +288,8 @@ const ExperimentMetadata g_experiment_metadata[] = { additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true}, {"tcp_rcv_lowat", description_tcp_rcv_lowat, additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true}, + {"time_caching_in_party", description_time_caching_in_party, + additional_constraints_time_caching_in_party, nullptr, 0, true, true}, {"trace_record_callops", description_trace_record_callops, additional_constraints_trace_record_callops, nullptr, 0, true, true}, {"unconstrained_max_quota_buffer_size", @@ -353,6 +365,10 @@ const char* const additional_constraints_tcp_frame_size_tuning = "{}"; const char* const description_tcp_rcv_lowat = "Use SO_RCVLOWAT to avoid wakeups on the read path."; const char* const additional_constraints_tcp_rcv_lowat = "{}"; +const char* const description_time_caching_in_party = + "Disable time caching in exec_ctx, and enable it only in a single party " + "execution."; +const char* const additional_constraints_time_caching_in_party = "{}"; const char* const description_trace_record_callops = "Enables tracing of call batch initiation and completion."; const char* const additional_constraints_trace_record_callops = "{}"; @@ -415,6 +431,8 @@ const ExperimentMetadata g_experiment_metadata[] = { additional_constraints_tcp_frame_size_tuning, nullptr, 0, false, true}, {"tcp_rcv_lowat", description_tcp_rcv_lowat, additional_constraints_tcp_rcv_lowat, nullptr, 0, false, true}, + {"time_caching_in_party", description_time_caching_in_party, + additional_constraints_time_caching_in_party, nullptr, 0, true, true}, {"trace_record_callops", description_trace_record_callops, additional_constraints_trace_record_callops, nullptr, 0, true, true}, {"unconstrained_max_quota_buffer_size", diff --git a/src/core/lib/experiments/experiments.h b/src/core/lib/experiments/experiments.h index 0b44aca703..b6fb4257c5 100644 --- a/src/core/lib/experiments/experiments.h +++ b/src/core/lib/experiments/experiments.h @@ -78,6 +78,8 @@ inline bool IsScheduleCancellationOverWriteEnabled() { return false; } inline bool IsServerPrivacyEnabled() { return false; } inline bool IsTcpFrameSizeTuningEnabled() { return false; } inline bool IsTcpRcvLowatEnabled() { return false; } +#define GRPC_EXPERIMENT_IS_INCLUDED_TIME_CACHING_IN_PARTY +inline bool IsTimeCachingInPartyEnabled() { return true; } #define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS inline bool IsTraceRecordCallopsEnabled() { return true; } inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } @@ -110,6 +112,8 @@ inline bool IsScheduleCancellationOverWriteEnabled() { return false; } inline bool IsServerPrivacyEnabled() { return false; } inline bool IsTcpFrameSizeTuningEnabled() { return false; } inline bool IsTcpRcvLowatEnabled() { return false; } +#define GRPC_EXPERIMENT_IS_INCLUDED_TIME_CACHING_IN_PARTY +inline bool IsTimeCachingInPartyEnabled() { return true; } #define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS inline bool IsTraceRecordCallopsEnabled() { return true; } inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } @@ -141,6 +145,8 @@ inline bool IsScheduleCancellationOverWriteEnabled() { return false; } inline bool IsServerPrivacyEnabled() { return false; } inline bool IsTcpFrameSizeTuningEnabled() { return false; } inline bool IsTcpRcvLowatEnabled() { return false; } +#define GRPC_EXPERIMENT_IS_INCLUDED_TIME_CACHING_IN_PARTY +inline bool IsTimeCachingInPartyEnabled() { return true; } #define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS inline bool IsTraceRecordCallopsEnabled() { return true; } inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; } @@ -168,6 +174,7 @@ enum ExperimentIds { kExperimentIdServerPrivacy, kExperimentIdTcpFrameSizeTuning, kExperimentIdTcpRcvLowat, + kExperimentIdTimeCachingInParty, kExperimentIdTraceRecordCallops, kExperimentIdUnconstrainedMaxQuotaBufferSize, kExperimentIdWorkSerializerClearsTimeCache, @@ -242,6 +249,10 @@ inline bool IsTcpFrameSizeTuningEnabled() { inline bool IsTcpRcvLowatEnabled() { return IsExperimentEnabled(); } +#define GRPC_EXPERIMENT_IS_INCLUDED_TIME_CACHING_IN_PARTY +inline bool IsTimeCachingInPartyEnabled() { + return IsExperimentEnabled(); +} #define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS inline bool IsTraceRecordCallopsEnabled() { return IsExperimentEnabled(); diff --git a/src/core/lib/gprpp/time.h b/src/core/lib/gprpp/time.h index 0e57349b78..8f1c65cfa3 100644 --- a/src/core/lib/gprpp/time.h +++ b/src/core/lib/gprpp/time.h @@ -296,6 +296,14 @@ class Duration { int64_t millis_; }; +inline std::ostream& operator<<(std::ostream& out, const Duration& d) { + return out << d.ToString(); +} + +inline std::ostream& operator<<(std::ostream& out, const Timestamp& d) { + return out << d.ToString(); +} + inline Duration operator+(Duration lhs, Duration rhs) { return Duration::Milliseconds( time_detail::MillisAdd(lhs.millis(), rhs.millis())); diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index ce41e5b92b..bcdb1a743d 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -35,6 +35,7 @@ #include #include +#include "src/core/lib/experiments/experiments.h" #include "src/core/lib/gprpp/crash.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/fork.h" @@ -116,6 +117,11 @@ class GRPC_DLL ExecCtx : public latent_see::ParentScope { ExecCtx() : latent_see::ParentScope(GRPC_LATENT_SEE_METADATA("ExecCtx")), flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { +#if !TARGET_OS_IPHONE + if (!IsTimeCachingInPartyEnabled()) { + time_cache_.emplace(); + } +#endif Fork::IncExecCtxCount(); Set(this); } @@ -126,6 +132,11 @@ class GRPC_DLL ExecCtx : public latent_see::ParentScope { explicit ExecCtx(uintptr_t fl, latent_see::Metadata* latent_see_metadata) : latent_see::ParentScope(latent_see_metadata), flags_(fl) { +#if !TARGET_OS_IPHONE + if (!IsTimeCachingInPartyEnabled()) { + time_cache_.emplace(); + } +#endif if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) { Fork::IncExecCtxCount(); } @@ -195,23 +206,18 @@ class GRPC_DLL ExecCtx : public latent_see::ParentScope { Timestamp Now() { return Timestamp::Now(); } void InvalidateNow() { -#if !TARGET_OS_IPHONE - time_cache_.InvalidateCache(); -#endif + if (time_cache_.has_value()) time_cache_->InvalidateCache(); } void SetNowIomgrShutdown() { -#if !TARGET_OS_IPHONE // We get to do a test only set now on this path just because iomgr // is getting removed and no point adding more interfaces for it. - time_cache_.TestOnlySetNow(Timestamp::InfFuture()); -#endif + TestOnlySetNow(Timestamp::InfFuture()); } void TestOnlySetNow(Timestamp now) { -#if !TARGET_OS_IPHONE - time_cache_.TestOnlySetNow(now); -#endif + if (!time_cache_.has_value()) time_cache_.emplace(); + time_cache_->TestOnlySetNow(now); } /// Gets pointer to current exec_ctx. @@ -237,9 +243,7 @@ class GRPC_DLL ExecCtx : public latent_see::ParentScope { CombinerData combiner_data_ = {nullptr, nullptr}; uintptr_t flags_; -#if !TARGET_OS_IPHONE - ScopedTimeCache time_cache_; -#endif + absl::optional time_cache_; #if !defined(_WIN32) || !defined(_DLL) static thread_local ExecCtx* exec_ctx_; diff --git a/src/core/lib/promise/party.cc b/src/core/lib/promise/party.cc index c8bde2d198..1fbc01fd3d 100644 --- a/src/core/lib/promise/party.cc +++ b/src/core/lib/promise/party.cc @@ -41,18 +41,18 @@ namespace grpc_core { // PartySyncUsingAtomics GRPC_MUST_USE_RESULT bool Party::RefIfNonZero() { - auto count = state_.load(std::memory_order_relaxed); + auto state = state_.load(std::memory_order_relaxed); do { // If zero, we are done (without an increment). If not, we must do a CAS // to maintain the contract: do not increment the counter if it is already // zero - if (count == 0) { + if ((state & kRefMask) == 0) { return false; } - } while (!state_.compare_exchange_weak(count, count + kOneRef, + } while (!state_.compare_exchange_weak(state, state + kOneRef, std::memory_order_acq_rel, std::memory_order_relaxed)); - LogStateChange("RefIfNonZero", count, count + kOneRef); + LogStateChange("RefIfNonZero", state, state + kOneRef); return true; } @@ -269,6 +269,12 @@ void Party::RunPartyAndUnref(uint64_t prev_state) { DCHECK_EQ(prev_state & ~(kRefMask | kAllocatedMask), 0u) << "Party should have contained no wakeups on lock"; prev_state |= kLocked; + absl::optional time_cache; +#if !TARGET_OS_IPHONE + if (IsTimeCachingInPartyEnabled()) { + time_cache.emplace(); + } +#endif for (;;) { uint64_t keep_allocated_mask = kAllocatedMask; // For each wakeup bit... diff --git a/src/core/lib/resource_quota/periodic_update.cc b/src/core/lib/resource_quota/periodic_update.cc index b4874fea1d..b7f9e9b9c0 100644 --- a/src/core/lib/resource_quota/periodic_update.cc +++ b/src/core/lib/resource_quota/periodic_update.cc @@ -68,8 +68,8 @@ bool PeriodicUpdate::MaybeEndPeriod(absl::FunctionRef f) { expected_updates_per_period_ = period_.seconds() * expected_updates_per_period_ / time_so_far.seconds(); if (expected_updates_per_period_ < 1) expected_updates_per_period_ = 1; - period_start_ = now; f(time_so_far); + period_start_ = Timestamp::Now(); updates_remaining_.store(expected_updates_per_period_, std::memory_order_release); return true; diff --git a/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.cc b/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.cc new file mode 100644 index 0000000000..11aa4e158d --- /dev/null +++ b/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.cc @@ -0,0 +1,196 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h" + +#include "absl/functional/any_invocable.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" + +#include + +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/status_conversion.h" +#include "src/core/lib/uri/uri_parser.h" +#include "src/core/util/json/json.h" +#include "src/core/util/json/json_args.h" +#include "src/core/util/json/json_object_loader.h" +#include "src/core/util/json/json_reader.h" + +namespace grpc_core { + +// +// JwtTokenFetcherCallCredentials +// + +// State held for a pending HTTP request. +class JwtTokenFetcherCallCredentials::HttpFetchRequest final + : public TokenFetcherCredentials::FetchRequest { + public: + HttpFetchRequest( + JwtTokenFetcherCallCredentials* creds, Timestamp deadline, + absl::AnyInvocable< + void(absl::StatusOr>)> + on_done) + : on_done_(std::move(on_done)) { + GRPC_CLOSURE_INIT(&on_http_response_, OnHttpResponse, this, nullptr); + Ref().release(); // Ref held by HTTP request callback. + http_request_ = creds->StartHttpRequest(creds->pollent(), deadline, + &response_, &on_http_response_); + } + + ~HttpFetchRequest() override { grpc_http_response_destroy(&response_); } + + void Orphan() override { + http_request_.reset(); + Unref(); + } + + private: + static void OnHttpResponse(void* arg, grpc_error_handle error) { + RefCountedPtr self(static_cast(arg)); + if (!error.ok()) { + // TODO(roth): It shouldn't be necessary to explicitly set the + // status to UNAVAILABLE here. Once the HTTP client code is + // migrated to stop using legacy grpc_error APIs to create + // statuses, we should be able to just propagate the status as-is. + self->on_done_(absl::UnavailableError(StatusToString(error))); + return; + } + if (self->response_.status != 200) { + grpc_status_code status_code = + grpc_http2_status_to_grpc_status(self->response_.status); + if (status_code != GRPC_STATUS_UNAVAILABLE) { + status_code = GRPC_STATUS_UNAUTHENTICATED; + } + self->on_done_(absl::Status(static_cast(status_code), + absl::StrCat("JWT fetch failed with status ", + self->response_.status))); + return; + } + absl::string_view body(self->response_.body, self->response_.body_length); + // Parse JWT token based on https://datatracker.ietf.org/doc/html/rfc7519. + // We don't do full verification here, just enough to extract the + // expiration time. + // First, split the 3 '.'-delimited parts. + std::vector parts = absl::StrSplit(body, '.'); + if (parts.size() != 3) { + self->on_done_(absl::UnauthenticatedError("error parsing JWT token")); + return; + } + // Base64-decode the payload. + std::string payload; + if (!absl::WebSafeBase64Unescape(parts[1], &payload)) { + self->on_done_(absl::UnauthenticatedError("error parsing JWT token")); + return; + } + // Parse as JSON. + auto json = JsonParse(payload); + if (!json.ok()) { + self->on_done_(absl::UnauthenticatedError("error parsing JWT token")); + return; + } + // Extract "exp" field. + struct ParsedPayload { + uint64_t exp = 0; + + static const JsonLoaderInterface* JsonLoader(const JsonArgs&) { + static const auto kJsonLoader = JsonObjectLoader() + .Field("exp", &ParsedPayload::exp) + .Finish(); + return kJsonLoader; + } + }; + auto parsed_payload = LoadFromJson(*json, JsonArgs(), ""); + if (!parsed_payload.ok()) { + self->on_done_(absl::UnauthenticatedError("error parsing JWT token")); + return; + } + gpr_timespec ts = gpr_time_0(GPR_CLOCK_REALTIME); + ts.tv_sec = parsed_payload->exp; + Timestamp expiration_time = Timestamp::FromTimespecRoundDown(ts); + // Return token object. + self->on_done_(MakeRefCounted( + Slice::FromCopiedString(absl::StrCat("Bearer ", body)), + expiration_time)); + } + + OrphanablePtr http_request_; + grpc_closure on_http_response_; + grpc_http_response response_; + absl::AnyInvocable>)> + on_done_; +}; + +OrphanablePtr +JwtTokenFetcherCallCredentials::FetchToken( + Timestamp deadline, + absl::AnyInvocable< + void(absl::StatusOr>)> + on_done) { + return MakeOrphanable(this, deadline, std::move(on_done)); +} + +// +// GcpServiceAccountIdentityCallCredentials +// + +std::string GcpServiceAccountIdentityCallCredentials::debug_string() { + return absl::StrCat("GcpServiceAccountIdentityCallCredentials(", audience_, + ")"); +} + +UniqueTypeName GcpServiceAccountIdentityCallCredentials::Type() { + static UniqueTypeName::Factory kFactory("GcpServiceAccountIdentity"); + return kFactory.Create(); +} + +OrphanablePtr +GcpServiceAccountIdentityCallCredentials::StartHttpRequest( + grpc_polling_entity* pollent, Timestamp deadline, + grpc_http_response* response, grpc_closure* on_complete) { + grpc_http_header header = {const_cast("Metadata-Flavor"), + const_cast("Google")}; + grpc_http_request request; + memset(&request, 0, sizeof(grpc_http_request)); + request.hdr_count = 1; + request.hdrs = &header; + // TODO(ctiller): Carry the memory quota in ctx and share it with the host + // channel. This would allow us to cancel an authentication query when under + // extreme memory pressure. + auto uri = URI::Create( + "http", "metadata.google.internal.", + "/computeMetadata/v1/instance/service-accounts/default/identity", + {{"audience", audience_}}, /*fragment=*/""); + CHECK_OK(uri); // params are hardcoded + auto http_request = + HttpRequest::Get(std::move(*uri), /*args=*/nullptr, pollent, &request, + deadline, on_complete, response, + RefCountedPtr( + grpc_insecure_credentials_create())); + http_request->Start(); + return http_request; +} + +} // namespace grpc_core diff --git a/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h b/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h new file mode 100644 index 0000000000..231e9bbccc --- /dev/null +++ b/src/core/lib/security/credentials/gcp_service_account_identity/gcp_service_account_identity_credentials.h @@ -0,0 +1,90 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_GCP_SERVICE_ACCOUNT_IDENTITY_GCP_SERVICE_ACCOUNT_IDENTITY_CREDENTIALS_H +#define GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_GCP_SERVICE_ACCOUNT_IDENTITY_GCP_SERVICE_ACCOUNT_IDENTITY_CREDENTIALS_H + +#include +#include + +#include +#include + +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/gprpp/unique_type_name.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/token_fetcher/token_fetcher_credentials.h" +#include "src/core/lib/slice/slice.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/util/http_client/httpcli.h" +#include "src/core/util/http_client/parser.h" + +namespace grpc_core { + +// A base class for JWT token fetching credentials. +// Subclasses must implement StartHttpRequest(). +class JwtTokenFetcherCallCredentials : public TokenFetcherCredentials { + public: + OrphanablePtr FetchToken( + Timestamp deadline, + absl::AnyInvocable< + void(absl::StatusOr>)> + on_done) final; + + private: + class HttpFetchRequest; + + virtual OrphanablePtr StartHttpRequest( + grpc_polling_entity* pollent, Timestamp deadline, + grpc_http_response* response, grpc_closure* on_complete) = 0; +}; + +// GCP service account identity call credentials. +// See gRFC A83 (https://github.com/grpc/proposal/pull/438). +class GcpServiceAccountIdentityCallCredentials + : public JwtTokenFetcherCallCredentials { + public: + explicit GcpServiceAccountIdentityCallCredentials(absl::string_view audience) + : audience_(audience) {} + + std::string debug_string() override; + + static UniqueTypeName Type(); + + UniqueTypeName type() const override { return Type(); } + + absl::string_view audience() const { return audience_; } + + private: + OrphanablePtr StartHttpRequest( + grpc_polling_entity* pollent, Timestamp deadline, + grpc_http_response* response, grpc_closure* on_complete) override; + + int cmp_impl(const grpc_call_credentials* other) const override { + // TODO(yashykt): Check if we can do something better here + return QsortCompare(static_cast(this), other); + } + + std::string audience_; +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_GCP_SERVICE_ACCOUNT_IDENTITY_GCP_SERVICE_ACCOUNT_IDENTITY_CREDENTIALS_H diff --git a/src/core/lib/security/credentials/token_fetcher/token_fetcher_credentials.cc b/src/core/lib/security/credentials/token_fetcher/token_fetcher_credentials.cc index 596641f0ff..2e9b35c551 100644 --- a/src/core/lib/security/credentials/token_fetcher/token_fetcher_credentials.cc +++ b/src/core/lib/security/credentials/token_fetcher/token_fetcher_credentials.cc @@ -60,15 +60,13 @@ void TokenFetcherCredentials::Token::AddTokenToClientInitialMetadata( TokenFetcherCredentials::FetchState::BackoffTimer::BackoffTimer( RefCountedPtr fetch_state) : fetch_state_(std::move(fetch_state)) { - const Timestamp next_attempt_time = fetch_state_->backoff_.NextAttemptTime(); - const Duration duration = next_attempt_time - Timestamp::Now(); + const Duration delay = fetch_state_->backoff_.NextAttemptDelay(); GRPC_TRACE_LOG(token_fetcher_credentials, INFO) << "[TokenFetcherCredentials " << fetch_state_->creds_.get() << "]: fetch_state=" << fetch_state_.get() << " backoff_timer=" << this - << ": starting backoff timer for " << next_attempt_time << " (" - << duration << " from now)"; + << ": starting backoff timer for " << delay; timer_handle_ = fetch_state_->creds_->event_engine().RunAfter( - duration, [self = Ref()]() mutable { + delay, [self = Ref()]() mutable { ApplicationCallbackExecCtx callback_exec_ctx; ExecCtx exec_ctx; self->OnTimer(); diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index a347400b98..daa6bacde9 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -22,6 +22,6 @@ #include #include -const char* grpc_version_string(void) { return "43.0.0"; } +const char* grpc_version_string(void) { return "44.0.0"; } -const char* grpc_g_stands_for(void) { return "gesundheit"; } +const char* grpc_g_stands_for(void) { return "groovy"; } diff --git a/src/core/load_balancing/grpclb/grpclb.cc b/src/core/load_balancing/grpclb/grpclb.cc index d91812d959..e71ba9913a 100644 --- a/src/core/load_balancing/grpclb/grpclb.cc +++ b/src/core/load_balancing/grpclb/grpclb.cc @@ -1655,12 +1655,12 @@ void GrpcLb::StartBalancerCallLocked() { } void GrpcLb::StartBalancerCallRetryTimerLocked() { - Duration timeout = lb_call_backoff_.NextAttemptTime() - Timestamp::Now(); + Duration delay = lb_call_backoff_.NextAttemptDelay(); if (GRPC_TRACE_FLAG_ENABLED(glb)) { LOG(INFO) << "[grpclb " << this << "] Connection to LB server lost..."; - if (timeout > Duration::Zero()) { + if (delay > Duration::Zero()) { LOG(INFO) << "[grpclb " << this << "] ... retry_timer_active in " - << timeout.millis() << "ms."; + << delay.millis() << "ms."; } else { LOG(INFO) << "[grpclb " << this << "] ... retry_timer_active immediately."; @@ -1668,7 +1668,7 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() { } lb_call_retry_timer_handle_ = channel_control_helper()->GetEventEngine()->RunAfter( - timeout, + delay, [self = RefAsSubclass( DEBUG_LOCATION, "on_balancer_call_retry_timer")]() mutable { ApplicationCallbackExecCtx callback_exec_ctx; diff --git a/src/core/load_balancing/rls/rls.cc b/src/core/load_balancing/rls/rls.cc index 9138d94e97..0318bd6740 100644 --- a/src/core/load_balancing/rls/rls.cc +++ b/src/core/load_balancing/rls/rls.cc @@ -526,7 +526,7 @@ class RlsLb final : public LoadBalancingPolicy { private: class BackoffTimer final : public InternallyRefCounted { public: - BackoffTimer(RefCountedPtr entry, Timestamp backoff_time); + BackoffTimer(RefCountedPtr entry, Duration delay); // Note: We are forced to disable lock analysis here because // Orphan() is called by OrphanablePtr<>, which cannot have lock @@ -1138,12 +1138,11 @@ LoadBalancingPolicy::PickResult RlsLb::Picker::PickFromDefaultTargetOrFail( // RlsLb::Cache::Entry::BackoffTimer::BackoffTimer(RefCountedPtr entry, - Timestamp backoff_time) + Duration delay) : entry_(std::move(entry)) { backoff_timer_task_handle_ = entry_->lb_policy_->channel_control_helper()->GetEventEngine()->RunAfter( - backoff_time - Timestamp::Now(), - [self = Ref(DEBUG_LOCATION, "BackoffTimer")]() mutable { + delay, [self = Ref(DEBUG_LOCATION, "BackoffTimer")]() mutable { ApplicationCallbackExecCtx callback_exec_ctx; ExecCtx exec_ctx; auto self_ptr = self.get(); @@ -1311,11 +1310,12 @@ RlsLb::Cache::Entry::OnRlsResponseLocked( } else { backoff_state_ = MakeCacheEntryBackoff(); } - backoff_time_ = backoff_state_->NextAttemptTime(); - Timestamp now = Timestamp::Now(); - backoff_expiration_time_ = now + (backoff_time_ - now) * 2; + const Duration delay = backoff_state_->NextAttemptDelay(); + const Timestamp now = Timestamp::Now(); + backoff_time_ = now + delay; + backoff_expiration_time_ = now + delay * 2; backoff_timer_ = MakeOrphanable( - Ref(DEBUG_LOCATION, "BackoffTimer"), backoff_time_); + Ref(DEBUG_LOCATION, "BackoffTimer"), delay); lb_policy_->UpdatePickerAsync(); return {}; } diff --git a/src/core/plugin_registry/grpc_plugin_registry_extra.cc b/src/core/plugin_registry/grpc_plugin_registry_extra.cc index a6013c2496..5b9dde4cf1 100644 --- a/src/core/plugin_registry/grpc_plugin_registry_extra.cc +++ b/src/core/plugin_registry/grpc_plugin_registry_extra.cc @@ -23,6 +23,8 @@ namespace grpc_core { #ifndef GRPC_NO_XDS extern void RbacFilterRegister(CoreConfiguration::Builder* builder); extern void StatefulSessionFilterRegister(CoreConfiguration::Builder* builder); +extern void GcpAuthenticationFilterRegister( + CoreConfiguration::Builder* builder); extern void RegisterXdsChannelStackModifier( CoreConfiguration::Builder* builder); extern void RegisterChannelDefaultCreds(CoreConfiguration::Builder* builder); @@ -47,6 +49,7 @@ void RegisterExtraFilters(CoreConfiguration::Builder* builder) { // re2 library by default RbacFilterRegister(builder); StatefulSessionFilterRegister(builder); + GcpAuthenticationFilterRegister(builder); RegisterXdsChannelStackModifier(builder); RegisterChannelDefaultCreds(builder); RegisterXdsResolver(builder); diff --git a/src/core/resolver/polling_resolver.cc b/src/core/resolver/polling_resolver.cc index e81b7c98dc..ec1af27059 100644 --- a/src/core/resolver/polling_resolver.cc +++ b/src/core/resolver/polling_resolver.cc @@ -104,10 +104,10 @@ void PollingResolver::ShutdownLocked() { request_.reset(); } -void PollingResolver::ScheduleNextResolutionTimer(const Duration& timeout) { +void PollingResolver::ScheduleNextResolutionTimer(Duration delay) { next_resolution_timer_handle_ = channel_args_.GetObject()->RunAfter( - timeout, [self = RefAsSubclass()]() mutable { + delay, [self = RefAsSubclass()]() mutable { ApplicationCallbackExecCtx callback_exec_ctx; ExecCtx exec_ctx; auto* self_ptr = self.get(); @@ -198,22 +198,13 @@ void PollingResolver::GetResultStatus(absl::Status status) { } } else { // Set up for retry. - // InvalidateNow to avoid getting stuck re-initializing this timer - // in a loop while draining the currently-held WorkSerializer. - // Also see https://github.com/grpc/grpc/issues/26079. - ExecCtx::Get()->InvalidateNow(); - const Timestamp next_try = backoff_.NextAttemptTime(); - const Duration timeout = next_try - Timestamp::Now(); + const Duration delay = backoff_.NextAttemptDelay(); CHECK(!next_resolution_timer_handle_.has_value()); if (GPR_UNLIKELY(tracer_ != nullptr && tracer_->enabled())) { - if (timeout > Duration::Zero()) { - LOG(INFO) << "[polling resolver " << this << "] retrying in " - << timeout.millis() << " ms"; - } else { - LOG(INFO) << "[polling resolver " << this << "] retrying immediately"; - } + LOG(INFO) << "[polling resolver " << this << "] retrying in " + << delay.millis() << " ms"; } - ScheduleNextResolutionTimer(timeout); + ScheduleNextResolutionTimer(delay); // Reset result_status_state_. Note that even if re-resolution was // requested while the result-health callback was pending, we can // ignore it here, because we are in backoff to re-resolve anyway. diff --git a/src/core/resolver/polling_resolver.h b/src/core/resolver/polling_resolver.h index e37c04722c..53b0270ec0 100644 --- a/src/core/resolver/polling_resolver.h +++ b/src/core/resolver/polling_resolver.h @@ -77,7 +77,7 @@ class PollingResolver : public Resolver { void OnRequestCompleteLocked(Result result); void GetResultStatus(absl::Status status); - void ScheduleNextResolutionTimer(const Duration& timeout); + void ScheduleNextResolutionTimer(Duration delay); void OnNextResolutionLocked(); void MaybeCancelNextResolutionTimer(); diff --git a/src/core/resolver/xds/xds_resolver.cc b/src/core/resolver/xds/xds_resolver.cc index 9cb4909853..9013474cca 100644 --- a/src/core/resolver/xds/xds_resolver.cc +++ b/src/core/resolver/xds/xds_resolver.cc @@ -510,7 +510,7 @@ XdsResolver::RouteConfigData::CreateMethodConfig( // Handle xDS HTTP filters. const auto& hcm = absl::get( resolver->current_config_->listener->listener); - auto result = XdsRouting::GeneratePerHTTPFilterConfigs( + auto result = XdsRouting::GeneratePerHTTPFilterConfigsForMethodConfig( static_cast(resolver->xds_client_->bootstrap()) .http_filter_registry(), hcm.http_filters, *resolver->current_config_->virtual_host, route, @@ -1041,18 +1041,27 @@ XdsResolver::CreateServiceConfig() { } std::vector config_parts; config_parts.push_back( - "{\n" - " \"loadBalancingConfig\":[\n" - " { \"xds_cluster_manager_experimental\":{\n" - " \"children\":{\n"); - config_parts.push_back(absl::StrJoin(clusters, ",\n")); - config_parts.push_back( - " }\n" - " } }\n" - " ]\n" - "}"); - std::string json = absl::StrJoin(config_parts, ""); - return ServiceConfigImpl::Create(args_, json.c_str()); + absl::StrCat(" \"loadBalancingConfig\":[\n" + " { \"xds_cluster_manager_experimental\":{\n" + " \"children\":{\n", + absl::StrJoin(clusters, ",\n"), + " }\n" + " } }\n" + " ]")); + auto& hcm = absl::get( + current_config_->listener->listener); + auto filter_configs = + XdsRouting::GeneratePerHTTPFilterConfigsForServiceConfig( + static_cast(xds_client_->bootstrap()) + .http_filter_registry(), + hcm.http_filters, args_); + if (!filter_configs.ok()) return filter_configs.status(); + for (const auto& p : filter_configs->per_filter_configs) { + config_parts.emplace_back(absl::StrCat( + " \"", p.first, "\": [\n", absl::StrJoin(p.second, ",\n"), "\n ]")); + } + std::string json = absl::StrCat("{", absl::StrJoin(config_parts, ",\n"), "}"); + return ServiceConfigImpl::Create(filter_configs->args, json.c_str()); } void XdsResolver::GenerateResult() { diff --git a/src/core/server/xds_server_config_fetcher.cc b/src/core/server/xds_server_config_fetcher.cc index 52a3703171..433f399680 100644 --- a/src/core/server/xds_server_config_fetcher.cc +++ b/src/core/server/xds_server_config_fetcher.cc @@ -677,8 +677,16 @@ void XdsServerConfigFetcher::ListenerWatcher:: // It should get cleaned up eventually. Ignore this update. return; } + bool first_good_update = filter_chain_match_manager_ == nullptr; + // Promote the pending FilterChainMatchManager + filter_chain_match_manager_ = std::move(pending_filter_chain_match_manager_); + // TODO(yashykt): Right now, the server_config_watcher_ does not invoke + // XdsServerConfigFetcher while holding a lock, but that might change in the + // future in which case we would want to execute this update outside the + // critical region through a WorkSerializer similar to XdsClient. + server_config_watcher_->UpdateConnectionManager(filter_chain_match_manager_); // Let the logger know about the update if there was no previous good update. - if (filter_chain_match_manager_ == nullptr) { + if (first_good_update) { if (serving_status_notifier_.on_serving_status_update != nullptr) { serving_status_notifier_.on_serving_status_update( serving_status_notifier_.user_data, listening_address_.c_str(), @@ -688,13 +696,6 @@ void XdsServerConfigFetcher::ListenerWatcher:: << listening_address_; } } - // Promote the pending FilterChainMatchManager - filter_chain_match_manager_ = std::move(pending_filter_chain_match_manager_); - // TODO(yashykt): Right now, the server_config_watcher_ does not invoke - // XdsServerConfigFetcher while holding a lock, but that might change in the - // future in which case we would want to execute this update outside the - // critical region through a WorkSerializer similar to XdsClient. - server_config_watcher_->UpdateConnectionManager(filter_chain_match_manager_); } // @@ -1176,7 +1177,7 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: config_selector_route.unsupported_action = absl::get_if( &route.action) == nullptr; - auto result = XdsRouting::GeneratePerHTTPFilterConfigs( + auto result = XdsRouting::GeneratePerHTTPFilterConfigsForMethodConfig( http_filter_registry, http_filters, vhost, route, nullptr, ChannelArgs()); if (!result.ok()) return result.status(); diff --git a/src/core/service_config/service_config_call_data.h b/src/core/service_config/service_config_call_data.h index a376b751bd..6d11caedab 100644 --- a/src/core/service_config/service_config_call_data.h +++ b/src/core/service_config/service_config_call_data.h @@ -35,9 +35,8 @@ namespace grpc_core { /// Stores the service config data associated with an individual call. -/// A pointer to this object is stored in the call_context -/// GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA element, so that filters can -/// easily access method and global parameters for the call. +/// A pointer to this object is stored in the call context, so that +/// filters can easily access method and global parameters for the call. /// /// Must be accessed when holding the call combiner (legacy filter) or from /// inside the activity (promise-based filter). diff --git a/src/core/util/http_client/httpcli.cc b/src/core/util/http_client/httpcli.cc index 4220cb58b6..e28f9b8b75 100644 --- a/src/core/util/http_client/httpcli.cc +++ b/src/core/util/http_client/httpcli.cc @@ -70,14 +70,14 @@ OrphanablePtr HttpRequest::Get( grpc_polling_entity* pollent, const grpc_http_request* request, Timestamp deadline, grpc_closure* on_done, grpc_http_response* response, RefCountedPtr channel_creds) { - absl::optional> test_only_generate_response; + absl::optional> test_only_generate_response; if (g_get_override != nullptr) { test_only_generate_response = [request, uri, deadline, on_done, response]() { // Note that capturing request here assumes it will remain alive // until after Start is called. This avoids making a copy as this // code path is only used for test mocks. - g_get_override(request, uri, deadline, on_done, response); + return g_get_override(request, uri, deadline, on_done, response); }; } std::string name = @@ -95,13 +95,13 @@ OrphanablePtr HttpRequest::Post( grpc_polling_entity* pollent, const grpc_http_request* request, Timestamp deadline, grpc_closure* on_done, grpc_http_response* response, RefCountedPtr channel_creds) { - absl::optional> test_only_generate_response; + absl::optional> test_only_generate_response; if (g_post_override != nullptr) { test_only_generate_response = [request, uri, deadline, on_done, response]() { - g_post_override(request, uri, - absl::string_view(request->body, request->body_length), - deadline, on_done, response); + return g_post_override( + request, uri, absl::string_view(request->body, request->body_length), + deadline, on_done, response); }; } std::string name = @@ -119,13 +119,13 @@ OrphanablePtr HttpRequest::Put( grpc_polling_entity* pollent, const grpc_http_request* request, Timestamp deadline, grpc_closure* on_done, grpc_http_response* response, RefCountedPtr channel_creds) { - absl::optional> test_only_generate_response; + absl::optional> test_only_generate_response; if (g_put_override != nullptr) { test_only_generate_response = [request, uri, deadline, on_done, response]() { - g_put_override(request, uri, - absl::string_view(request->body, request->body_length), - deadline, on_done, response); + return g_put_override( + request, uri, absl::string_view(request->body, request->body_length), + deadline, on_done, response); }; } std::string name = @@ -155,7 +155,7 @@ HttpRequest::HttpRequest( URI uri, const grpc_slice& request_text, grpc_http_response* response, Timestamp deadline, const grpc_channel_args* channel_args, grpc_closure* on_done, grpc_polling_entity* pollent, const char* name, - absl::optional> test_only_generate_response, + absl::optional> test_only_generate_response, RefCountedPtr channel_creds) : uri_(std::move(uri)), request_text_(request_text), @@ -202,8 +202,7 @@ HttpRequest::~HttpRequest() { void HttpRequest::Start() { MutexLock lock(&mu_); if (test_only_generate_response_.has_value()) { - test_only_generate_response_.value()(); - return; + if (test_only_generate_response_.value()()) return; } Ref().release(); // ref held by pending DNS resolution dns_request_handle_ = resolver_->LookupHostname( diff --git a/src/core/util/http_client/httpcli.h b/src/core/util/http_client/httpcli.h index dd676a5b1c..c5939da61f 100644 --- a/src/core/util/http_client/httpcli.h +++ b/src/core/util/http_client/httpcli.h @@ -165,7 +165,7 @@ class HttpRequest : public InternallyRefCounted { grpc_http_response* response, Timestamp deadline, const grpc_channel_args* channel_args, grpc_closure* on_done, grpc_polling_entity* pollent, const char* name, - absl::optional> test_only_generate_response, + absl::optional> test_only_generate_response, RefCountedPtr channel_creds); ~HttpRequest() override; @@ -250,7 +250,7 @@ class HttpRequest : public InternallyRefCounted { ResourceQuotaRefPtr resource_quota_; grpc_polling_entity* pollent_; grpc_pollset_set* pollset_set_; - const absl::optional> test_only_generate_response_; + const absl::optional> test_only_generate_response_; Mutex mu_; RefCountedPtr handshake_mgr_ ABSL_GUARDED_BY(mu_); bool cancelled_ ABSL_GUARDED_BY(mu_) = false; diff --git a/src/core/util/lru_cache.h b/src/core/util/lru_cache.h new file mode 100644 index 0000000000..d0bf5934f4 --- /dev/null +++ b/src/core/util/lru_cache.h @@ -0,0 +1,104 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_SRC_CORE_UTIL_LRU_CACHE_H +#define GRPC_SRC_CORE_UTIL_LRU_CACHE_H + +#include +#include +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/functional/any_invocable.h" +#include "absl/log/check.h" +#include "absl/types/optional.h" + +namespace grpc_core { + +// A simple LRU cache. Retains at most max_size entries. +// Caller is responsible for synchronization. +// TODO(roth): Support heterogenous lookups. +template +class LruCache { + public: + explicit LruCache(size_t max_size) : max_size_(max_size) { + CHECK_GT(max_size, 0UL); + } + + // Returns the value for key, or nullopt if not present. + absl::optional Get(Key key); + + // If key is present in the cache, returns the corresponding value. + // Otherwise, inserts a new entry in the map, calling create() to + // construct the new value. If inserting a new entry causes the cache + // to be too large, removes the least recently used entry. + Value GetOrInsert(Key key, absl::AnyInvocable create); + + private: + struct CacheEntry { + Value value; + typename std::list::iterator lru_iterator; + + explicit CacheEntry(Value v) : value(std::move(v)) {} + }; + + const size_t max_size_; + absl::flat_hash_map cache_; + std::list lru_list_; +}; + +// +// implementation -- no user-serviceable parts below +// + +template +absl::optional LruCache::Get(Key key) { + auto it = cache_.find(key); + if (it == cache_.end()) return absl::nullopt; + // Found the entry. Move the entry to the end of the LRU list. + auto new_lru_it = lru_list_.insert(lru_list_.end(), *it->second.lru_iterator); + lru_list_.erase(it->second.lru_iterator); + it->second.lru_iterator = new_lru_it; + return it->second.value; +} + +template +Value LruCache::GetOrInsert( + Key key, absl::AnyInvocable create) { + auto value = Get(key); + if (value.has_value()) return std::move(*value); + // Entry not found. We'll need to insert a new entry. + // If the cache is at max size, remove the least recently used entry. + if (cache_.size() == max_size_) { + auto lru_it = lru_list_.begin(); + CHECK(lru_it != lru_list_.end()); + auto cache_it = cache_.find(*lru_it); + CHECK(cache_it != cache_.end()); + cache_.erase(cache_it); + lru_list_.pop_front(); + } + // Create a new entry, insert it, and return it. + auto it = cache_ + .emplace(std::piecewise_construct, std::forward_as_tuple(key), + std::forward_as_tuple(create(key))) + .first; + it->second.lru_iterator = lru_list_.insert(lru_list_.end(), std::move(key)); + return it->second.value; +} + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_UTIL_LRU_CACHE_H diff --git a/src/core/util/string.cc b/src/core/util/string.cc index 31ffb9eb4b..56cc040809 100644 --- a/src/core/util/string.cc +++ b/src/core/util/string.cc @@ -29,6 +29,7 @@ #include #include "absl/strings/str_cat.h" +#include "absl/time/time.h" #include #include @@ -53,14 +54,14 @@ char* gpr_strdup(const char* src) { } std::string gpr_format_timespec(gpr_timespec tm) { - char time_buffer[35]; - char ns_buffer[11]; // '.' + 9 digits of precision - struct tm* tm_info = localtime(reinterpret_cast(&tm.tv_sec)); - strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); - snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); + const std::string time_str = + absl::FormatTime("%Y-%m-%d%ET%H:%M:%S", absl::FromUnixSeconds(tm.tv_sec), + absl::LocalTimeZone()); // This loop trims off trailing zeros by inserting a null character that the // right point. We iterate in chunks of three because we want 0, 3, 6, or 9 // fractional digits. + char ns_buffer[11]; // '.' + 9 digits of precision + snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); for (int i = 7; i >= 1; i -= 3) { if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && ns_buffer[i + 2] == '0') { @@ -73,7 +74,7 @@ std::string gpr_format_timespec(gpr_timespec tm) { break; } } - return absl::StrCat(time_buffer, ns_buffer, "Z"); + return absl::StrCat(time_str, ns_buffer, "Z"); } struct dump_out { diff --git a/src/core/xds/grpc/xds_bootstrap_grpc.cc b/src/core/xds/grpc/xds_bootstrap_grpc.cc index 58b958cb99..87b3541ced 100644 --- a/src/core/xds/grpc/xds_bootstrap_grpc.cc +++ b/src/core/xds/grpc/xds_bootstrap_grpc.cc @@ -18,8 +18,6 @@ #include -#include -#include #include #include #include @@ -36,29 +34,14 @@ #include #include -#include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gprpp/env.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/security/credentials/channel_creds_registry.h" #include "src/core/util/json/json.h" #include "src/core/util/json/json_object_loader.h" #include "src/core/util/json/json_reader.h" #include "src/core/util/json/json_writer.h" -#include "src/core/util/string.h" namespace grpc_core { -namespace { -bool IsFallbackExperimentEnabled() { - auto fallback_enabled = GetEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK"); - bool enabled = false; - return gpr_parse_bool_value(fallback_enabled.value_or("0").c_str(), - &enabled) && - enabled; -} - -} // namespace - // // GrpcXdsBootstrap::GrpcNode::Locality // @@ -106,16 +89,6 @@ const JsonLoaderInterface* GrpcXdsBootstrap::GrpcAuthority::JsonLoader( return loader; } -void GrpcXdsBootstrap::GrpcAuthority::JsonPostLoad( - const Json& /*json*/, const JsonArgs& /*args*/, - ValidationErrors* /*errors*/) { - if (!IsFallbackExperimentEnabled()) { - if (servers_.size() > 1) { - servers_.resize(1); - } - } -} - // // GrpcXdsBootstrap // @@ -190,11 +163,6 @@ void GrpcXdsBootstrap::JsonPostLoad(const Json& /*json*/, } } } - if (!IsFallbackExperimentEnabled()) { - if (servers_.size() > 1) { - servers_.resize(1); - } - } } std::string GrpcXdsBootstrap::ToString() const { diff --git a/src/core/xds/grpc/xds_bootstrap_grpc.h b/src/core/xds/grpc/xds_bootstrap_grpc.h index a21f0017aa..24c47e2ecc 100644 --- a/src/core/xds/grpc/xds_bootstrap_grpc.h +++ b/src/core/xds/grpc/xds_bootstrap_grpc.h @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -29,9 +28,7 @@ #include -#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/validation_errors.h" -#include "src/core/lib/security/credentials/channel_creds_registry.h" #include "src/core/util/json/json.h" #include "src/core/util/json/json_args.h" #include "src/core/util/json/json_object_loader.h" @@ -93,8 +90,6 @@ class GrpcXdsBootstrap final : public XdsBootstrap { } static const JsonLoaderInterface* JsonLoader(const JsonArgs&); - void JsonPostLoad(const Json& json, const JsonArgs& args, - ValidationErrors* errors); private: std::vector servers_; diff --git a/src/core/xds/grpc/xds_http_fault_filter.cc b/src/core/xds/grpc/xds_http_fault_filter.cc index e46eeb79f1..6bc74df820 100644 --- a/src/core/xds/grpc/xds_http_fault_filter.cc +++ b/src/core/xds/grpc/xds_http_fault_filter.cc @@ -87,6 +87,7 @@ void XdsHttpFaultFilter::PopulateSymtab(upb_DefPool* symtab) const { absl::optional XdsHttpFaultFilter::GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -208,11 +209,13 @@ XdsHttpFaultFilter::GenerateFilterConfig( absl::optional XdsHttpFaultFilter::GenerateFilterConfigOverride( + absl::string_view instance_name, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { // HTTPFault filter has the same message type in HTTP connection manager's // filter config and in overriding filter config field. - return GenerateFilterConfig(context, std::move(extension), errors); + return GenerateFilterConfig(instance_name, context, std::move(extension), + errors); } void XdsHttpFaultFilter::AddFilter(InterceptionChainBuilder& builder) const { @@ -229,7 +232,7 @@ ChannelArgs XdsHttpFaultFilter::ModifyChannelArgs( } absl::StatusOr -XdsHttpFaultFilter::GenerateServiceConfig( +XdsHttpFaultFilter::GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const { Json policy_json = filter_config_override != nullptr @@ -239,4 +242,10 @@ XdsHttpFaultFilter::GenerateServiceConfig( return ServiceConfigJsonEntry{"faultInjectionPolicy", JsonDump(policy_json)}; } +absl::StatusOr +XdsHttpFaultFilter::GenerateServiceConfig( + const FilterConfig& /*hcm_filter_config*/) const { + return ServiceConfigJsonEntry{"", ""}; +} + } // namespace grpc_core diff --git a/src/core/xds/grpc/xds_http_fault_filter.h b/src/core/xds/grpc/xds_http_fault_filter.h index b99b1d3008..c269ff17f0 100644 --- a/src/core/xds/grpc/xds_http_fault_filter.h +++ b/src/core/xds/grpc/xds_http_fault_filter.h @@ -39,17 +39,21 @@ class XdsHttpFaultFilter final : public XdsHttpFilterImpl { absl::string_view OverrideConfigProtoName() const override; void PopulateSymtab(upb_DefPool* symtab) const override; absl::optional GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; absl::optional GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; void AddFilter(InterceptionChainBuilder& builder) const override; const grpc_channel_filter* channel_filter() const override; ChannelArgs ModifyChannelArgs(const ChannelArgs& args) const override; - absl::StatusOr GenerateServiceConfig( + absl::StatusOr GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const override; + absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const override; bool IsSupportedOnClients() const override { return true; } bool IsSupportedOnServers() const override { return false; } }; diff --git a/src/core/xds/grpc/xds_http_filter.h b/src/core/xds/grpc/xds_http_filter.h index 6e8c79d128..8a9c54c6ef 100644 --- a/src/core/xds/grpc/xds_http_filter.h +++ b/src/core/xds/grpc/xds_http_filter.h @@ -60,6 +60,7 @@ class XdsHttpFilterImpl { // The value of this field in the method config will be a JSON array, // which will be populated with the elements returned by each filter // instance. + // Entry will be skipped if this field is empty. std::string service_config_field_name; // The element to add to the JSON array. std::string element; @@ -80,12 +81,14 @@ class XdsHttpFilterImpl { // Generates a Config from the xDS filter config proto. // Used for the top-level config in the HCM HTTP filter list. virtual absl::optional GenerateFilterConfig( + absl::string_view instance_name, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const = 0; // Generates a Config from the xDS filter config proto. // Used for the typed_per_filter_config override in VirtualHost and Route. virtual absl::optional GenerateFilterConfigOverride( + absl::string_view instance_name, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const = 0; @@ -106,10 +109,17 @@ class XdsHttpFilterImpl { // The filter_config_override comes from the first of the ClusterWeight, // Route, or VirtualHost entries that it is found in, or null if // there is no override in any of those locations. - virtual absl::StatusOr GenerateServiceConfig( + virtual absl::StatusOr GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const = 0; + // Function to convert the Configs into a JSON string to be added to the + // top level of the service config. + // The hcm_filter_config comes from the HttpConnectionManager config. + // Currently used only on the client side. + virtual absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const = 0; + // Returns true if the filter is supported on clients; false otherwise virtual bool IsSupportedOnClients() const = 0; diff --git a/src/core/xds/grpc/xds_http_filter_registry.cc b/src/core/xds/grpc/xds_http_filter_registry.cc index 9a6f18e226..9decfded32 100644 --- a/src/core/xds/grpc/xds_http_filter_registry.cc +++ b/src/core/xds/grpc/xds_http_filter_registry.cc @@ -29,8 +29,10 @@ #include "src/core/util/json/json.h" #include "src/core/xds/grpc/xds_http_fault_filter.h" +#include "src/core/xds/grpc/xds_http_gcp_authn_filter.h" #include "src/core/xds/grpc/xds_http_rbac_filter.h" #include "src/core/xds/grpc/xds_http_stateful_session_filter.h" +#include "src/core/xds/grpc/xds_metadata_parser.h" namespace grpc_core { @@ -52,6 +54,7 @@ void XdsHttpRouterFilter::PopulateSymtab(upb_DefPool* symtab) const { absl::optional XdsHttpRouterFilter::GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -71,6 +74,7 @@ XdsHttpRouterFilter::GenerateFilterConfig( absl::optional XdsHttpRouterFilter::GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& /*context*/, XdsExtension /*extension*/, ValidationErrors* errors) const { errors->AddError("router filter does not support config override"); @@ -87,6 +91,9 @@ XdsHttpFilterRegistry::XdsHttpFilterRegistry(bool register_builtins) { RegisterFilter(std::make_unique()); RegisterFilter(std::make_unique()); RegisterFilter(std::make_unique()); + if (XdsGcpAuthFilterEnabled()) { + RegisterFilter(std::make_unique()); + } } } diff --git a/src/core/xds/grpc/xds_http_filter_registry.h b/src/core/xds/grpc/xds_http_filter_registry.h index d25dc378b8..37950d01f1 100644 --- a/src/core/xds/grpc/xds_http_filter_registry.h +++ b/src/core/xds/grpc/xds_http_filter_registry.h @@ -45,19 +45,26 @@ class XdsHttpRouterFilter final : public XdsHttpFilterImpl { absl::string_view OverrideConfigProtoName() const override; void PopulateSymtab(upb_DefPool* symtab) const override; absl::optional GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; absl::optional GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; void AddFilter(InterceptionChainBuilder& /*builder*/) const override {} const grpc_channel_filter* channel_filter() const override { return nullptr; } - absl::StatusOr GenerateServiceConfig( + absl::StatusOr GenerateMethodConfig( const FilterConfig& /*hcm_filter_config*/, const FilterConfig* /*filter_config_override*/) const override { // This will never be called, since channel_filter() returns null. return absl::UnimplementedError("router filter should never be called"); } + absl::StatusOr GenerateServiceConfig( + const FilterConfig& /*hcm_filter_config*/) const override { + // This will never be called, since channel_filter() returns null. + return absl::UnimplementedError("router filter should never be called"); + } bool IsSupportedOnClients() const override { return true; } bool IsSupportedOnServers() const override { return true; } bool IsTerminalFilter() const override { return true; } diff --git a/src/core/xds/grpc/xds_http_gcp_authn_filter.cc b/src/core/xds/grpc/xds_http_gcp_authn_filter.cc new file mode 100644 index 0000000000..3378284c9c --- /dev/null +++ b/src/core/xds/grpc/xds_http_gcp_authn_filter.cc @@ -0,0 +1,142 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "src/core/xds/grpc/xds_http_gcp_authn_filter.h" + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/types/variant.h" +#include "envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.upb.h" +#include "envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.upbdefs.h" + +#include + +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h" +#include "src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/validation_errors.h" +#include "src/core/util/json/json.h" +#include "src/core/util/json/json_writer.h" +#include "src/core/xds/grpc/xds_common_types.h" +#include "src/core/xds/grpc/xds_common_types_parser.h" +#include "src/core/xds/grpc/xds_http_filter.h" + +namespace grpc_core { + +absl::string_view XdsHttpGcpAuthnFilter::ConfigProtoName() const { + return "envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig"; +} + +absl::string_view XdsHttpGcpAuthnFilter::OverrideConfigProtoName() const { + return ""; +} + +void XdsHttpGcpAuthnFilter::PopulateSymtab(upb_DefPool* symtab) const { + envoy_extensions_filters_http_gcp_authn_v3_GcpAuthnFilterConfig_getmsgdef( + symtab); +} + +namespace { + +Json::Object ValidateFilterConfig( + absl::string_view instance_name, + const envoy_extensions_filters_http_gcp_authn_v3_GcpAuthnFilterConfig* + gcp_auth, + ValidationErrors* errors) { + Json::Object config = { + {"filter_instance_name", Json::FromString(std::string(instance_name))}}; + const auto* cache_config = + envoy_extensions_filters_http_gcp_authn_v3_GcpAuthnFilterConfig_cache_config( + gcp_auth); + if (cache_config == nullptr) return config; + uint64_t cache_size = + ParseUInt64Value( + envoy_extensions_filters_http_gcp_authn_v3_TokenCacheConfig_cache_size( + cache_config)) + .value_or(10); + if (cache_size == 0 || cache_size >= INT64_MAX) { + ValidationErrors::ScopedField field(errors, ".cache_config.cache_size"); + errors->AddError("must be in the range (0, INT64_MAX)"); + } + config["cache_size"] = Json::FromNumber(cache_size); + return config; +} + +} // namespace + +absl::optional +XdsHttpGcpAuthnFilter::GenerateFilterConfig( + absl::string_view instance_name, + const XdsResourceType::DecodeContext& context, XdsExtension extension, + ValidationErrors* errors) const { + absl::string_view* serialized_filter_config = + absl::get_if(&extension.value); + if (serialized_filter_config == nullptr) { + errors->AddError("could not parse GCP auth filter config"); + return absl::nullopt; + } + auto* gcp_auth = + envoy_extensions_filters_http_gcp_authn_v3_GcpAuthnFilterConfig_parse( + serialized_filter_config->data(), serialized_filter_config->size(), + context.arena); + if (gcp_auth == nullptr) { + errors->AddError("could not parse GCP auth filter config"); + return absl::nullopt; + } + return FilterConfig{ConfigProtoName(), Json::FromObject(ValidateFilterConfig( + instance_name, gcp_auth, errors))}; +} + +absl::optional +XdsHttpGcpAuthnFilter::GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, + const XdsResourceType::DecodeContext& /*context*/, + XdsExtension /*extension*/, ValidationErrors* errors) const { + errors->AddError("GCP auth filter does not support config override"); + return absl::nullopt; +} + +void XdsHttpGcpAuthnFilter::AddFilter(InterceptionChainBuilder& builder) const { + builder.Add(); +} + +const grpc_channel_filter* XdsHttpGcpAuthnFilter::channel_filter() const { + return &GcpAuthenticationFilter::kFilter; +} + +ChannelArgs XdsHttpGcpAuthnFilter::ModifyChannelArgs( + const ChannelArgs& args) const { + return args.Set(GRPC_ARG_PARSE_GCP_AUTHENTICATION_METHOD_CONFIG, 1); +} + +absl::StatusOr +XdsHttpGcpAuthnFilter::GenerateMethodConfig( + const FilterConfig& /*hcm_filter_config*/, + const FilterConfig* /*filter_config_override*/) const { + return ServiceConfigJsonEntry{"", ""}; +} + +absl::StatusOr +XdsHttpGcpAuthnFilter::GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const { + return ServiceConfigJsonEntry{"gcp_authentication", + JsonDump(hcm_filter_config.config)}; +} + +} // namespace grpc_core diff --git a/src/core/xds/grpc/xds_http_gcp_authn_filter.h b/src/core/xds/grpc/xds_http_gcp_authn_filter.h new file mode 100644 index 0000000000..662e2c456a --- /dev/null +++ b/src/core/xds/grpc/xds_http_gcp_authn_filter.h @@ -0,0 +1,61 @@ +// +// Copyright 2024 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_SRC_CORE_XDS_GRPC_XDS_HTTP_GCP_AUTHN_FILTER_H +#define GRPC_SRC_CORE_XDS_GRPC_XDS_HTTP_GCP_AUTHN_FILTER_H + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "upb/reflection/def.h" + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_fwd.h" +#include "src/core/lib/gprpp/validation_errors.h" +#include "src/core/xds/grpc/xds_common_types.h" +#include "src/core/xds/grpc/xds_http_filter.h" +#include "src/core/xds/xds_client/xds_resource_type.h" + +namespace grpc_core { + +class XdsHttpGcpAuthnFilter final : public XdsHttpFilterImpl { + public: + absl::string_view ConfigProtoName() const override; + absl::string_view OverrideConfigProtoName() const override; + void PopulateSymtab(upb_DefPool* symtab) const override; + absl::optional GenerateFilterConfig( + absl::string_view instance_name, + const XdsResourceType::DecodeContext& context, XdsExtension extension, + ValidationErrors* errors) const override; + absl::optional GenerateFilterConfigOverride( + absl::string_view instance_name, + const XdsResourceType::DecodeContext& context, XdsExtension extension, + ValidationErrors* errors) const override; + void AddFilter(InterceptionChainBuilder& builder) const override; + const grpc_channel_filter* channel_filter() const override; + ChannelArgs ModifyChannelArgs(const ChannelArgs& args) const override; + absl::StatusOr GenerateMethodConfig( + const FilterConfig& hcm_filter_config, + const FilterConfig* filter_config_override) const override; + absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const override; + bool IsSupportedOnClients() const override { return true; } + bool IsSupportedOnServers() const override { return false; } +}; + +} // namespace grpc_core + +#endif // GRPC_SRC_CORE_XDS_GRPC_XDS_HTTP_GCP_AUTHN_FILTER_H diff --git a/src/core/xds/grpc/xds_http_rbac_filter.cc b/src/core/xds/grpc/xds_http_rbac_filter.cc index 64a793abad..4508ae41b9 100644 --- a/src/core/xds/grpc/xds_http_rbac_filter.cc +++ b/src/core/xds/grpc/xds_http_rbac_filter.cc @@ -515,6 +515,7 @@ void XdsHttpRbacFilter::PopulateSymtab(upb_DefPool* symtab) const { absl::optional XdsHttpRbacFilter::GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -536,6 +537,7 @@ XdsHttpRbacFilter::GenerateFilterConfig( absl::optional XdsHttpRbacFilter::GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -578,7 +580,7 @@ ChannelArgs XdsHttpRbacFilter::ModifyChannelArgs( } absl::StatusOr -XdsHttpRbacFilter::GenerateServiceConfig( +XdsHttpRbacFilter::GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const { const Json& policy_json = filter_config_override != nullptr @@ -588,4 +590,10 @@ XdsHttpRbacFilter::GenerateServiceConfig( return ServiceConfigJsonEntry{"rbacPolicy", JsonDump(policy_json)}; } +absl::StatusOr +XdsHttpRbacFilter::GenerateServiceConfig( + const FilterConfig& /*hcm_filter_config*/) const { + return ServiceConfigJsonEntry{"", ""}; +} + } // namespace grpc_core diff --git a/src/core/xds/grpc/xds_http_rbac_filter.h b/src/core/xds/grpc/xds_http_rbac_filter.h index 8aac5bf1d6..c7550575b7 100644 --- a/src/core/xds/grpc/xds_http_rbac_filter.h +++ b/src/core/xds/grpc/xds_http_rbac_filter.h @@ -39,17 +39,21 @@ class XdsHttpRbacFilter final : public XdsHttpFilterImpl { absl::string_view OverrideConfigProtoName() const override; void PopulateSymtab(upb_DefPool* symtab) const override; absl::optional GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; absl::optional GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; void AddFilter(InterceptionChainBuilder& builder) const override; const grpc_channel_filter* channel_filter() const override; ChannelArgs ModifyChannelArgs(const ChannelArgs& args) const override; - absl::StatusOr GenerateServiceConfig( + absl::StatusOr GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const override; + absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const override; bool IsSupportedOnClients() const override { return false; } bool IsSupportedOnServers() const override { return true; } }; diff --git a/src/core/xds/grpc/xds_http_stateful_session_filter.cc b/src/core/xds/grpc/xds_http_stateful_session_filter.cc index dd239bc009..8216d51ad0 100644 --- a/src/core/xds/grpc/xds_http_stateful_session_filter.cc +++ b/src/core/xds/grpc/xds_http_stateful_session_filter.cc @@ -141,6 +141,7 @@ Json::Object ValidateStatefulSession( absl::optional XdsHttpStatefulSessionFilter::GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -164,6 +165,7 @@ XdsHttpStatefulSessionFilter::GenerateFilterConfig( absl::optional XdsHttpStatefulSessionFilter::GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const { absl::string_view* serialized_filter_config = @@ -211,7 +213,7 @@ ChannelArgs XdsHttpStatefulSessionFilter::ModifyChannelArgs( } absl::StatusOr -XdsHttpStatefulSessionFilter::GenerateServiceConfig( +XdsHttpStatefulSessionFilter::GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const { const Json& config = filter_config_override != nullptr @@ -220,4 +222,10 @@ XdsHttpStatefulSessionFilter::GenerateServiceConfig( return ServiceConfigJsonEntry{"stateful_session", JsonDump(config)}; } +absl::StatusOr +XdsHttpStatefulSessionFilter::GenerateServiceConfig( + const FilterConfig& /*hcm_filter_config*/) const { + return ServiceConfigJsonEntry{"", ""}; +} + } // namespace grpc_core diff --git a/src/core/xds/grpc/xds_http_stateful_session_filter.h b/src/core/xds/grpc/xds_http_stateful_session_filter.h index fb3ce72b59..28df742b6c 100644 --- a/src/core/xds/grpc/xds_http_stateful_session_filter.h +++ b/src/core/xds/grpc/xds_http_stateful_session_filter.h @@ -39,17 +39,21 @@ class XdsHttpStatefulSessionFilter final : public XdsHttpFilterImpl { absl::string_view OverrideConfigProtoName() const override; void PopulateSymtab(upb_DefPool* symtab) const override; absl::optional GenerateFilterConfig( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; absl::optional GenerateFilterConfigOverride( + absl::string_view /*instance_name*/, const XdsResourceType::DecodeContext& context, XdsExtension extension, ValidationErrors* errors) const override; void AddFilter(InterceptionChainBuilder& builder) const override; const grpc_channel_filter* channel_filter() const override; ChannelArgs ModifyChannelArgs(const ChannelArgs& args) const override; - absl::StatusOr GenerateServiceConfig( + absl::StatusOr GenerateMethodConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const override; + absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config) const override; bool IsSupportedOnClients() const override { return true; } bool IsSupportedOnServers() const override { return false; } }; diff --git a/src/core/xds/grpc/xds_listener_parser.cc b/src/core/xds/grpc/xds_listener_parser.cc index b536472a80..e16efa43fa 100644 --- a/src/core/xds/grpc/xds_listener_parser.cc +++ b/src/core/xds/grpc/xds_listener_parser.cc @@ -268,8 +268,8 @@ XdsListenerResource::HttpConnectionManager HttpConnectionManagerParse( continue; } absl::optional filter_config = - filter_impl->GenerateFilterConfig(context, std::move(*extension), - errors); + filter_impl->GenerateFilterConfig(name, context, + std::move(*extension), errors); if (filter_config.has_value()) { http_connection_manager.http_filters.emplace_back( XdsListenerResource::HttpConnectionManager::HttpFilter{ diff --git a/src/core/xds/grpc/xds_route_config_parser.cc b/src/core/xds/grpc/xds_route_config_parser.cc index d6ac0f858a..d23f162456 100644 --- a/src/core/xds/grpc/xds_route_config_parser.cc +++ b/src/core/xds/grpc/xds_route_config_parser.cc @@ -441,7 +441,7 @@ XdsRouteConfigResource::TypedPerFilterConfig ParseTypedPerFilterConfig( } absl::optional filter_config = filter_impl->GenerateFilterConfigOverride( - context, std::move(*extension_to_use), errors); + key, context, std::move(*extension_to_use), errors); if (filter_config.has_value()) { typed_per_filter_config[std::string(key)] = std::move(*filter_config); } diff --git a/src/core/xds/grpc/xds_routing.cc b/src/core/xds/grpc/xds_routing.cc index 83c9d620e4..2a3a29088d 100644 --- a/src/core/xds/grpc/xds_routing.cc +++ b/src/core/xds/grpc/xds_routing.cc @@ -215,23 +215,21 @@ const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride( return nullptr; } -} // namespace - absl::StatusOr -XdsRouting::GeneratePerHTTPFilterConfigs( +GeneratePerHTTPFilterConfigs( const XdsHttpFilterRegistry& http_filter_registry, const std::vector& http_filters, - const XdsRouteConfigResource::VirtualHost& vhost, - const XdsRouteConfigResource::Route& route, - const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* - cluster_weight, - const ChannelArgs& args) { - GeneratePerHttpFilterConfigsResult result; + const ChannelArgs& args, + absl::FunctionRef( + const XdsHttpFilterImpl&, + const XdsListenerResource::HttpConnectionManager::HttpFilter&)> + generate_service_config) { + XdsRouting::GeneratePerHttpFilterConfigsResult result; result.args = args; for (const auto& http_filter : http_filters) { // Find filter. This is guaranteed to succeed, because it's checked - // at config validation time in the XdsApi code. + // at config validation time in the listener parsing code. const XdsHttpFilterImpl* filter_impl = http_filter_registry.GetFilterForType( http_filter.config.config_proto_type_name); @@ -242,22 +240,60 @@ XdsRouting::GeneratePerHTTPFilterConfigs( // Allow filter to add channel args that may affect service config // parsing. result.args = filter_impl->ModifyChannelArgs(result.args); - // Find config override, if any. - const XdsHttpFilterImpl::FilterConfig* config_override = - FindFilterConfigOverride(http_filter.name, vhost, route, - cluster_weight); // Generate service config for filter. - auto method_config_field = - filter_impl->GenerateServiceConfig(http_filter.config, config_override); - if (!method_config_field.ok()) { + auto service_config_field = + generate_service_config(*filter_impl, http_filter); + if (!service_config_field.ok()) { return absl::FailedPreconditionError(absl::StrCat( - "failed to generate method config for HTTP filter ", http_filter.name, - ": ", method_config_field.status().ToString())); + "failed to generate service config for HTTP filter ", + http_filter.name, ": ", service_config_field.status().ToString())); } - result.per_filter_configs[method_config_field->service_config_field_name] - .push_back(method_config_field->element); + if (service_config_field->service_config_field_name.empty()) continue; + result.per_filter_configs[service_config_field->service_config_field_name] + .push_back(service_config_field->element); } return result; } +} // namespace + +absl::StatusOr +XdsRouting::GeneratePerHTTPFilterConfigsForMethodConfig( + const XdsHttpFilterRegistry& http_filter_registry, + const std::vector& + http_filters, + const XdsRouteConfigResource::VirtualHost& vhost, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight, + const ChannelArgs& args) { + return GeneratePerHTTPFilterConfigs( + http_filter_registry, http_filters, args, + [&](const XdsHttpFilterImpl& filter_impl, + const XdsListenerResource::HttpConnectionManager::HttpFilter& + http_filter) { + const XdsHttpFilterImpl::FilterConfig* config_override = + FindFilterConfigOverride(http_filter.name, vhost, route, + cluster_weight); + // Generate service config for filter. + return filter_impl.GenerateMethodConfig(http_filter.config, + config_override); + }); +} + +absl::StatusOr +XdsRouting::GeneratePerHTTPFilterConfigsForServiceConfig( + const XdsHttpFilterRegistry& http_filter_registry, + const std::vector& + http_filters, + const ChannelArgs& args) { + return GeneratePerHTTPFilterConfigs( + http_filter_registry, http_filters, args, + [&](const XdsHttpFilterImpl& filter_impl, + const XdsListenerResource::HttpConnectionManager::HttpFilter& + http_filter) { + return filter_impl.GenerateServiceConfig(http_filter.config); + }); +} + } // namespace grpc_core diff --git a/src/core/xds/grpc/xds_routing.h b/src/core/xds/grpc/xds_routing.h index 1d4966961d..696599d846 100644 --- a/src/core/xds/grpc/xds_routing.h +++ b/src/core/xds/grpc/xds_routing.h @@ -88,9 +88,9 @@ class XdsRouting final { ChannelArgs args; }; - // Generates a map of per_filter_configs. \a args is consumed. + // Generates per-HTTP filter configs for a method config. static absl::StatusOr - GeneratePerHTTPFilterConfigs( + GeneratePerHTTPFilterConfigsForMethodConfig( const XdsHttpFilterRegistry& http_filter_registry, const std::vector& http_filters, @@ -99,6 +99,14 @@ class XdsRouting final { const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* cluster_weight, const ChannelArgs& args); + + // Generates per-HTTP filter configs for the top-level service config. + static absl::StatusOr + GeneratePerHTTPFilterConfigsForServiceConfig( + const XdsHttpFilterRegistry& http_filter_registry, + const std::vector& + http_filters, + const ChannelArgs& args); }; } // namespace grpc_core diff --git a/src/core/xds/xds_client/xds_client.cc b/src/core/xds/xds_client/xds_client.cc index 7c4cef0dd1..181bfbd3bb 100644 --- a/src/core/xds/xds_client/xds_client.cc +++ b/src/core/xds/xds_client/xds_client.cc @@ -210,6 +210,7 @@ class XdsClient::XdsChannel::AdsCall final if (timer_handle_.has_value() && ads_call_->xds_client()->engine()->Cancel(*timer_handle_)) { timer_handle_.reset(); + ads_call_.reset(); } } @@ -250,24 +251,28 @@ class XdsClient::XdsChannel::AdsCall final } void OnTimer() { - GRPC_TRACE_LOG(xds_client, INFO) - << "[xds_client " << ads_call_->xds_client() << "] xds server " - << ads_call_->xds_channel()->server_.server_uri() - << ": timeout obtaining resource {type=" << type_->type_url() - << " name=" - << XdsClient::ConstructFullXdsResourceName( - name_.authority, type_->type_url(), name_.key) - << "} from xds server"; { MutexLock lock(&ads_call_->xds_client()->mu_); timer_handle_.reset(); - resource_seen_ = true; auto& authority_state = ads_call_->xds_client()->authority_state_map_[name_.authority]; ResourceState& state = authority_state.resource_map[type_][name_.key]; - state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; - ads_call_->xds_client()->NotifyWatchersOnResourceDoesNotExist( - state.watchers, ReadDelayHandle::NoWait()); + // We might have received the resource after the timer fired but before + // the callback ran. + if (state.resource == nullptr) { + GRPC_TRACE_LOG(xds_client, INFO) + << "[xds_client " << ads_call_->xds_client() << "] xds server " + << ads_call_->xds_channel()->server_.server_uri() + << ": timeout obtaining resource {type=" << type_->type_url() + << " name=" + << XdsClient::ConstructFullXdsResourceName( + name_.authority, type_->type_url(), name_.key) + << "} from xds server"; + resource_seen_ = true; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; + ads_call_->xds_client()->NotifyWatchersOnResourceDoesNotExist( + state.watchers, ReadDelayHandle::NoWait()); + } } ads_call_->xds_client()->work_serializer_.DrainQueue(); ads_call_.reset(); @@ -715,16 +720,14 @@ void XdsClient::XdsChannel::RetryableCall::StartNewCallLocked() { template void XdsClient::XdsChannel::RetryableCall::StartRetryTimerLocked() { if (shutting_down_) return; - const Timestamp next_attempt_time = backoff_.NextAttemptTime(); - const Duration timeout = - std::max(next_attempt_time - Timestamp::Now(), Duration::Zero()); + const Duration delay = backoff_.NextAttemptDelay(); GRPC_TRACE_LOG(xds_client, INFO) << "[xds_client " << xds_channel()->xds_client() << "] xds server " << xds_channel()->server_.server_uri() - << ": call attempt failed; retry timer will fire in " << timeout.millis() + << ": call attempt failed; retry timer will fire in " << delay.millis() << "ms."; timer_handle_ = xds_channel()->xds_client()->engine()->RunAfter( - timeout, + delay, [self = this->Ref(DEBUG_LOCATION, "RetryableCall+retry_timer_start")]() { ApplicationCallbackExecCtx callback_exec_ctx; ExecCtx exec_ctx; diff --git a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec index b407eccc35..844e08cfcb 100644 --- a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCCppPlugin' - v = '1.67.0-dev' + v = '1.68.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates C++ files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 221ef815cb..9198288550 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.67.0-dev' + v = '1.68.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 260f6c6b90..91dec47c6c 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -39,7 +39,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL-GRPC' - version = '0.0.36' + version = '0.0.37' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' # Adapted from the homepage: @@ -76,7 +76,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/google/boringssl.git', - :commit => "16c8d3db1af20fcc04b5190b25242aadcb1fbb30", + :commit => "b8b3e6e11166719a8ebfa43c0cde9ad7d57a84f6", } s.ios.deployment_target = '10.0' @@ -132,7 +132,7 @@ Pod::Spec.new do |s| ss.source_files = 'src/ssl/*.{h,c,cc}', 'src/ssl/**/*.{h,c,cc}', 'src/crypto/*.{h,c,cc}', - 'src/crypto/**/*.{h,c,cc}', + 'src/crypto/**/*.{h,c,cc,inc}', # We have to include fiat because spake25519 depends on it 'src/third_party/fiat/*.{h,c,cc}', # Include the err_data.c pre-generated in boringssl's master-with-bazel branch @@ -143,11 +143,7 @@ Pod::Spec.new do |s| 'src/crypto/*.h', 'src/crypto/**/*.h', 'src/third_party/fiat/*.h' - # bcm.c includes other source files, creating duplicated symbols. Since it is not used, we - # explicitly exclude it from the pod. - # TODO (mxyan): Work with BoringSSL team to remove this hack. - ss.exclude_files = 'src/crypto/fipsmodule/bcm.c', - 'src/**/*_test.*', + ss.exclude_files = 'src/**/*_test.*', 'src/**/test_*.*', 'src/**/test/*.*' @@ -177,522 +173,529 @@ Pod::Spec.new do |s| *) opts="--ignore-garbage" ;; esac base64 --decode $opts < src/include/openssl/boringssl_prefix_symbols.h - H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oALS9XXPbuJaofT+/wnXm5kzVrpnY6WRn - v3eKrXQ0cWxvSenpzA2LkiCLOxSpEJRj968/AEmJ+FgL5FrwW7VrpmPpeRYFgPgiCPzXf108ikJUaS02 - F6uX8z+SVVllxaOUeXKoxDZ7TnYi3YjqP+XuoiwuPjafLha3F+tyv8/q/+/i8v36w+btZnWZbq/ebNfr - N7+t3l3+483q6t3Vb1dpulmvLrer1ds3//Zv//VfF9fl4aXKHnf1xf9d/8fF1ZvLD3+7+L0sH3NxMSvW - /6m+or/1IKp9JmWm4tXlxVGKv6loh5e/XezLTbZV/z8tNv9VVhebTNZVtjrW4qLeZfJCltv6V1qJi636 - MC1etOtwrA6lFBe/slr9gKr5/+WxvtgKcaGQnaiE/vVVWqiE+NvFoSqfso1KknqX1ur/iIt0VT4JbVqf - r70o62wt9FW0cQ/99Z4+OhxEWl1kxUWa55rMhDz9uuXn6cXi/tPyfybz6cVscfEwv/9jdjO9ufg/k4X6 - 9/+5mNzdNF+afFt+vp9f3MwW17eT2dfFxeT29kJR88ndcjZdaNf/zJafL+bT3ydzhdwrSvl699317beb - 2d3vDTj7+nA7U1F6wcX9J+34Op1ff1Z/mXyc3c6W35vwn2bLu+li8Z/KcXF3fzH9Y3q3vFh81h7jyj5O - L25nk4+304tP6l+Tu+9at3iYXs8mt39T1z2fXi//phSn/1Jfur6/W0z/+U3p1HcubiZfJ7/rC2no0z+b - H/Z5slzcq7hz9fMW326X+md8mt9/vbi9X+grv/i2mKoYk+VE0yoN1SUv/qa4qbrAub7uifrf9XJ2f6d9 - ClChl/OJvo676e+3s9+nd9dTzd43wPJ+rr77bdExf7uYzGcLHfT+21LT99rZFOH7u7tp85029XV6qGtp - rmI6VwnxddKIP9m58Z9N+f94P1dOdfskk5ub5GE+/TT78+KQylrIi/pXeaGKXlFn20xUUhUeVfjLQqhM - qHURU4V6L/UftCir9d2qS1y5vdin66q8EM+HtGgKofpfVsuLtHo87pVPXqyEgkUTSN29//lv/75Rd3Yh - wMv5v+nfLlb/AX6UzNRPn7dfCDrML16kF//+7xeJ/j+rf+up2X2yTVQtA19D/8f2D3/rgf+wHFLUVEuH - 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 - zH4XHtP0zp7SdLlyqJBjwzwRxTLtiG1G0CP9EgjKp7/r78zkWZ/hBrM2Sb7fQL4nyff2PPpCd9UFGe6q - KfrUOpkTcHD2rE2ToQO0WcAKD3N01GYfA1nwUqeiadADtZdJpOv6E1Q9EcUaO+iTHwkjJrwo9Z09qe1y - Re3Bc21DHUG8ns07CopHoHboD19+++ve7ge16wCmtlLZPdWrPRIM3+myFNv2vMqpc6FvrHkq1o/5FzCB - X1kfzPSV7csUzaEbdNoTZEUSaJfL8lVkry8jD/j9YA51tIuJzRw/FDGbBQQedqH8aH850mkgui8luMbU - tN7jO8ydpT7XzIpndV73yOc70EXE6bur7Y7VOwh1pRHXfrbMtGzVqhqYumfkMb9rn6f5w1Mx6rSwQaiP - HPRTwQdXE9KI23Tdi8qb+qXKy1bZewDxBOHvf/s/JvhepaXSBAA= + H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oALS9W3PbyJamfd+/QjFzMx2xo9uSyy7v + 746W6DLbsqQm6Zpy3yBAAhSxDQI0EpSl+vWTCYBAHtZKYK3UF7GjuyzifV4gz+f8z/+8eEyLtIrrNLnY + vPT/iDZllRWPQuTRsUp32XO0T+Mkrf5D7C/K4uJj8+tqdXuxLQ+HrP7/LjYfNm/T9+nl5eX7979f/jP+ + kG528W9vt2+2SfrPOPk9efd7/OG33ft/+7f//M+L6/L4UmWP+/ri/2z//eLqzeWHf1z8UZaPeXqxKLb/ + IR9RTz2k1SETIpN+dXlxEuk/pNvx5R8XhzLJdvL/x0Xyn2V1kWSirrLNqU4v6n0mLkS5q3/FVXqxkz/G + xYtiHU/VsRTpxa+slh9QNf+/PNUXuzS9kJJ9WqXq66u4kAHxj4tjVT5liQySeh/X8v+kF/GmfEoVadu/ + e1HW2TZVb9H6Hof3Pf90PKZxdZEVF3GeK2WWivPXrT/PL1b3n9b/d7acXyxWFw/L+z8XN/Obi/81W8l/ + /6+L2d1N89Ds2/rz/fLiZrG6vp0tvq4uZre3F1K1nN2tF/OVYv3fxfrzxXL+x2wpJfdSJXkD++769tvN + 4u6PRrj4+nC7kC4D4OL+k2J8nS+vP8u/zD4ubhfr7439p8X6br5a/YdkXNzdX8z/nN+tL1afFUd7s4/z + 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 + SWWH6qnMiloNzwDiCcK///V/4K+mmdHmBAA= EOF # PrivacyInfo.xcprivacy is not part of BoringSSL repo, inject it during pod installation @@ -706,10 +709,10 @@ Pod::Spec.new do |s| EOF # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists - find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include ;#include ;g' + find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' -or -path '*.inc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include ;#include ;g' END_OF_COMMAND end diff --git a/src/objective-c/GRPCClient/version.h b/src/objective-c/GRPCClient/version.h index 3817610281..46ede4a14b 100644 --- a/src/objective-c/GRPCClient/version.h +++ b/src/objective-c/GRPCClient/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.67.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.68.0-dev"