diff options
author | Craig Tiller <ctiller@google.com> | 2016-08-04 09:22:34 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2016-08-04 09:22:34 -0700 |
commit | 106df11093dbc19fe7e60fceeae5a7f9d3a7edf2 (patch) | |
tree | bef150c12f8dfefcd02f9fd91a980acfa853d369 /src | |
parent | 3e426718f05343d064fe998578acea6eaa7df622 (diff) | |
parent | f14effb6e421601639ef9a293f3f9b55a51e87ed (diff) |
Merge github.com:grpc/grpc into grand-unified-closures
Diffstat (limited to 'src')
224 files changed, 5225 insertions, 3672 deletions
diff --git a/src/compiler/ruby_generator_helpers-inl.h b/src/compiler/ruby_generator_helpers-inl.h index ff6939ed9f..aa3c22fea6 100644 --- a/src/compiler/ruby_generator_helpers-inl.h +++ b/src/compiler/ruby_generator_helpers-inl.h @@ -48,7 +48,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file, file->name().find_last_of(".proto") == file->name().size() - 1) { *file_name_or_error = file->name().substr(0, file->name().size() - proto_suffix_length) + - "_services.rb"; + "_services_pb.rb"; return true; } else { *file_name_or_error = "Invalid proto file name: must end with .proto"; @@ -58,7 +58,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file, inline grpc::string MessagesRequireName( const grpc::protobuf::FileDescriptor *file) { - return Replace(file->name(), ".proto", ""); + return Replace(file->name(), ".proto", "_pb"); } // Get leading or trailing comments in a string. Comment lines start with "# ". diff --git a/src/core/ext/census/base_resources.c b/src/core/ext/census/base_resources.c new file mode 100644 index 0000000000..f9aa4bb994 --- /dev/null +++ b/src/core/ext/census/base_resources.c @@ -0,0 +1,71 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/census/base_resources.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/census.h> +#include <grpc/support/log.h> + +#include "src/core/ext/census/resource.h" + +// Add base RPC resource definitions for use by RPC runtime. +// +// TODO(aveitch): All of these are currently hardwired definitions encoded in +// the code in this file. These should be converted to use an external +// configuration mechanism, in which these resources are defined in a text +// file, which is compiled to .pb format and read by still-to-be-written +// configuration functions. + +// Define all base resources. This should be called by census initialization. +void define_base_resources() { + google_census_Resource_BasicUnit numerator = + google_census_Resource_BasicUnit_SECS; + resource r = {"client_rpc_latency", // name + "Client RPC latency in seconds", // description + 0, // prefix + 1, // n_numerators + &numerator, // numerators + 0, // n_denominators + NULL}; // denominators + define_resource(&r); + r = (resource){"server_rpc_latency", // name + "Server RPC latency in seconds", // description + 0, // prefix + 1, // n_numerators + &numerator, // numerators + 0, // n_denominators + NULL}; // denominators + define_resource(&r); +} diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/core/ext/census/base_resources.h index c0080b5a47..e5a7696db4 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/core/ext/census/base_resources.h @@ -1,5 +1,4 @@ /* - * * Copyright 2016, Google Inc. * All rights reserved. * @@ -31,7 +30,10 @@ * */ -/* TODO(atash) remove cruft */ -#include <grpc/support/port_platform.h> +#ifndef GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H +#define GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H + +/* Define all base resources. This should be called by census initialization. */ +void define_base_resources(); -#include "imports.generated.h" +#endif /* GRPC_CORE_EXT_CENSUS_BASE_RESOURCES_H */ diff --git a/src/core/ext/census/gen/census.pb.c b/src/core/ext/census/gen/census.pb.c index d614636c90..647f0635b7 100644 --- a/src/core/ext/census/gen/census.pb.c +++ b/src/core/ext/census/gen/census.pb.c @@ -53,29 +53,24 @@ const pb_field_t google_census_Timestamp_fields[3] = { PB_LAST_FIELD }; -const pb_field_t google_census_Metric_fields[5] = { - PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Metric, name, name, 0), - PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Metric, description, name, 0), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, unit, description, &google_census_Metric_MeasurementUnit_fields), - PB_FIELD( 4, INT32 , OPTIONAL, STATIC , OTHER, google_census_Metric, id, unit, 0), +const pb_field_t google_census_Resource_fields[4] = { + PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Resource, name, name, 0), + PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Resource, description, name, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Resource, unit, description, &google_census_Resource_MeasurementUnit_fields), PB_LAST_FIELD }; -const pb_field_t google_census_Metric_BasicUnit_fields[2] = { - PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, google_census_Metric_BasicUnit, type, type, 0), +const pb_field_t google_census_Resource_MeasurementUnit_fields[4] = { + PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, google_census_Resource_MeasurementUnit, prefix, prefix, 0), + PB_FIELD( 2, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, numerator, prefix, 0), + PB_FIELD( 3, UENUM , REPEATED, CALLBACK, OTHER, google_census_Resource_MeasurementUnit, denominator, numerator, 0), PB_LAST_FIELD }; -const pb_field_t google_census_Metric_MeasurementUnit_fields[4] = { - PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, google_census_Metric_MeasurementUnit, prefix, prefix, 0), - PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, numerator, prefix, &google_census_Metric_BasicUnit_fields), - PB_FIELD( 3, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric_MeasurementUnit, denominator, numerator, &google_census_Metric_BasicUnit_fields), - PB_LAST_FIELD -}; - -const pb_field_t google_census_AggregationDescriptor_fields[3] = { - PB_ONEOF_FIELD(options, 1, MESSAGE , ONEOF, STATIC , FIRST, google_census_AggregationDescriptor, bucket_boundaries, bucket_boundaries, &google_census_AggregationDescriptor_BucketBoundaries_fields), - PB_ONEOF_FIELD(options, 2, MESSAGE , ONEOF, STATIC , FIRST, google_census_AggregationDescriptor, interval_boundaries, interval_boundaries, &google_census_AggregationDescriptor_IntervalBoundaries_fields), +const pb_field_t google_census_AggregationDescriptor_fields[4] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, google_census_AggregationDescriptor, type, type, 0), + PB_ONEOF_FIELD(options, 2, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, bucket_boundaries, type, &google_census_AggregationDescriptor_BucketBoundaries_fields), + PB_ONEOF_FIELD(options, 3, MESSAGE , ONEOF, STATIC , OTHER, google_census_AggregationDescriptor, interval_boundaries, type, &google_census_AggregationDescriptor_IntervalBoundaries_fields), PB_LAST_FIELD }; @@ -124,25 +119,27 @@ const pb_field_t google_census_Tag_fields[3] = { const pb_field_t google_census_View_fields[6] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_View, name, name, 0), PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, description, name, 0), - PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, google_census_View, metric_id, description, 0), - PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_View, aggregation, metric_id, &google_census_AggregationDescriptor_fields), + PB_FIELD( 3, STRING , OPTIONAL, CALLBACK, OTHER, google_census_View, resource_name, description, 0), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_View, aggregation, resource_name, &google_census_AggregationDescriptor_fields), PB_FIELD( 5, STRING , REPEATED, CALLBACK, OTHER, google_census_View, tag_key, aggregation, 0), PB_LAST_FIELD }; -const pb_field_t google_census_Aggregation_fields[6] = { +const pb_field_t google_census_Aggregation_fields[7] = { PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Aggregation, name, name, 0), PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, google_census_Aggregation, description, name, 0), - PB_ONEOF_FIELD(data, 3, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields), - PB_ONEOF_FIELD(data, 4, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields), - PB_FIELD( 5, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields), + PB_ONEOF_FIELD(data, 3, UINT64 , ONEOF, STATIC , OTHER, google_census_Aggregation, count, description, 0), + PB_ONEOF_FIELD(data, 4, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, distribution, description, &google_census_Distribution_fields), + PB_ONEOF_FIELD(data, 5, MESSAGE , ONEOF, STATIC , OTHER, google_census_Aggregation, interval_stats, description, &google_census_IntervalStats_fields), + PB_FIELD( 6, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Aggregation, tag, data.interval_stats, &google_census_Tag_fields), PB_LAST_FIELD }; -const pb_field_t google_census_ViewAggregations_fields[4] = { - PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, google_census_ViewAggregations, aggregation, aggregation, &google_census_Aggregation_fields), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_ViewAggregations, start, aggregation, &google_census_Timestamp_fields), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_ViewAggregations, end, start, &google_census_Timestamp_fields), +const pb_field_t google_census_Metric_fields[5] = { + PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, google_census_Metric, view_name, view_name, 0), + PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, google_census_Metric, aggregation, view_name, &google_census_Aggregation_fields), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, start, aggregation, &google_census_Timestamp_fields), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, google_census_Metric, end, start, &google_census_Timestamp_fields), PB_LAST_FIELD }; @@ -156,7 +153,7 @@ const pb_field_t google_census_ViewAggregations_fields[4] = { * numbers or field sizes that are larger than what can fit in 8 or 16 bit * field descriptors. */ -PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Metric, unit) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 65536 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_ViewAggregations, aggregation) < 65536 && pb_membersize(google_census_ViewAggregations, start) < 65536 && pb_membersize(google_census_ViewAggregations, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations) +PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Resource, unit) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 65536 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 65536 && pb_membersize(google_census_Distribution, range) < 65536 && pb_membersize(google_census_IntervalStats, window) < 65536 && pb_membersize(google_census_IntervalStats_Window, window_size) < 65536 && pb_membersize(google_census_View, aggregation) < 65536 && pb_membersize(google_census_Aggregation, data.distribution) < 65536 && pb_membersize(google_census_Aggregation, data.interval_stats) < 65536 && pb_membersize(google_census_Aggregation, tag) < 65536 && pb_membersize(google_census_Metric, aggregation) < 65536 && pb_membersize(google_census_Metric, start) < 65536 && pb_membersize(google_census_Metric, end) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) @@ -167,7 +164,7 @@ PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 65536 && pb_member * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Metric, unit) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, numerator) < 256 && pb_membersize(google_census_Metric_MeasurementUnit, denominator) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_ViewAggregations, aggregation) < 256 && pb_membersize(google_census_ViewAggregations, start) < 256 && pb_membersize(google_census_ViewAggregations, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Metric_google_census_Metric_BasicUnit_google_census_Metric_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_ViewAggregations) +PB_STATIC_ASSERT((pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Resource, unit) < 256 && pb_membersize(google_census_AggregationDescriptor, options.bucket_boundaries) < 256 && pb_membersize(google_census_AggregationDescriptor, options.interval_boundaries) < 256 && pb_membersize(google_census_Distribution, range) < 256 && pb_membersize(google_census_IntervalStats, window) < 256 && pb_membersize(google_census_IntervalStats_Window, window_size) < 256 && pb_membersize(google_census_View, aggregation) < 256 && pb_membersize(google_census_Aggregation, data.distribution) < 256 && pb_membersize(google_census_Aggregation, data.interval_stats) < 256 && pb_membersize(google_census_Aggregation, tag) < 256 && pb_membersize(google_census_Metric, aggregation) < 256 && pb_membersize(google_census_Metric, start) < 256 && pb_membersize(google_census_Metric, end) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_census_Duration_google_census_Timestamp_google_census_Resource_google_census_Resource_MeasurementUnit_google_census_AggregationDescriptor_google_census_AggregationDescriptor_BucketBoundaries_google_census_AggregationDescriptor_IntervalBoundaries_google_census_Distribution_google_census_Distribution_Range_google_census_IntervalStats_google_census_IntervalStats_Window_google_census_Tag_google_census_View_google_census_Aggregation_google_census_Metric) #endif diff --git a/src/core/ext/census/gen/census.pb.h b/src/core/ext/census/gen/census.pb.h index d040fe29e7..dae583f33d 100644 --- a/src/core/ext/census/gen/census.pb.h +++ b/src/core/ext/census/gen/census.pb.h @@ -45,14 +45,21 @@ extern "C" { #endif /* Enum definitions */ -typedef enum _google_census_Metric_BasicUnit_Measure { - google_census_Metric_BasicUnit_Measure_UNKNOWN = 0, - google_census_Metric_BasicUnit_Measure_BITS = 1, - google_census_Metric_BasicUnit_Measure_BYTES = 2, - google_census_Metric_BasicUnit_Measure_SECS = 3, - google_census_Metric_BasicUnit_Measure_CORES = 4, - google_census_Metric_BasicUnit_Measure_MAX_UNITS = 5 -} google_census_Metric_BasicUnit_Measure; +typedef enum _google_census_Resource_BasicUnit { + google_census_Resource_BasicUnit_UNKNOWN = 0, + google_census_Resource_BasicUnit_BITS = 1, + google_census_Resource_BasicUnit_BYTES = 2, + google_census_Resource_BasicUnit_SECS = 3, + google_census_Resource_BasicUnit_CORES = 4, + google_census_Resource_BasicUnit_MAX_UNITS = 5 +} google_census_Resource_BasicUnit; + +typedef enum _google_census_AggregationDescriptor_AggregationType { + google_census_AggregationDescriptor_AggregationType_UNKNOWN = 0, + google_census_AggregationDescriptor_AggregationType_COUNT = 1, + google_census_AggregationDescriptor_AggregationType_DISTRIBUTION = 2, + google_census_AggregationDescriptor_AggregationType_INTERVAL = 3 +} google_census_AggregationDescriptor_AggregationType; /* Struct definitions */ typedef struct _google_census_AggregationDescriptor_BucketBoundaries { @@ -68,6 +75,8 @@ typedef struct _google_census_IntervalStats { } google_census_IntervalStats; typedef struct _google_census_AggregationDescriptor { + bool has_type; + google_census_AggregationDescriptor_AggregationType type; pb_size_t which_options; union { google_census_AggregationDescriptor_BucketBoundaries bucket_boundaries; @@ -89,17 +98,12 @@ typedef struct _google_census_Duration { int32_t nanos; } google_census_Duration; -typedef struct _google_census_Metric_BasicUnit { - bool has_type; - google_census_Metric_BasicUnit_Measure type; -} google_census_Metric_BasicUnit; - -typedef struct _google_census_Metric_MeasurementUnit { +typedef struct _google_census_Resource_MeasurementUnit { bool has_prefix; int32_t prefix; pb_callback_t numerator; pb_callback_t denominator; -} google_census_Metric_MeasurementUnit; +} google_census_Resource_MeasurementUnit; typedef struct _google_census_Tag { bool has_key; @@ -135,37 +139,36 @@ typedef struct _google_census_IntervalStats_Window { } google_census_IntervalStats_Window; typedef struct _google_census_Metric { + pb_callback_t view_name; + pb_callback_t aggregation; + bool has_start; + google_census_Timestamp start; + bool has_end; + google_census_Timestamp end; +} google_census_Metric; + +typedef struct _google_census_Resource { pb_callback_t name; pb_callback_t description; bool has_unit; - google_census_Metric_MeasurementUnit unit; - bool has_id; - int32_t id; -} google_census_Metric; + google_census_Resource_MeasurementUnit unit; +} google_census_Resource; typedef struct _google_census_View { pb_callback_t name; pb_callback_t description; - bool has_metric_id; - int32_t metric_id; + pb_callback_t resource_name; bool has_aggregation; google_census_AggregationDescriptor aggregation; pb_callback_t tag_key; } google_census_View; -typedef struct _google_census_ViewAggregations { - pb_callback_t aggregation; - bool has_start; - google_census_Timestamp start; - bool has_end; - google_census_Timestamp end; -} google_census_ViewAggregations; - typedef struct _google_census_Aggregation { pb_callback_t name; pb_callback_t description; pb_size_t which_data; union { + uint64_t count; google_census_Distribution distribution; google_census_IntervalStats interval_stats; } data; @@ -177,10 +180,9 @@ typedef struct _google_census_Aggregation { /* Initializer values for message structs */ #define google_census_Duration_init_default {false, 0, false, 0} #define google_census_Timestamp_init_default {false, 0, false, 0} -#define google_census_Metric_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_default, false, 0} -#define google_census_Metric_BasicUnit_init_default {false, (google_census_Metric_BasicUnit_Measure)0} -#define google_census_Metric_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} -#define google_census_AggregationDescriptor_init_default {0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}} +#define google_census_Resource_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_default} +#define google_census_Resource_MeasurementUnit_init_default {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} +#define google_census_AggregationDescriptor_init_default {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_default}} #define google_census_AggregationDescriptor_BucketBoundaries_init_default {{{NULL}, NULL}} #define google_census_AggregationDescriptor_IntervalBoundaries_init_default {{{NULL}, NULL}} #define google_census_Distribution_init_default {false, 0, false, 0, false, google_census_Distribution_Range_init_default, {{NULL}, NULL}} @@ -188,15 +190,14 @@ typedef struct _google_census_Aggregation { #define google_census_IntervalStats_init_default {{{NULL}, NULL}} #define google_census_IntervalStats_Window_init_default {false, google_census_Duration_init_default, false, 0, false, 0} #define google_census_Tag_init_default {false, "", false, ""} -#define google_census_View_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}} -#define google_census_Aggregation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_default}, {{NULL}, NULL}} -#define google_census_ViewAggregations_init_default {{{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default} +#define google_census_View_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_default, {{NULL}, NULL}} +#define google_census_Aggregation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}} +#define google_census_Metric_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_default, false, google_census_Timestamp_init_default} #define google_census_Duration_init_zero {false, 0, false, 0} #define google_census_Timestamp_init_zero {false, 0, false, 0} -#define google_census_Metric_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Metric_MeasurementUnit_init_zero, false, 0} -#define google_census_Metric_BasicUnit_init_zero {false, (google_census_Metric_BasicUnit_Measure)0} -#define google_census_Metric_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} -#define google_census_AggregationDescriptor_init_zero {0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}} +#define google_census_Resource_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Resource_MeasurementUnit_init_zero} +#define google_census_Resource_MeasurementUnit_init_zero {false, 0, {{NULL}, NULL}, {{NULL}, NULL}} +#define google_census_AggregationDescriptor_init_zero {false, (google_census_AggregationDescriptor_AggregationType)0, 0, {google_census_AggregationDescriptor_BucketBoundaries_init_zero}} #define google_census_AggregationDescriptor_BucketBoundaries_init_zero {{{NULL}, NULL}} #define google_census_AggregationDescriptor_IntervalBoundaries_init_zero {{{NULL}, NULL}} #define google_census_Distribution_init_zero {false, 0, false, 0, false, google_census_Distribution_Range_init_zero, {{NULL}, NULL}} @@ -204,25 +205,25 @@ typedef struct _google_census_Aggregation { #define google_census_IntervalStats_init_zero {{{NULL}, NULL}} #define google_census_IntervalStats_Window_init_zero {false, google_census_Duration_init_zero, false, 0, false, 0} #define google_census_Tag_init_zero {false, "", false, ""} -#define google_census_View_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, 0, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}} -#define google_census_Aggregation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, {google_census_Distribution_init_zero}, {{NULL}, NULL}} -#define google_census_ViewAggregations_init_zero {{{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero} +#define google_census_View_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, google_census_AggregationDescriptor_init_zero, {{NULL}, NULL}} +#define google_census_Aggregation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, {0}, {{NULL}, NULL}} +#define google_census_Metric_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, google_census_Timestamp_init_zero, false, google_census_Timestamp_init_zero} /* Field tags (for use in manual encoding/decoding) */ #define google_census_AggregationDescriptor_BucketBoundaries_bounds_tag 1 #define google_census_AggregationDescriptor_IntervalBoundaries_window_size_tag 1 #define google_census_IntervalStats_window_tag 1 -#define google_census_AggregationDescriptor_bucket_boundaries_tag 1 +#define google_census_AggregationDescriptor_bucket_boundaries_tag 2 -#define google_census_AggregationDescriptor_interval_boundaries_tag 2 +#define google_census_AggregationDescriptor_interval_boundaries_tag 3 +#define google_census_AggregationDescriptor_type_tag 1 #define google_census_Distribution_Range_min_tag 1 #define google_census_Distribution_Range_max_tag 2 #define google_census_Duration_seconds_tag 1 #define google_census_Duration_nanos_tag 2 -#define google_census_Metric_BasicUnit_type_tag 1 -#define google_census_Metric_MeasurementUnit_prefix_tag 1 -#define google_census_Metric_MeasurementUnit_numerator_tag 2 -#define google_census_Metric_MeasurementUnit_denominator_tag 3 +#define google_census_Resource_MeasurementUnit_prefix_tag 1 +#define google_census_Resource_MeasurementUnit_numerator_tag 2 +#define google_census_Resource_MeasurementUnit_denominator_tag 3 #define google_census_Tag_key_tag 1 #define google_census_Tag_value_tag 2 #define google_census_Timestamp_seconds_tag 1 @@ -234,32 +235,33 @@ typedef struct _google_census_Aggregation { #define google_census_IntervalStats_Window_window_size_tag 1 #define google_census_IntervalStats_Window_count_tag 2 #define google_census_IntervalStats_Window_mean_tag 3 -#define google_census_Metric_name_tag 1 -#define google_census_Metric_description_tag 2 -#define google_census_Metric_unit_tag 3 -#define google_census_Metric_id_tag 4 +#define google_census_Metric_view_name_tag 1 +#define google_census_Metric_aggregation_tag 2 +#define google_census_Metric_start_tag 3 +#define google_census_Metric_end_tag 4 +#define google_census_Resource_name_tag 1 +#define google_census_Resource_description_tag 2 +#define google_census_Resource_unit_tag 3 #define google_census_View_name_tag 1 #define google_census_View_description_tag 2 -#define google_census_View_metric_id_tag 3 +#define google_census_View_resource_name_tag 3 #define google_census_View_aggregation_tag 4 #define google_census_View_tag_key_tag 5 -#define google_census_ViewAggregations_aggregation_tag 1 -#define google_census_ViewAggregations_start_tag 2 -#define google_census_ViewAggregations_end_tag 3 -#define google_census_Aggregation_distribution_tag 3 +#define google_census_Aggregation_count_tag 3 + +#define google_census_Aggregation_distribution_tag 4 -#define google_census_Aggregation_interval_stats_tag 4 +#define google_census_Aggregation_interval_stats_tag 5 #define google_census_Aggregation_name_tag 1 #define google_census_Aggregation_description_tag 2 -#define google_census_Aggregation_tag_tag 5 +#define google_census_Aggregation_tag_tag 6 /* Struct field encoding specification for nanopb */ extern const pb_field_t google_census_Duration_fields[3]; extern const pb_field_t google_census_Timestamp_fields[3]; -extern const pb_field_t google_census_Metric_fields[5]; -extern const pb_field_t google_census_Metric_BasicUnit_fields[2]; -extern const pb_field_t google_census_Metric_MeasurementUnit_fields[4]; -extern const pb_field_t google_census_AggregationDescriptor_fields[3]; +extern const pb_field_t google_census_Resource_fields[4]; +extern const pb_field_t google_census_Resource_MeasurementUnit_fields[4]; +extern const pb_field_t google_census_AggregationDescriptor_fields[4]; extern const pb_field_t google_census_AggregationDescriptor_BucketBoundaries_fields[2]; extern const pb_field_t google_census_AggregationDescriptor_IntervalBoundaries_fields[2]; extern const pb_field_t google_census_Distribution_fields[5]; @@ -268,13 +270,12 @@ extern const pb_field_t google_census_IntervalStats_fields[2]; extern const pb_field_t google_census_IntervalStats_Window_fields[4]; extern const pb_field_t google_census_Tag_fields[3]; extern const pb_field_t google_census_View_fields[6]; -extern const pb_field_t google_census_Aggregation_fields[6]; -extern const pb_field_t google_census_ViewAggregations_fields[4]; +extern const pb_field_t google_census_Aggregation_fields[7]; +extern const pb_field_t google_census_Metric_fields[5]; /* Maximum encoded size of messages (where known) */ #define google_census_Duration_size 22 #define google_census_Timestamp_size 22 -#define google_census_Metric_BasicUnit_size 2 #define google_census_Distribution_Range_size 18 #define google_census_IntervalStats_Window_size 44 #define google_census_Tag_size 516 diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c index f51d850e01..9dacc17eb4 100644 --- a/src/core/ext/census/grpc_filter.c +++ b/src/core/ext/census/grpc_filter.c @@ -127,38 +127,40 @@ static void server_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_next_op(exec_ctx, elem, op); } -static void client_init_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); memset(d, 0, sizeof(*d)); d->start_ts = gpr_now(GPR_CLOCK_REALTIME); + return GRPC_ERROR_NONE; } static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); /* TODO(hongyu): record rpc client stats and census_rpc_end_op here */ } -static void server_init_call_elem(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); memset(d, 0, sizeof(*d)); d->start_ts = gpr_now(GPR_CLOCK_REALTIME); /* TODO(hongyu): call census_tracing_start_op here. */ grpc_closure_init(&d->finish_recv, server_on_done_recv, elem); + return GRPC_ERROR_NONE; } static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *ignored) { call_data *d = elem->call_data; GPR_ASSERT(d != NULL); diff --git a/src/core/ext/census/initialize.c b/src/core/ext/census/initialize.c index 896276e44a..55cbbe8e95 100644 --- a/src/core/ext/census/initialize.c +++ b/src/core/ext/census/initialize.c @@ -32,19 +32,31 @@ */ #include <grpc/census.h> +#include "src/core/ext/census/base_resources.h" +#include "src/core/ext/census/resource.h" static int features_enabled = CENSUS_FEATURE_NONE; int census_initialize(int features) { if (features_enabled != CENSUS_FEATURE_NONE) { // Must have been a previous call to census_initialize; return error - return 1; + return -1; } - features_enabled = features; - return 0; + features_enabled = features & CENSUS_FEATURE_ALL; + if (features & CENSUS_FEATURE_STATS) { + initialize_resources(); + define_base_resources(); + } + + return features_enabled; } -void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; } +void census_shutdown(void) { + if (features_enabled & CENSUS_FEATURE_STATS) { + shutdown_resources(); + } + features_enabled = CENSUS_FEATURE_NONE; +} int census_supported(void) { /* TODO(aveitch): improve this as we implement features... */ diff --git a/src/core/ext/census/placeholders.c b/src/core/ext/census/placeholders.c index fe23d13971..9f99c5bdcf 100644 --- a/src/core/ext/census/placeholders.c +++ b/src/core/ext/census/placeholders.c @@ -62,48 +62,3 @@ int census_trace_scan_start(int consume) { (void)consume; abort(); } - -const census_aggregation *census_view_aggregrations(const census_view *view) { - (void)view; - abort(); -} - -census_view *census_view_create(uint32_t metric_id, const census_context *tags, - const census_aggregation *aggregations, - size_t naggregations) { - (void)metric_id; - (void)tags; - (void)aggregations; - (void)naggregations; - abort(); -} - -const census_context *census_view_tags(const census_view *view) { - (void)view; - abort(); -} - -void census_view_delete(census_view *view) { - (void)view; - abort(); -} - -const census_view_data *census_view_get_data(const census_view *view) { - (void)view; - abort(); -} - -size_t census_view_metric(const census_view *view) { - (void)view; - abort(); -} - -size_t census_view_naggregations(const census_view *view) { - (void)view; - abort(); -} - -void census_view_reset(census_view *view) { - (void)view; - abort(); -} diff --git a/src/core/ext/census/resource.c b/src/core/ext/census/resource.c new file mode 100644 index 0000000000..ed44f004f9 --- /dev/null +++ b/src/core/ext/census/resource.c @@ -0,0 +1,312 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/census/resource.h" +#include "third_party/nanopb/pb_decode.h" + +#include <grpc/census.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/sync.h> + +#include <stdbool.h> +#include <string.h> + +// Protect local resource data structures. +static gpr_mu resource_lock; + +// Deleteing and creating resources are relatively rare events, and should not +// be done in the critical path of performance sensitive code. We record +// current resource id's used in a simple array, and just search it each time +// we need to assign a new id, or look up a resource. +static resource **resources = NULL; + +// Number of entries in *resources +static size_t n_resources = 0; + +// Number of defined resources +static size_t n_defined_resources = 0; + +void initialize_resources(void) { + gpr_mu_init(&resource_lock); + gpr_mu_lock(&resource_lock); + GPR_ASSERT(resources == NULL && n_resources == 0 && n_defined_resources == 0); + gpr_mu_unlock(&resource_lock); +} + +// Delete a resource given it's ID. The ID must be a valid resource ID. Must be +// called with resource_lock held. +static void delete_resource_locked(size_t rid) { + GPR_ASSERT(resources[rid] != NULL); + gpr_free(resources[rid]->name); + gpr_free(resources[rid]->description); + gpr_free(resources[rid]->numerators); + gpr_free(resources[rid]->denominators); + gpr_free(resources[rid]); + resources[rid] = NULL; + n_defined_resources--; +} + +void shutdown_resources(void) { + gpr_mu_lock(&resource_lock); + for (size_t i = 0; i < n_resources; i++) { + if (resources[i] != NULL) { + delete_resource_locked(i); + } + } + GPR_ASSERT(n_defined_resources == 0); + gpr_free(resources); + resources = NULL; + n_resources = 0; + gpr_mu_unlock(&resource_lock); +} + +// Check the contents of string fields in a resource proto. +static bool validate_string(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + resource *vresource = (resource *)*arg; + switch (field->tag) { + case google_census_Resource_name_tag: + // Name must have at least one character + if (stream->bytes_left == 0) { + gpr_log(GPR_INFO, "Zero-length Resource name."); + return false; + } + vresource->name = gpr_malloc(stream->bytes_left + 1); + vresource->name[stream->bytes_left] = '\0'; + if (!pb_read(stream, (uint8_t *)vresource->name, stream->bytes_left)) { + return false; + } + // Can't have same name as an existing resource. + for (size_t i = 0; i < n_resources; i++) { + resource *compare = resources[i]; + if (compare == vresource || compare == NULL) continue; + if (strcmp(compare->name, vresource->name) == 0) { + gpr_log(GPR_INFO, "Duplicate Resource name %s.", vresource->name); + return false; + } + } + break; + case google_census_Resource_description_tag: + if (stream->bytes_left == 0) { + return true; + } + vresource->description = gpr_malloc(stream->bytes_left + 1); + vresource->description[stream->bytes_left] = '\0'; + if (!pb_read(stream, (uint8_t *)vresource->description, + stream->bytes_left)) { + return false; + } + break; + default: + // No other string fields in Resource. Print warning and skip. + gpr_log(GPR_INFO, "Unknown string field type in Resource protobuf."); + if (!pb_read(stream, NULL, stream->bytes_left)) { + return false; + } + break; + } + return true; +} + +// Decode numerators/denominators in a stream. The `count` and `bup` +// (BasicUnit pointer) are pointers to the approriate fields in a resource +// struct. +static bool validate_units_helper(pb_istream_t *stream, int *count, + google_census_Resource_BasicUnit **bup) { + while (stream->bytes_left) { + (*count)++; + // Have to allocate a new array of values. Normal case is 0 or 1, so + // this should normally not be an issue. + google_census_Resource_BasicUnit *new_bup = + gpr_malloc((size_t)*count * sizeof(google_census_Resource_BasicUnit)); + if (*count != 1) { + memcpy(new_bup, *bup, + (size_t)(*count - 1) * sizeof(google_census_Resource_BasicUnit)); + gpr_free(*bup); + } + *bup = new_bup; + uint64_t value; + if (!pb_decode_varint(stream, &value)) { + return false; + } + *(*bup + *count - 1) = (google_census_Resource_BasicUnit)value; + } + return true; +} + +// Validate units field of a Resource proto. +static bool validate_units(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + resource *vresource = (resource *)(*arg); + switch (field->tag) { + case google_census_Resource_MeasurementUnit_numerator_tag: + return validate_units_helper(stream, &vresource->n_numerators, + &vresource->numerators); + break; + case google_census_Resource_MeasurementUnit_denominator_tag: + return validate_units_helper(stream, &vresource->n_denominators, + &vresource->denominators); + break; + default: + gpr_log(GPR_ERROR, "Unknown field type."); + return false; + break; + } + return true; +} + +// Validate the contents of a Resource proto. `id` is the intended resource id. +static bool validate_resource_pb(const uint8_t *resource_pb, + size_t resource_pb_size, size_t id) { + GPR_ASSERT(id < n_resources); + if (resource_pb == NULL) { + return false; + } + google_census_Resource vresource; + vresource.name.funcs.decode = &validate_string; + vresource.name.arg = resources[id]; + vresource.description.funcs.decode = &validate_string; + vresource.description.arg = resources[id]; + vresource.unit.numerator.funcs.decode = &validate_units; + vresource.unit.numerator.arg = resources[id]; + vresource.unit.denominator.funcs.decode = &validate_units; + vresource.unit.denominator.arg = resources[id]; + + pb_istream_t stream = + pb_istream_from_buffer((uint8_t *)resource_pb, resource_pb_size); + if (!pb_decode(&stream, google_census_Resource_fields, &vresource)) { + return false; + } + // A Resource must have a name, a unit, with at least one numerator. + return (resources[id]->name != NULL && vresource.has_unit && + resources[id]->n_numerators > 0); +} + +// Allocate a blank resource, and return associated ID. Must be called with +// resource_lock held. +size_t allocate_resource(void) { + // use next_id to optimize expected placement of next new resource. + static size_t next_id = 0; + size_t id = n_resources; // resource ID - initialize to invalid value. + // Expand resources if needed. + if (n_resources == n_defined_resources) { + size_t new_n_resources = n_resources ? n_resources * 2 : 2; + resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *)); + memcpy(new_resources, resources, n_resources * sizeof(resource *)); + memset(new_resources + n_resources, 0, + (new_n_resources - n_resources) * sizeof(resource *)); + gpr_free(resources); + resources = new_resources; + n_resources = new_n_resources; + id = n_defined_resources; + } else { + GPR_ASSERT(n_defined_resources < n_resources); + // Find a free id. + for (size_t base = 0; base < n_resources; base++) { + id = (next_id + base) % n_resources; + if (resources[id] == NULL) break; + } + } + GPR_ASSERT(id < n_resources && resources[id] == NULL); + resources[id] = gpr_malloc(sizeof(resource)); + memset(resources[id], 0, sizeof(resource)); + n_defined_resources++; + next_id = (id + 1) % n_resources; + return id; +} + +int32_t census_define_resource(const uint8_t *resource_pb, + size_t resource_pb_size) { + if (resource_pb == NULL) { + return -1; + } + gpr_mu_lock(&resource_lock); + size_t id = allocate_resource(); + // Validate pb, extract name. + if (!validate_resource_pb(resource_pb, resource_pb_size, id)) { + delete_resource_locked(id); + gpr_mu_unlock(&resource_lock); + return -1; + } + gpr_mu_unlock(&resource_lock); + return (int32_t)id; +} + +void census_delete_resource(int32_t rid) { + gpr_mu_lock(&resource_lock); + if (rid >= 0 && (size_t)rid < n_resources && resources[rid] != NULL) { + delete_resource_locked((size_t)rid); + } + gpr_mu_unlock(&resource_lock); +} + +int32_t census_resource_id(const char *name) { + gpr_mu_lock(&resource_lock); + for (int32_t id = 0; (size_t)id < n_resources; id++) { + if (resources[id] != NULL && strcmp(resources[id]->name, name) == 0) { + gpr_mu_unlock(&resource_lock); + return id; + } + } + gpr_mu_unlock(&resource_lock); + return -1; +} + +int32_t define_resource(const resource *base) { + GPR_ASSERT(base != NULL && base->name != NULL && base->n_numerators > 0 && + base->numerators != NULL); + gpr_mu_lock(&resource_lock); + size_t id = allocate_resource(); + size_t len = strlen(base->name) + 1; + resources[id]->name = gpr_malloc(len); + memcpy(resources[id]->name, base->name, len); + if (base->description) { + len = strlen(base->description) + 1; + resources[id]->description = gpr_malloc(len); + memcpy(resources[id]->description, base->description, len); + } + resources[id]->prefix = base->prefix; + resources[id]->n_numerators = base->n_numerators; + len = (size_t)base->n_numerators * sizeof(*base->numerators); + resources[id]->numerators = gpr_malloc(len); + memcpy(resources[id]->numerators, base->numerators, len); + resources[id]->n_denominators = base->n_denominators; + if (base->n_denominators != 0) { + len = (size_t)base->n_denominators * sizeof(*base->denominators); + resources[id]->denominators = gpr_malloc(len); + memcpy(resources[id]->denominators, base->denominators, len); + } + gpr_mu_unlock(&resource_lock); + return (int32_t)id; +} diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/core/ext/census/resource.h index 8e5c9a8ce2..591bff07da 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/core/ext/census/resource.h @@ -31,20 +31,33 @@ * */ -/* TODO(atash) remove cruft */ -#ifndef PYGRPC_CYTHON_WINDOWS_IMPORTS_H_ -#define PYGRPC_CYTHON_WINDOWS_IMPORTS_H_ +/* Census-internal resource definition and manipluation functions. */ +#ifndef GRPC_CORE_EXT_CENSUS_RESOURCE_H +#define GRPC_CORE_EXT_CENSUS_RESOURCE_H -#include <grpc/support/port_platform.h> - -#include <grpc/byte_buffer.h> -#include <grpc/byte_buffer_reader.h> -#include <grpc/compression.h> #include <grpc/grpc.h> -#include <grpc/grpc_security.h> -#include <grpc/support/alloc.h> -#include <grpc/support/slice.h> -#include <grpc/support/time.h> -#include <grpc/status.h> +#include "src/core/ext/census/gen/census.pb.h" + +/* Internal representation of a resource. */ +typedef struct { + char *name; + char *description; + int32_t prefix; + int n_numerators; + google_census_Resource_BasicUnit *numerators; + int n_denominators; + google_census_Resource_BasicUnit *denominators; +} resource; + +/* Initialize and shutdown the resources subsystem. */ +void initialize_resources(void); +void shutdown_resources(void); + +/* Add a new resource, given a proposed resource structure. Returns the + resource ID, or -ve on failure. + TODO(aveitch): this function exists to support addition of the base + resources. It should be removed when we have the ability to add resources + from configuration files. */ +int32_t define_resource(const resource *base); -#endif +#endif /* GRPC_CORE_EXT_CENSUS_RESOURCE_H */ diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index a096435c98..2c0c4abffc 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -436,15 +436,17 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem, args->call_stack); + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *and_free_memory) { grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data); gpr_free(and_free_memory); diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h index 3cfd041d3a..a2f5446fc6 100644 --- a/src/core/ext/client_config/lb_policy.h +++ b/src/core/ext/client_config/lb_policy.h @@ -73,7 +73,7 @@ struct grpc_lb_policy_vtable { void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure); - /** try to enter a READY connectivity state */ + /** Try to enter a READY connectivity state */ void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); /** check the current connectivity of the lb_policy */ @@ -82,7 +82,9 @@ struct grpc_lb_policy_vtable { grpc_error **connectivity_error); /** call notify when the connectivity state of a channel changes from *state. - Updates *state with the new state of the policy */ + Updates *state with the new state of the policy. Calling with a NULL \a + state cancels the subscription. + */ void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connectivity_state *state, @@ -125,7 +127,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy, /** Given initial metadata in \a initial_metadata, find an appropriate target for this rpc, and 'return' it by calling \a on_complete after setting \a target. - Picking can be asynchronous. Any IO should be done under \a pollset. */ + Picking can be asynchronous. Any IO should be done under \a pollent. */ int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_polling_entity *pollent, grpc_metadata_batch *initial_metadata, @@ -147,8 +149,11 @@ void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq); +/** Try to enter a READY connectivity state */ void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); +/* Call notify when the connectivity state of a channel changes from \a *state. + * Updates \a *state with the new state of the policy */ void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_connectivity_state *state, diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index 43b88d2ce4..2c4364b259 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -700,19 +700,26 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel( return GET_CONNECTED_SUBCHANNEL(c, acq); } -grpc_subchannel_call *grpc_connected_subchannel_create_call( +grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, - grpc_polling_entity *pollent) { + grpc_polling_entity *pollent, grpc_subchannel_call **call) { grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); - grpc_subchannel_call *call = - gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); - grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call); - call->connection = con; + *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); + grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); + (*call)->connection = con; // Ref is added below. + grpc_error *error = + grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call, + NULL, NULL, callstk); + if (error != GRPC_ERROR_NONE) { + const char *error_string = grpc_error_string(error); + gpr_log(GPR_ERROR, "error: %s", error_string); + grpc_error_free_string(error_string); + gpr_free(*call); + return error; + } GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); - grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, call, - NULL, NULL, callstk); grpc_call_stack_set_pollset_or_pollset_set(exec_ctx, callstk, pollent); - return call; + return GRPC_ERROR_NONE; } grpc_call_stack *grpc_subchannel_call_get_call_stack( diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h index b6d39f5dc5..ae1d96e640 100644 --- a/src/core/ext/client_config/subchannel.h +++ b/src/core/ext/client_config/subchannel.h @@ -108,9 +108,9 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, GRPC_SUBCHANNEL_REF_EXTRA_ARGS); /** construct a subchannel call */ -grpc_subchannel_call *grpc_connected_subchannel_create_call( +grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, - grpc_polling_entity *pollent); + grpc_polling_entity *pollent, grpc_subchannel_call **subchannel_call); /** process a transport level op */ void grpc_connected_subchannel_process_transport_op( diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c index b10b204ff2..cda939b4a0 100644 --- a/src/core/ext/client_config/subchannel_call_holder.c +++ b/src/core/ext/client_config/subchannel_call_holder.c @@ -84,6 +84,11 @@ void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx, gpr_free(holder->waiting_ops); } +// The logic here is fairly complicated, due to (a) the fact that we +// need to handle the case where we receive the send op before the +// initial metadata op, and (b) the need for efficiency, especially in +// the streaming case. +// TODO(ctiller): Explain this more thoroughly. void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder, grpc_transport_stream_op *op) { @@ -121,7 +126,8 @@ retry: } /* if this is a cancellation, then we can raise our cancelled flag */ if (op->cancel_error != GRPC_ERROR_NONE) { - if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, 1)) { + if (!gpr_atm_rel_cas(&holder->subchannel_call, 0, + (gpr_atm)(uintptr_t)CANCELLED_CALL)) { goto retry; } else { switch (holder->creation_phase) { @@ -158,10 +164,17 @@ retry: /* if we've got a subchannel, then let's ask it to create a call */ if (holder->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && holder->connected_subchannel != NULL) { - gpr_atm_rel_store( - &holder->subchannel_call, - (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call( - exec_ctx, holder->connected_subchannel, holder->pollent)); + grpc_subchannel_call *subchannel_call = NULL; + grpc_error *error = grpc_connected_subchannel_create_call( + exec_ctx, holder->connected_subchannel, holder->pollent, + &subchannel_call); + if (error != GRPC_ERROR_NONE) { + subchannel_call = CANCELLED_CALL; + fail_locked(exec_ctx, holder, GRPC_ERROR_REF(error)); + grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error); + } + gpr_atm_rel_store(&holder->subchannel_call, + (gpr_atm)(uintptr_t)subchannel_call); retry_waiting_locked(exec_ctx, holder); goto retry; } @@ -189,10 +202,17 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, GRPC_ERROR_CREATE_REFERENCING( "Cancelled before creating subchannel", &error, 1)); } else { - gpr_atm_rel_store( - &holder->subchannel_call, - (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call( - exec_ctx, holder->connected_subchannel, holder->pollent)); + grpc_subchannel_call *subchannel_call = NULL; + grpc_error *new_error = grpc_connected_subchannel_create_call( + exec_ctx, holder->connected_subchannel, holder->pollent, + &subchannel_call); + if (new_error != GRPC_ERROR_NONE) { + new_error = grpc_error_add_child(new_error, error); + subchannel_call = CANCELLED_CALL; + fail_locked(exec_ctx, holder, new_error); + } + gpr_atm_rel_store(&holder->subchannel_call, + (gpr_atm)(uintptr_t)subchannel_call); retry_waiting_locked(exec_ctx, holder); } gpr_mu_unlock(&holder->mu); diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c new file mode 100644 index 0000000000..dec25efe61 --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -0,0 +1,1039 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** Implementation of the gRPC LB policy. + * + * This policy takes as input a set of resolved addresses {a1..an} for which the + * LB set was set (it's the resolver's responsibility to ensure this). That is + * to say, {a1..an} represent a collection of LB servers. + * + * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}. + * This channel behaves just like a regular channel. In particular, the + * constructed URI over the addresses a1..an will use the default pick first + * policy to select from this list of LB server backends. + * + * The first time the policy gets a request for a pick, a ping, or to exit the + * idle state, \a query_for_backends() is called. It creates an instance of \a + * lb_client_data, an internal struct meant to contain the data associated with + * the internal communication with the LB server. This instance is created via + * \a lb_client_data_create(). There, the call over lb_channel to pick-first + * from {a1..an} is created, the \a LoadBalancingRequest message is assembled + * and all necessary callbacks for the progress of the internal call configured. + * + * Back in \a query_for_backends(), the internal *streaming* call to the LB + * server (whichever address from {a1..an} pick-first chose) is kicked off. + * It'll progress over the callbacks configured in \a lb_client_data_create() + * (see the field docstrings of \a lb_client_data for more details). + * + * If the call fails with UNIMPLEMENTED, the original call will also fail. + * There's a misconfiguration somewhere: at least one of {a1..an} isn't a LB + * server, which contradicts the LB bit being set. If the internal call times + * out, the usual behavior of pick-first applies, continuing to pick from the + * list {a1..an}. + * + * Upon sucesss, a \a LoadBalancingResponse is expected in \a res_recv_cb. An + * invalid one results in the termination of the streaming call. A new streaming + * call should be created if possible, failing the original call otherwise. + * For a valid \a LoadBalancingResponse, the server list of actual backends is + * extracted. A Round Robin policy will be created from this list. There are two + * possible scenarios: + * + * 1. This is the first server list received. There was no previous instance of + * the Round Robin policy. \a rr_handover() will instantiate the RR policy + * and perform all the pending operations over it. + * 2. There's already a RR policy instance active. We need to introduce the new + * one build from the new serverlist, but taking care not to disrupt the + * operations in progress over the old RR instance. This is done by + * decreasing the reference count on the old policy. The moment no more + * references are held on the old RR policy, it'll be destroyed and \a + * rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN state. + * At this point we can transition to a new RR instance safely, which is done + * once again via \a rr_handover(). + * + * + * Once a RR policy instance is in place (and getting updated as described), + * calls to for a pick, a ping or a cancellation will be serviced right away by + * forwarding them to the RR instance. Any time there's no RR policy available + * (ie, right after the creation of the gRPCLB policy, if an empty serverlist + * is received, etc), pick/ping requests are added to a list of pending + * picks/pings to be flushed and serviced as part of \a rr_handover() the moment + * the RR policy instance becomes available. + * + * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the + * high level design and details. */ + +/* TODO(dgq): + * - Implement LB service forwarding (point 2c. in the doc's diagram). + */ + +#include <string.h> + +#include <grpc/byte_buffer_reader.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/string_util.h> + +#include "src/core/ext/client_config/client_channel_factory.h" +#include "src/core/ext/client_config/lb_policy_registry.h" +#include "src/core/ext/client_config/parse_address.h" +#include "src/core/ext/lb_policy/grpclb/grpclb.h" +#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/channel.h" + +int grpc_lb_glb_trace = 0; + +typedef struct wrapped_rr_closure_arg { + /* the original closure. Usually a on_complete/notify cb for pick() and ping() + * calls against the internal RR instance, respectively. */ + grpc_closure *wrapped_closure; + + /* The RR instance related to the closure */ + grpc_lb_policy *rr_policy; + + /* when not NULL, represents a pending_{pick,ping} node to be freed upon + * closure execution */ + void *owning_pending_node; /* to be freed if not NULL */ +} wrapped_rr_closure_arg; + +/* The \a on_complete closure passed as part of the pick requires keeping a + * reference to its associated round robin instance. We wrap this closure in + * order to unref the round robin instance upon its invocation */ +static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + wrapped_rr_closure_arg *wc_arg = arg; + if (wc_arg->rr_policy != NULL) { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", + (intptr_t)wc_arg->rr_policy); + } + GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); + } + GPR_ASSERT(wc_arg->wrapped_closure != NULL); + grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, error, NULL); + gpr_free(wc_arg->owning_pending_node); +} + +/* Linked list of pending pick requests. It stores all information needed to + * eventually call (Round Robin's) pick() on them. They mainly stay pending + * waiting for the RR policy to be created/updated. + * + * One particularity is the wrapping of the user-provided \a on_complete closure + * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in + * order to correctly unref the RR policy instance upon completion of the pick. + * See \a wrapped_rr_closure for details. */ +typedef struct pending_pick { + struct pending_pick *next; + + /* polling entity for the pick()'s async notification */ + grpc_polling_entity *pollent; + + /* the initial metadata for the pick. See grpc_lb_policy_pick() */ + grpc_metadata_batch *initial_metadata; + + /* bitmask passed to pick() and used for selective cancelling. See + * grpc_lb_policy_cancel_picks() */ + uint32_t initial_metadata_flags; + + /* output argument where to store the pick()ed connected subchannel, or NULL + * upon error. */ + grpc_connected_subchannel **target; + + /* a closure wrapping the original on_complete one to be invoked once the + * pick() has completed (regardless of success) */ + grpc_closure wrapped_on_complete; + + /* args for wrapped_on_complete */ + wrapped_rr_closure_arg wrapped_on_complete_arg; +} pending_pick; + +static void add_pending_pick(pending_pick **root, grpc_polling_entity *pollent, + grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, + grpc_connected_subchannel **target, + grpc_closure *on_complete) { + pending_pick *pp = gpr_malloc(sizeof(*pp)); + memset(pp, 0, sizeof(pending_pick)); + memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg)); + pp->next = *root; + pp->pollent = pollent; + pp->target = target; + pp->initial_metadata = initial_metadata; + pp->initial_metadata_flags = initial_metadata_flags; + pp->wrapped_on_complete_arg.wrapped_closure = on_complete; + grpc_closure_init(&pp->wrapped_on_complete, wrapped_rr_closure, + &pp->wrapped_on_complete_arg); + *root = pp; +} + +/* Same as the \a pending_pick struct but for ping operations */ +typedef struct pending_ping { + struct pending_ping *next; + + /* a closure wrapping the original on_complete one to be invoked once the + * ping() has completed (regardless of success) */ + grpc_closure wrapped_notify; + + /* args for wrapped_notify */ + wrapped_rr_closure_arg wrapped_notify_arg; +} pending_ping; + +static void add_pending_ping(pending_ping **root, grpc_closure *notify) { + pending_ping *pping = gpr_malloc(sizeof(*pping)); + memset(pping, 0, sizeof(pending_ping)); + memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg)); + pping->next = *root; + grpc_closure_init(&pping->wrapped_notify, wrapped_rr_closure, + &pping->wrapped_notify_arg); + pping->wrapped_notify_arg.wrapped_closure = notify; + *root = pping; +} + +/* + * glb_lb_policy + */ +typedef struct rr_connectivity_data rr_connectivity_data; +struct lb_client_data; +static const grpc_lb_policy_vtable glb_lb_policy_vtable; +typedef struct glb_lb_policy { + /** base policy: must be first */ + grpc_lb_policy base; + + /** mutex protecting remaining members */ + gpr_mu mu; + + grpc_client_channel_factory *cc_factory; + + /** for communicating with the LB server */ + grpc_channel *lb_channel; + + /** the RR policy to use of the backend servers returned by the LB server */ + grpc_lb_policy *rr_policy; + + bool started_picking; + + /** our connectivity state tracker */ + grpc_connectivity_state_tracker state_tracker; + + /** stores the deserialized response from the LB. May be NULL until one such + * response has arrived. */ + grpc_grpclb_serverlist *serverlist; + + /** list of picks that are waiting on RR's policy connectivity */ + pending_pick *pending_picks; + + /** list of pings that are waiting on RR's policy connectivity */ + pending_ping *pending_pings; + + /** client data associated with the LB server communication */ + struct lb_client_data *lb_client; + + /** for tracking of the RR connectivity */ + rr_connectivity_data *rr_connectivity; + + /* a wrapped (see \a wrapped_rr_closure) on-complete closure for readily + * available RR picks */ + grpc_closure wrapped_on_complete; + + /* arguments for the wrapped_on_complete closure */ + wrapped_rr_closure_arg wc_arg; +} glb_lb_policy; + +/* Keeps track and reacts to changes in connectivity of the RR instance */ +struct rr_connectivity_data { + grpc_closure on_change; + grpc_connectivity_state state; + glb_lb_policy *glb_policy; +}; + +static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx, + const grpc_grpclb_serverlist *serverlist, + glb_lb_policy *glb_policy) { + /* TODO(dgq): support mixed ip version */ + GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0); + char **host_ports = gpr_malloc(sizeof(char *) * serverlist->num_servers); + for (size_t i = 0; i < serverlist->num_servers; ++i) { + gpr_join_host_port(&host_ports[i], serverlist->servers[i]->ip_address, + serverlist->servers[i]->port); + } + + size_t uri_path_len; + char *concat_ipports = gpr_strjoin_sep( + (const char **)host_ports, serverlist->num_servers, ",", &uri_path_len); + + grpc_lb_policy_args args; + args.client_channel_factory = glb_policy->cc_factory; + args.addresses = gpr_malloc(sizeof(grpc_resolved_addresses)); + args.addresses->naddrs = serverlist->num_servers; + args.addresses->addrs = + gpr_malloc(sizeof(grpc_resolved_address) * args.addresses->naddrs); + size_t out_addrs_idx = 0; + for (size_t i = 0; i < serverlist->num_servers; ++i) { + grpc_uri uri; + struct sockaddr_storage sa; + size_t sa_len; + uri.path = host_ports[i]; + if (parse_ipv4(&uri, &sa, &sa_len)) { /* TODO(dgq): add support for ipv6 */ + memcpy(args.addresses->addrs[out_addrs_idx].addr, &sa, sa_len); + args.addresses->addrs[out_addrs_idx].len = sa_len; + ++out_addrs_idx; + } else { + gpr_log(GPR_ERROR, "Invalid LB service address '%s', ignoring.", + host_ports[i]); + } + } + + grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args); + + gpr_free(concat_ipports); + for (size_t i = 0; i < serverlist->num_servers; i++) { + gpr_free(host_ports[i]); + } + gpr_free(host_ports); + gpr_free(args.addresses->addrs); + gpr_free(args.addresses); + return rr; +} + +static void rr_handover(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy, + grpc_error *error) { + GRPC_ERROR_REF(error); + glb_policy->rr_policy = + create_rr(exec_ctx, glb_policy->serverlist, glb_policy); + + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Created RR policy (0x%" PRIxPTR ")", + (intptr_t)glb_policy->rr_policy); + } + GPR_ASSERT(glb_policy->rr_policy != NULL); + glb_policy->rr_connectivity->state = grpc_lb_policy_check_connectivity( + exec_ctx, glb_policy->rr_policy, &error); + grpc_lb_policy_notify_on_state_change( + exec_ctx, glb_policy->rr_policy, &glb_policy->rr_connectivity->state, + &glb_policy->rr_connectivity->on_change); + grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, + glb_policy->rr_connectivity->state, error, + "rr_handover"); + grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy); + + /* flush pending ops */ + pending_pick *pp; + while ((pp = glb_policy->pending_picks)) { + glb_policy->pending_picks = pp->next; + GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick"); + pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy; + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "", + (intptr_t)glb_policy->rr_policy); + } + grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pp->pollent, + pp->initial_metadata, pp->initial_metadata_flags, + pp->target, &pp->wrapped_on_complete); + pp->wrapped_on_complete_arg.owning_pending_node = pp; + } + + pending_ping *pping; + while ((pping = glb_policy->pending_pings)) { + glb_policy->pending_pings = pping->next; + GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping"); + pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy; + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "", + (intptr_t)glb_policy->rr_policy); + } + grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, + &pping->wrapped_notify); + pping->wrapped_notify_arg.owning_pending_node = pping; + } + GRPC_ERROR_UNREF(error); +} + +static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + rr_connectivity_data *rr_conn_data = arg; + glb_lb_policy *glb_policy = rr_conn_data->glb_policy; + if (rr_conn_data->state == GRPC_CHANNEL_SHUTDOWN) { + if (glb_policy->serverlist != NULL) { + /* a RR policy is shutting down but there's a serverlist available -> + * perform a handover */ + rr_handover(exec_ctx, glb_policy, error); + } else { + /* shutting down and no new serverlist available. Bail out. */ + gpr_free(rr_conn_data); + } + } else { + if (error == GRPC_ERROR_NONE) { + /* RR not shutting down. Mimic the RR's policy state */ + grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, + rr_conn_data->state, error, + "rr_connectivity_changed"); + /* resubscribe */ + grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy, + &rr_conn_data->state, + &rr_conn_data->on_change); + } else { /* error */ + gpr_free(rr_conn_data); + } + } + GRPC_ERROR_UNREF(error); +} + +static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, + grpc_lb_policy_factory *factory, + grpc_lb_policy_args *args) { + glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy)); + memset(glb_policy, 0, sizeof(*glb_policy)); + + /* All input addresses in args->addresses come from a resolver that claims + * they are LB services. It's the resolver's responsibility to make sure this + * policy is only instantiated and used in that case. + * + * Create a client channel over them to communicate with a LB service */ + glb_policy->cc_factory = args->client_channel_factory; + GPR_ASSERT(glb_policy->cc_factory != NULL); + if (args->addresses->naddrs == 0) { + return NULL; + } + + /* construct a target from the args->addresses, in the form + * ipvX://ip1:port1,ip2:port2,... + * TODO(dgq): support mixed ip version */ + char **addr_strs = gpr_malloc(sizeof(char *) * args->addresses->naddrs); + addr_strs[0] = + grpc_sockaddr_to_uri((const struct sockaddr *)&args->addresses->addrs[0]); + for (size_t i = 1; i < args->addresses->naddrs; i++) { + GPR_ASSERT(grpc_sockaddr_to_string( + &addr_strs[i], + (const struct sockaddr *)&args->addresses->addrs[i], + true) == 0); + } + size_t uri_path_len; + char *target_uri_str = gpr_strjoin_sep( + (const char **)addr_strs, args->addresses->naddrs, ",", &uri_path_len); + + /* will pick using pick_first */ + glb_policy->lb_channel = grpc_client_channel_factory_create_channel( + exec_ctx, glb_policy->cc_factory, target_uri_str, + GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL); + + gpr_free(target_uri_str); + for (size_t i = 0; i < args->addresses->naddrs; i++) { + gpr_free(addr_strs[i]); + } + gpr_free(addr_strs); + + if (glb_policy->lb_channel == NULL) { + gpr_free(glb_policy); + return NULL; + } + + rr_connectivity_data *rr_connectivity = + gpr_malloc(sizeof(rr_connectivity_data)); + memset(rr_connectivity, 0, sizeof(rr_connectivity_data)); + grpc_closure_init(&rr_connectivity->on_change, rr_connectivity_changed, + rr_connectivity); + rr_connectivity->glb_policy = glb_policy; + glb_policy->rr_connectivity = rr_connectivity; + + grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable); + gpr_mu_init(&glb_policy->mu); + grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE, + "grpclb"); + return &glb_policy->base; +} + +static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + GPR_ASSERT(glb_policy->pending_picks == NULL); + GPR_ASSERT(glb_policy->pending_pings == NULL); + grpc_channel_destroy(glb_policy->lb_channel); + glb_policy->lb_channel = NULL; + grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker); + if (glb_policy->serverlist != NULL) { + grpc_grpclb_destroy_serverlist(glb_policy->serverlist); + } + gpr_mu_destroy(&glb_policy->mu); + gpr_free(glb_policy); +} + +static void lb_client_data_destroy(struct lb_client_data *lb_client); +static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + + pending_pick *pp = glb_policy->pending_picks; + glb_policy->pending_picks = NULL; + pending_ping *pping = glb_policy->pending_pings; + glb_policy->pending_pings = NULL; + gpr_mu_unlock(&glb_policy->mu); + + while (pp != NULL) { + pending_pick *next = pp->next; + *pp->target = NULL; + grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, GRPC_ERROR_NONE, + NULL); + gpr_free(pp); + pp = next; + } + + while (pping != NULL) { + pending_ping *next = pping->next; + grpc_exec_ctx_sched(exec_ctx, &pping->wrapped_notify, GRPC_ERROR_NONE, + NULL); + pping = next; + } + + if (glb_policy->rr_policy) { + /* unsubscribe */ + grpc_lb_policy_notify_on_state_change( + exec_ctx, glb_policy->rr_policy, NULL, + &glb_policy->rr_connectivity->on_change); + GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown"); + } + + lb_client_data_destroy(glb_policy->lb_client); + glb_policy->lb_client = NULL; + + grpc_connectivity_state_set( + exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN, + GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown"); +} + +static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + grpc_connected_subchannel **target) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + pending_pick *pp = glb_policy->pending_picks; + glb_policy->pending_picks = NULL; + while (pp != NULL) { + pending_pick *next = pp->next; + if (pp->target == target) { + grpc_polling_entity_del_from_pollset_set( + exec_ctx, pp->pollent, glb_policy->base.interested_parties); + *target = NULL; + grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, + GRPC_ERROR_CANCELLED, NULL); + gpr_free(pp); + } else { + pp->next = glb_policy->pending_picks; + glb_policy->pending_picks = pp; + } + pp = next; + } + gpr_mu_unlock(&glb_policy->mu); +} + +static grpc_call *lb_client_data_get_call(struct lb_client_data *lb_client); +static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + uint32_t initial_metadata_flags_mask, + uint32_t initial_metadata_flags_eq) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + if (glb_policy->lb_client != NULL) { + /* cancel the call to the load balancer service, if any */ + grpc_call_cancel(lb_client_data_get_call(glb_policy->lb_client), NULL); + } + pending_pick *pp = glb_policy->pending_picks; + glb_policy->pending_picks = NULL; + while (pp != NULL) { + pending_pick *next = pp->next; + if ((pp->initial_metadata_flags & initial_metadata_flags_mask) == + initial_metadata_flags_eq) { + grpc_polling_entity_del_from_pollset_set( + exec_ctx, pp->pollent, glb_policy->base.interested_parties); + grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, + GRPC_ERROR_CANCELLED, NULL); + gpr_free(pp); + } else { + pp->next = glb_policy->pending_picks; + glb_policy->pending_picks = pp; + } + pp = next; + } + gpr_mu_unlock(&glb_policy->mu); +} + +static void query_for_backends(grpc_exec_ctx *exec_ctx, + glb_lb_policy *glb_policy); +static void start_picking(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) { + glb_policy->started_picking = true; + query_for_backends(exec_ctx, glb_policy); +} + +static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + if (!glb_policy->started_picking) { + start_picking(exec_ctx, glb_policy); + } + gpr_mu_unlock(&glb_policy->mu); +} + +static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + grpc_polling_entity *pollent, + grpc_metadata_batch *initial_metadata, + uint32_t initial_metadata_flags, + grpc_connected_subchannel **target, + grpc_closure *on_complete) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + int r; + + if (glb_policy->rr_policy != NULL) { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "about to PICK from 0x%" PRIxPTR "", + (intptr_t)glb_policy->rr_policy); + } + GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick"); + memset(&glb_policy->wc_arg, 0, sizeof(wrapped_rr_closure_arg)); + glb_policy->wc_arg.rr_policy = glb_policy->rr_policy; + glb_policy->wc_arg.wrapped_closure = on_complete; + grpc_closure_init(&glb_policy->wrapped_on_complete, wrapped_rr_closure, + &glb_policy->wc_arg); + r = grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pollent, + initial_metadata, initial_metadata_flags, target, + &glb_policy->wrapped_on_complete); + if (r != 0) { + /* the call to grpc_lb_policy_pick has been sychronous. Unreffing the RR + * policy and notify the original callback */ + glb_policy->wc_arg.wrapped_closure = NULL; + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", + (intptr_t)glb_policy->wc_arg.rr_policy); + } + GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->wc_arg.rr_policy, "glb_pick"); + grpc_exec_ctx_sched(exec_ctx, glb_policy->wc_arg.wrapped_closure, + GRPC_ERROR_NONE, NULL); + } + } else { + grpc_polling_entity_add_to_pollset_set(exec_ctx, pollent, + glb_policy->base.interested_parties); + add_pending_pick(&glb_policy->pending_picks, pollent, initial_metadata, + initial_metadata_flags, target, on_complete); + + if (!glb_policy->started_picking) { + start_picking(exec_ctx, glb_policy); + } + r = 0; + } + gpr_mu_unlock(&glb_policy->mu); + return r; +} + +static grpc_connectivity_state glb_check_connectivity( + grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + grpc_error **connectivity_error) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + grpc_connectivity_state st; + gpr_mu_lock(&glb_policy->mu); + st = grpc_connectivity_state_check(&glb_policy->state_tracker, + connectivity_error); + gpr_mu_unlock(&glb_policy->mu); + return st; +} + +static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, + grpc_closure *closure) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + if (glb_policy->rr_policy) { + grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure); + } else { + add_pending_ping(&glb_policy->pending_pings, closure); + if (!glb_policy->started_picking) { + start_picking(exec_ctx, glb_policy); + } + } + gpr_mu_unlock(&glb_policy->mu); +} + +static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx, + grpc_lb_policy *pol, + grpc_connectivity_state *current, + grpc_closure *notify) { + glb_lb_policy *glb_policy = (glb_lb_policy *)pol; + gpr_mu_lock(&glb_policy->mu); + grpc_connectivity_state_notify_on_state_change( + exec_ctx, &glb_policy->state_tracker, current, notify); + + gpr_mu_unlock(&glb_policy->mu); +} + +/* + * lb_client_data + * + * Used internally for the client call to the LB */ +typedef struct lb_client_data { + gpr_mu mu; + + /* called once initial metadata's been sent */ + grpc_closure md_sent; + + /* called once initial metadata's been received */ + grpc_closure md_rcvd; + + /* called once the LoadBalanceRequest has been sent to the LB server. See + * src/proto/grpc/.../load_balancer.proto */ + grpc_closure req_sent; + + /* A response from the LB server has been received (or error). Process it */ + grpc_closure res_rcvd; + + /* After the client has sent a close to the LB server */ + grpc_closure close_sent; + + /* ... and the status from the LB server has been received */ + grpc_closure srv_status_rcvd; + + grpc_call *lb_call; /* streaming call to the LB server, */ + gpr_timespec deadline; /* for the streaming call to the LB server */ + + grpc_metadata_array initial_metadata_recv; /* initial MD from LB server */ + grpc_metadata_array trailing_metadata_recv; /* trailing MD from LB server */ + + /* what's being sent to the LB server. Note that its value may vary if the LB + * server indicates a redirect. */ + grpc_byte_buffer *request_payload; + + /* response from the LB server, if any. Processed in res_recv_cb() */ + grpc_byte_buffer *response_payload; + + /* the call's status and status detailset in srv_status_rcvd_cb() */ + grpc_status_code status; + char *status_details; + size_t status_details_capacity; + + /* pointer back to the enclosing policy */ + glb_lb_policy *glb_policy; +} lb_client_data; + +static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); +static void md_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); +static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); +static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); +static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); + +static lb_client_data *lb_client_data_create(glb_lb_policy *glb_policy) { + lb_client_data *lb_client = gpr_malloc(sizeof(lb_client_data)); + memset(lb_client, 0, sizeof(lb_client_data)); + + gpr_mu_init(&lb_client->mu); + grpc_closure_init(&lb_client->md_sent, md_sent_cb, lb_client); + + grpc_closure_init(&lb_client->md_rcvd, md_recv_cb, lb_client); + grpc_closure_init(&lb_client->req_sent, req_sent_cb, lb_client); + grpc_closure_init(&lb_client->res_rcvd, res_recv_cb, lb_client); + grpc_closure_init(&lb_client->close_sent, close_sent_cb, lb_client); + grpc_closure_init(&lb_client->srv_status_rcvd, srv_status_rcvd_cb, lb_client); + + /* TODO(dgq): get the deadline from the client config instead of fabricating + * one here. */ + lb_client->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(3, GPR_TIMESPAN)); + + lb_client->lb_call = grpc_channel_create_pollset_set_call( + glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS, + glb_policy->base.interested_parties, "/BalanceLoad", + NULL, /* FIXME(dgq): which "host" value to use? */ + lb_client->deadline, NULL); + + grpc_metadata_array_init(&lb_client->initial_metadata_recv); + grpc_metadata_array_init(&lb_client->trailing_metadata_recv); + + grpc_grpclb_request *request = grpc_grpclb_request_create( + "load.balanced.service.name"); /* FIXME(dgq): get the name of the load + balanced service from the resolver */ + gpr_slice request_payload_slice = grpc_grpclb_request_encode(request); + lb_client->request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + gpr_slice_unref(request_payload_slice); + grpc_grpclb_request_destroy(request); + + lb_client->status_details = NULL; + lb_client->status_details_capacity = 0; + lb_client->glb_policy = glb_policy; + return lb_client; +} + +static void lb_client_data_destroy(lb_client_data *lb_client) { + grpc_call_destroy(lb_client->lb_call); + grpc_metadata_array_destroy(&lb_client->initial_metadata_recv); + grpc_metadata_array_destroy(&lb_client->trailing_metadata_recv); + + grpc_byte_buffer_destroy(lb_client->request_payload); + + gpr_free(lb_client->status_details); + gpr_mu_destroy(&lb_client->mu); + gpr_free(lb_client); +} +static grpc_call *lb_client_data_get_call(lb_client_data *lb_client) { + return lb_client->lb_call; +} + +/* + * Auxiliary functions and LB client callbacks. + */ +static void query_for_backends(grpc_exec_ctx *exec_ctx, + glb_lb_policy *glb_policy) { + GPR_ASSERT(glb_policy->lb_channel != NULL); + + glb_policy->lb_client = lb_client_data_create(glb_policy); + grpc_call_error call_error; + grpc_op ops[1]; + memset(ops, 0, sizeof(ops)); + grpc_op *op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + call_error = grpc_call_start_batch_and_execute( + exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops), + &glb_policy->lb_client->md_sent); + GPR_ASSERT(GRPC_CALL_OK == call_error); + + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &glb_policy->lb_client->trailing_metadata_recv; + op->data.recv_status_on_client.status = &glb_policy->lb_client->status; + op->data.recv_status_on_client.status_details = + &glb_policy->lb_client->status_details; + op->data.recv_status_on_client.status_details_capacity = + &glb_policy->lb_client->status_details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + call_error = grpc_call_start_batch_and_execute( + exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops), + &glb_policy->lb_client->srv_status_rcvd); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + lb_client_data *lb_client = arg; + GPR_ASSERT(lb_client->lb_call); + grpc_op ops[1]; + memset(ops, 0, sizeof(ops)); + grpc_op *op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &lb_client->initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops), + &lb_client->md_rcvd); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +static void md_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + lb_client_data *lb_client = arg; + GPR_ASSERT(lb_client->lb_call); + grpc_op ops[1]; + memset(ops, 0, sizeof(ops)); + grpc_op *op = ops; + + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = lb_client->request_payload; + op->flags = 0; + op->reserved = NULL; + op++; + grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops), + &lb_client->req_sent); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + lb_client_data *lb_client = arg; + + grpc_op ops[1]; + memset(ops, 0, sizeof(ops)); + grpc_op *op = ops; + + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &lb_client->response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops), + &lb_client->res_rcvd); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + lb_client_data *lb_client = arg; + grpc_op ops[2]; + memset(ops, 0, sizeof(ops)); + grpc_op *op = ops; + if (lb_client->response_payload != NULL) { + /* Received data from the LB server. Look inside + * lb_client->response_payload, for + * a serverlist. */ + grpc_byte_buffer_reader bbr; + grpc_byte_buffer_reader_init(&bbr, lb_client->response_payload); + gpr_slice response_slice = grpc_byte_buffer_reader_readall(&bbr); + grpc_byte_buffer_destroy(lb_client->response_payload); + grpc_grpclb_serverlist *serverlist = + grpc_grpclb_response_parse_serverlist(response_slice); + if (serverlist != NULL) { + gpr_slice_unref(response_slice); + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Serverlist with %zu servers received", + serverlist->num_servers); + } + + /* update serverlist */ + if (serverlist->num_servers > 0) { + if (grpc_grpclb_serverlist_equals(lb_client->glb_policy->serverlist, + serverlist)) { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "Incoming server list identical to current, ignoring."); + } + } else { /* new serverlist */ + if (lb_client->glb_policy->serverlist != NULL) { + /* dispose of the old serverlist */ + grpc_grpclb_destroy_serverlist(lb_client->glb_policy->serverlist); + } + /* and update the copy in the glb_lb_policy instance */ + lb_client->glb_policy->serverlist = serverlist; + } + if (lb_client->glb_policy->rr_policy == NULL) { + /* initial "handover", in this case from a null RR policy, meaning + * it'll just create the first RR policy instance */ + rr_handover(exec_ctx, lb_client->glb_policy, error); + } else { + /* unref the RR policy, eventually leading to its substitution with a + * new one constructed from the received serverlist (see + * rr_connectivity_changed) */ + GRPC_LB_POLICY_UNREF(exec_ctx, lb_client->glb_policy->rr_policy, + "serverlist_received"); + } + } else { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "Received empty server list. Picks will stay pending until a " + "response with > 0 servers is received"); + } + } + + /* keep listening for serverlist updates */ + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &lb_client->response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + const grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops), + &lb_client->res_rcvd); /* loop */ + GPR_ASSERT(GRPC_CALL_OK == call_error); + return; + } + + GPR_ASSERT(serverlist == NULL); + gpr_log(GPR_ERROR, "Invalid LB response received: '%s'", + gpr_dump_slice(response_slice, GPR_DUMP_ASCII)); + gpr_slice_unref(response_slice); + + /* Disconnect from server returning invalid response. */ + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops), + &lb_client->close_sent); + GPR_ASSERT(GRPC_CALL_OK == call_error); + } + /* empty payload: call cancelled by server. Cleanups happening in + * srv_status_rcvd_cb */ +} + +static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "Close from LB client sent. Waiting from server status now"); + } +} + +static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + lb_client_data *lb_client = arg; + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "status from lb server received. Status = %d, Details = '%s', " + "Capaticy " + "= %zu", + lb_client->status, lb_client->status_details, + lb_client->status_details_capacity); + } + /* TODO(dgq): deal with stream termination properly (fire up another one? fail + * the original call?) */ +} + +/* Code wiring the policy with the rest of the core */ +static const grpc_lb_policy_vtable glb_lb_policy_vtable = { + glb_destroy, glb_shutdown, glb_pick, + glb_cancel_pick, glb_cancel_picks, glb_ping_one, + glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change}; + +static void glb_factory_ref(grpc_lb_policy_factory *factory) {} + +static void glb_factory_unref(grpc_lb_policy_factory *factory) {} + +static const grpc_lb_policy_factory_vtable glb_factory_vtable = { + glb_factory_ref, glb_factory_unref, glb_create, "grpclb"}; + +static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable}; + +grpc_lb_policy_factory *grpc_glb_lb_factory_create() { + return &glb_lb_policy_factory; +} + +/* Plugin registration */ +void grpc_lb_policy_grpclb_init() { + grpc_register_lb_policy(grpc_glb_lb_factory_create()); + grpc_register_tracer("glb", &grpc_lb_glb_trace); +} + +void grpc_lb_policy_grpclb_shutdown() {} diff --git a/src/python/grpcio/grpc/_cython/loader.c b/src/core/ext/lb_policy/grpclb/grpclb.h index 34bd897549..83552b4fa0 100644 --- a/src/python/grpcio/grpc/_cython/loader.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.h @@ -31,22 +31,14 @@ * */ -#include <Python.h> -#include "loader.h" +#ifndef GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H +#define GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ +#include "src/core/ext/client_config/lb_policy_factory.h" -int pygrpc_load_core(char *path) { return 1; } - -// Cython doesn't have Py_AtExit bindings, so we call the C_API directly -int pygrpc_initialize_core(void) { - grpc_init(); - return Py_AtExit(grpc_shutdown) < 0 ? 0 : 1; -} - -#ifdef __cplusplus -} -#endif /* __cpluslus */ +/** Returns a load balancing factory for the glb policy, which tries to connect + * to a load balancing server to decide the next successfully connected + * subchannel to pick. */ +grpc_lb_policy_factory *grpc_glb_lb_factory_create(); +#endif /* GRPC_CORE_EXT_LB_POLICY_GRPCLB_GRPCLB_H */ diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c index 59b89997dd..f4720a1345 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c @@ -38,9 +38,15 @@ #include <grpc/support/alloc.h> typedef struct decode_serverlist_arg { - int first_pass; - int i; + /* The first pass counts the number of servers in the server list. The second + * one allocates and decodes. */ + bool first_pass; + /* The decoding callback is invoked once per server in serverlist. Remember + * which index of the serverlist are we currently decoding */ + size_t decoding_idx; + /* Populated after the first pass. Number of server in the input serverlist */ size_t num_servers; + /* The decoded serverlist */ grpc_grpclb_server **servers; } decode_serverlist_arg; @@ -48,23 +54,24 @@ typedef struct decode_serverlist_arg { static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, void **arg) { decode_serverlist_arg *dec_arg = *arg; - if (dec_arg->first_pass != 0) { /* first pass */ + if (dec_arg->first_pass) { /* count how many server do we have */ grpc_grpclb_server server; if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) { return false; } dec_arg->num_servers++; - } else { /* second pass */ + } else { /* second pass. Actually decode. */ grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server)); + memset(server, 0, sizeof(grpc_grpclb_server)); GPR_ASSERT(dec_arg->num_servers > 0); - if (dec_arg->i == 0) { /* first iteration of second pass */ + if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */ dec_arg->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers); } if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) { return false; } - dec_arg->servers[dec_arg->i++] = server; + dec_arg->servers[dec_arg->decoding_idx++] = server; } return true; @@ -102,57 +109,59 @@ void grpc_grpclb_request_destroy(grpc_grpclb_request *request) { gpr_free(request); } -grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) { - bool status; +typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response; +grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse( + gpr_slice encoded_grpc_grpclb_response) { pb_istream_t stream = - pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response), - GPR_SLICE_LENGTH(encoded_response)); - grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response)); - memset(res, 0, sizeof(*res)); - status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); - if (!status) { - grpc_grpclb_response_destroy(res); + pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response), + GPR_SLICE_LENGTH(encoded_grpc_grpclb_response)); + grpc_grpclb_response res; + memset(&res, 0, sizeof(grpc_grpclb_response)); + if (!pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res)) { return NULL; } - return res; + grpc_grpclb_initial_response *initial_res = + gpr_malloc(sizeof(grpc_grpclb_initial_response)); + memcpy(initial_res, &res.initial_response, + sizeof(grpc_grpclb_initial_response)); + + return initial_res; } grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( - gpr_slice encoded_response) { + gpr_slice encoded_grpc_grpclb_response) { bool status; decode_serverlist_arg arg; pb_istream_t stream = - pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response), - GPR_SLICE_LENGTH(encoded_response)); + pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_grpc_grpclb_response), + GPR_SLICE_LENGTH(encoded_grpc_grpclb_response)); pb_istream_t stream_at_start = stream; - grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response)); - memset(res, 0, sizeof(*res)); + grpc_grpclb_response res; + memset(&res, 0, sizeof(grpc_grpclb_response)); memset(&arg, 0, sizeof(decode_serverlist_arg)); - res->server_list.servers.funcs.decode = decode_serverlist; - res->server_list.servers.arg = &arg; - arg.first_pass = 1; - status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); + res.server_list.servers.funcs.decode = decode_serverlist; + res.server_list.servers.arg = &arg; + arg.first_pass = true; + status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res); if (!status) { - grpc_grpclb_response_destroy(res); return NULL; } - arg.first_pass = 0; + arg.first_pass = false; status = - pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, res); + pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res); if (!status) { - grpc_grpclb_response_destroy(res); return NULL; } grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist)); + memset(sl, 0, sizeof(*sl)); sl->num_servers = arg.num_servers; sl->servers = arg.servers; - if (res->server_list.has_expiration_interval) { - sl->expiration_interval = res->server_list.expiration_interval; + if (res.server_list.has_expiration_interval) { + sl->expiration_interval = res.server_list.expiration_interval; } - grpc_grpclb_response_destroy(res); return sl; } @@ -167,6 +176,72 @@ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) { gpr_free(serverlist); } -void grpc_grpclb_response_destroy(grpc_grpclb_response *response) { +grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy( + const grpc_grpclb_serverlist *sl) { + grpc_grpclb_serverlist *copy = gpr_malloc(sizeof(grpc_grpclb_serverlist)); + memset(copy, 0, sizeof(grpc_grpclb_serverlist)); + copy->num_servers = sl->num_servers; + memcpy(©->expiration_interval, &sl->expiration_interval, + sizeof(grpc_grpclb_duration)); + copy->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * sl->num_servers); + for (size_t i = 0; i < sl->num_servers; i++) { + copy->servers[i] = gpr_malloc(sizeof(grpc_grpclb_server)); + memcpy(copy->servers[i], sl->servers[i], sizeof(grpc_grpclb_server)); + } + return copy; +} + +bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs, + const grpc_grpclb_serverlist *rhs) { + if ((lhs == NULL) || (rhs == NULL)) { + return false; + } + if (lhs->num_servers != rhs->num_servers) { + return false; + } + if (grpc_grpclb_duration_compare(&lhs->expiration_interval, + &rhs->expiration_interval) != 0) { + return false; + } + for (size_t i = 0; i < lhs->num_servers; i++) { + if (!grpc_grpclb_server_equals(lhs->servers[i], rhs->servers[i])) { + return false; + } + } + return true; +} + +bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs, + const grpc_grpclb_server *rhs) { + return memcmp(lhs, rhs, sizeof(grpc_grpclb_server)) == 0; +} + +int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, + const grpc_grpclb_duration *rhs) { + GPR_ASSERT(lhs && rhs); + if (lhs->has_seconds && rhs->has_seconds) { + if (lhs->seconds < rhs->seconds) return -1; + if (lhs->seconds > rhs->seconds) return 1; + } else if (lhs->has_seconds) { + return 1; + } else if (rhs->has_seconds) { + return -1; + } + + GPR_ASSERT(lhs->seconds == rhs->seconds); + if (lhs->has_nanos && rhs->has_nanos) { + if (lhs->nanos < rhs->nanos) return -1; + if (lhs->nanos > rhs->nanos) return 1; + } else if (lhs->has_nanos) { + return 1; + } else if (rhs->has_nanos) { + return -1; + } + + return 0; +} + +void grpc_grpclb_initial_response_destroy( + grpc_grpclb_initial_response *response) { gpr_free(response); } diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/lb_policy/grpclb/load_balancer_api.h index 71b5616d0c..9726c87a37 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.h @@ -46,7 +46,7 @@ extern "C" { #define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128 typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request; -typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response; +typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response; typedef grpc_lb_v1_Server grpc_grpclb_server; typedef grpc_lb_v1_Duration grpc_grpclb_duration; typedef struct grpc_grpclb_serverlist { @@ -64,19 +64,37 @@ gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request); /** Destroy \a request */ void grpc_grpclb_request_destroy(grpc_grpclb_request *request); -/** Parse (ie, decode) the bytes in \a encoded_response as a \a - * grpc_grpclb_response */ -grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response); +/** Parse (ie, decode) the bytes in \a encoded_grpc_grpclb_response as a \a + * grpc_grpclb_initial_response */ +grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse( + gpr_slice encoded_grpc_grpclb_response); + +/** Parse the list of servers from an encoded \a grpc_grpclb_response */ +grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( + gpr_slice encoded_grpc_grpclb_response); + +/** Return a copy of \a sl. The caller is responsible for calling \a + * grpc_grpclb_destroy_serverlist on the returned copy. */ +grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy( + const grpc_grpclb_serverlist *sl); + +bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs, + const grpc_grpclb_serverlist *rhs); + +bool grpc_grpclb_server_equals(const grpc_grpclb_server *lhs, + const grpc_grpclb_server *rhs); /** Destroy \a serverlist */ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist); -/** Parse the list of servers from an encoded \a grpc_grpclb_response */ -grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( - gpr_slice encoded_response); +/** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal, + * < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */ +int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, + const grpc_grpclb_duration *rhs); -/** Destroy \a response */ -void grpc_grpclb_response_destroy(grpc_grpclb_response *response); +/** Destroy \a initial_response */ +void grpc_grpclb_initial_response_destroy( + grpc_grpclb_initial_response *response); #ifdef __cplusplus } diff --git a/src/core/ext/load_reporting/load_reporting.c b/src/core/ext/load_reporting/load_reporting.c index 9e4d32676f..df1ea0ec9a 100644 --- a/src/core/ext/load_reporting/load_reporting.c +++ b/src/core/ext/load_reporting/load_reporting.c @@ -42,42 +42,12 @@ #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/surface/channel_init.h" -struct grpc_load_reporting_config { - grpc_load_reporting_fn fn; - void *user_data; -}; - -grpc_load_reporting_config *grpc_load_reporting_config_create( - grpc_load_reporting_fn fn, void *user_data) { - GPR_ASSERT(fn != NULL); - grpc_load_reporting_config *lrc = - gpr_malloc(sizeof(grpc_load_reporting_config)); - lrc->fn = fn; - lrc->user_data = user_data; - return lrc; -} - -grpc_load_reporting_config *grpc_load_reporting_config_copy( - grpc_load_reporting_config *src) { - return grpc_load_reporting_config_create(src->fn, src->user_data); -} - -void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc) { - gpr_free(lrc); -} - -void grpc_load_reporting_config_call( - grpc_load_reporting_config *lrc, - const grpc_load_reporting_call_data *call_data) { - lrc->fn(call_data, lrc->user_data); -} - static bool is_load_reporting_enabled(const grpc_channel_args *a) { if (a == NULL) return false; for (size_t i = 0; i < a->num_args; i++) { if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_LOAD_REPORTING)) { - return a->args[i].type == GRPC_ARG_POINTER && - a->args[i].value.pointer.p != NULL; + return a->args[i].type == GRPC_ARG_INTEGER && + a->args[i].value.integer != 0; } } return false; @@ -94,37 +64,17 @@ static bool maybe_add_load_reporting_filter(grpc_channel_stack_builder *builder, return true; } -static void lrd_arg_destroy(void *p) { grpc_load_reporting_config_destroy(p); } - -static void *lrd_arg_copy(void *p) { - return grpc_load_reporting_config_copy(p); -} - -static int lrd_arg_cmp(void *a, void *b) { - grpc_load_reporting_config *lhs = a; - grpc_load_reporting_config *rhs = b; - return !(lhs->fn == rhs->fn && lhs->user_data == rhs->user_data); -} - -static const grpc_arg_pointer_vtable lrd_ptr_vtable = { - lrd_arg_copy, lrd_arg_destroy, lrd_arg_cmp}; - -grpc_arg grpc_load_reporting_config_create_arg( - grpc_load_reporting_config *lrc) { +grpc_arg grpc_load_reporting_enable_arg() { grpc_arg arg; - arg.type = GRPC_ARG_POINTER; + arg.type = GRPC_ARG_INTEGER; arg.key = GRPC_ARG_ENABLE_LOAD_REPORTING; - arg.value.pointer.p = lrc; - arg.value.pointer.vtable = &lrd_ptr_vtable; + arg.value.integer = 1; return arg; } /* Plugin registration */ void grpc_load_reporting_plugin_init(void) { - grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MAX, - maybe_add_load_reporting_filter, - (void *)&grpc_load_reporting_filter); grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, maybe_add_load_reporting_filter, (void *)&grpc_load_reporting_filter); diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h index 316cd89bd7..e37817d8c2 100644 --- a/src/core/ext/load_reporting/load_reporting.h +++ b/src/core/ext/load_reporting/load_reporting.h @@ -34,42 +34,47 @@ #ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/surface/call.h" +#include <grpc/impl/codegen/grpc_types.h> +#include "src/core/lib/channel/channel_stack.h" -typedef struct grpc_load_reporting_config grpc_load_reporting_config; +/** Metadata key for initial metadata coming from clients */ +/* TODO(dgq): change to the final value TBD */ +#define GRPC_LOAD_REPORTING_INITIAL_MD_KEY "load-reporting-initial" -/** Call information to be passed to the provided load reporting function upon - * completion of the call */ -typedef struct grpc_load_reporting_call_data { - const grpc_call_stats *stats; /**< Stats for the call */ - const char *trailing_md_string; /**< LR trailing metadata info */ -} grpc_load_reporting_call_data; +/** Metadata key for trailing metadata from servers */ +/* TODO(dgq): change to the final value TBD */ +#define GRPC_LOAD_REPORTING_TRAILING_MD_KEY "load-reporting-trailing" -/** Custom function to be called by the load reporting filter. */ -typedef void (*grpc_load_reporting_fn)( - const grpc_load_reporting_call_data *call_data, void *user_data); +/** Identifiers for the invocation point of the users LR callback */ +typedef enum grpc_load_reporting_source { + GRPC_LR_POINT_UNKNOWN = 0, + GRPC_LR_POINT_CHANNEL_CREATION, + GRPC_LR_POINT_CHANNEL_DESTRUCTION, + GRPC_LR_POINT_CALL_CREATION, + GRPC_LR_POINT_CALL_DESTRUCTION +} grpc_load_reporting_source; -/** Register \a fn as the function to be invoked by the load reporting filter. - * \a fn will be invoked at the beginning and at the end of the call. - * - * For the first invocation, \a fn's first argument - * (grpc_load_reporting_call_data*) will be NULL. \a user_data is always passed - * as-is. */ -grpc_load_reporting_config *grpc_load_reporting_config_create( - grpc_load_reporting_fn fn, void *user_data); +/** Call information to be passed to the provided LR callback. */ +typedef struct grpc_load_reporting_call_data { + const grpc_load_reporting_source source; /**< point of last data update. */ + + /** Unique identifier for the channel associated with the data */ + intptr_t channel_id; -grpc_load_reporting_config *grpc_load_reporting_config_copy( - grpc_load_reporting_config *src); + /** Unique identifier for the call associated with the data. If the call + * hasn't been created yet, it'll have a value of zero. */ + intptr_t call_id; -void grpc_load_reporting_config_destroy(grpc_load_reporting_config *lrc); + /** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is, + * once the call has completed */ + const grpc_call_final_info *final_info; -/** Invoke the function registered by \a grpc_load_reporting_init. */ -void grpc_load_reporting_config_call( - grpc_load_reporting_config *lrc, - const grpc_load_reporting_call_data *call_data); + const char *initial_md_string; /**< value string for LR's initial md key */ + const char *trailing_md_string; /**< value string for LR's trailing md key */ + const char *method_name; /**< Corresponds to :path header */ +} grpc_load_reporting_call_data; /** Return a \a grpc_arg enabling load reporting */ -grpc_arg grpc_load_reporting_config_create_arg(grpc_load_reporting_config *lrc); +grpc_arg grpc_load_reporting_enable_arg(); #endif /* GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H */ diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c index f372f88c3a..394f0cb832 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.c +++ b/src/core/ext/load_reporting/load_reporting_filter.c @@ -31,6 +31,7 @@ * */ +#include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> #include <grpc/support/sync.h> @@ -42,38 +43,112 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/transport/static_metadata.h" -typedef struct call_data { const char *trailing_md_string; } call_data; +typedef struct call_data { + intptr_t id; /**< an id unique to the call */ + char *trailing_md_string; + char *initial_md_string; + const char *service_method; + + /* stores the recv_initial_metadata op's ready closure, which we wrap with our + * own (on_initial_md_ready) in order to capture the incoming initial metadata + * */ + grpc_closure *ops_recv_initial_metadata_ready; + + /* to get notified of the availability of the incoming initial metadata. */ + grpc_closure on_initial_md_ready; + grpc_metadata_batch *recv_initial_metadata; +} call_data; + typedef struct channel_data { - gpr_mu mu; - grpc_load_reporting_config *lrc; + intptr_t id; /**< an id unique to the channel */ } channel_data; -static void invoke_lr_fn_locked(grpc_load_reporting_config *lrc, - grpc_load_reporting_call_data *lr_call_data) { - GPR_TIMER_BEGIN("load_reporting_config_fn", 0); - grpc_load_reporting_config_call(lrc, lr_call_data); - GPR_TIMER_END("load_reporting_config_fn", 0); +typedef struct { + grpc_call_element *elem; + grpc_exec_ctx *exec_ctx; +} recv_md_filter_args; + +static grpc_mdelem *recv_md_filter(void *user_data, grpc_mdelem *md) { + recv_md_filter_args *a = user_data; + grpc_call_element *elem = a->elem; + call_data *calld = elem->call_data; + + if (md->key == GRPC_MDSTR_PATH) { + calld->service_method = grpc_mdstr_as_c_string(md->value); + } else if (md->key == GRPC_MDSTR_LOAD_REPORTING_INITIAL) { + calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); + return NULL; + } + + return md; +} + +static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_error *err) { + grpc_call_element *elem = user_data; + call_data *calld = elem->call_data; + + if (err == GRPC_ERROR_NONE) { + recv_md_filter_args a; + a.elem = elem; + a.exec_ctx = exec_ctx; + grpc_metadata_batch_filter(calld->recv_initial_metadata, recv_md_filter, + &a); + if (calld->service_method == NULL) { + err = + grpc_error_add_child(err, GRPC_ERROR_CREATE("Missing :path header")); + } + } else { + GRPC_ERROR_REF(err); + } + calld->ops_recv_initial_metadata_ready->cb( + exec_ctx, calld->ops_recv_initial_metadata_ready->cb_arg, err); + GRPC_ERROR_UNREF(err); } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *calld = elem->call_data; memset(calld, 0, sizeof(call_data)); + + calld->id = (intptr_t)args->call_stack; + grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem); + + /* TODO(dgq): do something with the data + channel_data *chand = elem->channel_data; + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION, + (intptr_t)chand->id, + (intptr_t)calld->id, + NULL, + NULL, + NULL, + NULL}; + */ + + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) { - channel_data *chand = elem->channel_data; + const grpc_call_final_info *final_info, + void *ignored) { call_data *calld = elem->call_data; - grpc_load_reporting_call_data lr_call_data = {stats, - calld->trailing_md_string}; - - gpr_mu_lock(&chand->mu); - invoke_lr_fn_locked(chand->lrc, &lr_call_data); - gpr_mu_unlock(&chand->mu); + /* TODO(dgq): do something with the data + channel_data *chand = elem->channel_data; + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION, + (intptr_t)chand->id, + (intptr_t)calld->id, + final_info, + calld->initial_md_string, + calld->trailing_md_string, + calld->service_method}; + */ + + gpr_free(calld->initial_md_string); + gpr_free(calld->trailing_md_string); } /* Constructor for channel_data */ @@ -85,37 +160,40 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx, channel_data *chand = elem->channel_data; memset(chand, 0, sizeof(channel_data)); - gpr_mu_init(&chand->mu); - for (size_t i = 0; i < args->channel_args->num_args; i++) { - if (0 == strcmp(args->channel_args->args[i].key, - GRPC_ARG_ENABLE_LOAD_REPORTING)) { - grpc_load_reporting_config *arg_lrc = - args->channel_args->args[i].value.pointer.p; - chand->lrc = grpc_load_reporting_config_copy(arg_lrc); - GPR_ASSERT(chand->lrc != NULL); - break; - } - } - GPR_ASSERT(chand->lrc != NULL); /* arg actually found */ - - gpr_mu_lock(&chand->mu); - invoke_lr_fn_locked(chand->lrc, NULL); - gpr_mu_unlock(&chand->mu); + chand->id = (intptr_t)args->channel_stack; + + /* TODO(dgq): do something with the data + grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION, + (intptr_t)chand, + 0, + NULL, + NULL, + NULL, + NULL}; + */ } /* Destructor for channel data */ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) { + /* TODO(dgq): do something with the data channel_data *chand = elem->channel_data; - gpr_mu_destroy(&chand->mu); - grpc_load_reporting_config_destroy(chand->lrc); + grpc_load_reporting_call_data lr_call_data = { + GRPC_LR_POINT_CHANNEL_DESTRUCTION, + (intptr_t)chand->id, + 0, + NULL, + NULL, + NULL, + NULL}; + */ } static grpc_mdelem *lr_trailing_md_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; - if (md->key == GRPC_MDSTR_LOAD_REPORTING) { + if (md->key == GRPC_MDSTR_LOAD_REPORTING_TRAILING) { calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); return NULL; } @@ -127,8 +205,14 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { GPR_TIMER_BEGIN("lr_start_transport_stream_op", 0); + call_data *calld = elem->call_data; - if (op->send_trailing_metadata) { + if (op->recv_initial_metadata) { + calld->recv_initial_metadata = op->recv_initial_metadata; + /* substitute our callback for the higher callback */ + calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready; + op->recv_initial_metadata_ready = &calld->on_initial_md_ready; + } else if (op->send_trailing_metadata) { grpc_metadata_batch_filter(op->send_trailing_metadata, lr_trailing_md_filter, elem); } diff --git a/src/core/ext/load_reporting/load_reporting_filter.h b/src/core/ext/load_reporting/load_reporting_filter.h index f69cd6fdc6..160ed32af9 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.h +++ b/src/core/ext/load_reporting/load_reporting_filter.h @@ -34,6 +34,7 @@ #ifndef GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H #define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_FILTER_H +#include "src/core/ext/load_reporting/load_reporting.h" #include "src/core/lib/channel/channel_stack.h" extern const grpc_channel_filter grpc_load_reporting_filter; diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index 85f9efb3b6..6f6855584a 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -45,6 +45,7 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/compress_filter.h" +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/surface/api_trace.h" @@ -63,6 +64,8 @@ typedef struct { grpc_endpoint *tcp; grpc_closure connected; + + grpc_handshake_manager *handshake_mgr; } connector; static void connector_ref(grpc_connector *con) { @@ -74,6 +77,7 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { connector *c = (connector *)con; if (gpr_unref(&c->refs)) { /* c->initial_string_buffer does not need to be destroyed */ + grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); gpr_free(c); } } @@ -83,9 +87,22 @@ static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, connector_unref(exec_ctx, arg); } +static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, + grpc_channel_args *args, void *user_data, + grpc_error *error) { + connector *c = user_data; + c->result->transport = + grpc_create_chttp2_transport(exec_ctx, args, endpoint, 1); + GPR_ASSERT(c->result->transport); + grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0); + c->result->channel_args = args; + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); +} + static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector *c = arg; - grpc_closure *notify; grpc_endpoint *tcp = c->tcp; if (tcp != NULL) { if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { @@ -97,19 +114,17 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector_ref(arg); grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); + } else { + grpc_handshake_manager_do_handshake( + exec_ctx, c->handshake_mgr, tcp, c->args.channel_args, + c->args.deadline, NULL /* acceptor */, on_handshake_done, c); } - c->result->transport = - grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1); - grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, - 0); - GPR_ASSERT(c->result->transport); - c->result->channel_args = grpc_channel_args_copy(c->args.channel_args); } else { memset(c->result, 0, sizeof(*c->result)); + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); } - notify = c->notify; - c->notify = NULL; - grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); } static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {} @@ -171,6 +186,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel( memset(c, 0, sizeof(*c)); c->base.vtable = &connector_vtable; gpr_ref_init(&c->refs, 1); + c->handshake_mgr = grpc_handshake_manager_create(); args->args = final_args; s = grpc_subchannel_create(exec_ctx, &c->base, args); grpc_connector_unref(exec_ctx, &c->base); diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 9acacbd92d..4e33b6fa61 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -44,6 +44,7 @@ #include "src/core/ext/client_config/resolver_registry.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" @@ -69,6 +70,11 @@ typedef struct { grpc_endpoint *newly_connecting_endpoint; grpc_closure connected_closure; + + grpc_handshake_manager *handshake_mgr; + + // TODO(roth): Remove once we eliminate on_secure_handshake_done(). + grpc_channel_args *tmp_args; } connector; static void connector_ref(grpc_connector *con) { @@ -80,6 +86,8 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) { connector *c = (connector *)con; if (gpr_unref(&c->refs)) { /* c->initial_string_buffer does not need to be destroyed */ + grpc_channel_args_destroy(c->tmp_args); + grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr); gpr_free(c); } } @@ -89,7 +97,6 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { connector *c = arg; - grpc_closure *notify; gpr_mu_lock(&c->mu); grpc_error *error = GRPC_ERROR_NONE; if (c->connecting_endpoint == NULL) { @@ -110,25 +117,43 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0); auth_context_arg = grpc_auth_context_to_arg(auth_context); - c->result->channel_args = grpc_channel_args_copy_and_add( - c->args.channel_args, &auth_context_arg, 1); + c->result->channel_args = + grpc_channel_args_copy_and_add(c->tmp_args, &auth_context_arg, 1); } - notify = c->notify; + grpc_closure *notify = c->notify; c->notify = NULL; grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); } +static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, + grpc_channel_args *args, void *user_data, + grpc_error *error) { + connector *c = user_data; + if (error != GRPC_ERROR_NONE) { + grpc_closure *notify = c->notify; + c->notify = NULL; + grpc_exec_ctx_sched(exec_ctx, notify, error, NULL); + } else { + // TODO(roth, jboeuf): Convert security connector handshaking to use new + // handshake API, and then move the code from on_secure_handshake_done() + // into this function. + c->tmp_args = args; + grpc_channel_security_connector_do_handshake( + exec_ctx, c->security_connector, endpoint, c->args.deadline, + on_secure_handshake_done, c); + } +} + static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector *c = arg; - grpc_channel_security_connector_do_handshake( - exec_ctx, c->security_connector, c->connecting_endpoint, c->args.deadline, - on_secure_handshake_done, c); + grpc_handshake_manager_do_handshake( + exec_ctx, c->handshake_mgr, c->connecting_endpoint, c->args.channel_args, + c->args.deadline, NULL /* acceptor */, on_handshake_done, c); } static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector *c = arg; - grpc_closure *notify; grpc_endpoint *tcp = c->newly_connecting_endpoint; if (tcp != NULL) { gpr_mu_lock(&c->mu); @@ -144,13 +169,13 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); } else { - grpc_channel_security_connector_do_handshake( - exec_ctx, c->security_connector, tcp, c->args.deadline, - on_secure_handshake_done, c); + grpc_handshake_manager_do_handshake( + exec_ctx, c->handshake_mgr, tcp, c->args.channel_args, + c->args.deadline, NULL /* acceptor */, on_handshake_done, c); } } else { memset(c->result, 0, sizeof(*c->result)); - notify = c->notify; + grpc_closure *notify = c->notify; c->notify = NULL; grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); } @@ -229,6 +254,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel( memset(c, 0, sizeof(*c)); c->base.vtable = &connector_vtable; c->security_connector = f->security_connector; + c->handshake_mgr = grpc_handshake_manager_create(); gpr_mu_init(&c->mu); gpr_ref_init(&c->refs, 1); args->args = final_args; diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c index 054f15c8ff..9cd374777e 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c @@ -37,35 +37,74 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> #include <grpc/support/useful.h> + #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" -static void new_transport(grpc_exec_ctx *exec_ctx, void *server, - grpc_endpoint *tcp, grpc_pollset *accepting_pollset, - grpc_tcp_server_acceptor *acceptor) { - /* - * Beware that the call to grpc_create_chttp2_transport() has to happen before - * grpc_tcp_server_destroy(). This is fine here, but similar code - * asynchronously doing a handshake instead of calling grpc_tcp_server_start() - * (as in server_secure_chttp2.c) needs to add synchronization to avoid this - * case. - */ - grpc_transport *transport = grpc_create_chttp2_transport( - exec_ctx, grpc_server_get_channel_args(server), tcp, 0); - grpc_server_setup_transport(exec_ctx, server, transport, accepting_pollset, - grpc_server_get_channel_args(server)); - grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0); +typedef struct server_connect_state { + grpc_server *server; + grpc_pollset *accepting_pollset; + grpc_tcp_server_acceptor *acceptor; + grpc_handshake_manager *handshake_mgr; +} server_connect_state; + +static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, + grpc_channel_args *args, void *user_data, + grpc_error *error) { + server_connect_state *state = user_data; + if (error != GRPC_ERROR_NONE) { + const char *error_str = grpc_error_string(error); + gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); + grpc_error_free_string(error_str); + GRPC_ERROR_UNREF(error); + grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr); + } else { + // Beware that the call to grpc_create_chttp2_transport() has to happen + // before grpc_tcp_server_destroy(). This is fine here, but similar code + // asynchronously doing a handshake instead of calling + // grpc_tcp_server_start() (as in server_secure_chttp2.c) needs to add + // synchronization to avoid this case. + grpc_transport *transport = + grpc_create_chttp2_transport(exec_ctx, args, endpoint, 0); + grpc_server_setup_transport(exec_ctx, state->server, transport, + state->accepting_pollset, + grpc_server_get_channel_args(state->server)); + grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0); + } + // Clean up. + grpc_channel_args_destroy(args); + grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); + gpr_free(state); +} + +static void on_accept(grpc_exec_ctx *exec_ctx, void *server, grpc_endpoint *tcp, + grpc_pollset *accepting_pollset, + grpc_tcp_server_acceptor *acceptor) { + server_connect_state *state = gpr_malloc(sizeof(server_connect_state)); + state->server = server; + state->accepting_pollset = accepting_pollset; + state->acceptor = acceptor; + state->handshake_mgr = grpc_handshake_manager_create(); + // TODO(roth): We should really get this timeout value from channel + // args instead of hard-coding it. + const gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); + grpc_handshake_manager_do_handshake( + exec_ctx, state->handshake_mgr, tcp, grpc_server_get_channel_args(server), + deadline, acceptor, on_handshake_done, state); } /* Server callback: start listening on our ports */ static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp, grpc_pollset **pollsets, size_t pollset_count) { grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport, + grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, on_accept, server); } diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c index 7131cf5972..ccea15a648 100644 --- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c @@ -42,6 +42,7 @@ #include <grpc/support/useful.h> #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" @@ -58,7 +59,7 @@ typedef struct server_secure_state { grpc_tcp_server *tcp; grpc_server_security_connector *sc; grpc_server_credentials *creds; - int is_shutdown; + bool is_shutdown; gpr_mu mu; gpr_refcount refcount; grpc_closure destroy_closure; @@ -68,6 +69,12 @@ typedef struct server_secure_state { typedef struct server_secure_connect { server_secure_state *state; grpc_pollset *accepting_pollset; + grpc_tcp_server_acceptor *acceptor; + grpc_handshake_manager *handshake_mgr; + // TODO(roth): Remove the following two fields when we eliminate + // grpc_server_security_connector_do_handshake(). + gpr_timespec deadline; + grpc_channel_args *args; } server_secure_connect; static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); } @@ -89,21 +96,18 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { server_secure_connect *state = statep; - grpc_transport *transport; if (status == GRPC_SECURITY_OK) { if (secure_endpoint) { gpr_mu_lock(&state->state->mu); if (!state->state->is_shutdown) { - transport = grpc_create_chttp2_transport( + grpc_transport *transport = grpc_create_chttp2_transport( exec_ctx, grpc_server_get_channel_args(state->state->server), secure_endpoint, 0); - grpc_channel_args *args_copy; grpc_arg args_to_add[2]; args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds); args_to_add[1] = grpc_auth_context_to_arg(auth_context); - args_copy = grpc_channel_args_copy_and_add( - grpc_server_get_channel_args(state->state->server), args_to_add, - GPR_ARRAY_SIZE(args_to_add)); + grpc_channel_args *args_copy = grpc_channel_args_copy_and_add( + state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); grpc_server_setup_transport(exec_ctx, state->state->server, transport, state->accepting_pollset, args_copy); grpc_channel_args_destroy(args_copy); @@ -118,10 +122,38 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, } else { gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); } + grpc_channel_args_destroy(state->args); state_unref(state->state); gpr_free(state); } +static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, + grpc_channel_args *args, void *user_data, + grpc_error *error) { + server_secure_connect *state = user_data; + if (error != GRPC_ERROR_NONE) { + const char *error_str = grpc_error_string(error); + gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); + grpc_error_free_string(error_str); + GRPC_ERROR_UNREF(error); + grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr); + grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); + grpc_channel_args_destroy(args); + state_unref(state->state); + gpr_free(state); + return; + } + grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); + state->handshake_mgr = NULL; + // TODO(roth, jboeuf): Convert security connector handshaking to use new + // handshake API, and then move the code from on_secure_handshake_done() + // into this function. + state->args = args; + grpc_server_security_connector_do_handshake( + exec_ctx, state->state->sc, state->acceptor, endpoint, state->deadline, + on_secure_handshake_done, state); +} + static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { @@ -129,11 +161,16 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp, state->state = statep; state_ref(state->state); state->accepting_pollset = accepting_pollset; - grpc_server_security_connector_do_handshake( - exec_ctx, state->state->sc, acceptor, tcp, - gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_seconds(120, GPR_TIMESPAN)), - on_secure_handshake_done, state); + state->acceptor = acceptor; + state->handshake_mgr = grpc_handshake_manager_create(); + // TODO(roth): We should really get this timeout value from channel + // args instead of hard-coding it. + state->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(120, GPR_TIMESPAN)); + grpc_handshake_manager_do_handshake( + exec_ctx, state->handshake_mgr, tcp, + grpc_server_get_channel_args(state->state->server), state->deadline, + acceptor, on_handshake_done, state); } /* Server callback: start listening on our ports */ @@ -162,7 +199,7 @@ static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep, server_secure_state *state = statep; grpc_tcp_server *tcp; gpr_mu_lock(&state->mu); - state->is_shutdown = 1; + state->is_shutdown = true; state->destroy_callback = callback; tcp = state->tcp; gpr_mu_unlock(&state->mu); @@ -227,7 +264,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, state->tcp = tcp; state->sc = sc; state->creds = grpc_server_credentials_ref(creds); - state->is_shutdown = 0; + state->is_shutdown = false; gpr_mu_init(&state->mu); gpr_ref_init(&state->refcount, 1); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index ced74dc8ff..fc71d2804a 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -46,12 +46,12 @@ #include "src/core/ext/transport/chttp2/transport/http2_errors.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/status_conversion.h" -#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/string.h" #include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/transport_impl.h" #define DEFAULT_WINDOW 65535 @@ -1940,6 +1940,7 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_chttp2_transport *t = arg; + grpc_error *err = GRPC_ERROR_NONE; GPR_TIMER_BEGIN("reading_action.parse", 0); size_t i = 0; grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE, @@ -1948,15 +1949,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing, t->read_buffer.slices[i]); }; - if (i != t->read_buffer.count) { + if (errors[1] == GRPC_ERROR_NONE) { + err = GRPC_ERROR_REF(error); + } else { errors[2] = try_http_parsing(exec_ctx, t); + err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors, + GPR_ARRAY_SIZE(errors)); } - grpc_error *err = - errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE && - errors[2] == GRPC_ERROR_NONE - ? GRPC_ERROR_NONE - : GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors, - GPR_ARRAY_SIZE(errors)); for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c index ebeee37f0d..2cb8205d94 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c @@ -47,10 +47,10 @@ #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" #include "src/core/ext/transport/chttp2/transport/hpack_table.h" -#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/timeout_encoding.h" #define HASH_FRAGMENT_1(x) ((x)&255) #define HASH_FRAGMENT_2(x) ((x >> 8) & 255) @@ -456,9 +456,9 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem, static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { - char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; + char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_mdelem *mdelem; - grpc_chttp2_encode_timeout( + grpc_http2_encode_timeout( gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); mdelem = grpc_mdelem_from_metadata_strings( GRPC_MDSTR_GRPC_TIMEOUT, grpc_mdstr_from_string(timeout_str)); diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 64ddbf0265..cd128c3310 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -41,9 +41,9 @@ #include "src/core/ext/transport/chttp2/transport/http2_errors.h" #include "src/core/ext/transport/chttp2/transport/status_conversion.h" -#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/timeout_encoding.h" #define TRANSPORT_FROM_PARSING(tp) \ ((grpc_chttp2_transport *)((char *)(tp)-offsetof(grpc_chttp2_transport, \ @@ -672,8 +672,8 @@ static void on_initial_header(void *tp, grpc_mdelem *md) { if (!cached_timeout) { /* not already parsed: parse it now, and store the result away */ cached_timeout = gpr_malloc(sizeof(gpr_timespec)); - if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value), - cached_timeout)) { + if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value), + cached_timeout)) { gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", grpc_mdstr_as_c_string(md->value)); *cached_timeout = gpr_inf_future(GPR_TIMESPAN); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 9e6555cdd3..4da9aa4f49 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -203,6 +203,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, GPR_TIMER_BEGIN("finalize_outbuf", 0); + bool is_first_data_frame = true; while ( grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) { uint32_t max_outgoing = @@ -267,6 +268,11 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, stream_writing->id, &stream_writing->flow_controlled_buffer, send_bytes, is_last_frame, &stream_writing->stats, &transport_writing->outbuf); + if (is_first_data_frame) { + /* TODO(dgq): this is a hack. It'll be fix in a future refactoring */ + stream_writing->stats.data_bytes -= 5; /* discount grpc framing */ + is_first_data_frame = false; + } GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing, outgoing_window, send_bytes); diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index 653d04f427..aec61ee7c6 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -37,6 +37,8 @@ #include <grpc/compression.h> #include <grpc/grpc.h> +// Channel args are intentionally immutable, to avoid the need for locking. + /** Copy the arguments in \a src into a new instance */ grpc_channel_args *grpc_channel_args_copy(const grpc_channel_args *src); diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index e1375348a9..0655b9353f 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -158,12 +158,13 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, } } -void grpc_call_stack_init(grpc_exec_ctx *exec_ctx, - grpc_channel_stack *channel_stack, int initial_refs, - grpc_iomgr_cb_func destroy, void *destroy_arg, - grpc_call_context_element *context, - const void *transport_server_data, - grpc_call_stack *call_stack) { +grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, + grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, + void *destroy_arg, + grpc_call_context_element *context, + const void *transport_server_data, + grpc_call_stack *call_stack) { grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); grpc_call_element_args args; size_t count = channel_stack->count; @@ -179,6 +180,7 @@ void grpc_call_stack_init(grpc_exec_ctx *exec_ctx, ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ + grpc_error *first_error = GRPC_ERROR_NONE; for (i = 0; i < count; i++) { args.call_stack = call_stack; args.server_transport_data = transport_server_data; @@ -186,10 +188,19 @@ void grpc_call_stack_init(grpc_exec_ctx *exec_ctx, call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].call_data = user_data; - call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args); + grpc_error *error = + call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i], &args); + if (error != GRPC_ERROR_NONE) { + if (first_error == GRPC_ERROR_NONE) { + first_error = error; + } else { + GRPC_ERROR_UNREF(error); + } + } user_data += ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } + return first_error; } void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, @@ -218,7 +229,7 @@ void grpc_call_stack_ignore_set_pollset_or_pollset_set( grpc_polling_entity *pollent) {} void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, - const grpc_call_stats *call_stats, + const grpc_call_final_info *final_info, void *and_free_memory) { grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack); size_t count = stack->count; @@ -226,7 +237,7 @@ void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, /* destroy per-filter data */ for (i = 0; i < count; i++) { - elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], call_stats, + elems[i].filter->destroy_call_elem(exec_ctx, &elems[i], final_info, i == count - 1 ? and_free_memory : NULL); } } diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index d72c015b67..ee68701456 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -75,9 +75,14 @@ typedef struct { typedef struct { grpc_transport_stream_stats transport_stream_stats; gpr_timespec latency; /* From call creating to enqueing of received status */ - grpc_status_code final_status; } grpc_call_stats; +/** Information about the call upon completion. */ +typedef struct { + grpc_call_stats stats; + grpc_status_code final_status; +} grpc_call_final_info; + /* Channel filters specify: 1. the amount of memory needed in the channel & call (via the sizeof_XXX members) @@ -110,8 +115,9 @@ typedef struct { on a client; if it is non-NULL, then it points to memory owned by the transport and is on the server. Most filters want to ignore this argument. */ - void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args); + grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args); void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_polling_entity *pollent); @@ -119,16 +125,17 @@ typedef struct { The filter does not need to do any chaining. The bottom filter of a stack will be passed a non-NULL pointer to \a and_free_memory that should be passed to gpr_free when destruction - is complete. */ + is complete. \a final_info contains data about the completed call, mainly + for reporting purposes. */ void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *and_free_memory); /* sizeof(per channel data) */ size_t sizeof_channel_data; /* Initialize per-channel data. - elem is initialized at the start of the call, and elem->channel_data is - what needs initializing. + elem is initialized at the creating of the channel, and elem->channel_data + is what needs initializing. is_first, is_last designate this elements position in the stack, and are useful for asserting correct configuration by upper layer code. The filter does not need to do any chaining */ @@ -209,12 +216,13 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, /* Initialize a call stack given a channel stack. transport_server_data is expected to be NULL on a client, or an opaque transport owned pointer on the server. */ -void grpc_call_stack_init(grpc_exec_ctx *exec_ctx, - grpc_channel_stack *channel_stack, int initial_refs, - grpc_iomgr_cb_func destroy, void *destroy_arg, - grpc_call_context_element *context, - const void *transport_server_data, - grpc_call_stack *call_stack); +grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, + grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, + void *destroy_arg, + grpc_call_context_element *context, + const void *transport_server_data, + grpc_call_stack *call_stack); /* Set a pollset or a pollset_set for a call stack: must occur before the first * op is started */ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, @@ -243,7 +251,7 @@ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destroy a call stack */ void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack, - const grpc_call_stats *call_stats, + const grpc_call_final_info *final_info, void *and_free_memory); /* Ignore set pollset{_set} - used by filters if they don't care about pollsets diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c index d4b1cf0296..0981d59f63 100644 --- a/src/core/lib/channel/compress_filter.c +++ b/src/core/lib/channel/compress_filter.c @@ -256,8 +256,9 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; @@ -266,11 +267,14 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, calld->has_compression_algorithm = 0; grpc_closure_init(&calld->got_slice, got_slice, elem); grpc_closure_init(&calld->send_done, send_done, elem); + + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) { + const grpc_call_final_info *final_info, + void *ignored) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; gpr_slice_buffer_destroy(&calld->slices); diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c index 0a7d27a1dc..918379c845 100644 --- a/src/core/lib/channel/connected_channel.c +++ b/src/core/lib/channel/connected_channel.c @@ -81,16 +81,16 @@ static void con_start_transport_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; - int r; - - r = grpc_transport_init_stream( + int r = grpc_transport_init_stream( exec_ctx, chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), &args->call_stack->refcount, args->server_transport_data); - GPR_ASSERT(r == 0); + return r == 0 ? GRPC_ERROR_NONE + : GRPC_ERROR_CREATE("transport stream initialization failed"); } static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, @@ -104,7 +104,7 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *and_free_memory) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c new file mode 100644 index 0000000000..6c3ca198b7 --- /dev/null +++ b/src/core/lib/channel/handshaker.c @@ -0,0 +1,197 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <string.h> + +#include <grpc/impl/codegen/alloc.h> +#include <grpc/impl/codegen/log.h> + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/handshaker.h" + +// +// grpc_handshaker +// + +void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable, + grpc_handshaker* handshaker) { + handshaker->vtable = vtable; +} + +void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker) { + handshaker->vtable->destroy(exec_ctx, handshaker); +} + +void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker) { + handshaker->vtable->shutdown(exec_ctx, handshaker); +} + +void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker, + grpc_endpoint* endpoint, + grpc_channel_args* args, + gpr_timespec deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_handshaker_done_cb cb, void* user_data) { + handshaker->vtable->do_handshake(exec_ctx, handshaker, endpoint, args, + deadline, acceptor, cb, user_data); +} + +// +// grpc_handshake_manager +// + +// State used while chaining handshakers. +struct grpc_handshaker_state { + // The index of the handshaker to invoke next. + size_t index; + // The deadline for all handshakers. + gpr_timespec deadline; + // The acceptor to call the handshakers with. + grpc_tcp_server_acceptor* acceptor; + // The final callback and user_data to invoke after the last handshaker. + grpc_handshaker_done_cb final_cb; + void* final_user_data; +}; + +struct grpc_handshake_manager { + // An array of handshakers added via grpc_handshake_manager_add(). + size_t count; + grpc_handshaker** handshakers; + // State used while chaining handshakers. + struct grpc_handshaker_state* state; +}; + +grpc_handshake_manager* grpc_handshake_manager_create() { + grpc_handshake_manager* mgr = gpr_malloc(sizeof(grpc_handshake_manager)); + memset(mgr, 0, sizeof(*mgr)); + return mgr; +} + +static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; } + +void grpc_handshake_manager_add(grpc_handshake_manager* mgr, + grpc_handshaker* handshaker) { + // To avoid allocating memory for each handshaker we add, we double + // the number of elements every time we need more. + size_t realloc_count = 0; + if (mgr->count == 0) { + realloc_count = 2; + } else if (mgr->count >= 2 && is_power_of_2(mgr->count)) { + realloc_count = mgr->count * 2; + } + if (realloc_count > 0) { + mgr->handshakers = + gpr_realloc(mgr->handshakers, realloc_count * sizeof(grpc_handshaker*)); + } + mgr->handshakers[mgr->count++] = handshaker; +} + +void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr) { + for (size_t i = 0; i < mgr->count; ++i) { + grpc_handshaker_destroy(exec_ctx, mgr->handshakers[i]); + } + gpr_free(mgr->handshakers); + gpr_free(mgr); +} + +void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr) { + for (size_t i = 0; i < mgr->count; ++i) { + grpc_handshaker_shutdown(exec_ctx, mgr->handshakers[i]); + } + if (mgr->state != NULL) { + gpr_free(mgr->state); + mgr->state = NULL; + } +} + +// A function used as the handshaker-done callback when chaining +// handshakers together. +static void call_next_handshaker(grpc_exec_ctx* exec_ctx, + grpc_endpoint* endpoint, + grpc_channel_args* args, void* user_data, + grpc_error* error) { + grpc_handshake_manager* mgr = user_data; + GPR_ASSERT(mgr->state != NULL); + GPR_ASSERT(mgr->state->index < mgr->count); + // If we got an error, skip all remaining handshakers and invoke the + // caller-supplied callback immediately. + if (error != GRPC_ERROR_NONE) { + mgr->state->final_cb(exec_ctx, endpoint, args, mgr->state->final_user_data, + error); + return; + } + grpc_handshaker_done_cb cb = call_next_handshaker; + // If this is the last handshaker, use the caller-supplied callback + // and user_data instead of chaining back to this function again. + if (mgr->state->index == mgr->count - 1) { + cb = mgr->state->final_cb; + user_data = mgr->state->final_user_data; + } + // Invoke handshaker. + grpc_handshaker_do_handshake(exec_ctx, mgr->handshakers[mgr->state->index], + endpoint, args, mgr->state->deadline, + mgr->state->acceptor, cb, user_data); + ++mgr->state->index; + // If this is the last handshaker, clean up state. + if (mgr->state->index == mgr->count) { + gpr_free(mgr->state); + mgr->state = NULL; + } +} + +void grpc_handshake_manager_do_handshake( + grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, + grpc_endpoint* endpoint, const grpc_channel_args* args, + gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, + grpc_handshaker_done_cb cb, void* user_data) { + grpc_channel_args* args_copy = grpc_channel_args_copy(args); + if (mgr->count == 0) { + // No handshakers registered, so we just immediately call the done + // callback with the passed-in endpoint. + cb(exec_ctx, endpoint, args_copy, user_data, GRPC_ERROR_NONE); + } else { + GPR_ASSERT(mgr->state == NULL); + mgr->state = gpr_malloc(sizeof(struct grpc_handshaker_state)); + memset(mgr->state, 0, sizeof(*mgr->state)); + mgr->state->deadline = deadline; + mgr->state->acceptor = acceptor; + mgr->state->final_cb = cb; + mgr->state->final_user_data = user_data; + call_next_handshaker(exec_ctx, endpoint, args_copy, mgr, GRPC_ERROR_NONE); + } +} diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h new file mode 100644 index 0000000000..dfc469c417 --- /dev/null +++ b/src/core/lib/channel/handshaker.h @@ -0,0 +1,145 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H +#define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H + +#include <grpc/impl/codegen/grpc_types.h> +#include <grpc/impl/codegen/time.h> + +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/tcp_server.h" + +/// Handshakers are used to perform initial handshakes on a connection +/// before the client sends the initial request. Some examples of what +/// a handshaker can be used for includes support for HTTP CONNECT on +/// the client side and various types of security initialization. +/// +/// In general, handshakers should be used via a handshake manager. + +/// +/// grpc_handshaker +/// + +typedef struct grpc_handshaker grpc_handshaker; + +/// Callback type invoked when a handshaker is done. +/// Takes ownership of \a args. +typedef void (*grpc_handshaker_done_cb)(grpc_exec_ctx* exec_ctx, + grpc_endpoint* endpoint, + grpc_channel_args* args, + void* user_data, grpc_error* error); + +struct grpc_handshaker_vtable { + /// Destroys the handshaker. + void (*destroy)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); + + /// Shuts down the handshaker (e.g., to clean up when the operation is + /// aborted in the middle). + void (*shutdown)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker); + + /// Performs handshaking. When finished, calls \a cb with \a user_data. + /// Takes ownership of \a args. + /// \a acceptor will be NULL for client-side handshakers. + void (*do_handshake)(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, + grpc_endpoint* endpoint, grpc_channel_args* args, + gpr_timespec deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_handshaker_done_cb cb, void* user_data); +}; + +/// Base struct. To subclass, make this the first member of the +/// implementation struct. +struct grpc_handshaker { + const struct grpc_handshaker_vtable* vtable; +}; + +/// Called by concrete implementations to initialize the base struct. +void grpc_handshaker_init(const struct grpc_handshaker_vtable* vtable, + grpc_handshaker* handshaker); + +/// Convenient wrappers for invoking methods via the vtable. +/// These probably do not need to be called from anywhere but +/// grpc_handshake_manager. +void grpc_handshaker_destroy(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker); +void grpc_handshaker_shutdown(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker); +void grpc_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker, + grpc_endpoint* endpoint, + grpc_channel_args* args, + gpr_timespec deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_handshaker_done_cb cb, void* user_data); + +/// +/// grpc_handshake_manager +/// + +typedef struct grpc_handshake_manager grpc_handshake_manager; + +/// Creates a new handshake manager. Caller takes ownership. +grpc_handshake_manager* grpc_handshake_manager_create(); + +/// Adds a handshaker to the handshake manager. +/// Takes ownership of \a handshaker. +void grpc_handshake_manager_add(grpc_handshake_manager* mgr, + grpc_handshaker* handshaker); + +/// Destroys the handshake manager. +void grpc_handshake_manager_destroy(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr); + +/// Shuts down the handshake manager (e.g., to clean up when the operation is +/// aborted in the middle). +/// The caller must still call grpc_handshake_manager_destroy() after +/// calling this function. +void grpc_handshake_manager_shutdown(grpc_exec_ctx* exec_ctx, + grpc_handshake_manager* mgr); + +/// Invokes handshakers in the order they were added. +/// Does NOT take ownership of \a args. Instead, makes a copy before +/// invoking the first handshaker. +/// \a acceptor will be NULL for client-side handshakers. +/// Invokes \a cb with \a user_data after either a handshaker fails or +/// all handshakers have completed successfully. +void grpc_handshake_manager_do_handshake( + grpc_exec_ctx* exec_ctx, grpc_handshake_manager* mgr, + grpc_endpoint* endpoint, const grpc_channel_args* args, + gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, + grpc_handshaker_done_cb cb, void* user_data); + +#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */ diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index 8057e251f0..a7a775cc53 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -175,16 +175,19 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *calld = elem->call_data; calld->on_done_recv = NULL; grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem); + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) {} + const grpc_call_final_info *final_info, + void *ignored) {} static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) { unsigned i; diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c index d0beebd817..5ce51f9016 100644 --- a/src/core/lib/channel/http_server_filter.c +++ b/src/core/lib/channel/http_server_filter.c @@ -224,18 +224,21 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; /* initialize members */ memset(calld, 0, sizeof(*calld)); grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem); + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) {} + const grpc_call_final_info *final_info, + void *ignored) {} /* Constructor for channel_data */ static void init_channel_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 13f898e31a..bc7781250e 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -171,6 +171,8 @@ grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which, gpr_timespec value) GRPC_MUST_USE_RESULT; grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which, const char *value) GRPC_MUST_USE_RESULT; +/// Returns NULL if the specified string is not set. +/// Caller does NOT own return value. const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which); /// Add a child error: an error that is believed to have contributed to this /// error occurring. Allows root causing high level errors from lower level diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c index 90c074b007..b4bb7e3cf7 100644 --- a/src/core/lib/iomgr/network_status_tracker.c +++ b/src/core/lib/iomgr/network_status_tracker.c @@ -56,6 +56,15 @@ void grpc_network_status_init(void) { // TODO(makarandd): Install callback with OS to monitor network status. } +void grpc_destroy_network_status_monitor() { + for (endpoint_ll_node *curr = head; curr != NULL;) { + endpoint_ll_node *next = curr->next; + gpr_free(curr); + curr = next; + } + gpr_mu_destroy(&g_endpoint_mutex); +} + void grpc_network_status_register_endpoint(grpc_endpoint *ep) { gpr_mu_lock(&g_endpoint_mutex); if (head == NULL) { diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index fa4b72acbb..92767721d5 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -284,7 +284,7 @@ static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, } /* returns true if done, false if pending; if returning true, *error is set */ -#define MAX_WRITE_IOVEC 1024 +#define MAX_WRITE_IOVEC 1000 static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 1ebccf2ee2..48032412a2 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -60,6 +60,7 @@ #include <grpc/support/string_util.h> #include <grpc/support/sync.h> #include <grpc/support/time.h> +#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -128,7 +129,7 @@ grpc_udp_server *grpc_udp_server_create(void) { } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { - grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1, NULL); + grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); gpr_mu_destroy(&s->mu); gpr_cv_destroy(&s->cv); @@ -138,7 +139,7 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { } static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, - bool success) { + grpc_error *error) { grpc_udp_server *s = server; gpr_mu_lock(&s->mu); s->destroyed_ports++; @@ -217,14 +218,23 @@ static int prepare_socket(int fd, const struct sockaddr *addr, goto error; } - if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1)) { - gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd, - strerror(errno)); + if (grpc_set_socket_nonblocking(fd, 1) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set nonblocking %d: %s", fd, strerror(errno)); + goto error; + } + if (grpc_set_socket_cloexec(fd, 1) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set cloexec %d: %s", fd, strerror(errno)); + goto error; } - if (grpc_set_socket_ip_pktinfo_if_possible(fd) && - addr->sa_family == AF_INET6) { - grpc_set_socket_ipv6_recvpktinfo_if_possible(fd); + if (grpc_set_socket_ip_pktinfo_if_possible(fd) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set ip_pktinfo."); + goto error; + } else if (addr->sa_family == AF_INET6) { + if (grpc_set_socket_ipv6_recvpktinfo_if_possible(fd) != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "Unable to set ipv6_recvpktinfo."); + goto error; + } } GPR_ASSERT(addr_len < ~(socklen_t)0); @@ -241,13 +251,13 @@ static int prepare_socket(int fd, const struct sockaddr *addr, goto error; } - if (!grpc_set_socket_sndbuf(fd, buffer_size_bytes)) { + if (grpc_set_socket_sndbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes", buffer_size_bytes); goto error; } - if (!grpc_set_socket_rcvbuf(fd, buffer_size_bytes)) { + if (grpc_set_socket_rcvbuf(fd, buffer_size_bytes) != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to set receive buffer size to %d bytes", buffer_size_bytes); goto error; @@ -263,10 +273,10 @@ error: } /* event manager callback when reads are ready */ -static void on_read(grpc_exec_ctx *exec_ctx, void *arg, bool success) { +static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { server_port *sp = arg; - if (!success) { + if (error != GRPC_ERROR_NONE) { gpr_mu_lock(&sp->server->mu); if (0 == --sp->server->active_ports) { gpr_mu_unlock(&sp->server->mu); @@ -369,7 +379,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, /* Try listening on IPv6 first. */ addr = (struct sockaddr *)&wild6; addr_len = sizeof(wild6); - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); + // TODO(rjshade): Test and propagate the returned grpc_error*: + grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); allocated_port1 = add_socket_to_server(s, fd, addr, addr_len, read_cb, orphan_cb); if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) { @@ -384,7 +395,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr, addr_len = sizeof(wild4); } - fd = grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode); + // TODO(rjshade): Test and propagate the returned grpc_error*: + grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd); if (fd < 0) { gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno)); } diff --git a/src/core/lib/json/json_reader.c b/src/core/lib/json/json_reader.c index bc04bccc65..5b42ca53ff 100644 --- a/src/core/lib/json/json_reader.c +++ b/src/core/lib/json/json_reader.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -171,8 +171,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { switch (reader->state) { case GRPC_JSON_STATE_OBJECT_KEY_STRING: case GRPC_JSON_STATE_VALUE_STRING: - if (reader->unicode_high_surrogate != 0) + if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; + } json_reader_string_add_char(reader, c); break; @@ -289,8 +290,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { break; case GRPC_JSON_STATE_OBJECT_KEY_STRING: - if (reader->unicode_high_surrogate != 0) + if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; + } if (c == '"') { reader->state = GRPC_JSON_STATE_OBJECT_KEY_END; json_reader_set_key(reader); @@ -302,8 +304,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { break; case GRPC_JSON_STATE_VALUE_STRING: - if (reader->unicode_high_surrogate != 0) + if (reader->unicode_high_surrogate != 0) { return GRPC_JSON_PARSE_ERROR; + } if (c == '"') { reader->state = GRPC_JSON_STATE_VALUE_END; json_reader_set_string(reader); @@ -383,8 +386,9 @@ grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { } else { reader->state = GRPC_JSON_STATE_VALUE_STRING; } - if (reader->unicode_high_surrogate && c != 'u') + if (reader->unicode_high_surrogate && c != 'u') { return GRPC_JSON_PARSE_ERROR; + } switch (c) { case '"': case '/': diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index b13bd55df1..b366d1410f 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -272,10 +272,12 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *calld = elem->call_data; memset(calld, 0, sizeof(*calld)); + return GRPC_ERROR_NONE; } static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, @@ -287,7 +289,8 @@ static void set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) { + const grpc_call_final_info *final_info, + void *ignored) { call_data *calld = elem->call_data; grpc_call_credentials_unref(calld->creds); if (calld->host != NULL) { diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c index b374ca7633..540a17283d 100644 --- a/src/core/lib/security/transport/handshake.c +++ b/src/core/lib/security/transport/handshake.c @@ -357,8 +357,9 @@ void grpc_do_security_handshake( gpr_mu_unlock(&server_connector->mu); } send_handshake_bytes_to_peer(exec_ctx, h); - grpc_timer_init(exec_ctx, &h->timer, deadline, on_timeout, h, - gpr_now(deadline.clock_type)); + grpc_timer_init(exec_ctx, &h->timer, + gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), + on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC)); } void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index 1958a72b93..b2c6815af8 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -204,8 +204,9 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, } /* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; @@ -227,11 +228,14 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; args->context[GRPC_CONTEXT_SECURITY].destroy = grpc_server_security_context_destroy; + + return GRPC_ERROR_NONE; } /* Destructor for call_data */ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) {} + const grpc_call_final_info *final_info, + void *ignored) {} /* Constructor for channel_data */ static void init_channel_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c index bae0957df7..899f1218b6 100644 --- a/src/core/lib/support/log.c +++ b/src/core/lib/support/log.c @@ -79,17 +79,18 @@ void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) { void gpr_log_verbosity_init() { char *verbosity = gpr_getenv("GRPC_VERBOSITY"); - if (verbosity == NULL) return; - gpr_atm min_severity_to_print = GPR_LOG_VERBOSITY_UNSET; - if (strcmp(verbosity, "DEBUG") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG; - } else if (strcmp(verbosity, "INFO") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO; - } else if (strcmp(verbosity, "ERROR") == 0) { - min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR; + gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR; + if (verbosity != NULL) { + if (strcmp(verbosity, "DEBUG") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG; + } else if (strcmp(verbosity, "INFO") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO; + } else if (strcmp(verbosity, "ERROR") == 0) { + min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR; + } + gpr_free(verbosity); } - gpr_free(verbosity); if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) == GPR_LOG_VERBOSITY_UNSET) { gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print); diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 36eec253c2..119f5e82ab 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -158,8 +158,9 @@ struct grpc_call { /* Received call statuses from various sources */ received_status status[STATUS_SOURCE_COUNT]; - /* Call stats: only valid after trailing metadata received */ - grpc_call_stats stats; + /* Call data useful used for reporting. Only valid after the call has + * completed */ + grpc_call_final_info final_info; /* Compression algorithm for *incoming* data */ grpc_compression_algorithm incoming_compression_algorithm; @@ -267,9 +268,19 @@ grpc_call *grpc_call_create( gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); GRPC_CHANNEL_INTERNAL_REF(channel, "call"); /* initial refcount dropped by grpc_call_destroy */ - grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call, - call->context, server_transport_data, - CALL_STACK_FROM_CALL(call)); + grpc_error *error = grpc_call_stack_init( + &exec_ctx, channel_stack, 1, destroy_call, call, call->context, + server_transport_data, CALL_STACK_FROM_CALL(call)); + if (error != GRPC_ERROR_NONE) { + intptr_t status; + if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) + status = GRPC_STATUS_UNKNOWN; + const char *error_str = + grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION); + close_with_status(&exec_ctx, call, (grpc_status_code)status, + error_str == NULL ? "unknown error" : error_str); + GRPC_ERROR_UNREF(error); + } if (cq != NULL) { GPR_ASSERT( pollset_set_alternative == NULL && @@ -365,6 +376,25 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) { GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON); } +static void get_final_status(grpc_call *call, + void (*set_value)(grpc_status_code code, + void *user_data), + void *set_value_user_data) { + int i; + for (i = 0; i < STATUS_SOURCE_COUNT; i++) { + if (call->status[i].is_set) { + set_value(call->status[i].code, set_value_user_data); + return; + } + } + if (call->is_client) { + set_value(GRPC_STATUS_UNKNOWN, set_value_user_data); + } else { + set_value(GRPC_STATUS_OK, set_value_user_data); + } +} + +static void set_status_value_directly(grpc_status_code status, void *dest); static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, grpc_error *error) { size_t i; @@ -396,7 +426,11 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } grpc_channel *channel = c->channel; - grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->stats, c); + + get_final_status(call, set_status_value_directly, + &c->final_info.final_status); + + grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call"); GPR_TIMER_END("destroy_call", 0); } @@ -418,24 +452,6 @@ static void set_status_details(grpc_call *call, status_source source, } } -static void get_final_status(grpc_call *call, - void (*set_value)(grpc_status_code code, - void *user_data), - void *set_value_user_data) { - int i; - for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (call->status[i].is_set) { - set_value(call->status[i].code, set_value_user_data); - return; - } - } - if (call->is_client) { - set_value(GRPC_STATUS_UNKNOWN, set_value_user_data); - } else { - set_value(GRPC_STATUS_OK, set_value_user_data); - } -} - static void set_status_from_error(grpc_call *call, status_source source, grpc_error *error) { intptr_t status; @@ -1363,6 +1379,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, int num_completion_callbacks_needed = 1; grpc_call_error error = GRPC_CALL_OK; + // sent_initial_metadata guards against variable reuse. + grpc_metadata compression_md; + GPR_TIMER_BEGIN("grpc_call_start_batch", 0); GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); @@ -1409,8 +1428,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, goto done_with_error; } /* process compression level */ - grpc_metadata compression_md; - memset(&compression_md, 0, sizeof(grpc_metadata)); + memset(&compression_md, 0, sizeof(compression_md)); size_t additional_metadata_count = 0; grpc_compression_level effective_compression_level; bool level_set = false; @@ -1611,7 +1629,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->recv_final_op = 1; stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op->collect_stats = &call->stats.transport_stream_stats; + stream_op->collect_stats = + &call->final_info.stats.transport_stream_stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: /* Flag validation: currently allow no flags */ @@ -1633,7 +1652,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->recv_final_op = 1; stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op->collect_stats = &call->stats.transport_stream_stats; + stream_op->collect_stats = + &call->final_info.stats.transport_stream_stats; break; } } diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c index 203d614b31..d32c884e8e 100644 --- a/src/core/lib/surface/lame_client.c +++ b/src/core/lib/surface/lame_client.c @@ -107,11 +107,14 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, } } -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) {} +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { + return GRPC_ERROR_NONE; +} static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, + const grpc_call_final_info *final_info, void *and_free_memory) { gpr_free(and_free_memory); } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 964333c57b..11795cf0c3 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -859,8 +859,9 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, } } -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_call_element_args *args) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; memset(calld, 0, sizeof(call_data)); @@ -872,10 +873,12 @@ static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, server_on_recv_initial_metadata, elem); server_ref(chand->server); + return GRPC_ERROR_NONE; } static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - const grpc_call_stats *stats, void *ignored) { + const grpc_call_final_info *final_info, + void *ignored) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index c5f16e530d..8f3e5b5b40 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -45,21 +45,21 @@ grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 8, 6, 2, 4, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = - {11, 35, 10, 35, 12, 35, 12, 49, 13, 35, 14, 35, 15, 35, 16, 35, 17, 35, - 19, 35, 20, 35, 21, 35, 24, 35, 25, 35, 26, 35, 27, 35, 28, 35, 29, 35, - 30, 18, 30, 35, 31, 35, 32, 35, 36, 35, 37, 35, 38, 35, 39, 35, 42, 33, - 42, 34, 42, 48, 42, 53, 42, 54, 42, 55, 42, 56, 43, 33, 43, 48, 43, 53, - 46, 0, 46, 1, 46, 2, 50, 35, 57, 35, 58, 35, 59, 35, 60, 35, 61, 35, - 62, 35, 63, 35, 64, 35, 65, 35, 66, 35, 67, 40, 67, 69, 67, 72, 68, 80, - 68, 81, 70, 35, 71, 35, 73, 35, 74, 35, 75, 35, 76, 35, 77, 41, 77, 51, - 77, 52, 78, 35, 79, 35, 82, 3, 82, 4, 82, 5, 82, 6, 82, 7, 82, 8, - 82, 9, 83, 35, 84, 85, 86, 35, 87, 35, 88, 35, 89, 35, 90, 35}; + {11, 33, 10, 33, 12, 33, 12, 49, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33, + 19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33, + 28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31, + 40, 32, 40, 48, 40, 53, 40, 54, 40, 55, 40, 56, 42, 31, 42, 48, 42, 53, + 45, 0, 45, 1, 45, 2, 50, 33, 57, 33, 58, 33, 59, 33, 60, 33, 61, 33, + 62, 33, 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 38, 68, 70, 68, 73, + 69, 81, 69, 82, 71, 33, 72, 33, 74, 33, 75, 33, 76, 33, 77, 33, 78, 39, + 78, 51, 78, 52, 79, 33, 80, 33, 83, 3, 83, 4, 83, 5, 83, 6, 83, 7, + 83, 8, 83, 9, 84, 33, 85, 86, 87, 33, 88, 33, 89, 33, 90, 33, 91, 33}; const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "0", @@ -84,8 +84,6 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { ":authority", "authorization", "cache-control", - "census-bin", - "census-binary-bin", "content-disposition", "content-encoding", "content-language", @@ -105,11 +103,13 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "GET", "grpc", "grpc-accept-encoding", + "grpc-census-bin", "grpc-encoding", "grpc-internal-encoding-request", "grpc-message", "grpc-status", "grpc-timeout", + "grpc-tracing-bin", "gzip", "gzip, deflate", "host", @@ -126,7 +126,8 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "if-unmodified-since", "last-modified", "link", - "load-reporting", + "load-reporting-initial", + "load-reporting-trailing", "location", "max-forwards", ":method", diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index 5ff0d2f3bc..b51bacac50 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -44,7 +44,7 @@ #include "src/core/lib/transport/metadata.h" -#define GRPC_STATIC_MDSTR_COUNT 91 +#define GRPC_STATIC_MDSTR_COUNT 92 extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; /* "0" */ #define GRPC_MDSTR_0 (&grpc_static_mdstr_table[0]) @@ -90,58 +90,58 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_AUTHORIZATION (&grpc_static_mdstr_table[20]) /* "cache-control" */ #define GRPC_MDSTR_CACHE_CONTROL (&grpc_static_mdstr_table[21]) -/* "census-bin" */ -#define GRPC_MDSTR_CENSUS_BIN (&grpc_static_mdstr_table[22]) -/* "census-binary-bin" */ -#define GRPC_MDSTR_CENSUS_BINARY_BIN (&grpc_static_mdstr_table[23]) /* "content-disposition" */ -#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[24]) +#define GRPC_MDSTR_CONTENT_DISPOSITION (&grpc_static_mdstr_table[22]) /* "content-encoding" */ -#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[25]) +#define GRPC_MDSTR_CONTENT_ENCODING (&grpc_static_mdstr_table[23]) /* "content-language" */ -#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[26]) +#define GRPC_MDSTR_CONTENT_LANGUAGE (&grpc_static_mdstr_table[24]) /* "content-length" */ -#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[27]) +#define GRPC_MDSTR_CONTENT_LENGTH (&grpc_static_mdstr_table[25]) /* "content-location" */ -#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[28]) +#define GRPC_MDSTR_CONTENT_LOCATION (&grpc_static_mdstr_table[26]) /* "content-range" */ -#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[29]) +#define GRPC_MDSTR_CONTENT_RANGE (&grpc_static_mdstr_table[27]) /* "content-type" */ -#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[30]) +#define GRPC_MDSTR_CONTENT_TYPE (&grpc_static_mdstr_table[28]) /* "cookie" */ -#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[31]) +#define GRPC_MDSTR_COOKIE (&grpc_static_mdstr_table[29]) /* "date" */ -#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[32]) +#define GRPC_MDSTR_DATE (&grpc_static_mdstr_table[30]) /* "deflate" */ -#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[33]) +#define GRPC_MDSTR_DEFLATE (&grpc_static_mdstr_table[31]) /* "deflate,gzip" */ -#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[34]) +#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (&grpc_static_mdstr_table[32]) /* "" */ -#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[35]) +#define GRPC_MDSTR_EMPTY (&grpc_static_mdstr_table[33]) /* "etag" */ -#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[36]) +#define GRPC_MDSTR_ETAG (&grpc_static_mdstr_table[34]) /* "expect" */ -#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[37]) +#define GRPC_MDSTR_EXPECT (&grpc_static_mdstr_table[35]) /* "expires" */ -#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[38]) +#define GRPC_MDSTR_EXPIRES (&grpc_static_mdstr_table[36]) /* "from" */ -#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[39]) +#define GRPC_MDSTR_FROM (&grpc_static_mdstr_table[37]) /* "GET" */ -#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[40]) +#define GRPC_MDSTR_GET (&grpc_static_mdstr_table[38]) /* "grpc" */ -#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[41]) +#define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39]) /* "grpc-accept-encoding" */ -#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[42]) +#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40]) +/* "grpc-census-bin" */ +#define GRPC_MDSTR_GRPC_CENSUS_BIN (&grpc_static_mdstr_table[41]) /* "grpc-encoding" */ -#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[43]) +#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[42]) /* "grpc-internal-encoding-request" */ -#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[44]) +#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[43]) /* "grpc-message" */ -#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[45]) +#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[44]) /* "grpc-status" */ -#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46]) +#define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[45]) /* "grpc-timeout" */ -#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[47]) +#define GRPC_MDSTR_GRPC_TIMEOUT (&grpc_static_mdstr_table[46]) +/* "grpc-tracing-bin" */ +#define GRPC_MDSTR_GRPC_TRACING_BIN (&grpc_static_mdstr_table[47]) /* "gzip" */ #define GRPC_MDSTR_GZIP (&grpc_static_mdstr_table[48]) /* "gzip, deflate" */ @@ -175,62 +175,64 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[62]) /* "link" */ #define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[63]) -/* "load-reporting" */ -#define GRPC_MDSTR_LOAD_REPORTING (&grpc_static_mdstr_table[64]) +/* "load-reporting-initial" */ +#define GRPC_MDSTR_LOAD_REPORTING_INITIAL (&grpc_static_mdstr_table[64]) +/* "load-reporting-trailing" */ +#define GRPC_MDSTR_LOAD_REPORTING_TRAILING (&grpc_static_mdstr_table[65]) /* "location" */ -#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[65]) +#define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[66]) /* "max-forwards" */ -#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[66]) +#define GRPC_MDSTR_MAX_FORWARDS (&grpc_static_mdstr_table[67]) /* ":method" */ -#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[67]) +#define GRPC_MDSTR_METHOD (&grpc_static_mdstr_table[68]) /* ":path" */ -#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[68]) +#define GRPC_MDSTR_PATH (&grpc_static_mdstr_table[69]) /* "POST" */ -#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[69]) +#define GRPC_MDSTR_POST (&grpc_static_mdstr_table[70]) /* "proxy-authenticate" */ -#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[70]) +#define GRPC_MDSTR_PROXY_AUTHENTICATE (&grpc_static_mdstr_table[71]) /* "proxy-authorization" */ -#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[71]) +#define GRPC_MDSTR_PROXY_AUTHORIZATION (&grpc_static_mdstr_table[72]) /* "PUT" */ -#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[72]) +#define GRPC_MDSTR_PUT (&grpc_static_mdstr_table[73]) /* "range" */ -#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[73]) +#define GRPC_MDSTR_RANGE (&grpc_static_mdstr_table[74]) /* "referer" */ -#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[74]) +#define GRPC_MDSTR_REFERER (&grpc_static_mdstr_table[75]) /* "refresh" */ -#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[75]) +#define GRPC_MDSTR_REFRESH (&grpc_static_mdstr_table[76]) /* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[76]) +#define GRPC_MDSTR_RETRY_AFTER (&grpc_static_mdstr_table[77]) /* ":scheme" */ -#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[77]) +#define GRPC_MDSTR_SCHEME (&grpc_static_mdstr_table[78]) /* "server" */ -#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[78]) +#define GRPC_MDSTR_SERVER (&grpc_static_mdstr_table[79]) /* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[79]) +#define GRPC_MDSTR_SET_COOKIE (&grpc_static_mdstr_table[80]) /* "/" */ -#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[80]) +#define GRPC_MDSTR_SLASH (&grpc_static_mdstr_table[81]) /* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[81]) +#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (&grpc_static_mdstr_table[82]) /* ":status" */ -#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[82]) +#define GRPC_MDSTR_STATUS (&grpc_static_mdstr_table[83]) /* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[83]) +#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (&grpc_static_mdstr_table[84]) /* "te" */ -#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[84]) +#define GRPC_MDSTR_TE (&grpc_static_mdstr_table[85]) /* "trailers" */ -#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[85]) +#define GRPC_MDSTR_TRAILERS (&grpc_static_mdstr_table[86]) /* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[86]) +#define GRPC_MDSTR_TRANSFER_ENCODING (&grpc_static_mdstr_table[87]) /* "user-agent" */ -#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[87]) +#define GRPC_MDSTR_USER_AGENT (&grpc_static_mdstr_table[88]) /* "vary" */ -#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[88]) +#define GRPC_MDSTR_VARY (&grpc_static_mdstr_table[89]) /* "via" */ -#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[89]) +#define GRPC_MDSTR_VIA (&grpc_static_mdstr_table[90]) /* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[90]) +#define GRPC_MDSTR_WWW_AUTHENTICATE (&grpc_static_mdstr_table[91]) -#define GRPC_STATIC_MDELEM_COUNT 80 +#define GRPC_STATIC_MDELEM_COUNT 81 extern grpc_mdelem grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; /* "accept-charset": "" */ @@ -335,73 +337,76 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; #define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45]) /* "link": "" */ #define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[46]) -/* "load-reporting": "" */ -#define GRPC_MDELEM_LOAD_REPORTING_EMPTY (&grpc_static_mdelem_table[47]) +/* "load-reporting-initial": "" */ +#define GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY (&grpc_static_mdelem_table[47]) +/* "load-reporting-trailing": "" */ +#define GRPC_MDELEM_LOAD_REPORTING_TRAILING_EMPTY \ + (&grpc_static_mdelem_table[48]) /* "location": "" */ -#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[48]) +#define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[49]) /* "max-forwards": "" */ -#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[49]) +#define GRPC_MDELEM_MAX_FORWARDS_EMPTY (&grpc_static_mdelem_table[50]) /* ":method": "GET" */ -#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[50]) +#define GRPC_MDELEM_METHOD_GET (&grpc_static_mdelem_table[51]) /* ":method": "POST" */ -#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[51]) +#define GRPC_MDELEM_METHOD_POST (&grpc_static_mdelem_table[52]) /* ":method": "PUT" */ -#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[52]) +#define GRPC_MDELEM_METHOD_PUT (&grpc_static_mdelem_table[53]) /* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[53]) +#define GRPC_MDELEM_PATH_SLASH (&grpc_static_mdelem_table[54]) /* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[54]) +#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML (&grpc_static_mdelem_table[55]) /* "proxy-authenticate": "" */ -#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[55]) +#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[56]) /* "proxy-authorization": "" */ -#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[56]) +#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY (&grpc_static_mdelem_table[57]) /* "range": "" */ -#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[57]) +#define GRPC_MDELEM_RANGE_EMPTY (&grpc_static_mdelem_table[58]) /* "referer": "" */ -#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[58]) +#define GRPC_MDELEM_REFERER_EMPTY (&grpc_static_mdelem_table[59]) /* "refresh": "" */ -#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[59]) +#define GRPC_MDELEM_REFRESH_EMPTY (&grpc_static_mdelem_table[60]) /* "retry-after": "" */ -#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[60]) +#define GRPC_MDELEM_RETRY_AFTER_EMPTY (&grpc_static_mdelem_table[61]) /* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[61]) +#define GRPC_MDELEM_SCHEME_GRPC (&grpc_static_mdelem_table[62]) /* ":scheme": "http" */ -#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[62]) +#define GRPC_MDELEM_SCHEME_HTTP (&grpc_static_mdelem_table[63]) /* ":scheme": "https" */ -#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[63]) +#define GRPC_MDELEM_SCHEME_HTTPS (&grpc_static_mdelem_table[64]) /* "server": "" */ -#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[64]) +#define GRPC_MDELEM_SERVER_EMPTY (&grpc_static_mdelem_table[65]) /* "set-cookie": "" */ -#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[65]) +#define GRPC_MDELEM_SET_COOKIE_EMPTY (&grpc_static_mdelem_table[66]) /* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[66]) +#define GRPC_MDELEM_STATUS_200 (&grpc_static_mdelem_table[67]) /* ":status": "204" */ -#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[67]) +#define GRPC_MDELEM_STATUS_204 (&grpc_static_mdelem_table[68]) /* ":status": "206" */ -#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[68]) +#define GRPC_MDELEM_STATUS_206 (&grpc_static_mdelem_table[69]) /* ":status": "304" */ -#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[69]) +#define GRPC_MDELEM_STATUS_304 (&grpc_static_mdelem_table[70]) /* ":status": "400" */ -#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[70]) +#define GRPC_MDELEM_STATUS_400 (&grpc_static_mdelem_table[71]) /* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[71]) +#define GRPC_MDELEM_STATUS_404 (&grpc_static_mdelem_table[72]) /* ":status": "500" */ -#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[72]) +#define GRPC_MDELEM_STATUS_500 (&grpc_static_mdelem_table[73]) /* "strict-transport-security": "" */ #define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (&grpc_static_mdelem_table[73]) + (&grpc_static_mdelem_table[74]) /* "te": "trailers" */ -#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[74]) +#define GRPC_MDELEM_TE_TRAILERS (&grpc_static_mdelem_table[75]) /* "transfer-encoding": "" */ -#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[75]) +#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY (&grpc_static_mdelem_table[76]) /* "user-agent": "" */ -#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[76]) +#define GRPC_MDELEM_USER_AGENT_EMPTY (&grpc_static_mdelem_table[77]) /* "vary": "" */ -#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[77]) +#define GRPC_MDELEM_VARY_EMPTY (&grpc_static_mdelem_table[78]) /* "via": "" */ -#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[78]) +#define GRPC_MDELEM_VIA_EMPTY (&grpc_static_mdelem_table[79]) /* "www-authenticate": "" */ -#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[79]) +#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY (&grpc_static_mdelem_table[80]) extern const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2]; diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.c b/src/core/lib/transport/timeout_encoding.c index b7f7912493..b58ebbd0a8 100644 --- a/src/core/ext/transport/chttp2/transport/timeout_encoding.c +++ b/src/core/lib/transport/timeout_encoding.c @@ -31,7 +31,7 @@ * */ -#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" +#include "src/core/lib/transport/timeout_encoding.h" #include <stdio.h> #include <string.h> @@ -117,7 +117,7 @@ static void enc_micros(char *buffer, int64_t x) { } } -void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer) { +void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer) { if (timeout.tv_sec < 0) { enc_tiny(buffer); } else if (timeout.tv_sec == 0) { @@ -136,7 +136,7 @@ static int is_all_whitespace(const char *p) { return *p == 0; } -int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) { +int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout) { int32_t x = 0; const uint8_t *p = (const uint8_t *)buffer; int have_digit = 0; diff --git a/src/core/ext/transport/chttp2/transport/timeout_encoding.h b/src/core/lib/transport/timeout_encoding.h index df2324c791..92f02f6ecd 100644 --- a/src/core/ext/transport/chttp2/transport/timeout_encoding.h +++ b/src/core/lib/transport/timeout_encoding.h @@ -31,17 +31,17 @@ * */ -#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H -#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H +#ifndef GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H +#define GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H #include <grpc/support/time.h> #include "src/core/lib/support/string.h" -#define GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1) +#define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE (GPR_LTOA_MIN_BUFSIZE + 1) -/* Encode/decode timeouts to the GRPC over HTTP2 format; +/* Encode/decode timeouts to the GRPC over HTTP/2 format; encoding may round up arbitrarily */ -void grpc_chttp2_encode_timeout(gpr_timespec timeout, char *buffer); -int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout); +void grpc_http2_encode_timeout(gpr_timespec timeout, char *buffer); +int grpc_http2_decode_timeout(const char *buffer, gpr_timespec *timeout); -#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_TIMEOUT_ENCODING_H */ +#endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */ diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 508b57a5b4..4f82794235 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -143,7 +143,7 @@ typedef struct grpc_transport_stream_op { /** If != GRPC_ERROR_NONE, cancel this stream */ grpc_error *cancel_error; - /** If != GRPC_ERROR, send grpc-status, grpc-message, and close this + /** If != GRPC_ERROR_NONE, send grpc-status, grpc-message, and close this stream for both reading and writing */ grpc_error *close_error; diff --git a/src/core/plugin_registry/grpc_plugin_registry.c b/src/core/plugin_registry/grpc_plugin_registry.c index 905cd59e23..7a7a9ce477 100644 --- a/src/core/plugin_registry/grpc_plugin_registry.c +++ b/src/core/plugin_registry/grpc_plugin_registry.c @@ -37,6 +37,8 @@ extern void grpc_chttp2_plugin_init(void); extern void grpc_chttp2_plugin_shutdown(void); extern void grpc_client_config_init(void); extern void grpc_client_config_shutdown(void); +extern void grpc_lb_policy_grpclb_init(void); +extern void grpc_lb_policy_grpclb_shutdown(void); extern void grpc_lb_policy_pick_first_init(void); extern void grpc_lb_policy_pick_first_shutdown(void); extern void grpc_lb_policy_round_robin_init(void); @@ -55,6 +57,8 @@ void grpc_register_built_in_plugins(void) { grpc_chttp2_plugin_shutdown); grpc_register_plugin(grpc_client_config_init, grpc_client_config_shutdown); + grpc_register_plugin(grpc_lb_policy_grpclb_init, + grpc_lb_policy_grpclb_shutdown); grpc_register_plugin(grpc_lb_policy_pick_first_init, grpc_lb_policy_pick_first_shutdown); grpc_register_plugin(grpc_lb_policy_round_robin_init, diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c index 7995078725..ad4ddf0ff4 100644 --- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.c +++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.c @@ -43,6 +43,8 @@ extern void grpc_resolver_sockaddr_init(void); extern void grpc_resolver_sockaddr_shutdown(void); extern void grpc_load_reporting_plugin_init(void); extern void grpc_load_reporting_plugin_shutdown(void); +extern void grpc_lb_policy_grpclb_init(void); +extern void grpc_lb_policy_grpclb_shutdown(void); extern void grpc_lb_policy_pick_first_init(void); extern void grpc_lb_policy_pick_first_shutdown(void); extern void grpc_lb_policy_round_robin_init(void); @@ -61,6 +63,8 @@ void grpc_register_built_in_plugins(void) { grpc_resolver_sockaddr_shutdown); grpc_register_plugin(grpc_load_reporting_plugin_init, grpc_load_reporting_plugin_shutdown); + grpc_register_plugin(grpc_lb_policy_grpclb_init, + grpc_lb_policy_grpclb_shutdown); grpc_register_plugin(grpc_lb_policy_pick_first_init, grpc_lb_policy_pick_first_shutdown); grpc_register_plugin(grpc_lb_policy_round_robin_init, diff --git a/src/cpp/ext/proto_server_reflection.h b/src/cpp/ext/proto_server_reflection.h index 23c130513d..f66f3c2c9a 100644 --- a/src/cpp/ext/proto_server_reflection.h +++ b/src/cpp/ext/proto_server_reflection.h @@ -30,13 +30,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + +/* + - If the generated header `grpc++/ext/reflection.grpc.pb.h` needs to be + installed, target `grpc++_reflection` in `build.yaml` should use the + filegroup `grpc++_reflection_proto`, and GRPC_NO_GENERATED_CODE should not + be defined. + - If the server reflection library needs to generate `reflection.grpc.pb.h` + from `reflection.proto` at compile time, the generated header + `grpc++/ext/reflection.grpc.pb.h` should not be installed. In this case, + target `grpc++_reflection` should depend on `grpc++_reflection_codegen`, and + GRPC_NO_GENERATED_CODE should be defined. +*/ + #ifndef GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H #define GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H #include <unordered_set> #include <vector> +// GRPC_NO_GENERATED_CODE indicates generated pb files should not be used +#ifdef GRPC_NO_GENERATED_CODE +#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h" +#else #include <grpc++/ext/reflection.grpc.pb.h> +#endif // GRPC_NO_GENERATED_CODE #include <grpc++/grpc++.h> namespace grpc { diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 43117fd1e9..1ca6a2b906 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -129,7 +129,8 @@ ServerContext::ServerContext() deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)), call_(nullptr), cq_(nullptr), - sent_initial_metadata_(false) {} + sent_initial_metadata_(false), + compression_level_set_(false) {} ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata, size_t metadata_count) @@ -139,7 +140,8 @@ ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata, deadline_(deadline), call_(nullptr), cq_(nullptr), - sent_initial_metadata_(false) { + sent_initial_metadata_(false), + compression_level_set_(false) { for (size_t i = 0; i < metadata_count; i++) { client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>( metadata[i].key, @@ -194,15 +196,6 @@ bool ServerContext::IsCancelled() const { } } -void ServerContext::set_compression_level(grpc_compression_level level) { - // TODO(dgq): get rid of grpc_call_compression_for_level and propagate the - // compression level by adding a new argument to - // CallOpSendInitialMetadata::SendInitialMetadata. - const grpc_compression_algorithm algorithm_for_level = - grpc_call_compression_for_level(call_, level); - set_compression_algorithm(algorithm_for_level); -} - void ServerContext::set_compression_algorithm( grpc_compression_algorithm algorithm) { char* algorithm_name = NULL; diff --git a/src/csharp/.nuget/packages.config b/src/csharp/.nuget/packages.config deleted file mode 100644 index 6154b3561f..0000000000 --- a/src/csharp/.nuget/packages.config +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packages> - <package id="NUnit.ConsoleRunner" version="3.2.0" /> - <package id="OpenCover" version="4.6.519" /> - <package id="ReportGenerator" version="2.4.4.0" /> -</packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json index 08429f1d46..6215ca3585 100644 --- a/src/csharp/Grpc.Auth/project.json +++ b/src/csharp/Grpc.Auth/project.json @@ -32,9 +32,9 @@ "net45" ], "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Threading.Tasks": "4.0.11-rc2-24027" + "Microsoft.NETCore.Portable.Compatibility": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Threading.Tasks": "4.0.11" } } } diff --git a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs index 064bc13cab..d7ebdb4201 100644 --- a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs +++ b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs @@ -40,7 +40,7 @@ namespace Grpc.Core.Tests { public class AppDomainUnloadTest { -#if NETSTANDARD1_5 +#if NETCOREAPP1_0 [Test] [Ignore("Not supported for CoreCLR")] public void AppDomainUnloadHookCanCleanupAbandonedCall() diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs index 24a9f846d1..870c726ac0 100644 --- a/src/csharp/Grpc.Core.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs @@ -49,7 +49,7 @@ namespace Grpc.Core.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); -#if NETSTANDARD1_5 +#if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs index 501992c569..df887d82b3 100644 --- a/src/csharp/Grpc.Core.Tests/SanityTest.cs +++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs @@ -46,7 +46,7 @@ namespace Grpc.Core.Tests public class SanityTest { // TODO: make sanity test work for CoreCLR as well -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 /// <summary> /// Because we depend on a native library, sometimes when things go wrong, the /// entire NUnit test process crashes. To be able to track down problems better, @@ -58,10 +58,11 @@ namespace Grpc.Core.Tests [Test] public void TestsJsonUpToDate() { - var discoveredTests = DiscoverAllTestClasses(); - string discoveredTestsJson = JsonConvert.SerializeObject(discoveredTests, Formatting.Indented); + Dictionary<string, List<string>> discoveredTests = DiscoverAllTestClasses(); + Dictionary<string, List<string>> testsFromFile + = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(ReadTestsJson()); - Assert.AreEqual(discoveredTestsJson, ReadTestsJson()); + Assert.AreEqual(discoveredTests, testsFromFile); } /// <summary> diff --git a/src/csharp/Grpc.Core.Tests/packages.config b/src/csharp/Grpc.Core.Tests/packages.config index aa7d951fdc..6a930c17ee 100644 --- a/src/csharp/Grpc.Core.Tests/packages.config +++ b/src/csharp/Grpc.Core.Tests/packages.config @@ -4,4 +4,7 @@ <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="NUnit" version="3.2.0" targetFramework="net45" /> <package id="NUnitLite" version="3.2.0" targetFramework="net45" /> -</packages>
\ No newline at end of file + <package id="NUnit.ConsoleRunner" version="3.2.0" /> + <package id="OpenCover" version="4.6.519" /> + <package id="ReportGenerator" version="2.4.4.0" /> +</packages> diff --git a/src/csharp/Grpc.Core.Tests/project.json b/src/csharp/Grpc.Core.Tests/project.json index f58bcbb515..014e2262e9 100644 --- a/src/csharp/Grpc.Core.Tests/project.json +++ b/src/csharp/Grpc.Core.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -54,16 +54,20 @@ }, "Newtonsoft.Json": "8.0.3", "NUnit": "3.2.0", - "NUnitLite": "3.2.0-*" + "NUnitLite": "3.2.0-*", + "NUnit.ConsoleRunner": "3.2.0", + "OpenCover": "4.6.519", + "ReportGenerator": "2.4.4.0" }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } }, diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index 47593f787b..543549eb2d 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -25,11 +25,11 @@ <file src="**\*.cs" target="src" /> <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" /> <!-- without backslashes in the the source path, nuget won't copy the files --> - <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" /> - <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" /> - <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" /> - <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" /> - <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" /> - <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" /> + <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x86.dll" /> + <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x64.dll" /> + <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x86.so" /> + <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x64.so" /> + <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x86.dylib" /> + <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x64.dylib" /> </files> </package> diff --git a/src/csharp/Grpc.Core/Grpc.Core.targets b/src/csharp/Grpc.Core/Grpc.Core.targets index 501fc50548..3367d51a80 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.targets +++ b/src/csharp/Grpc.Core/Grpc.Core.targets @@ -1,29 +1,29 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x86\grpc_csharp_ext.dll"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x86.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x86.dll</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x64\grpc_csharp_ext.dll"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win\native\grpc_csharp_ext.x64.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x64\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x64.dll</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x86\libgrpc_csharp_ext.so"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x86.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x86\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x86.so</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x64\libgrpc_csharp_ext.so"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\linux\native\libgrpc_csharp_ext.x64.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x64.so</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x86\libgrpc_csharp_ext.dylib"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x86.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x86.dylib</Link> </Content> - <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x64\libgrpc_csharp_ext.dylib"> + <Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\osx\native\libgrpc_csharp_ext.x64.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x64\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x64.dylib</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index eeed699712..574e900a0e 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -47,7 +47,6 @@ namespace Grpc.Core /// </summary> public class GrpcEnvironment { - const LogLevel DefaultLogLevel = LogLevel.Info; const int MinDefaultThreadPoolSize = 4; static object staticLock = new object(); @@ -58,7 +57,7 @@ namespace Grpc.Core static readonly HashSet<Channel> registeredChannels = new HashSet<Channel>(); static readonly HashSet<Server> registeredServers = new HashSet<Server>(); - static ILogger logger = new LogLevelFilterLogger(new ConsoleLogger(), DefaultLogLevel); + static ILogger logger = new NullLogger(); readonly object myLock = new object(); readonly GrpcThreadPool threadPool; diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index a6d7925816..509baf7cb1 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -44,9 +44,6 @@ namespace Grpc.Core.Internal /// </summary> internal sealed class NativeExtension { - const string NativeLibrariesDir = "nativelibs"; - const string DnxStyleNativeLibrariesDir = "../../build/native/bin/"; - static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>(); static readonly object staticLock = new object(); static volatile NativeExtension instance; @@ -98,20 +95,25 @@ namespace Grpc.Core.Internal private static UnmanagedLibrary Load() { // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property). - - var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString()); - + // See https://github.com/grpc/grpc/pull/7303 for one option. var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder // alongside the compiled assembly. - var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + // With dotnet cli projects, the native libraries (just the required ones) are similarly copied to the built output folder, + // through the magic of Microsoft.NETCore.Platforms. + var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename()); // DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. - var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); - return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath}); + // TODO: Support .NET Core applications, which act slightly differently. We may be okay if "dotnet publish" + // is used, but "dotnet run" leaves the native libraries in-package, while copying assemblies. + string platform = GetPlatformString(); + string relativeDirectory = string.Format("../../runtimes/{0}/native", platform); + var dnxStylePath = Path.Combine(assemblyDirectory, relativeDirectory, GetNativeLibraryFilename()); + string[] paths = new[] { classicPath, dnxStylePath }; + return new UnmanagedLibrary(paths); } private static string GetAssemblyPath() @@ -147,7 +149,7 @@ namespace Grpc.Core.Internal { if (PlatformApis.IsWindows) { - return "windows"; + return "win"; } if (PlatformApis.IsLinux) { @@ -155,7 +157,7 @@ namespace Grpc.Core.Internal } if (PlatformApis.IsMacOSX) { - return "macosx"; + return "osx"; } throw new InvalidOperationException("Unsupported platform."); } @@ -176,17 +178,18 @@ namespace Grpc.Core.Internal // platform specific file name of the extension library private static string GetNativeLibraryFilename() { + string architecture = GetArchitectureString(); if (PlatformApis.IsWindows) { - return "grpc_csharp_ext.dll"; + return string.Format("grpc_csharp_ext.{0}.dll", architecture); } if (PlatformApis.IsLinux) { - return "libgrpc_csharp_ext.so"; + return string.Format("libgrpc_csharp_ext.{0}.so", architecture); } if (PlatformApis.IsMacOSX) { - return "libgrpc_csharp_ext.dylib"; + return string.Format("libgrpc_csharp_ext.{0}.dylib", architecture); } throw new InvalidOperationException("Unsupported platform."); } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index 65607ed120..f457c9dbf1 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -159,215 +159,107 @@ namespace Grpc.Core.Internal public NativeMethods(UnmanagedLibrary library) { - if (PlatformApis.IsLinux || PlatformApis.IsMacOSX) - { - this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library); - this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library); - this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library); - - this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library); - this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library); - this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library); - this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library); - this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library); - this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library); - this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library); - this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library); - - this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library); - this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library); - - this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library); - this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library); - this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library); - this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library); - this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library); - this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library); - this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library); - this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library); - this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library); - this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library); - this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library); - this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library); - this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library); - this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library); - this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library); - this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library); - - this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library); - this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library); - this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library); - this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library); - - this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library); - this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library); - this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library); - this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library); - - this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library); - this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library); - this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library); - this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library); - this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library); - this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library); - this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library); - - this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library); - - this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library); - this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library); - this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library); - this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library); - this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library); - - this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library); - - this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library); - this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library); - this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library); - this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library); - this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library); - this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library); - this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library); - - this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library); - - this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library); - this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library); - - this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library); - this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library); - - this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library); - this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library); - this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library); - this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library); - this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library); - this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library); - this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library); - this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library); - this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library); - - this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library); - this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library); - this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library); - this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library); - this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library); - - this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library); - this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library); - } - else - { - // Windows or fallback - this.grpcsharp_init = PInvokeMethods.grpcsharp_init; - this.grpcsharp_shutdown = PInvokeMethods.grpcsharp_shutdown; - this.grpcsharp_version_string = PInvokeMethods.grpcsharp_version_string; - - this.grpcsharp_batch_context_create = PInvokeMethods.grpcsharp_batch_context_create; - this.grpcsharp_batch_context_recv_initial_metadata = PInvokeMethods.grpcsharp_batch_context_recv_initial_metadata; - this.grpcsharp_batch_context_recv_message_length = PInvokeMethods.grpcsharp_batch_context_recv_message_length; - this.grpcsharp_batch_context_recv_message_to_buffer = PInvokeMethods.grpcsharp_batch_context_recv_message_to_buffer; - this.grpcsharp_batch_context_recv_status_on_client_status = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_status; - this.grpcsharp_batch_context_recv_status_on_client_details = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_details; - this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; - this.grpcsharp_batch_context_server_rpc_new_call = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_call; - this.grpcsharp_batch_context_server_rpc_new_method = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_method; - this.grpcsharp_batch_context_server_rpc_new_host = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_host; - this.grpcsharp_batch_context_server_rpc_new_deadline = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_deadline; - this.grpcsharp_batch_context_server_rpc_new_request_metadata = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_request_metadata; - this.grpcsharp_batch_context_recv_close_on_server_cancelled = PInvokeMethods.grpcsharp_batch_context_recv_close_on_server_cancelled; - this.grpcsharp_batch_context_destroy = PInvokeMethods.grpcsharp_batch_context_destroy; - - this.grpcsharp_composite_call_credentials_create = PInvokeMethods.grpcsharp_composite_call_credentials_create; - this.grpcsharp_call_credentials_release = PInvokeMethods.grpcsharp_call_credentials_release; - - this.grpcsharp_call_cancel = PInvokeMethods.grpcsharp_call_cancel; - this.grpcsharp_call_cancel_with_status = PInvokeMethods.grpcsharp_call_cancel_with_status; - this.grpcsharp_call_start_unary = PInvokeMethods.grpcsharp_call_start_unary; - this.grpcsharp_call_start_client_streaming = PInvokeMethods.grpcsharp_call_start_client_streaming; - this.grpcsharp_call_start_server_streaming = PInvokeMethods.grpcsharp_call_start_server_streaming; - this.grpcsharp_call_start_duplex_streaming = PInvokeMethods.grpcsharp_call_start_duplex_streaming; - this.grpcsharp_call_send_message = PInvokeMethods.grpcsharp_call_send_message; - this.grpcsharp_call_send_close_from_client = PInvokeMethods.grpcsharp_call_send_close_from_client; - this.grpcsharp_call_send_status_from_server = PInvokeMethods.grpcsharp_call_send_status_from_server; - this.grpcsharp_call_recv_message = PInvokeMethods.grpcsharp_call_recv_message; - this.grpcsharp_call_recv_initial_metadata = PInvokeMethods.grpcsharp_call_recv_initial_metadata; - this.grpcsharp_call_start_serverside = PInvokeMethods.grpcsharp_call_start_serverside; - this.grpcsharp_call_send_initial_metadata = PInvokeMethods.grpcsharp_call_send_initial_metadata; - this.grpcsharp_call_set_credentials = PInvokeMethods.grpcsharp_call_set_credentials; - this.grpcsharp_call_get_peer = PInvokeMethods.grpcsharp_call_get_peer; - this.grpcsharp_call_destroy = PInvokeMethods.grpcsharp_call_destroy; - - this.grpcsharp_channel_args_create = PInvokeMethods.grpcsharp_channel_args_create; - this.grpcsharp_channel_args_set_string = PInvokeMethods.grpcsharp_channel_args_set_string; - this.grpcsharp_channel_args_set_integer = PInvokeMethods.grpcsharp_channel_args_set_integer; - this.grpcsharp_channel_args_destroy = PInvokeMethods.grpcsharp_channel_args_destroy; - - this.grpcsharp_override_default_ssl_roots = PInvokeMethods.grpcsharp_override_default_ssl_roots; - this.grpcsharp_ssl_credentials_create = PInvokeMethods.grpcsharp_ssl_credentials_create; - this.grpcsharp_composite_channel_credentials_create = PInvokeMethods.grpcsharp_composite_channel_credentials_create; - this.grpcsharp_channel_credentials_release = PInvokeMethods.grpcsharp_channel_credentials_release; - - this.grpcsharp_insecure_channel_create = PInvokeMethods.grpcsharp_insecure_channel_create; - this.grpcsharp_secure_channel_create = PInvokeMethods.grpcsharp_secure_channel_create; - this.grpcsharp_channel_create_call = PInvokeMethods.grpcsharp_channel_create_call; - this.grpcsharp_channel_check_connectivity_state = PInvokeMethods.grpcsharp_channel_check_connectivity_state; - this.grpcsharp_channel_watch_connectivity_state = PInvokeMethods.grpcsharp_channel_watch_connectivity_state; - this.grpcsharp_channel_get_target = PInvokeMethods.grpcsharp_channel_get_target; - this.grpcsharp_channel_destroy = PInvokeMethods.grpcsharp_channel_destroy; - - this.grpcsharp_sizeof_grpc_event = PInvokeMethods.grpcsharp_sizeof_grpc_event; - - this.grpcsharp_completion_queue_create = PInvokeMethods.grpcsharp_completion_queue_create; - this.grpcsharp_completion_queue_shutdown = PInvokeMethods.grpcsharp_completion_queue_shutdown; - this.grpcsharp_completion_queue_next = PInvokeMethods.grpcsharp_completion_queue_next; - this.grpcsharp_completion_queue_pluck = PInvokeMethods.grpcsharp_completion_queue_pluck; - this.grpcsharp_completion_queue_destroy = PInvokeMethods.grpcsharp_completion_queue_destroy; - - this.gprsharp_free = PInvokeMethods.gprsharp_free; - - this.grpcsharp_metadata_array_create = PInvokeMethods.grpcsharp_metadata_array_create; - this.grpcsharp_metadata_array_add = PInvokeMethods.grpcsharp_metadata_array_add; - this.grpcsharp_metadata_array_count = PInvokeMethods.grpcsharp_metadata_array_count; - this.grpcsharp_metadata_array_get_key = PInvokeMethods.grpcsharp_metadata_array_get_key; - this.grpcsharp_metadata_array_get_value = PInvokeMethods.grpcsharp_metadata_array_get_value; - this.grpcsharp_metadata_array_get_value_length = PInvokeMethods.grpcsharp_metadata_array_get_value_length; - this.grpcsharp_metadata_array_destroy_full = PInvokeMethods.grpcsharp_metadata_array_destroy_full; - - this.grpcsharp_redirect_log = PInvokeMethods.grpcsharp_redirect_log; - - this.grpcsharp_metadata_credentials_create_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_create_from_plugin; - this.grpcsharp_metadata_credentials_notify_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_notify_from_plugin; - - this.grpcsharp_ssl_server_credentials_create = PInvokeMethods.grpcsharp_ssl_server_credentials_create; - this.grpcsharp_server_credentials_release = PInvokeMethods.grpcsharp_server_credentials_release; - - this.grpcsharp_server_create = PInvokeMethods.grpcsharp_server_create; - this.grpcsharp_server_register_completion_queue = PInvokeMethods.grpcsharp_server_register_completion_queue; - this.grpcsharp_server_add_insecure_http2_port = PInvokeMethods.grpcsharp_server_add_insecure_http2_port; - this.grpcsharp_server_add_secure_http2_port = PInvokeMethods.grpcsharp_server_add_secure_http2_port; - this.grpcsharp_server_start = PInvokeMethods.grpcsharp_server_start; - this.grpcsharp_server_request_call = PInvokeMethods.grpcsharp_server_request_call; - this.grpcsharp_server_cancel_all_calls = PInvokeMethods.grpcsharp_server_cancel_all_calls; - this.grpcsharp_server_shutdown_and_notify_callback = PInvokeMethods.grpcsharp_server_shutdown_and_notify_callback; - this.grpcsharp_server_destroy = PInvokeMethods.grpcsharp_server_destroy; - - this.gprsharp_now = PInvokeMethods.gprsharp_now; - this.gprsharp_inf_future = PInvokeMethods.gprsharp_inf_future; - this.gprsharp_inf_past = PInvokeMethods.gprsharp_inf_past; - this.gprsharp_convert_clock_type = PInvokeMethods.gprsharp_convert_clock_type; - this.gprsharp_sizeof_timespec = PInvokeMethods.gprsharp_sizeof_timespec; - - this.grpcsharp_test_callback = PInvokeMethods.grpcsharp_test_callback; - this.grpcsharp_test_nop = PInvokeMethods.grpcsharp_test_nop; - } + this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library); + this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library); + this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library); + + this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library); + this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library); + this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library); + this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library); + + this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library); + this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library); + + this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library); + this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library); + this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library); + this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library); + this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library); + this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library); + this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library); + this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library); + this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library); + this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library); + this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library); + this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library); + this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library); + this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library); + this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library); + this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library); + + this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library); + this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library); + this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library); + this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library); + + this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots>(library); + this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library); + this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library); + this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library); + + this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library); + this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library); + this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library); + this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library); + this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library); + this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library); + this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library); + + this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library); + + this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library); + this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library); + this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library); + this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library); + this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library); + + this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library); + + this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library); + this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library); + this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library); + this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library); + this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library); + this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library); + this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library); + + this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library); + + this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library); + this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library); + + this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library); + this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library); + + this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library); + this.grpcsharp_server_register_completion_queue = GetMethodDelegate<Delegates.grpcsharp_server_register_completion_queue_delegate>(library); + this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library); + this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library); + this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library); + this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library); + this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library); + this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library); + this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library); + + this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library); + this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library); + this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library); + this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library); + this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library); + + this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library); + this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library); } /// <summary> @@ -516,317 +408,5 @@ namespace Grpc.Core.Internal public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); } - - /// <summary> - /// Default PInvoke bindings for native methods that are used on Windows. - /// Alternatively, they can also be used as a fallback on Mono - /// (if libgrpc_csharp_ext is installed on your system, or is made accessible through e.g. LD_LIBRARY_PATH environment variable - /// or using Mono's dllMap feature). - /// </summary> - private class PInvokeMethods - { - // Environment - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_init(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_shutdown(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_version_string(); // returns not-owned const char* - - // BatchContextSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_batch_context_recv_message_to_buffer(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); - - [DllImport("grpc_csharp_ext.dll")] - public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallSafeHandle grpcsharp_batch_context_server_rpc_new_call(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_method(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_host(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec grpcsharp_batch_context_server_rpc_new_deadline(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); - - // CallCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_call_credentials_release(IntPtr credentials); - - // CallSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, - MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, - BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, - byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_call_destroy(IntPtr call); - - // ChannelArgsSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_args_destroy(IntPtr args); - - // ChannelCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); - - // ChannelSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); - - [DllImport("grpc_csharp_ext.dll")] - public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, - Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_channel_destroy(IntPtr channel); - - // CompletionQueueEvent - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_sizeof_grpc_event(); - - // CompletionQueueSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create(); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); - - // CStringSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern void gprsharp_free(IntPtr ptr); - - // MetadataArraySafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); - - [DllImport("grpc_csharp_ext.dll")] - public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern UIntPtr grpcsharp_metadata_array_get_value_length(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); - - // NativeLogRedirector - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_redirect_log(GprLogDelegate callback); - - // NativeMetadataCredentialsPlugin - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); - - // ServerCredentialsSafeHandle - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_credentials_release(IntPtr credentials); - - // ServerSafeHandle - - [DllImport("grpc_csharp_ext.dll")] - public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_start(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - public static extern void grpcsharp_server_destroy(IntPtr server); - - // Timespec - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_now(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_inf_future(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_inf_past(ClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); - - [DllImport("grpc_csharp_ext.dll")] - public static extern int gprsharp_sizeof_timespec(); - - // Testing - - [DllImport("grpc_csharp_ext.dll")] - public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); - - [DllImport("grpc_csharp_ext.dll")] - public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); - } } } diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs index 5a80746101..dc629bd714 100644 --- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -82,6 +82,32 @@ namespace Grpc.Core.Internal /// <returns></returns> public IntPtr LoadSymbol(string symbolName) { + if (PlatformApis.IsWindows) + { + // See http://stackoverflow.com/questions/10473310 for background on this. + if (PlatformApis.Is64Bit) + { + return Windows.GetProcAddress(this.handle, symbolName); + } + else + { + // Yes, we could potentially predict the size... but it's a lot simpler to just try + // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying + // many options - and if it takes a little bit longer to fail if we've really got the wrong + // library, that's not a big problem. This is only called once per function in the native library. + symbolName = "_" + symbolName + "@"; + for (int stackSize = 0; stackSize < 128; stackSize += 4) + { + IntPtr candidate = Windows.GetProcAddress(this.handle, symbolName + stackSize); + if (candidate != IntPtr.Zero) + { + return candidate; + } + } + // Fail. + return IntPtr.Zero; + } + } if (PlatformApis.IsLinux) { if (PlatformApis.IsMono) @@ -142,13 +168,18 @@ namespace Grpc.Core.Internal return path; } } - throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives)); + throw new FileNotFoundException( + String.Format("Error loading native library. Not found in any of the possible locations: {0}", + string.Join(",", libraryPathAlternatives))); } private static class Windows { [DllImport("kernel32.dll")] internal static extern IntPtr LoadLibrary(string filename); + + [DllImport("kernel32.dll")] + internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); } private static class Linux diff --git a/src/csharp/Grpc.Core/NativeDeps.Linux.targets b/src/csharp/Grpc.Core/NativeDeps.Linux.targets index a3848c6f2e..e0c9132b1d 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Linux.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Linux.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.so"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + <Link>libgrpc_csharp_ext.x64.so</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.targets b/src/csharp/Grpc.Core/NativeDeps.Mac.targets index c3c6264fd3..e22c7384fc 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Mac.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Mac.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + <Link>libgrpc_csharp_ext.x86.dylib</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets index f6a3405e29..93db0935bc 100644 --- a/src/csharp/Grpc.Core/NativeDeps.Windows.targets +++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets @@ -3,7 +3,7 @@ <ItemGroup> <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + <Link>grpc_csharp_ext.x86.dll</Link> </Content> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json index 4545d26aa5..901b0ce5d0 100644 --- a/src/csharp/Grpc.Core/project.json +++ b/src/csharp/Grpc.Core/project.json @@ -14,12 +14,12 @@ "files": { "mappings": { "build/net45/": "Grpc.Core.targets", - "build/native/bin/windows_x86/": "../nativelibs/windows_x86/grpc_csharp_ext.dll", - "build/native/bin/windows_x64/": "../nativelibs/windows_x64/grpc_csharp_ext.dll", - "build/native/bin/linux_x86/": "../nativelibs/linux_x86/libgrpc_csharp_ext.so", - "build/native/bin/linux_x64/": "../nativelibs/linux_x64/libgrpc_csharp_ext.so", - "build/native/bin/macosx_x86/": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib", - "build/native/bin/macosx_x64/": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib" + "runtimes/win/native/grpc_csharp_ext.x86.dll": "../nativelibs/windows_x86/grpc_csharp_ext.dll", + "runtimes/win/native/grpc_csharp_ext.x64.dll": "../nativelibs/windows_x64/grpc_csharp_ext.dll", + "runtimes/linux/native/libgrpc_csharp_ext.x86.so": "../nativelibs/linux_x86/libgrpc_csharp_ext.so", + "runtimes/linux/native/libgrpc_csharp_ext.x64.so": "../nativelibs/linux_x64/libgrpc_csharp_ext.so", + "runtimes/osx/native/libgrpc_csharp_ext.x86.dylib": "../nativelibs/macosx_x86/libgrpc_csharp_ext.dylib", + "runtimes/osx/native/libgrpc_csharp_ext.x64.dylib": "../nativelibs/macosx_x64/libgrpc_csharp_ext.dylib" } } }, @@ -40,8 +40,8 @@ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027" + "NETStandard.Library": "1.6.0", + "System.Threading.Thread": "4.0.0" } } } diff --git a/src/csharp/Grpc.Examples.MathClient/packages.config b/src/csharp/Grpc.Examples.MathClient/packages.config new file mode 100644 index 0000000000..79ece06bef --- /dev/null +++ b/src/csharp/Grpc.Examples.MathClient/packages.config @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> +</packages> diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json index b865cd5011..ad319478ab 100644 --- a/src/csharp/Grpc.Examples.MathClient/project.json +++ b/src/csharp/Grpc.Examples.MathClient/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -55,12 +55,13 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.Examples.MathServer/packages.config b/src/csharp/Grpc.Examples.MathServer/packages.config new file mode 100644 index 0000000000..79ece06bef --- /dev/null +++ b/src/csharp/Grpc.Examples.MathServer/packages.config @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> +</packages> diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json index b865cd5011..ad319478ab 100644 --- a/src/csharp/Grpc.Examples.MathServer/project.json +++ b/src/csharp/Grpc.Examples.MathServer/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -55,12 +55,13 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs index 1a522cab93..7ba1074d44 100644 --- a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs @@ -49,7 +49,7 @@ namespace Grpc.Examples.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); -#if NETSTANDARD1_5 +#if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.Examples.Tests/project.json b/src/csharp/Grpc.Examples.Tests/project.json index cc518eb6ff..1cd1848e99 100644 --- a/src/csharp/Grpc.Examples.Tests/project.json +++ b/src/csharp/Grpc.Examples.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,12 +57,13 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.Examples/project.json b/src/csharp/Grpc.Examples/project.json index 7d3f4dcbb1..48ec530abb 100644 --- a/src/csharp/Grpc.Examples/project.json +++ b/src/csharp/Grpc.Examples/project.json @@ -20,7 +20,7 @@ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs index 44634671ce..dca61e3f96 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs @@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); -#if NETSTANDARD1_5 +#if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.HealthCheck.Tests/project.json b/src/csharp/Grpc.HealthCheck.Tests/project.json index fbf8d92f04..faa4400304 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/project.json +++ b/src/csharp/Grpc.HealthCheck.Tests/project.json @@ -14,10 +14,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -33,10 +33,10 @@ }, "copyToOutput": { "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,12 +57,13 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json index 0e03e89d6a..7c062a7e40 100644 --- a/src/csharp/Grpc.HealthCheck/project.json +++ b/src/csharp/Grpc.HealthCheck/project.json @@ -37,7 +37,7 @@ "portable-net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.Client/project.json b/src/csharp/Grpc.IntegrationTesting.Client/project.json index 4a2846feea..287950720f 100644 --- a/src/csharp/Grpc.IntegrationTesting.Client/project.json +++ b/src/csharp/Grpc.IntegrationTesting.Client/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,13 +57,14 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45", "net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config new file mode 100644 index 0000000000..79ece06bef --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> +</packages> diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json index 4a2846feea..287950720f 100644 --- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,13 +57,14 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45", "net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.Server/project.json b/src/csharp/Grpc.IntegrationTesting.Server/project.json index 4a2846feea..287950720f 100644 --- a/src/csharp/Grpc.IntegrationTesting.Server/project.json +++ b/src/csharp/Grpc.IntegrationTesting.Server/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,13 +57,14 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45", "net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config b/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config new file mode 100644 index 0000000000..79ece06bef --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> +</packages> diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json index 4a2846feea..287950720f 100644 --- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -57,13 +57,14 @@ }, "frameworks": { "net45": { }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45", "net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0" } } } diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs index eb7b55a286..c17ede7561 100644 --- a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs @@ -49,7 +49,7 @@ namespace Grpc.IntegrationTesting TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient(); // TODO: replace Moq by some mocking library with CoreCLR support. -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 [Test] public void ExpandedParamOverloadCanBeMocked() { diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index e27fe5b3d8..ec407d3fcf 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -145,7 +145,7 @@ namespace Grpc.IntegrationTesting if (options.TestCase == "jwt_token_creds") { -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); Assert.IsTrue(googleCredential.IsCreateScopedRequired); credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); @@ -157,7 +157,7 @@ namespace Grpc.IntegrationTesting if (options.TestCase == "compute_engine_creds") { -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); Assert.IsFalse(googleCredential.IsCreateScopedRequired); credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); @@ -395,7 +395,7 @@ namespace Grpc.IntegrationTesting public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope) { -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 Console.WriteLine("running oauth2_auth_token"); ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope }); string oauth2Token = await credential.GetAccessTokenForRequestAsync(); @@ -421,7 +421,7 @@ namespace Grpc.IntegrationTesting public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope) { -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 Console.WriteLine("running per_rpc_creds"); ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); @@ -731,7 +731,7 @@ namespace Grpc.IntegrationTesting // extracts the client_email field from service account file used for auth test cases private static string GetEmailFromServiceAccountFile() { -#if !NETSTANDARD1_5 +#if !NETCOREAPP1_0 string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); Assert.IsNotNull(keyFile); var jobject = JObject.Parse(File.ReadAllText(keyFile)); diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs index 100ff0b5de..21c8adb45c 100644 --- a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs +++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs @@ -49,7 +49,7 @@ namespace Grpc.IntegrationTesting { // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error)); -#if NETSTANDARD1_5 +#if NETCOREAPP1_0 return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In); #else return new AutoRun().Execute(args); diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json index 6297600ddc..bb61a679c1 100644 --- a/src/csharp/Grpc.IntegrationTesting/project.json +++ b/src/csharp/Grpc.IntegrationTesting/project.json @@ -15,10 +15,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/dbg/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib" } } } @@ -35,10 +35,10 @@ "copyToOutput": { "include": "data/*", "mappings": { - "nativelibs/windows_x64/grpc_csharp_ext.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", - "nativelibs/windows_x86/grpc_csharp_ext.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", - "nativelibs/linux_x64/libgrpc_csharp_ext.so": "../../../libs/opt/libgrpc_csharp_ext.so", - "nativelibs/macosx_x64/libgrpc_csharp_ext.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" + "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll", + "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll", + "libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so", + "libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib" } } } @@ -72,14 +72,15 @@ "System.IO": "" } }, - "netstandard1.5": { + "netcoreapp1.0": { "imports": [ "portable-net45", "net45" ], "dependencies": { - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027" + "Microsoft.NETCore.App": "1.0.0", + "NETStandard.Library": "1.6.0", + "System.Linq.Expressions": "4.1.0" } } } diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc index 3c8f0c56da..81fc552fd1 100644 --- a/src/node/ext/call_credentials.cc +++ b/src/node/ext/call_credentials.cc @@ -68,6 +68,8 @@ using v8::Value; Nan::Callback *CallCredentials::constructor; Persistent<FunctionTemplate> CallCredentials::fun_tpl; +static Callback *plugin_callback; + CallCredentials::CallCredentials(grpc_call_credentials *credentials) : wrapped_credentials(credentials) {} @@ -88,6 +90,11 @@ void CallCredentials::Init(Local<Object> exports) { Nan::New<FunctionTemplate>(CreateFromPlugin)).ToLocalChecked()); Nan::Set(exports, Nan::New("CallCredentials").ToLocalChecked(), ctr); constructor = new Nan::Callback(ctr); + + Local<FunctionTemplate> callback_tpl = + Nan::New<FunctionTemplate>(PluginCallback); + plugin_callback = new Callback( + Nan::GetFunction(callback_tpl).ToLocalChecked()); } bool CallCredentials::HasInstance(Local<Value> val) { @@ -195,23 +202,28 @@ NAN_METHOD(PluginCallback) { return Nan::ThrowTypeError( "The callback's third argument must be an object"); } + if (!info[3]->IsObject()) { + return Nan::ThrowTypeError( + "The callback's fourth argument must be an object"); + } shared_ptr<Resources> resources(new Resources); grpc_status_code code = static_cast<grpc_status_code>( Nan::To<uint32_t>(info[0]).FromJust()); Utf8String details_utf8_str(info[1]); char *details = *details_utf8_str; grpc_metadata_array array; + Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked(); if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(), &array, resources)){ return Nan::ThrowError("Failed to parse metadata"); } grpc_credentials_plugin_metadata_cb cb = reinterpret_cast<grpc_credentials_plugin_metadata_cb>( - Nan::Get(info.Callee(), + Nan::Get(callback_data, Nan::New("cb").ToLocalChecked() ).ToLocalChecked().As<External>()->Value()); void *user_data = - Nan::Get(info.Callee(), + Nan::Get(callback_data, Nan::New("user_data").ToLocalChecked() ).ToLocalChecked().As<External>()->Value(); cb(user_data, array.metadata, array.count, code, details); @@ -227,17 +239,17 @@ NAUV_WORK_CB(SendPluginCallback) { while (!callbacks.empty()) { plugin_callback_data *data = callbacks.front(); callbacks.pop_front(); - // Attach cb and user_data to plugin_callback so that it can access them later - v8::Local<v8::Function> plugin_callback = Nan::GetFunction( - Nan::New<v8::FunctionTemplate>(PluginCallback)).ToLocalChecked(); - Nan::Set(plugin_callback, Nan::New("cb").ToLocalChecked(), + Local<Object> callback_data = Nan::New<Object>(); + Nan::Set(callback_data, Nan::New("cb").ToLocalChecked(), Nan::New<v8::External>(reinterpret_cast<void*>(data->cb))); - Nan::Set(plugin_callback, Nan::New("user_data").ToLocalChecked(), + Nan::Set(callback_data, Nan::New("user_data").ToLocalChecked(), Nan::New<v8::External>(data->user_data)); - const int argc = 2; + const int argc = 3; v8::Local<v8::Value> argv[argc] = { Nan::New(data->service_url).ToLocalChecked(), - plugin_callback + callback_data, + // Get Local<Function> from Nan::Callback* + **plugin_callback }; Nan::Callback *callback = state->callback; callback->Call(argc, argv); diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json index 67f5301df7..40e276055b 100644 --- a/src/node/health_check/package.json +++ b/src/node/health_check/package.json @@ -19,11 +19,11 @@ "lodash": "^3.9.3", "google-protobuf": "^3.0.0-alpha.5" }, - "files": { + "files": [ "LICENSE", "health.js", "v1" - }, + ], "main": "src/node/index.js", "license": "BSD-3-Clause" } diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js index b746d0625d..043df06a66 100644 --- a/src/node/src/credentials.js +++ b/src/node/src/credentials.js @@ -92,7 +92,8 @@ exports.createSsl = ChannelCredentials.createSsl; * @return {CallCredentials} The credentials object */ exports.createFromMetadataGenerator = function(metadata_generator) { - return CallCredentials.createFromPlugin(function(service_url, callback) { + return CallCredentials.createFromPlugin(function(service_url, cb_data, + callback) { metadata_generator({service_url: service_url}, function(error, metadata) { var code = grpc.status.OK; var message = ''; @@ -107,7 +108,7 @@ exports.createFromMetadataGenerator = function(metadata_generator) { metadata = new Metadata(); } } - callback(code, message, metadata._getCoreRepresentation()); + callback(code, message, metadata._getCoreRepresentation(), cb_data); }); }); }; diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 72cadb9319..97f4f586b7 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -36,7 +36,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 = '0.14.0' + v = '1.0.0-pre1' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC @@ -82,7 +82,7 @@ Pod::Spec.new do |s| s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } repo = 'grpc/grpc' - release = 'release-0_14_1' + release = "objective-c-v#{v}" file = "grpc_objective_c_plugin-#{v}-macos-x86_64.zip" s.source = { :http => "https://github.com/#{repo}/releases/download/#{release}/#{file}", diff --git a/src/objective-c/!ProtoCompiler.podspec b/src/objective-c/!ProtoCompiler.podspec index 5e59b25aee..56aacc3330 100644 --- a/src/objective-c/!ProtoCompiler.podspec +++ b/src/objective-c/!ProtoCompiler.podspec @@ -97,10 +97,9 @@ Pod::Spec.new do |s| s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } repo = 'google/protobuf' - release = "v#{v}" file = "protoc-#{v}-osx-x86_64.zip" s.source = { - :http => "https://github.com/#{repo}/releases/download/#{release}/#{file}", + :http => "https://github.com/#{repo}/releases/download/v#{v}/#{file}", # TODO(jcanizales): Add sha1 or sha256 # :sha1 => '??', } diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec index 42b4434d0d..b759997c11 100644 --- a/src/objective-c/BoringSSL.podspec +++ b/src/objective-c/BoringSSL.podspec @@ -31,7 +31,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL' - version = '4.0' + version = '5.0' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.' # Adapted from the homepage: @@ -67,8 +67,11 @@ Pod::Spec.new do |s| # "The name and email addresses of the library maintainers, not the Podspec maintainer." s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' - s.source = { :git => 'https://boringssl.googlesource.com/boringssl', - :tag => "version_for_cocoapods_#{version}" } + s.source = { + :git => 'https://boringssl.googlesource.com/boringssl', + :tag => "version_for_cocoapods_#{version}", + # :commit => '8d343b44bbab829d1a28fdef650ca95f7db4412e', + } name = 'openssl' @@ -219,7 +222,7 @@ Pod::Spec.new do |s| * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - /* This file was generated by err_data_generate.go. */ + /* This file was generated by err_data_generate.go. */ #include <openssl/base.h> #include <openssl/err.h> @@ -385,42 +388,42 @@ Pod::Spec.new do |s| 0x28340c19, 0x283480ac, 0x283500ea, - 0x2c322775, - 0x2c32a783, - 0x2c332795, - 0x2c33a7a7, - 0x2c3427bb, - 0x2c34a7cd, - 0x2c3527e8, - 0x2c35a7fa, - 0x2c36280d, + 0x2c3227cb, + 0x2c32a7d9, + 0x2c3327eb, + 0x2c33a7fd, + 0x2c342811, + 0x2c34a823, + 0x2c35283e, + 0x2c35a850, + 0x2c362863, 0x2c36832d, - 0x2c37281a, - 0x2c37a82c, - 0x2c38283f, - 0x2c38a856, - 0x2c392864, - 0x2c39a874, - 0x2c3a2886, - 0x2c3aa89a, - 0x2c3b28ab, - 0x2c3ba8ca, - 0x2c3c28de, - 0x2c3ca8f4, - 0x2c3d290d, - 0x2c3da92a, - 0x2c3e293b, - 0x2c3ea949, - 0x2c3f2961, - 0x2c3fa979, - 0x2c402986, + 0x2c372870, + 0x2c37a882, + 0x2c382895, + 0x2c38a8ac, + 0x2c3928ba, + 0x2c39a8ca, + 0x2c3a28dc, + 0x2c3aa8f0, + 0x2c3b2901, + 0x2c3ba920, + 0x2c3c2934, + 0x2c3ca94a, + 0x2c3d2963, + 0x2c3da980, + 0x2c3e2991, + 0x2c3ea99f, + 0x2c3f29b7, + 0x2c3fa9cf, + 0x2c4029dc, 0x2c4090e7, - 0x2c412997, - 0x2c41a9aa, + 0x2c4129ed, + 0x2c41aa00, 0x2c4210c0, - 0x2c42a9bb, + 0x2c42aa11, 0x2c430720, - 0x2c43a8bc, + 0x2c43a912, 0x30320000, 0x30328015, 0x3033001f, @@ -594,145 +597,148 @@ Pod::Spec.new do |s| 0x404619e8, 0x40469a08, 0x40471a16, - 0x40479a2a, - 0x40481a3f, - 0x40489a58, - 0x40491a6f, - 0x40499a89, - 0x404a1aa0, - 0x404a9abe, - 0x404b1ad6, - 0x404b9aed, - 0x404c1b03, - 0x404c9b15, - 0x404d1b36, - 0x404d9b58, - 0x404e1b6c, - 0x404e9b79, - 0x404f1b90, - 0x404f9ba0, - 0x40501bca, - 0x40509bde, - 0x40511bf9, - 0x40519c09, - 0x40521c20, - 0x40529c32, - 0x40531c4a, - 0x40539c5d, - 0x40541c72, - 0x40549c95, - 0x40551ca3, - 0x40559cc0, - 0x40561ccd, - 0x40569ce6, - 0x40571cfe, - 0x40579d11, - 0x40581d26, - 0x40589d38, - 0x40591d48, - 0x40599d61, - 0x405a1d75, - 0x405a9d85, - 0x405b1d9d, - 0x405b9dae, - 0x405c1dc1, - 0x405c9dd2, - 0x405d1ddf, - 0x405d9df6, - 0x405e1e16, + 0x40479a3d, + 0x40481a52, + 0x40489a6b, + 0x40491a82, + 0x40499a9c, + 0x404a1ab3, + 0x404a9ad1, + 0x404b1ae9, + 0x404b9b00, + 0x404c1b16, + 0x404c9b28, + 0x404d1b49, + 0x404d9b6b, + 0x404e1b7f, + 0x404e9b8c, + 0x404f1ba3, + 0x404f9bb3, + 0x40501bdd, + 0x40509bf1, + 0x40511c0c, + 0x40519c1c, + 0x40521c33, + 0x40529c45, + 0x40531c5d, + 0x40539c70, + 0x40541c85, + 0x40549ca8, + 0x40551cb6, + 0x40559cd3, + 0x40561ce0, + 0x40569cf9, + 0x40571d11, + 0x40579d24, + 0x40581d39, + 0x40589d4b, + 0x40591d7a, + 0x40599d93, + 0x405a1da7, + 0x405a9db7, + 0x405b1dcf, + 0x405b9de0, + 0x405c1df3, + 0x405c9e04, + 0x405d1e11, + 0x405d9e28, + 0x405e1e48, 0x405e8a95, - 0x405f1e37, - 0x405f9e44, - 0x40601e52, - 0x40609e74, - 0x40611e9c, - 0x40619eb1, - 0x40621ec8, - 0x40629ed9, - 0x40631eea, - 0x40639eff, - 0x40641f16, - 0x40649f27, - 0x40651f42, - 0x40659f59, - 0x40661f71, - 0x40669f9b, - 0x40671fc6, - 0x40679fe7, - 0x40681ffa, - 0x4068a01b, - 0x4069204d, - 0x4069a07b, - 0x406a209c, - 0x406aa0bc, - 0x406b2244, - 0x406ba267, - 0x406c227d, - 0x406ca4a9, - 0x406d24d8, - 0x406da500, - 0x406e2519, - 0x406ea531, - 0x406f2550, - 0x406fa565, - 0x40702578, - 0x4070a595, + 0x405f1e69, + 0x405f9e76, + 0x40601e84, + 0x40609ea6, + 0x40611ece, + 0x40619ee3, + 0x40621efa, + 0x40629f0b, + 0x40631f1c, + 0x40639f31, + 0x40641f48, + 0x40649f59, + 0x40651f74, + 0x40659f8b, + 0x40661fa3, + 0x40669fcd, + 0x40671ff8, + 0x4067a019, + 0x4068202c, + 0x4068a04d, + 0x4069207f, + 0x4069a0ad, + 0x406a20ce, + 0x406aa0ee, + 0x406b2276, + 0x406ba299, + 0x406c22af, + 0x406ca4db, + 0x406d250a, + 0x406da532, + 0x406e254b, + 0x406ea563, + 0x406f2582, + 0x406fa597, + 0x407025aa, + 0x4070a5c7, 0x40710800, - 0x4071a5a7, - 0x407225ba, - 0x4072a5d3, - 0x407325eb, + 0x4071a5d9, + 0x407225ec, + 0x4072a605, + 0x4073261d, 0x4073936d, - 0x407425ff, - 0x4074a619, - 0x4075262a, - 0x4075a63e, - 0x4076264c, + 0x40742631, + 0x4074a64b, + 0x4075265c, + 0x4075a670, + 0x4076267e, 0x407691aa, - 0x40772671, - 0x4077a693, - 0x407826ae, - 0x4078a6c3, - 0x407926da, - 0x4079a6f0, - 0x407a26fc, - 0x407aa70f, - 0x407b2724, - 0x407ba736, - 0x407c274b, - 0x407ca754, - 0x407d2036, - 0x407d9bb0, - 0x41f4216f, - 0x41f92201, - 0x41fe20f4, - 0x41fea2d0, - 0x41ff23c1, - 0x42032188, - 0x420821aa, - 0x4208a1e6, - 0x420920d8, - 0x4209a220, - 0x420a212f, - 0x420aa10f, - 0x420b214f, - 0x420ba1c8, - 0x420c23dd, - 0x420ca29d, - 0x420d22b7, - 0x420da2ee, - 0x42122308, - 0x421723a4, - 0x4217a34a, - 0x421c236c, - 0x421f2327, - 0x422123f4, - 0x42262387, - 0x422b248d, - 0x422ba456, - 0x422c2475, - 0x422ca430, - 0x422d240f, + 0x407726a3, + 0x4077a6c5, + 0x407826e0, + 0x4078a719, + 0x40792730, + 0x4079a746, + 0x407a2752, + 0x407aa765, + 0x407b277a, + 0x407ba78c, + 0x407c27a1, + 0x407ca7aa, + 0x407d2068, + 0x407d9bc3, + 0x407e26f5, + 0x407e9d5b, + 0x407f1a2a, + 0x41f421a1, + 0x41f92233, + 0x41fe2126, + 0x41fea302, + 0x41ff23f3, + 0x420321ba, + 0x420821dc, + 0x4208a218, + 0x4209210a, + 0x4209a252, + 0x420a2161, + 0x420aa141, + 0x420b2181, + 0x420ba1fa, + 0x420c240f, + 0x420ca2cf, + 0x420d22e9, + 0x420da320, + 0x4212233a, + 0x421723d6, + 0x4217a37c, + 0x421c239e, + 0x421f2359, + 0x42212426, + 0x422623b9, + 0x422b24bf, + 0x422ba488, + 0x422c24a7, + 0x422ca462, + 0x422d2441, 0x4432072b, 0x4432873a, 0x44330746, @@ -775,69 +781,69 @@ Pod::Spec.new do |s| 0x4c3d136d, 0x4c3d937c, 0x4c3e1389, - 0x503229cd, - 0x5032a9dc, - 0x503329e7, - 0x5033a9f7, - 0x50342a10, - 0x5034aa2a, - 0x50352a38, - 0x5035aa4e, - 0x50362a60, - 0x5036aa76, - 0x50372a8f, - 0x5037aaa2, - 0x50382aba, - 0x5038aacb, - 0x50392ae0, - 0x5039aaf4, - 0x503a2b14, - 0x503aab2a, - 0x503b2b42, - 0x503bab54, - 0x503c2b70, - 0x503cab87, - 0x503d2ba0, - 0x503dabb6, - 0x503e2bc3, - 0x503eabd9, - 0x503f2beb, + 0x50322a23, + 0x5032aa32, + 0x50332a3d, + 0x5033aa4d, + 0x50342a66, + 0x5034aa80, + 0x50352a8e, + 0x5035aaa4, + 0x50362ab6, + 0x5036aacc, + 0x50372ae5, + 0x5037aaf8, + 0x50382b10, + 0x5038ab21, + 0x50392b36, + 0x5039ab4a, + 0x503a2b6a, + 0x503aab80, + 0x503b2b98, + 0x503babaa, + 0x503c2bc6, + 0x503cabdd, + 0x503d2bf6, + 0x503dac0c, + 0x503e2c19, + 0x503eac2f, + 0x503f2c41, 0x503f8382, - 0x50402bfe, - 0x5040ac0e, - 0x50412c28, - 0x5041ac37, - 0x50422c51, - 0x5042ac6e, - 0x50432c7e, - 0x5043ac8e, - 0x50442c9d, + 0x50402c54, + 0x5040ac64, + 0x50412c7e, + 0x5041ac8d, + 0x50422ca7, + 0x5042acc4, + 0x50432cd4, + 0x5043ace4, + 0x50442cf3, 0x5044843f, - 0x50452cb1, - 0x5045accf, - 0x50462ce2, - 0x5046acf8, - 0x50472d0a, - 0x5047ad1f, - 0x50482d45, - 0x5048ad53, - 0x50492d66, - 0x5049ad7b, - 0x504a2d91, - 0x504aada1, - 0x504b2dc1, - 0x504badd4, - 0x504c2df7, - 0x504cae25, - 0x504d2e37, - 0x504dae54, - 0x504e2e6f, - 0x504eae8b, - 0x504f2e9d, - 0x504faeb4, - 0x50502ec3, + 0x50452d07, + 0x5045ad25, + 0x50462d38, + 0x5046ad4e, + 0x50472d60, + 0x5047ad75, + 0x50482d9b, + 0x5048ada9, + 0x50492dbc, + 0x5049add1, + 0x504a2de7, + 0x504aadf7, + 0x504b2e17, + 0x504bae2a, + 0x504c2e4d, + 0x504cae7b, + 0x504d2e8d, + 0x504daeaa, + 0x504e2ec5, + 0x504eaee1, + 0x504f2ef3, + 0x504faf0a, + 0x50502f19, 0x505086ef, - 0x50512ed6, + 0x50512f2c, 0x58320ec9, 0x68320e8b, 0x68328c25, @@ -1218,6 +1224,7 @@ Pod::Spec.new do |s| "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" "DH_P_TOO_LONG\\0" "DIGEST_CHECK_FAILED\\0" + "DOWNGRADE_DETECTED\\0" "DTLS_MESSAGE_TOO_BIG\\0" "ECC_CERT_NOT_FOR_SIGNING\\0" "EMS_STATE_INCONSISTENT\\0" @@ -1254,6 +1261,7 @@ Pod::Spec.new do |s| "NO_CIPHERS_AVAILABLE\\0" "NO_CIPHERS_PASSED\\0" "NO_CIPHER_MATCH\\0" + "NO_COMMON_SIGNATURE_ALGORITHMS\\0" "NO_COMPRESSION_SPECIFIED\\0" "NO_METHOD_SPECIFIED\\0" "NO_P256_SUPPORT\\0" @@ -1344,6 +1352,7 @@ Pod::Spec.new do |s| "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" "UNSUPPORTED_ELLIPTIC_CURVE\\0" "UNSUPPORTED_PROTOCOL\\0" + "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" "WRONG_CERTIFICATE_TYPE\\0" "WRONG_CIPHER_RETURNED\\0" "WRONG_CURVE\\0" diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h index 646bf43b54..4a3f3fa4a1 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h @@ -43,7 +43,10 @@ * Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls * to the specified @c host. */ -+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host; ++ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host; + +/** The default response size limit is 4MB. Set this to override that default. */ ++ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host; + (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, " "and might be removed or modified at any " diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index bcc3b91507..7fab357e93 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -37,15 +37,16 @@ @implementation GRPCCall (ChannelArg) -+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host { - if (!host) { - [NSException raise:NSInvalidArgumentException - format:@"host and userAgentPrefix must be provided."]; - } ++ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; hostConfig.userAgentPrefix = userAgentPrefix; } ++ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host { + GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; + hostConfig.responseSizeLimitOverride = @(limit); +} + + (void)closeOpenConnections { [GRPCHost flushChannelCache]; } diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.h b/src/objective-c/GRPCClient/GRPCCall+Tests.h index ccc5723ec7..184ad09c5c 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.h +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.h @@ -57,4 +57,10 @@ * more than one invocation of the methods of this category. */ + (void)useInsecureConnectionsForHost:(NSString *)host; + +/** + * Resets all host configurations to their default values, and flushes all connections from the + * cache. + */ ++ (void)resetHostSettings; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.m b/src/objective-c/GRPCClient/GRPCCall+Tests.m index b9456691bd..656cba8fec 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.m +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.m @@ -61,4 +61,7 @@ hostConfig.secure = NO; } ++ (void)resetHostSettings { + [GRPCHost resetAllHostSettings]; +} @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 40e78a92d6..5bada2dd50 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -59,8 +59,8 @@ struct grpc_channel_credentials; * Creates a secure channel to the specified @c host using Cronet as a transport mechanism. */ #ifdef GRPC_COMPILE_WITH_CRONET -+ (nullable GRPCChannel *)secureCronetChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)channelArgs; ++ (nullable GRPCChannel *)secureCronetChannelWithHost:(nonnull NSString *)host + channelArgs:(nonnull NSDictionary *)channelArgs; #endif /** * Creates a secure channel to the specified @c host using the specified @c credentials and diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 7b7b79e1c6..e49aceefe1 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -47,7 +47,7 @@ #endif #import "GRPCCompletionQueue.h" -void freeChannelArgs(grpc_channel_args *channel_args) { +static void FreeChannelArgs(grpc_channel_args *channel_args) { for (size_t i = 0; i < channel_args->num_args; ++i) { grpc_arg *arg = &channel_args->args[i]; gpr_free(arg->key); @@ -65,7 +65,7 @@ void freeChannelArgs(grpc_channel_args *channel_args) { * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. */ -grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) { +static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { if (!dictionary) { return NULL; } @@ -115,10 +115,12 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) { } if (self = [super init]) { - _channelArgs = buildChannelArgs(channelArgs); + _channelArgs = BuildChannelArgs(channelArgs); _host = [host copy]; - _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs, - NULL); + _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, + _host.UTF8String, + _channelArgs, + NULL); } return self; @@ -138,7 +140,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) { } if (self = [super init]) { - _channelArgs = buildChannelArgs(channelArgs); + _channelArgs = BuildChannelArgs(channelArgs); _host = [host copy]; if (secure) { _unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs, @@ -155,7 +157,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) { // TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely, // as in the past that made this call to crash. grpc_channel_destroy(_unmanagedChannel); - freeChannelArgs(_channelArgs); + FreeChannelArgs(_channelArgs); } #ifdef GRPC_COMPILE_WITH_CRONET diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h index 350c69bf8e..c8b5dd315b 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.h +++ b/src/objective-c/GRPCClient/private/GRPCHost.h @@ -42,6 +42,7 @@ struct grpc_channel_credentials; @interface GRPCHost : NSObject + (void)flushChannelCache; ++ (void)resetAllHostSettings; @property(nonatomic, readonly) NSString *address; @property(nonatomic, copy, nullable) NSString *userAgentPrefix; @@ -53,6 +54,10 @@ struct grpc_channel_credentials; @property(nonatomic, copy, nullable) NSString *hostNameOverride; +/** The default response size limit is 4MB. Set this to override that default. */ +@property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride; + + - (nullable instancetype)init NS_UNAVAILABLE; /** Host objects initialized with the same address are the same. */ + (nullable instancetype)hostWithAddress:(NSString *)address; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 08c699f99e..477ddf51d9 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN // TODO(jcanizales): Generate the version in a standalone header, from templates. Like // templates/src/core/surface/version.c.template . -#define GRPC_OBJC_VERSION_STRING @"0.13.0" +#define GRPC_OBJC_VERSION_STRING @"1.0.0-pre1" static NSMutableDictionary *kHostCache; @@ -113,6 +113,12 @@ static NSMutableDictionary *kHostCache; } } ++ (void)resetAllHostSettings { + @synchronized (kHostCache) { + kHostCache = [NSMutableDictionary dictionary]; + } +} + - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue { GRPCChannel *channel; @@ -209,6 +215,10 @@ static NSMutableDictionary *kHostCache; if (_secure && _hostNameOverride) { args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride; } + + if (_responseSizeLimitOverride) { + args[@GRPC_ARG_MAX_MESSAGE_LENGTH] = _responseSizeLimitOverride; + } return args; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index e7232f2683..83d1b655e8 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -33,7 +33,11 @@ #import "ProtoRPC.h" -#import <Protobuf/GPBProtocolBuffers.h> +#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import <Protobuf/GPBProtocolBuffers.h> +#else + #import <GPBProtocolBuffers.h> +#endif #import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriter+Transformations.h> diff --git a/src/objective-c/README.md b/src/objective-c/README.md index a0ca5f448a..6e917ddd81 100644 --- a/src/objective-c/README.md +++ b/src/objective-c/README.md @@ -48,7 +48,7 @@ Pod::Spec.new do |s| src = '.' # We'll use protoc with the gRPC plugin. - s.dependency '!ProtoCompiler-gRPCPlugin', '~> 0.14' + s.dependency '!ProtoCompiler-gRPCPlugin', '~> 1.0.0-pre1' # Pods directory corresponding to this app's Podfile, relative to the location of this podspec. pods_root = '<path to your Podfile>/Pods' diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec index 6e783fb5ad..7222a80b88 100644 --- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec +++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. - s.dependency "!ProtoCompiler-gRPCPlugin", "~> 0.14" + s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1" repo_root = '../../../..' bin_dir = "#{repo_root}/bins/$CONFIG" diff --git a/src/objective-c/examples/RemoteTestClient/empty.proto b/src/objective-c/examples/RemoteTestClient/empty.proto deleted file mode 100644 index a678048289..0000000000 --- a/src/objective-c/examples/RemoteTestClient/empty.proto +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2015, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package grpc.testing; - -option objc_class_prefix = "RMT"; - -// An empty message that you can re-use to avoid defining duplicated empty -// messages in your project. A typical example is to use it as argument or the -// return value of a service API. For instance: -// -// service Foo { -// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; -// }; -// -message Empty {} diff --git a/src/objective-c/examples/RemoteTestClient/test.proto b/src/objective-c/examples/RemoteTestClient/test.proto index 514c3b8095..5c359c5c12 100644 --- a/src/objective-c/examples/RemoteTestClient/test.proto +++ b/src/objective-c/examples/RemoteTestClient/test.proto @@ -31,7 +31,7 @@ // of unary/streaming requests/responses. syntax = "proto3"; -import "empty.proto"; +import "google/protobuf/empty.proto"; import "messages.proto"; package grpc.testing; @@ -42,7 +42,7 @@ option objc_class_prefix = "RMT"; // performance with various types of payload. service TestService { // One empty request followed by one empty response. - rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); + rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty); // One request followed by one response. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile index 8740b2f963..f6f0c00d5d 100644 --- a/src/objective-c/examples/Sample/Podfile +++ b/src/objective-c/examples/Sample/Podfile @@ -3,6 +3,8 @@ platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false +use_frameworks! if ENV['FRAMEWORKS'] == 'YES' + # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../../..' diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj index 5c2a6d14f9..ab7159cda2 100644 --- a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C20055928615A6F8434E26B4 /* libPods-Sample.a */; }; + 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; @@ -26,7 +26,7 @@ 6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; }; 6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; - C20055928615A6F8434E26B4 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E3C01DF315C4E7433BCEC6E6 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -35,7 +35,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 426A5020E0E158A101BCA1D9 /* libPods-Sample.a in Frameworks */, + 3F035697392F601049D3DDE1 /* Pods_Sample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -95,7 +95,7 @@ C4C2C5219053E079C9EFB930 /* Frameworks */ = { isa = PBXGroup; children = ( - C20055928615A6F8434E26B4 /* libPods-Sample.a */, + CC1B27EA0C428429B07BC34B /* Pods_Sample.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -129,7 +129,7 @@ 6369A2621A9322E20015FC5C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 6369A2691A9322E20015FC5C = { @@ -260,6 +260,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -325,6 +326,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -336,6 +338,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Sample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/src/objective-c/examples/Sample/Sample/Info.plist b/src/objective-c/examples/Sample/Sample/Info.plist index 4436635ab4..2cdf09dc2f 100644 --- a/src/objective-c/examples/Sample/Sample/Info.plist +++ b/src/objective-c/examples/Sample/Sample/Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> - <string>org.grpc.$(PRODUCT_NAME:rfc1034identifier)</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m index 433a8a2ba3..70244ee62d 100644 --- a/src/objective-c/examples/Sample/Sample/ViewController.m +++ b/src/objective-c/examples/Sample/Sample/ViewController.m @@ -66,9 +66,9 @@ // Same example call using the generic gRPC client library: - ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:@"grpc.testing" - service:@"TestService" - method:@"UnaryCall"]; + GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing" + service:@"TestService" + method:@"UnaryCall"]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; diff --git a/src/objective-c/examples/SwiftSample/Info.plist b/src/objective-c/examples/SwiftSample/Info.plist index 10f0450b34..2cdf09dc2f 100644 --- a/src/objective-c/examples/SwiftSample/Info.plist +++ b/src/objective-c/examples/SwiftSample/Info.plist @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>$(EXECUTABLE_NAME)</string> <key>CFBundleIdentifier</key> - <string>io.grpc.$(PRODUCT_NAME:rfc1034identifier)</string> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile index 2f783340f5..b08a346ae2 100644 --- a/src/objective-c/examples/SwiftSample/Podfile +++ b/src/objective-c/examples/SwiftSample/Podfile @@ -3,6 +3,8 @@ platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false +use_frameworks! + # Location of gRPC's repo root relative to this file. GRPC_LOCAL_SRC = '../../../..' diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj index 2a1b30f2cf..afc3da7116 100644 --- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */; }; 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; }; 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; }; 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; }; 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; }; - 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -21,9 +21,8 @@ 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; - 6367AD231B951655007FD3A4 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; }; - 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SwiftSample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A7E614A494D89D01BB395761 /* Pods-SwiftSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.debug.xcconfig"; sourceTree = "<group>"; }; + B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C314E3E246AF23AC29B38FCF /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -32,7 +31,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 92EDB1408A1E1E7DDAB25D9C /* libPods-SwiftSample.a in Frameworks */, + 2C0B024CB798839E17F76126 /* Pods_SwiftSample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -74,7 +73,6 @@ 633BFFCB1B950B210007E424 /* Main.storyboard */, 633BFFCE1B950B210007E424 /* Images.xcassets */, 633BFFC51B950B210007E424 /* Supporting Files */, - 6367AD231B951655007FD3A4 /* Bridging-Header.h */, ); name = SwiftSample; sourceTree = SOURCE_ROOT; @@ -90,7 +88,7 @@ 9D63A7F6423989BA306810CA /* Frameworks */ = { isa = PBXGroup; children = ( - 69BB5C6CA3C1F97E007AC527 /* libPods-SwiftSample.a */, + B394F343BDE186C5436DBDB9 /* Pods_SwiftSample.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -125,7 +123,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0730; ORGANIZATIONNAME = gRPC; TargetAttributes = { 633BFFC11B950B210007E424 = { @@ -256,6 +254,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -325,8 +324,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; @@ -338,8 +338,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; USER_HEADER_SEARCH_PATHS = ""; }; name = Release; diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index 2a95d2de51..e7bab13762 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -33,6 +33,8 @@ import UIKit +import RemoteTest + class ViewController: UIViewController { override func viewDidLoad() { @@ -60,7 +62,7 @@ class ViewController: UIViewController { // Same but manipulating headers: - var RPC : ProtoRPC! // Needed to convince Swift to capture by reference (__block) + var RPC : GRPCProtoCall! // Needed to convince Swift to capture by reference (__block) RPC = service.RPCToUnaryCallWithRequest(request) { response, error in if let response = response { NSLog("2. Finished successfully with response:\n\(response)") @@ -79,7 +81,7 @@ class ViewController: UIViewController { // Same example call using the generic gRPC client library: - let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") + let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") let requestsWriter = GRXWriter(value: request.data()) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 1167a715bb..916a335802 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -292,15 +292,6 @@ static GRPCProtoMethod *kUnaryCallMethod; // TODO(makarandd): Move to a different file that contains only unit tests - (void)testExceptions { - // Try to set userAgentPrefix for host that is nil. This should cause - // an exception. - @try { - [GRPCCall setUserAgentPrefix:@"Foo" forHost:nil]; - XCTFail(@"Did not receive an exception when host is nil"); - } @catch(NSException *theException) { - NSLog(@"Received exception as expected: %@", theException.name); - } - // Try to set parameters to nil for GRPCCall. This should cause an exception @try { (void)[[GRPCCall alloc] initWithHost:nil diff --git a/src/objective-c/tests/InteropTests.h b/src/objective-c/tests/InteropTests.h index 6d54343b13..ecab606a78 100644 --- a/src/objective-c/tests/InteropTests.h +++ b/src/objective-c/tests/InteropTests.h @@ -46,4 +46,11 @@ * Override in a subclass to perform these tests against a specific address. */ + (NSString *)host; + +/** + * Bytes of overhead of test proto responses due to encoding. This is used to excercise the behavior + * when responses are just above or below the max response size. For some reason, the local and + * remote servers enconde responses with different overhead (?), so this is defined per-subclass. + */ +- (int32_t)encodingOverhead; @end diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 494743d604..f04a7e6441 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -80,10 +80,6 @@ #pragma mark Tests -#ifdef GRPC_COMPILE_WITH_CRONET -static cronet_engine *cronetEngine = NULL; -#endif - @implementation InteropTests { RMTTestService *_service; } @@ -92,15 +88,22 @@ static cronet_engine *cronetEngine = NULL; return nil; } +- (int32_t)encodingOverhead { + return 0; +} + - (void)setUp { + self.continueAfterFailure = NO; + + [GRPCCall resetHostSettings]; + _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil; #ifdef GRPC_COMPILE_WITH_CRONET if (cronetEngine == NULL) { // Cronet setup [Cronet setHttp2Enabled:YES]; [Cronet start]; - cronetEngine = [Cronet getGlobalEngine]; - [GRPCCall useCronetWithEngine:cronetEngine]; + [GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]]; } #endif } @@ -146,6 +149,64 @@ static cronet_engine *cronetEngine = NULL; [self waitForExpectationsWithTimeout:16 handler:nil]; } +- (void)test4MBResponsesAreAccepted { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead + request.responseSize = kPayloadSize; + + [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertEqual(response.payload.body.length, kPayloadSize); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:16 handler:nil]; +} + +- (void)testResponsesOverMaxSizeFailWithActionableMessage { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size + request.responseSize = kPayloadSize; + + [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { + // TODO(jcanizales): Catch the error and rethrow it with an actionable message: + // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit. + // - If you're developing the server, consider using response streaming, or let clients filter + // responses by setting a google.protobuf.FieldMask in the request: + // https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto + XCTAssertEqualObjects(error.localizedDescription, @"Max message size exceeded"); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:16 handler:nil]; +} + +- (void)testResponsesOver4MBAreAcceptedIfOptedIn { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = + [self expectationWithDescription:@"HigherResponseSizeLimit"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB + request.responseSize = kPayloadSize; + + [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host]; + + [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertEqual(response.payload.body.length, kPayloadSize); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:16 handler:nil]; +} + - (void)testClientStreamingRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m index 56927a8af6..b41210f50f 100644 --- a/src/objective-c/tests/InteropTestsLocalCleartext.m +++ b/src/objective-c/tests/InteropTestsLocalCleartext.m @@ -47,11 +47,15 @@ static NSString * const kLocalCleartextHost = @"localhost:5050"; return kLocalCleartextHost; } +- (int32_t)encodingOverhead { + return 10; // bytes +} + - (void)setUp { + [super setUp]; + // Register test server as non-SSL. [GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost]; - - [super setUp]; } @end diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index f0f4b1d71f..1479c5896c 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -47,14 +47,18 @@ static NSString * const kLocalSSLHost = @"localhost:5051"; return kLocalSSLHost; } +- (int32_t)encodingOverhead { + return 10; // bytes +} + - (void)setUp { + [super setUp]; + // Register test server certificates and name. NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; [GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:kLocalSSLHost]; - - [super setUp]; } - (void)testExceptions { diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m index 758cc9346a..70f84753bb 100644 --- a/src/objective-c/tests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTestsRemote.m @@ -47,4 +47,8 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; return kRemoteSSLHost; } +- (int32_t)encodingOverhead { + return 12; // bytes +} + @end diff --git a/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist b/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist new file mode 100644 index 0000000000..ba72822e87 --- /dev/null +++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/Info.plist @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m index 65f768a760..fab8ad8d25 100644 --- a/src/objective-c/examples/SwiftSample/Bridging-Header.h +++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m @@ -31,15 +31,20 @@ * */ -#ifndef SwiftSample_Bridging_Header_h -#define SwiftSample_Bridging_Header_h +#import <GRPCClient/GRPCCall+Tests.h> -#import <RxLibrary/GRXWriteable.h> -#import <RxLibrary/GRXWriter.h> -#import <RxLibrary/GRXWriter+Immediate.h> -#import <GRPCClient/GRPCCall.h> -#import <ProtoRPC/ProtoMethod.h> -#import <ProtoRPC/ProtoRPC.h> -#import <RemoteTest/Test.pbrpc.h> +#import "InteropTests.h" -#endif +static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com"; + +/** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */ +@interface InteropTestsRemoteWithCronet : InteropTests +@end + +@implementation InteropTestsRemoteWithCronet + ++ (NSString *)host { + return kRemoteSSLHost; +} + +@end diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index db11208a1b..17478fab12 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -14,6 +14,7 @@ GRPC_LOCAL_SRC = '../../..' InteropTestsRemote InteropTestsLocalSSL InteropTestsLocalCleartext + InteropTestsRemoteWithCronet ).each do |target_name| target target_name do pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true @@ -28,6 +29,11 @@ GRPC_LOCAL_SRC = '../../..' pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC pod 'RemoteTest', :path => "RemoteTestClient" + + if target_name == 'InteropTestsRemoteWithCronet' + pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC + pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" + end end end @@ -36,7 +42,8 @@ target 'CoreCronetEnd2EndTests' do pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC - pod 'gRPC-Core/Cronet-Tests', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC end # gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's @@ -75,7 +82,11 @@ post_install do |installer| target.build_configurations.each do |config| config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' end - if target.name == 'gRPC-Core' or target.name == 'gRPC-Core.default-Cronet-Interface-Cronet-Tests' + + # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include + # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core.' + # and require the same error suppresion. + if target.name == 'gRPC-Core' or target.name.start_with?('gRPC-Core.') target.build_configurations.each do |config| # TODO(zyc): Remove this setting after the issue is resolved # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void @@ -83,5 +94,15 @@ post_install do |installer| config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' end end + + # Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by + # the test target 'InteropTestsRemoteWithCronet' + if target.name == 'gRPC' + target.build_configurations.each do |config| + if config.name == 'Cronet' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1' + end + end + end end end diff --git a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec index 7d84a5ae4d..53ba101913 100644 --- a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec +++ b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec @@ -11,7 +11,7 @@ Pod::Spec.new do |s| s.osx.deployment_target = '10.9' # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. - s.dependency "!ProtoCompiler-gRPCPlugin", "~> 0.14" + s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1" repo_root = '../../../..' bin_dir = "#{repo_root}/bins/$CONFIG" diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 2c80b08d03..c4a6567ae0 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */; }; 0F9232F984C08643FD40C34F /* libPods-InteropTestsRemote.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */; }; 16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; }; 20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; }; @@ -14,6 +15,9 @@ 3D7C85F6AA68C4A205E3BA16 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */; }; 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */; }; 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */; }; + 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 60D2A57ED559F34428C2EEC5 /* libPods-CoreCronetEnd2EndTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */; }; 6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; 63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; @@ -48,6 +52,13 @@ remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; + 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 635697BF1B14FC11007A7283 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 635697C61B14FC11007A7283; + remoteInfo = Tests; + }; 63423F4B1B150A5F006CF63C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; @@ -102,15 +113,23 @@ 07D10A965323BEA7FE59A74B /* Pods-RxLibraryUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.debug.xcconfig"; sourceTree = "<group>"; }; 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; }; 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = "<group>"; }; + 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = "<group>"; }; + 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = "<group>"; }; 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.release.xcconfig"; sourceTree = "<group>"; }; + 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; sourceTree = "<group>"; }; 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.release.xcconfig"; sourceTree = "<group>"; }; + 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.cronet.xcconfig"; sourceTree = "<group>"; }; 51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.release.xcconfig"; sourceTree = "<group>"; }; 553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.debug.xcconfig"; sourceTree = "<group>"; }; + 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = "<group>"; }; 5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.release.xcconfig"; sourceTree = "<group>"; }; 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CoreCronetEnd2EndTests.m; sourceTree = "<group>"; }; + 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemoteWithCronet.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsRemoteWithCronet.m; sourceTree = "<group>"; }; + 5EE84BF51D4717E40050C6CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GRPCClientTests.m; sourceTree = "<group>"; }; 63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = "<group>"; }; @@ -127,8 +146,12 @@ 63E240CC1B6C4D3A005F3B0E /* InteropTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteropTests.h; sourceTree = "<group>"; }; 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTestsLocalSSL.m; sourceTree = "<group>"; }; 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TestCertificates.bundle; sourceTree = "<group>"; }; + 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.cronet.xcconfig"; sourceTree = "<group>"; }; 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.release.xcconfig"; sourceTree = "<group>"; }; + 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = "<group>"; }; + AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = "<group>"; }; B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = "<group>"; }; CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AllTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemote.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -137,6 +160,8 @@ E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = "<group>"; }; E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = "<group>"; }; E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = "<group>"; }; + E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = "<group>"; }; + F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.cronet.xcconfig"; sourceTree = "<group>"; }; FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; }; @@ -152,6 +177,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EE84BEE1D4717E40050C6CC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EE84BF61D4717E40050C6CC /* libTests.a in Frameworks */, + 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 63423F411B150A5F006CF63C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -219,6 +253,7 @@ A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */, 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */, FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */, + 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */, ); name = Frameworks; sourceTree = "<group>"; @@ -242,6 +277,16 @@ E6733B838B28453434B556E2 /* Pods-Tests.release.xcconfig */, 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */, 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */, + 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */, + AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */, + E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */, + 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */, + AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */, + 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */, + 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */, + 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */, + 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */, + F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */, ); name = Pods; sourceTree = "<group>"; @@ -254,12 +299,22 @@ path = CoreCronetEnd2EndTests; sourceTree = "<group>"; }; + 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = { + isa = PBXGroup; + children = ( + 5EE84BF31D4717E40050C6CC /* InteropTestsRemoteWithCronet.m */, + 5EE84BF51D4717E40050C6CC /* Info.plist */, + ); + path = InteropTestsRemoteWithCronet; + sourceTree = "<group>"; + }; 635697BE1B14FC11007A7283 = { isa = PBXGroup; children = ( 635697C91B14FC11007A7283 /* Tests */, 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */, 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */, + 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, 136D535E19727099B941D7B1 /* Frameworks */, @@ -276,6 +331,7 @@ 63DC84341BE15294000708E8 /* InteropTestsLocalSSL.xctest */, 63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */, 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */, + 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */, ); name = Products; sourceTree = "<group>"; @@ -328,6 +384,27 @@ productReference = 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */; + buildPhases = ( + C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */, + 5EE84BED1D4717E40050C6CC /* Sources */, + 5EE84BEE1D4717E40050C6CC /* Frameworks */, + 5EE84BEF1D4717E40050C6CC /* Resources */, + 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */, + DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */, + ); + name = InteropTestsRemoteWithCronet; + productName = InteropTestsRemoteWithCronet; + productReference = 5EE84BF11D4717E40050C6CC /* InteropTestsRemoteWithCronet.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 63423F431B150A5F006CF63C /* AllTests */ = { isa = PBXNativeTarget; buildConfigurationList = 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */; @@ -464,6 +541,9 @@ 5E8A5DA31D3840B4000F8BC4 = { CreatedOnToolsVersion = 7.3.1; }; + 5EE84BF01D4717E40050C6CC = { + CreatedOnToolsVersion = 7.3.1; + }; 63423F431B150A5F006CF63C = { CreatedOnToolsVersion = 6.3.1; }; @@ -503,6 +583,7 @@ 63DC84331BE15294000708E8 /* InteropTestsLocalSSL */, 63DC84421BE152B5000708E8 /* InteropTestsLocalCleartext */, 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */, + 5EE84BF01D4717E40050C6CC /* InteropTestsRemoteWithCronet */, ); }; /* End PBXProject section */ @@ -515,6 +596,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EE84BEF1D4717E40050C6CC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 63423F421B150A5F006CF63C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -555,6 +643,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 4C406327D3907A5E5FBA8AC9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -780,6 +883,21 @@ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; + C0F7B1FF6F88CC5FBF362F4C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -825,6 +943,21 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + DB4D0E73C229F2FF3B364AB3 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -866,6 +999,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EE84BED1D4717E40050C6CC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EE84BFE1D471D400050C6CC /* InteropTests.m in Sources */, + 5EE84BF41D4717E40050C6CC /* InteropTestsRemoteWithCronet.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 63423F401B150A5F006CF63C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -931,6 +1073,11 @@ target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */; }; + 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 635697C61B14FC11007A7283 /* Tests */; + targetProxy = 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */; + }; 63423F4C1B150A5F006CF63C /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; @@ -991,6 +1138,216 @@ }; name = Release; }; + 5EC3C7A01D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Cronet; + }; + 5EC3C7A11D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F671D4CAD2864FB203B920B4 /* Pods-Tests.cronet.xcconfig */; + buildSettings = { + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Cronet; + }; + 5EC3C7A21D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EC3C7A31D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.RxLibraryUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EC3C7A41D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EC3C7A51D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalSSL; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EC3C7A61D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */; + buildSettings = { + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsLocalCleartext; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EC3C7A71D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.CoreCronetEnd2EndTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/../../../..\""; + }; + name = Cronet; + }; + 5EC3C7A81D4FC18C000330E2 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "$(inherited)", + "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + "GRPC_COMPILE_WITH_CRONET=1", + ); + INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Cronet; + }; + 5EE84BF91D4717E40050C6CC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "$(inherited)", + "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + ); + INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 5EE84BFA1D4717E40050C6CC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "$(inherited)", + "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + "GRPC_COMPILE_WITH_CRONET=1", + ); + INFOPLIST_FILE = InteropTestsRemoteWithCronet/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsRemoteWithCronet; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 63423F4E1B150A5F006CF63C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */; @@ -1234,15 +1591,27 @@ isa = XCConfigurationList; buildConfigurations = ( 5E8A5DAC1D3840B4000F8BC4 /* Debug */, + 5EC3C7A71D4FC18C000330E2 /* Cronet */, 5E8A5DAD1D3840B4000F8BC4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 5EE84BFB1D4717E40050C6CC /* Build configuration list for PBXNativeTarget "InteropTestsRemoteWithCronet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5EE84BF91D4717E40050C6CC /* Debug */, + 5EC3C7A81D4FC18C000330E2 /* Cronet */, + 5EE84BFA1D4717E40050C6CC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 63423F4D1B150A5F006CF63C /* Build configuration list for PBXNativeTarget "AllTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 63423F4E1B150A5F006CF63C /* Debug */, + 5EC3C7A21D4FC18C000330E2 /* Cronet */, 63423F4F1B150A5F006CF63C /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1252,6 +1621,7 @@ isa = XCConfigurationList; buildConfigurations = ( 635697D91B14FC11007A7283 /* Debug */, + 5EC3C7A01D4FC18C000330E2 /* Cronet */, 635697DA1B14FC11007A7283 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1261,6 +1631,7 @@ isa = XCConfigurationList; buildConfigurations = ( 635697DC1B14FC11007A7283 /* Debug */, + 5EC3C7A11D4FC18C000330E2 /* Cronet */, 635697DD1B14FC11007A7283 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1270,6 +1641,7 @@ isa = XCConfigurationList; buildConfigurations = ( 63DC841C1BE15179000708E8 /* Debug */, + 5EC3C7A31D4FC18C000330E2 /* Cronet */, 63DC841D1BE15179000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1279,6 +1651,7 @@ isa = XCConfigurationList; buildConfigurations = ( 63DC842C1BE15267000708E8 /* Debug */, + 5EC3C7A41D4FC18C000330E2 /* Cronet */, 63DC842D1BE15267000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1288,6 +1661,7 @@ isa = XCConfigurationList; buildConfigurations = ( 63DC843D1BE15294000708E8 /* Debug */, + 5EC3C7A51D4FC18C000330E2 /* Cronet */, 63DC843E1BE15294000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1297,6 +1671,7 @@ isa = XCConfigurationList; buildConfigurations = ( 63DC844C1BE152B5000708E8 /* Debug */, + 5EC3C7A61D4FC18C000330E2 /* Cronet */, 63DC844D1BE152B5000708E8 /* Release */, ); defaultConfigurationIsVisible = 0; diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme index e6a052a8ce..d1d616c4cf 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme @@ -39,12 +39,6 @@ </BuildableReference> <SkippedTests> <Test - Identifier = "GRPCClientTests/testConnectionToRemoteServer"> - </Test> - <Test - Identifier = "GRPCClientTests/testMetadata"> - </Test> - <Test Identifier = "InteropTests"> </Test> <Test diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme new file mode 100644 index 0000000000..1d211115f7 --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteWithCronet.xcscheme @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "0730" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5EE84BF01D4717E40050C6CC" + BuildableName = "InteropTestsRemoteWithCronet.xctest" + BlueprintName = "InteropTestsRemoteWithCronet" + ReferencedContainer = "container:Tests.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Cronet" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES"> + <Testables> + <TestableReference + skipped = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5EE84BF01D4717E40050C6CC" + BuildableName = "InteropTestsRemoteWithCronet.xctest" + BlueprintName = "InteropTestsRemoteWithCronet" + ReferencedContainer = "container:Tests.xcodeproj"> + </BuildableReference> + <SkippedTests> + <Test + Identifier = "InteropTests"> + </Test> + </SkippedTests> + </TestableReference> + </Testables> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5EE84BF01D4717E40050C6CC" + BuildableName = "InteropTestsRemoteWithCronet.xctest" + BlueprintName = "InteropTestsRemoteWithCronet" + ReferencedContainer = "container:Tests.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> + </TestAction> + <LaunchAction + buildConfiguration = "Cronet" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + allowLocationSimulation = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5EE84BF01D4717E40050C6CC" + BuildableName = "InteropTestsRemoteWithCronet.xctest" + BlueprintName = "InteropTestsRemoteWithCronet" + ReferencedContainer = "container:Tests.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <AdditionalOptions> + </AdditionalOptions> + </LaunchAction> + <ProfileAction + buildConfiguration = "Cronet" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "5EE84BF01D4717E40050C6CC" + BuildableName = "InteropTestsRemoteWithCronet.xctest" + BlueprintName = "InteropTestsRemoteWithCronet" + ReferencedContainer = "container:Tests.xcodeproj"> + </BuildableReference> + </MacroExpansion> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Cronet"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Cronet" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/src/objective-c/tests/build_example_test.sh b/src/objective-c/tests/build_example_test.sh index 5c3766b4c0..ae75941ec6 100755 --- a/src/objective-c/tests/build_example_test.sh +++ b/src/objective-c/tests/build_example_test.sh @@ -31,44 +31,33 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -eo pipefail +set -evo pipefail cd `dirname $0` -BINDIR=`pwd`/../../../bins/$CONFIG -TMP_PATH=$PATH - -# If `protoc` is not found, add bins/$CONFIG/protobuf/protoc to the search path -hash protoc 2>/dev/null || TMP_PATH=$BINDIR/protobuf:$TMP_PATH - -# If `protoc-gen-objcgrpc` is not found, make a symlink from -# bins/$CONGIF/grpc_objective_c_plugin and add it to the search path -PATH=$TMP_PATH hash protoc-gen-objcgrpc 2>/dev/null || { - ln -sf $BINDIR/grpc_objective_c_plugin $BINDIR/protoc-gen-objcgrpc - TMP_PATH=$BINDIR:$TMP_PATH -} - SCHEME=HelloWorld \ EXAMPLE_PATH=examples/objective-c/helloworld \ - PATH=$TMP_PATH \ ./build_one_example.sh SCHEME=RouteGuideClient \ EXAMPLE_PATH=examples/objective-c/route_guide \ - PATH=$TMP_PATH \ ./build_one_example.sh SCHEME=AuthSample \ EXAMPLE_PATH=examples/objective-c/auth_sample \ - PATH=$TMP_PATH \ + ./build_one_example.sh + +rm -f ../examples/RemoteTestClient/*.{h,m} + +SCHEME=Sample \ + EXAMPLE_PATH=src/objective-c/examples/Sample \ ./build_one_example.sh SCHEME=Sample \ EXAMPLE_PATH=src/objective-c/examples/Sample \ - PATH=$TMP_PATH \ + FRAMEWORKS=YES \ ./build_one_example.sh SCHEME=SwiftSample \ EXAMPLE_PATH=src/objective-c/examples/SwiftSample \ - PATH=$TMP_PATH \ ./build_one_example.sh diff --git a/src/objective-c/tests/build_one_example.sh b/src/objective-c/tests/build_one_example.sh index 24fb8b7bab..9fef6582a3 100755 --- a/src/objective-c/tests/build_one_example.sh +++ b/src/objective-c/tests/build_one_example.sh @@ -31,7 +31,7 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -e +set -ev # Params: # EXAMPLE_PATH - directory of the example @@ -54,7 +54,7 @@ pod install set -o pipefail XCODEBUILD_FILTER='(^===|^\*\*|\bfatal\b|\berror\b|\bwarning\b|\bfail)' xcodebuild \ - clean build \ + build \ -workspace *.xcworkspace \ -scheme $SCHEME \ -destination name="iPhone 6" \ diff --git a/src/objective-c/tests/build_tests.sh b/src/objective-c/tests/build_tests.sh index 8547bfd3a8..bc5bc04494 100755 --- a/src/objective-c/tests/build_tests.sh +++ b/src/objective-c/tests/build_tests.sh @@ -44,26 +44,10 @@ hash xcodebuild 2>/dev/null || { exit 1 } -BINDIR=../../../bins/$CONFIG - -if [ ! -f $BINDIR/protobuf/protoc ]; then - hash protoc 2>/dev/null || { - echo >&2 "Can't find protoc. Make sure run_tests.py is making" \ - "grpc_objective_c_plugin before calling this script." - exit 1 - } - # When protoc is already installed, make doesn't compile one. Put a link - # there so the podspecs can do codegen using that path. - mkdir -p $BINDIR/protobuf - ln -s `which protoc` $BINDIR/protobuf/protoc -fi - -[ -f $BINDIR/interop_server ] || { - echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ - "interop_server before calling this script. It needs to be done" \ - "before because pod install of gRPC renames some C gRPC files" \ - "and not the server's code references to them." - exit 1 -} +# clean the directory +rm -rf Pods +rm -rf Tests.xcworkspace +rm -f Podfile.lock +rm -f RemoteTestClient/*.{h,m} pod install diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index c4fc5644f2..a265149f48 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -31,13 +31,21 @@ # Don't run this script standalone. Instead, run from the repository root: # ./tools/run_tests/run_tests.py -l objc -set -e +set -ev cd $(dirname $0) # Run the tests server. -../../../bins/$CONFIG/interop_server --port=5050 & -../../../bins/$CONFIG/interop_server --port=5051 --use_tls & + +BINDIR=../../../bins/$CONFIG + +[ -f $BINDIR/interop_server ] || { + echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ + "interop_server before calling this script." + exit 1 +} +$BINDIR/interop_server --port=5050 & +$BINDIR/interop_server --port=5051 --use_tls & # Kill them when this script exits. trap 'kill -9 `jobs -p`' EXIT diff --git a/src/php/README.md b/src/php/README.md index 8abedc40a3..7e9819b256 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -9,23 +9,12 @@ GA ## Environment -Prerequisite: `php` >=5.5, `phpize`, `pecl`, `phpunit` - -**Linux (Debian):** - -```sh -$ sudo apt-get install php5 php5-dev php-pear -``` - -**Linux (CentOS):** - -```sh -$ yum install php55w -$ yum --enablerepo=remi,remi-php55 install php-devel php-pear -``` - -**Mac OS X:** +Prerequisite: +* `php` 5.5 or above, 7.0 or above +* `pear` and `pecl` +* `phpunit` +**PEAR:** ```sh $ curl -O http://pear.php.net/go-pear.phar $ sudo php -d detect_unicode=0 go-pear.phar @@ -72,13 +61,7 @@ $ sudo make install ### gRPC PHP extension -Install the gRPC PHP extension from PECL - -```sh -$ sudo pecl install grpc -``` - -Or, compile from source +Compile the gRPC PHP extension ```sh $ cd grpc/src/php/ext/grpc @@ -148,12 +131,8 @@ Alternatively, you can download `protoc` binaries from [the protocol buffers Git You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files. ```sh -$ cd grpc/src/php/vendor/stanley-cheung/protobuf-php # if you had run `composer install` in the previous step - -OR - -$ git clone https://github.com/stanley-cheung/Protobuf-PHP # clone from github repo - +$ git clone https://github.com/stanley-cheung/Protobuf-PHP +$ cd Protobuf-PHP $ gem install rake ronn $ rake pear:package version=1.0 $ sudo pear install Protobuf-1.0.tgz @@ -175,7 +154,7 @@ Run a local server serving the math services. Please see [Node][] for how to run ```sh $ cd grpc $ npm install -$ nodejs src/node/test/math/math_server.js +$ node src/node/test/math/math_server.js ``` ### Run test client @@ -212,7 +191,7 @@ Make sure the Node math server is still running, as above. ```sh $ cd grpc $ npm install -$ nodejs src/node/test/math/math_server.js +$ node src/node/test/math/math_server.js ``` Make sure you have run `composer install` to generate the `vendor/autoload.php` file @@ -282,7 +261,7 @@ Make sure the Node math server is still running, as above. ```sh $ cd grpc $ npm install -$ nodejs src/node/test/math/math_server.js +$ node src/node/test/math/math_server.js ``` Make sure you have run `composer install` to generate the `vendor/autoload.php` file diff --git a/src/php/bin/determine_extension_dir.sh b/src/php/bin/determine_extension_dir.sh index b4342ac89f..a59882506f 100755 --- a/src/php/bin/determine_extension_dir.sh +++ b/src/php/bin/determine_extension_dir.sh @@ -29,11 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set -e default_extension_dir=$(php-config --extension-dir) -if command -v brew > /dev/null && \ - brew ls --versions | grep php5[56]-grpc > /dev/null; then - # the grpc php extension was installed by homebrew - : -elif [ ! -e $default_extension_dir/grpc.so ]; then +if [ ! -e $default_extension_dir/grpc.so ]; then # the grpc extension is not found in the default PHP extension dir # try the source modules directory module_dir=../ext/grpc/modules diff --git a/src/php/composer.json b/src/php/composer.json index 88418206e8..1eacc643a2 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -8,7 +8,9 @@ "version": "1.0.0", "require": { "php": ">=5.5.0", - "stanley-cheung/protobuf-php": "v0.6", + "stanley-cheung/protobuf-php": "v0.6" + }, + "require-dev": { "google/auth": "v0.9" }, "autoload": { diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index bd1eccb01b..66ca1513ed 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -58,66 +58,44 @@ #include "byte_buffer.h" zend_class_entry *grpc_ce_call; - -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers call_ce_handlers; +#endif /* Frees and destroys an instance of wrapped_grpc_call */ -void free_wrapped_grpc_call(void *object TSRMLS_DC) { - wrapped_grpc_call *call = (wrapped_grpc_call *)object; - if (call->owned && call->wrapped != NULL) { - grpc_call_destroy(call->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call) + if (p->owned && p->wrapped != NULL) { + grpc_call_destroy(p->wrapped); } - zend_object_std_dtor(&call->std TSRMLS_CC); - efree(call); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call to be associated with an object * of a class specified by class_type */ -zend_object_value create_wrapped_grpc_call(zend_class_entry *class_type - TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_call *intern; - - intern = (wrapped_grpc_call *)emalloc(sizeof(wrapped_grpc_call)); - memset(intern, 0, sizeof(wrapped_grpc_call)); - +php_grpc_zend_object create_wrapped_grpc_call(zend_class_entry *class_type + TSRMLS_DC) { + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_call, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; -} - -/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the struct - should be destroyed at the end of the object's lifecycle */ -zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) { - zval *call_object; - MAKE_STD_ZVAL(call_object); - object_init_ex(call_object, grpc_ce_call); - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(call_object TSRMLS_CC); - call->wrapped = wrapped; - call->owned = owned; - return call_object; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call, call_ce_handlers); } /* Creates and returns a PHP array object with the data in a * grpc_metadata_array. Returns NULL on failure */ -zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) { +zval *grpc_parse_metadata_array(grpc_metadata_array + *metadata_array TSRMLS_DC) { int count = metadata_array->count; grpc_metadata *elements = metadata_array->metadata; - int i; zval *array; - zval **data = NULL; + PHP_GRPC_MAKE_STD_ZVAL(array); + array_init(array); + int i; HashTable *array_hash; zval *inner_array; char *str_key; char *str_val; size_t key_len; - MAKE_STD_ZVAL(array); - array_init(array); + zval *data = NULL; + array_hash = Z_ARRVAL_P(array); grpc_metadata *elem; for (i = 0; i < count; i++) { @@ -127,9 +105,9 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) { memcpy(str_key, elem->key, key_len); str_val = ecalloc(elem->value_length + 1, sizeof(char)); memcpy(str_val, elem->value, elem->value_length); - if (zend_hash_find(array_hash, str_key, key_len, (void **)data) == - SUCCESS) { - if (Z_TYPE_P(*data) != IS_ARRAY) { + if (php_grpc_zend_hash_find(array_hash, str_key, key_len, (void **)&data) + == SUCCESS) { + if (Z_TYPE_P(data) != IS_ARRAY) { zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Metadata hash somehow contains wrong types.", 1 TSRMLS_CC); @@ -137,11 +115,13 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) { efree(str_val); return NULL; } - add_next_index_stringl(*data, str_val, elem->value_length, false); + php_grpc_add_next_index_stringl(data, str_val, elem->value_length, + false); } else { - MAKE_STD_ZVAL(inner_array); + PHP_GRPC_MAKE_STD_ZVAL(inner_array); array_init(inner_array); - add_next_index_stringl(inner_array, str_val, elem->value_length, false); + php_grpc_add_next_index_stringl(inner_array, str_val, + elem->value_length, false); add_assoc_zval(array, str_key, inner_array); } } @@ -151,185 +131,64 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC) { /* Populates a grpc_metadata_array with the data in a PHP array object. Returns true on success and false on failure */ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { - zval **inner_array; - zval **value; HashTable *array_hash; - HashPosition array_pointer; HashTable *inner_array_hash; - HashPosition inner_array_pointer; - char *key; - uint key_len; - ulong index; - if (Z_TYPE_P(array) != IS_ARRAY) { - return false; - } - grpc_metadata_array_init(metadata); - array_hash = Z_ARRVAL_P(array); - for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); - zend_hash_get_current_data_ex(array_hash, (void**)&inner_array, - &array_pointer) == SUCCESS; - zend_hash_move_forward_ex(array_hash, &array_pointer)) { - if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0, - &array_pointer) != HASH_KEY_IS_STRING) { - return false; - } - if (Z_TYPE_P(*inner_array) != IS_ARRAY) { - return false; - } - inner_array_hash = Z_ARRVAL_P(*inner_array); - metadata->capacity += zend_hash_num_elements(inner_array_hash); - } - metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata)); - for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); - zend_hash_get_current_data_ex(array_hash, (void**)&inner_array, - &array_pointer) == SUCCESS; - zend_hash_move_forward_ex(array_hash, &array_pointer)) { - if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0, - &array_pointer) != HASH_KEY_IS_STRING) { - return false; - } - inner_array_hash = Z_ARRVAL_P(*inner_array); - for (zend_hash_internal_pointer_reset_ex(inner_array_hash, - &inner_array_pointer); - zend_hash_get_current_data_ex(inner_array_hash, (void**)&value, - &inner_array_pointer) == SUCCESS; - zend_hash_move_forward_ex(inner_array_hash, &inner_array_pointer)) { - if (Z_TYPE_P(*value) != IS_STRING) { - return false; - } - metadata->metadata[metadata->count].key = key; - metadata->metadata[metadata->count].value = Z_STRVAL_P(*value); - metadata->metadata[metadata->count].value_length = Z_STRLEN_P(*value); - metadata->count += 1; - } - } - return true; -} - -#else - -static zend_object_handlers call_ce_handlers; - -/* Frees and destroys an instance of wrapped_grpc_call */ -static void free_wrapped_grpc_call(zend_object *object) { - wrapped_grpc_call *call = wrapped_grpc_call_from_obj(object); - if (call->owned && call->wrapped != NULL) { - grpc_call_destroy(call->wrapped); - } - zend_object_std_dtor(&call->std); -} - -/* Initializes an instance of wrapped_grpc_call to be associated with an - * object of a class specified by class_type */ -zend_object *create_wrapped_grpc_call(zend_class_entry *class_type) { - wrapped_grpc_call *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_call) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &call_ce_handlers; - return &intern->std; -} - -/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the - struct should be destroyed at the end of the object's lifecycle */ -void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object) { - object_init_ex(call_object, grpc_ce_call); - wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object); - call->wrapped = wrapped; - call->owned = owned; -} - -/* Creates and returns a PHP array object with the data in a - * grpc_metadata_array. Returns NULL on failure */ -void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, - zval *array) { - int count = metadata_array->count; - grpc_metadata *elements = metadata_array->metadata; - int i; - zval *data; - HashTable *array_hash; - zval inner_array; - char *str_key; - char *str_val; - size_t key_len; - - array_init(array); - array_hash = HASH_OF(array); - grpc_metadata *elem; - for (i = 0; i < count; i++) { - elem = &elements[i]; - key_len = strlen(elem->key); - str_key = ecalloc(key_len + 1, sizeof(char)); - memcpy(str_key, elem->key, key_len); - str_val = ecalloc(elem->value_length + 1, sizeof(char)); - memcpy(str_val, elem->value, elem->value_length); - if ((data = zend_hash_str_find(array_hash, str_key, key_len)) != NULL) { - if (Z_TYPE_P(data) != IS_ARRAY) { - zend_throw_exception(zend_exception_get_default(), - "Metadata hash somehow contains wrong types.", - 1); - efree(str_key); - efree(str_val); - return; - } - add_next_index_stringl(data, str_val, elem->value_length); - } else { - array_init(&inner_array); - add_next_index_stringl(&inner_array, str_val, elem->value_length); - add_assoc_zval(array, str_key, &inner_array); - } - } -} - -/* Populates a grpc_metadata_array with the data in a PHP array object. - Returns true on success and false on failure */ -bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { - zval *inner_array; zval *value; - HashTable *array_hash; - HashTable *inner_array_hash; - zend_string *key; + zval *inner_array; if (Z_TYPE_P(array) != IS_ARRAY) { return false; } grpc_metadata_array_init(metadata); - array_hash = HASH_OF(array); + array_hash = Z_ARRVAL_P(array); - ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { - if (key == NULL) { + char *key; + int key_type; + PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type, + inner_array) + if (key_type != HASH_KEY_IS_STRING || key == NULL) { return false; } if (Z_TYPE_P(inner_array) != IS_ARRAY) { return false; } - inner_array_hash = HASH_OF(inner_array); + inner_array_hash = Z_ARRVAL_P(inner_array); metadata->capacity += zend_hash_num_elements(inner_array_hash); - } - ZEND_HASH_FOREACH_END(); + PHP_GRPC_HASH_FOREACH_END() metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata)); - ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { - if (key == NULL) { + char *key1 = NULL; + int key_type1; + PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key1, key_type1, + inner_array) + if (key_type1 != HASH_KEY_IS_STRING) { return false; } - inner_array_hash = HASH_OF(inner_array); - - ZEND_HASH_FOREACH_VAL(inner_array_hash, value) { + inner_array_hash = Z_ARRVAL_P(inner_array); + PHP_GRPC_HASH_FOREACH_VAL_START(inner_array_hash, value) if (Z_TYPE_P(value) != IS_STRING) { return false; } - metadata->metadata[metadata->count].key = ZSTR_VAL(key); + metadata->metadata[metadata->count].key = key1; metadata->metadata[metadata->count].value = Z_STRVAL_P(value); metadata->metadata[metadata->count].value_length = Z_STRLEN_P(value); metadata->count += 1; - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FOREACH_END(); + PHP_GRPC_HASH_FOREACH_END() + PHP_GRPC_HASH_FOREACH_END() return true; } -#endif +/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the + struct should be destroyed at the end of the object's lifecycle */ +zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC) { + zval *call_object; + PHP_GRPC_MAKE_STD_ZVAL(call_object); + object_init_ex(call_object, grpc_ce_call); + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object); + call->wrapped = wrapped; + call->owned = owned; + return call_object; +} /** * Constructs a new instance of the Call class. @@ -341,18 +200,11 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { PHP_METHOD(Call, __construct) { zval *channel_obj; char *method; + php_grpc_int method_len; zval *deadline_obj; char *host_override = NULL; -#if PHP_MAJOR_VERSION < 7 - int method_len; - int host_override_len = 0; - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else - size_t method_len; - size_t host_override_len = 0; + php_grpc_int host_override_len = 0; wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); -#endif /* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj, @@ -364,13 +216,7 @@ PHP_METHOD(Call, __construct) { "an optional String", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object( - channel_obj TSRMLS_CC); -#else wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj); -#endif if (channel->wrapped == NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "Call cannot be constructed from a closed Channel", @@ -378,13 +224,7 @@ PHP_METHOD(Call, __construct) { return; } add_property_zval(getThis(), "channel", channel_obj); -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *deadline = - (wrapped_grpc_timeval *)zend_object_store_get_object( - deadline_obj TSRMLS_CC); -#else wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); -#endif call->wrapped = grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, completion_queue, method, host_override, @@ -398,32 +238,18 @@ PHP_METHOD(Call, __construct) { * @return object Object with results of all actions */ PHP_METHOD(Call, startBatch) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); - zval **value; - zval **inner_value; - HashPosition array_pointer; - zval **message_value; - zval **message_flags; - char *key; - uint key_len; - ulong index; zval *result; - zval *recv_status; - MAKE_STD_ZVAL(result); + PHP_GRPC_MAKE_STD_ZVAL(result); object_init(result); -#else - wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); + php_grpc_ulong index; + zval *recv_status; + PHP_GRPC_MAKE_STD_ZVAL(recv_status); + object_init(recv_status); zval *value; zval *inner_value; zval *message_value; zval *message_flags; - zend_string *key; - zend_ulong index; - zval recv_status; - object_init(return_value); -#endif + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); grpc_op ops[8]; size_t op_num = 0; @@ -445,7 +271,6 @@ PHP_METHOD(Call, startBatch) { char *message_str; size_t message_len; - grpc_metadata_array_init(&metadata); grpc_metadata_array_init(&trailing_metadata); grpc_metadata_array_init(&recv_metadata); @@ -460,67 +285,63 @@ PHP_METHOD(Call, startBatch) { goto cleanup; } -#if PHP_MAJOR_VERSION < 7 - array_hash = Z_ARRVAL_P(array); - for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); - zend_hash_get_current_data_ex(array_hash, (void**)&value, - &array_pointer) == SUCCESS; - zend_hash_move_forward_ex(array_hash, &array_pointer)) { - if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0, - &array_pointer) != HASH_KEY_IS_LONG) { + + char *key = NULL; + int key_type; + PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(array_hash, key, key_type, index, + value) + if (key_type != HASH_KEY_IS_LONG || key != NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "batch keys must be integers", 1 TSRMLS_CC); goto cleanup; } switch(index) { case GRPC_OP_SEND_INITIAL_METADATA: - if (!create_metadata_array(*value, &metadata)) { + if (!create_metadata_array(value, &metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad metadata value given", 1 TSRMLS_CC); goto cleanup; } - ops[op_num].data.send_initial_metadata.count = - metadata.count; - ops[op_num].data.send_initial_metadata.metadata = - metadata.metadata; + ops[op_num].data.send_initial_metadata.count = metadata.count; + ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: - if (Z_TYPE_PP(value) != IS_ARRAY) { + if (Z_TYPE_P(value) != IS_ARRAY) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an array for send message", 1 TSRMLS_CC); goto cleanup; } - message_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(message_hash, "flags", sizeof("flags"), + message_hash = Z_ARRVAL_P(value); + if (php_grpc_zend_hash_find(message_hash, "flags", sizeof("flags"), (void **)&message_flags) == SUCCESS) { - if (Z_TYPE_PP(message_flags) != IS_LONG) { + if (Z_TYPE_P(message_flags) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an int for message flags", 1 TSRMLS_CC); } - ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; } - if (zend_hash_find(message_hash, "message", sizeof("message"), + if (php_grpc_zend_hash_find(message_hash, "message", sizeof("message"), (void **)&message_value) != SUCCESS || - Z_TYPE_PP(message_value) != IS_STRING) { + Z_TYPE_P(message_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected a string for send message", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_message = - string_to_byte_buffer(Z_STRVAL_PP(message_value), - Z_STRLEN_PP(message_value)); + string_to_byte_buffer(Z_STRVAL_P(message_value), + Z_STRLEN_P(message_value)); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; case GRPC_OP_SEND_STATUS_FROM_SERVER: - status_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(status_hash, "metadata", sizeof("metadata"), + status_hash = Z_ARRVAL_P(value); + if (php_grpc_zend_hash_find(status_hash, "metadata", sizeof("metadata"), (void **)&inner_value) == SUCCESS) { - if (!create_metadata_array(*inner_value, &trailing_metadata)) { + if (!create_metadata_array(inner_value, &trailing_metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad trailing metadata value given", 1 TSRMLS_CC); @@ -531,32 +352,32 @@ PHP_METHOD(Call, startBatch) { ops[op_num].data.send_status_from_server.trailing_metadata_count = trailing_metadata.count; } - if (zend_hash_find(status_hash, "code", sizeof("code"), + if (php_grpc_zend_hash_find(status_hash, "code", sizeof("code"), (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_LONG) { + if (Z_TYPE_P(inner_value) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status code must be an integer", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_status_from_server.status = - Z_LVAL_PP(inner_value); + Z_LVAL_P(inner_value); } else { zend_throw_exception(spl_ce_InvalidArgumentException, "Integer status code is required", 1 TSRMLS_CC); goto cleanup; } - if (zend_hash_find(status_hash, "details", sizeof("details"), + if (php_grpc_zend_hash_find(status_hash, "details", sizeof("details"), (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_STRING) { + if (Z_TYPE_P(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status details must be a string", 1 TSRMLS_CC); goto cleanup; } ops[op_num].data.send_status_from_server.status_details = - Z_STRVAL_PP(inner_value); + Z_STRVAL_P(inner_value); } else { zend_throw_exception(spl_ce_InvalidArgumentException, "String status details is required", @@ -591,132 +412,7 @@ PHP_METHOD(Call, startBatch) { ops[op_num].flags = 0; ops[op_num].reserved = NULL; op_num++; - } - -#else - -array_hash = HASH_OF(array); - ZEND_HASH_FOREACH_KEY_VAL(array_hash, index, key, value) { - if (key) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "batch keys must be integers", 1); - goto cleanup; - } - - switch(index) { - case GRPC_OP_SEND_INITIAL_METADATA: - if (!create_metadata_array(value, &metadata)) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad metadata value given", 1); - goto cleanup; - } - ops[op_num].data.send_initial_metadata.count = metadata.count; - ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; - break; - case GRPC_OP_SEND_MESSAGE: - if (Z_TYPE_P(value) != IS_ARRAY) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an array for send message", 1); - goto cleanup; - } - message_hash = HASH_OF(value); - if ((message_flags = - zend_hash_str_find(message_hash, "flags", - sizeof("flags") - 1)) != NULL) { - if (Z_TYPE_P(message_flags) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an int for message flags", 1); - } - ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; - } - if ((message_value = zend_hash_str_find(message_hash, "message", - sizeof("message") - 1)) - == NULL || Z_TYPE_P(message_value) != IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected a string for send message", 1); - goto cleanup; - } - ops[op_num].data.send_message = - string_to_byte_buffer(Z_STRVAL_P(message_value), - Z_STRLEN_P(message_value)); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - status_hash = HASH_OF(value); - if ((inner_value = zend_hash_str_find(status_hash, "metadata", - sizeof("metadata") - 1)) - != NULL) { - if (!create_metadata_array(inner_value, &trailing_metadata)) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad trailing metadata value given", 1); - goto cleanup; - } - ops[op_num].data.send_status_from_server.trailing_metadata = - trailing_metadata.metadata; - ops[op_num].data.send_status_from_server.trailing_metadata_count = - trailing_metadata.count; - } - if ((inner_value = zend_hash_str_find(status_hash, "code", - sizeof("code") - 1)) != NULL) { - if (Z_TYPE_P(inner_value) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status code must be an integer", 1); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status = - Z_LVAL_P(inner_value); - } else { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Integer status code is required", 1); - goto cleanup; - } - if ((inner_value = zend_hash_str_find(status_hash, "details", - sizeof("details") - 1)) != NULL) { - if (Z_TYPE_P(inner_value) != IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status details must be a string", 1); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status_details = - Z_STRVAL_P(inner_value); - } else { - zend_throw_exception(spl_ce_InvalidArgumentException, - "String status details is required", 1); - goto cleanup; - } - break; - case GRPC_OP_RECV_INITIAL_METADATA: - ops[op_num].data.recv_initial_metadata = &recv_metadata; - break; - case GRPC_OP_RECV_MESSAGE: - ops[op_num].data.recv_message = &message; - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - ops[op_num].data.recv_status_on_client.trailing_metadata = - &recv_trailing_metadata; - ops[op_num].data.recv_status_on_client.status = &status; - ops[op_num].data.recv_status_on_client.status_details = - &status_details; - ops[op_num].data.recv_status_on_client.status_details_capacity = - &status_details_capacity; - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - ops[op_num].data.recv_close_on_server.cancelled = &cancelled; - break; - default: - zend_throw_exception(spl_ce_InvalidArgumentException, - "Unrecognized key in batch", 1); - goto cleanup; - } - ops[op_num].op = (grpc_op_type)index; - ops[op_num].flags = 0; - ops[op_num].reserved = NULL; - op_num++; - } - ZEND_HASH_FOREACH_END(); - -#endif + PHP_GRPC_HASH_FOREACH_END() error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped, NULL); @@ -728,7 +424,9 @@ array_hash = HASH_OF(array); } grpc_completion_queue_pluck(completion_queue, call->wrapped, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 + zval recv_md; +#endif for (int i = 0; i < op_num; i++) { switch(ops[i].op) { case GRPC_OP_SEND_INITIAL_METADATA: @@ -744,29 +442,38 @@ array_hash = HASH_OF(array); add_property_bool(result, "send_status", true); break; case GRPC_OP_RECV_INITIAL_METADATA: +#if PHP_MAJOR_VERSION < 7 array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); add_property_zval(result, "metadata", array); - Z_DELREF_P(array); +#else + recv_md = *grpc_parse_metadata_array(&recv_metadata); + add_property_zval(result, "metadata", &recv_md); +#endif + PHP_GRPC_DELREF(array); break; case GRPC_OP_RECV_MESSAGE: byte_buffer_to_string(message, &message_str, &message_len); if (message_str == NULL) { add_property_null(result, "message"); } else { - add_property_stringl(result, "message", message_str, message_len, - false); + php_grpc_add_property_stringl(result, "message", message_str, + message_len, false); } break; case GRPC_OP_RECV_STATUS_ON_CLIENT: - MAKE_STD_ZVAL(recv_status); - object_init(recv_status); +#if PHP_MAJOR_VERSION < 7 array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); add_property_zval(recv_status, "metadata", array); - Z_DELREF_P(array); +#else + recv_md = *grpc_parse_metadata_array(&recv_trailing_metadata); + add_property_zval(recv_status, "metadata", &recv_md); +#endif + PHP_GRPC_DELREF(array); add_property_long(recv_status, "code", status); - add_property_string(recv_status, "details", status_details, true); + php_grpc_add_property_string(recv_status, "details", status_details, + true); add_property_zval(result, "status", recv_status); - Z_DELREF_P(recv_status); + PHP_GRPC_DELREF(recv_status); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: add_property_bool(result, "cancelled", cancelled); @@ -775,50 +482,6 @@ array_hash = HASH_OF(array); break; } } -#else - for (int i = 0; i < op_num; i++) { - switch(ops[i].op) { - case GRPC_OP_SEND_INITIAL_METADATA: - add_property_bool(return_value, "send_metadata", true); - break; - case GRPC_OP_SEND_MESSAGE: - add_property_bool(return_value, "send_message", true); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - add_property_bool(return_value, "send_close", true); - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - add_property_bool(return_value, "send_status", true); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - grpc_parse_metadata_array(&recv_metadata, array); - add_property_zval(return_value, "metadata", array); - break; - case GRPC_OP_RECV_MESSAGE: - byte_buffer_to_string(message, &message_str, &message_len); - if (message_str == NULL) { - add_property_null(return_value, "message"); - } else { - add_property_stringl(return_value, "message", message_str, - message_len); - } - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - object_init(&recv_status); - grpc_parse_metadata_array(&recv_trailing_metadata, array); - add_property_zval(&recv_status, "metadata", array); - add_property_long(&recv_status, "code", status); - add_property_string(&recv_status, "details", status_details); - add_property_zval(return_value, "status", &recv_status); - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - add_property_bool(return_value, "cancelled", cancelled); - break; - default: - break; - } - } -#endif cleanup: grpc_metadata_array_destroy(&metadata); @@ -836,11 +499,7 @@ cleanup: grpc_byte_buffer_destroy(message); } } -#if PHP_MAJOR_VERSION < 7 RETURN_DESTROY_ZVAL(result); -#else - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -848,14 +507,8 @@ cleanup: * @return string The URI of the endpoint */ PHP_METHOD(Call, getPeer) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); - RETURN_STRING(grpc_call_get_peer(call->wrapped), 1); -#else wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); - RETURN_STRING(grpc_call_get_peer(call->wrapped)); -#endif + PHP_GRPC_RETURN_STRING(grpc_call_get_peer(call->wrapped), 1); } /** @@ -863,12 +516,7 @@ PHP_METHOD(Call, getPeer) { * has not already ended with another status. */ PHP_METHOD(Call, cancel) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); -#endif grpc_call_cancel(call->wrapped, NULL); } @@ -889,17 +537,9 @@ PHP_METHOD(Call, setCredentials) { return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_call_credentials *creds = - (wrapped_grpc_call_credentials *)zend_object_store_get_object( - creds_obj TSRMLS_CC); - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_call_credentials *creds = Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj); wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); -#endif grpc_call_error error = GRPC_CALL_ERROR; error = grpc_call_set_credentials(call->wrapped, creds->wrapped); @@ -920,10 +560,5 @@ void grpc_init_call(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\Call", call_methods); ce.create_object = create_wrapped_grpc_call; grpc_ce_call = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&call_ce_handlers, zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - call_ce_handlers.offset = XtOffsetOf(wrapped_grpc_call, std); - call_ce_handlers.free_obj = free_wrapped_grpc_call; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_call, call_ce_handlers); } diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h index 9fc52d7820..e49f9b382a 100644 --- a/src/php/ext/grpc/call.h +++ b/src/php/ext/grpc/call.h @@ -48,31 +48,19 @@ /* Class entry for the Call PHP class */ extern zend_class_entry *grpc_ce_call; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_call that can be associated with a PHP object */ -typedef struct wrapped_grpc_call { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call) bool owned; grpc_call *wrapped; -} wrapped_grpc_call; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call) -/* Creates a Call object that wraps the given grpc_call struct */ -zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); +#if PHP_MAJOR_VERSION < 7 -/* Creates and returns a PHP associative array of metadata from a C array of - * call metadata */ -zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC); +#define Z_WRAPPED_GRPC_CALL_P(zv) \ + (wrapped_grpc_call *)zend_object_store_get_object(zv TSRMLS_CC) #else -/* Wrapper struct for grpc_call that can be associated with a PHP object */ -typedef struct wrapped_grpc_call { - bool owned; - grpc_call *wrapped; - zend_object std; -} wrapped_grpc_call; - static inline wrapped_grpc_call *wrapped_grpc_call_from_obj(zend_object *obj) { return (wrapped_grpc_call*)((char*)(obj) - @@ -81,15 +69,14 @@ static inline wrapped_grpc_call #define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv))) -/* Creates a Call object that wraps the given grpc_call struct */ -void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object); +#endif /* PHP_MAJOR_VERSION */ /* Creates and returns a PHP associative array of metadata from a C array of * call metadata */ -void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, - zval *array); +zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC); -#endif /* PHP_MAJOR_VERSION */ +/* Creates a Call object that wraps the given grpc_call struct */ +zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); /* Initializes the Call PHP class */ void grpc_init_call(TSRMLS_D); diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c index 70aaffb848..6921a5df17 100644 --- a/src/php/ext/grpc/call_credentials.c +++ b/src/php/ext/grpc/call_credentials.c @@ -52,88 +52,39 @@ #include <grpc/grpc_security.h> zend_class_entry *grpc_ce_call_credentials; - -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers call_credentials_ce_handlers; +#endif /* Frees and destroys an instance of wrapped_grpc_call_credentials */ -void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) { - wrapped_grpc_call_credentials *creds = - (wrapped_grpc_call_credentials *)object; - if (creds->wrapped != NULL) { - grpc_call_credentials_release(creds->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call_credentials) + if (p->wrapped != NULL) { + grpc_call_credentials_release(p->wrapped); } - zend_object_std_dtor(&creds->std TSRMLS_CC); - efree(creds); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call_credentials to be * associated with an object of a class specified by class_type */ -zend_object_value create_wrapped_grpc_call_credentials( +php_grpc_zend_object create_wrapped_grpc_call_credentials( zend_class_entry *class_type TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_call_credentials *intern; - - intern = (wrapped_grpc_call_credentials *)emalloc( - sizeof(wrapped_grpc_call_credentials)); - memset(intern, 0, sizeof(wrapped_grpc_call_credentials)); - + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_call_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_call_credentials, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_call_credentials, + call_credentials_ce_handlers); } -zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) { +zval *grpc_php_wrap_call_credentials(grpc_call_credentials + *wrapped TSRMLS_DC) { zval *credentials_object; - MAKE_STD_ZVAL(credentials_object); - object_init_ex(credentials_object, grpc_ce_call_credentials); - wrapped_grpc_call_credentials *credentials = - (wrapped_grpc_call_credentials *)zend_object_store_get_object( - credentials_object TSRMLS_CC); - credentials->wrapped = wrapped; - return credentials_object; -} - -#else - -static zend_object_handlers call_credentials_ce_handlers; - -/* Frees and destroys an instance of wrapped_grpc_call_credentials */ -static void free_wrapped_grpc_call_credentials(zend_object *object) { - wrapped_grpc_call_credentials *creds = - wrapped_grpc_call_creds_from_obj(object); - if (creds->wrapped != NULL) { - grpc_call_credentials_release(creds->wrapped); - } - zend_object_std_dtor(&creds->std); -} - -/* Initializes an instance of wrapped_grpc_call_credentials to be - * associated with an object of a class specified by class_type */ -zend_object *create_wrapped_grpc_call_credentials(zend_class_entry - *class_type) { - wrapped_grpc_call_credentials *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_call_credentials) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &call_credentials_ce_handlers; - return &intern->std; -} - -void grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped, - zval *credentials_object) { + PHP_GRPC_MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_call_credentials); wrapped_grpc_call_credentials *credentials = Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object); credentials->wrapped = wrapped; + return credentials_object; } -#endif - /** * Create composite credentials from two existing credentials. * @param CallCredentials cred1 The first credential @@ -153,29 +104,17 @@ PHP_METHOD(CallCredentials, createComposite) { 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call_credentials *cred1 = - (wrapped_grpc_call_credentials *)zend_object_store_get_object( - cred1_obj TSRMLS_CC); + Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj); wrapped_grpc_call_credentials *cred2 = - (wrapped_grpc_call_credentials *)zend_object_store_get_object( - cred2_obj TSRMLS_CC); + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); grpc_call_credentials *creds = grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - wrapped_grpc_call_credentials *cred1 = - Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj); - wrapped_grpc_call_credentials *cred2 = - Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); - grpc_call_credentials *creds = - grpc_composite_call_credentials_create(cred1->wrapped, - cred2->wrapped, NULL); - grpc_php_wrap_call_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -216,13 +155,10 @@ PHP_METHOD(CallCredentials, createFromPlugin) { grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); -#if PHP_MAJOR_VERSION < 7 - zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - grpc_php_wrap_call_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /* Callback function for plugin creds API */ @@ -235,37 +171,28 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, /* prepare to call the user callback function with info from the * grpc_auth_metadata_context */ -#if PHP_MAJOR_VERSION < 7 - zval **params[1]; zval *arg; - zval *retval; - MAKE_STD_ZVAL(arg); + PHP_GRPC_MAKE_STD_ZVAL(arg); object_init(arg); - add_property_string(arg, "service_url", context.service_url, true); - add_property_string(arg, "method_name", context.method_name, true); + php_grpc_add_property_string(arg, "service_url", context.service_url, true); + php_grpc_add_property_string(arg, "method_name", context.method_name, true); + zval *retval; + PHP_GRPC_MAKE_STD_ZVAL(retval); +#if PHP_MAJOR_VERSION < 7 + zval **params[1]; params[0] = &arg; - state->fci->param_count = 1; state->fci->params = params; state->fci->retval_ptr_ptr = &retval; #else - zval arg; - zval retval; - object_init(&arg); - add_property_string(&arg, "service_url", context.service_url); - add_property_string(&arg, "method_name", context.method_name); - state->fci->param_count = 1; - state->fci->params = &arg; - state->fci->retval = &retval; + state->fci->params = arg; + state->fci->retval = retval; #endif + state->fci->param_count = 1; /* call the user callback function */ zend_call_function(state->fci, state->fci_cache TSRMLS_CC); -#if PHP_MAJOR_VERSION < 7 if (Z_TYPE_P(retval) != IS_ARRAY) { -#else - if (Z_TYPE_P(&retval) != IS_ARRAY) { -#endif zend_throw_exception(spl_ce_InvalidArgumentException, "plugin callback must return metadata array", 1 TSRMLS_CC); @@ -273,11 +200,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, } grpc_metadata_array metadata; -#if PHP_MAJOR_VERSION < 7 if (!create_metadata_array(retval, &metadata)) { -#else - if (!create_metadata_array(&retval, &metadata)) { -#endif zend_throw_exception(spl_ce_InvalidArgumentException, "invalid metadata", 1 TSRMLS_CC); grpc_metadata_array_destroy(&metadata); @@ -312,13 +235,6 @@ void grpc_init_call_credentials(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods); ce.create_object = create_wrapped_grpc_call_credentials; grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&call_credentials_ce_handlers, - zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - call_credentials_ce_handlers.offset = - XtOffsetOf(wrapped_grpc_call_credentials, std); - call_credentials_ce_handlers.free_obj = - free_wrapped_grpc_call_credentials; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_call_credentials, + call_credentials_ce_handlers); } diff --git a/src/php/ext/grpc/call_credentials.h b/src/php/ext/grpc/call_credentials.h index e05e14698b..c1d85c0fb2 100755 --- a/src/php/ext/grpc/call_credentials.h +++ b/src/php/ext/grpc/call_credentials.h @@ -49,34 +49,27 @@ /* Class entry for the CallCredentials PHP class */ extern zend_class_entry *grpc_ce_call_credentials; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_call_credentials that can be associated * with a PHP object */ -typedef struct wrapped_grpc_call_credentials { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_call_credentials) grpc_call_credentials *wrapped; -} wrapped_grpc_call_credentials; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_call_credentials) -#else +#if PHP_MAJOR_VERSION < 7 -/* Wrapper struct for grpc_call_credentials that can be associated - * with a PHP object */ -typedef struct wrapped_grpc_call_credentials { - grpc_call_credentials *wrapped; - zend_object std; -} wrapped_grpc_call_credentials; +#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ + (wrapped_grpc_call_credentials *)zend_object_store_get_object(zv TSRMLS_CC) + +#else static inline wrapped_grpc_call_credentials -*wrapped_grpc_call_creds_from_obj(zend_object *obj) { - return - (wrapped_grpc_call_credentials*)((char*)(obj) - - XtOffsetOf(wrapped_grpc_call_credentials, - std)); +*wrapped_grpc_call_credentials_from_obj(zend_object *obj) { + return (wrapped_grpc_call_credentials*)( + (char*)(obj) - XtOffsetOf(wrapped_grpc_call_credentials, std)); } -#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ - wrapped_grpc_call_creds_from_obj(Z_OBJ_P((zv))) +#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ + wrapped_grpc_call_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 6737e340f9..b5a2c9f6ba 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -56,123 +56,52 @@ #include "timeval.h" zend_class_entry *grpc_ce_channel; - -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers channel_ce_handlers; +#endif /* Frees and destroys an instance of wrapped_grpc_channel */ -void free_wrapped_grpc_channel(void *object TSRMLS_DC) { - wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object; - if (channel->wrapped != NULL) { - grpc_channel_destroy(channel->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel) + if (p->wrapped != NULL) { + grpc_channel_destroy(p->wrapped); } - zend_object_std_dtor(&channel->std TSRMLS_CC); - efree(channel); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_channel to be associated with an * object of a class specified by class_type */ -zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type - TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_channel *intern; - intern = (wrapped_grpc_channel *)emalloc(sizeof(wrapped_grpc_channel)); - memset(intern, 0, sizeof(wrapped_grpc_channel)); +php_grpc_zend_object create_wrapped_grpc_channel(zend_class_entry *class_type + TSRMLS_DC) { + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_channel, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel, channel_ce_handlers); } void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) { HashTable *array_hash; - HashPosition array_pointer; int args_index; - zval **data; - char *key; - uint key_len; - ulong index; array_hash = Z_ARRVAL_P(args_array); - args->num_args = zend_hash_num_elements(array_hash); - args->args = ecalloc(args->num_args, sizeof(grpc_arg)); - args_index = 0; - for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); - zend_hash_get_current_data_ex(array_hash, (void **)&data, - &array_pointer) == SUCCESS; - zend_hash_move_forward_ex(array_hash, &array_pointer)) { - if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0, - &array_pointer) != HASH_KEY_IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "args keys must be strings", 1 TSRMLS_CC); - return; - } - args->args[args_index].key = key; - switch (Z_TYPE_P(*data)) { - case IS_LONG: - args->args[args_index].value.integer = (int)Z_LVAL_P(*data); - args->args[args_index].type = GRPC_ARG_INTEGER; - break; - case IS_STRING: - args->args[args_index].value.string = Z_STRVAL_P(*data); - args->args[args_index].type = GRPC_ARG_STRING; - break; - default: - zend_throw_exception(spl_ce_InvalidArgumentException, - "args values must be int or string", 1 TSRMLS_CC); - return; - } - args_index++; - } -} - -#else - -static zend_object_handlers channel_ce_handlers; - -/* Frees and destroys an instance of wrapped_grpc_channel */ -static void free_wrapped_grpc_channel(zend_object *object) { - wrapped_grpc_channel *channel = wrapped_grpc_channel_from_obj(object); - if (channel->wrapped != NULL) { - grpc_channel_destroy(channel->wrapped); - } - zend_object_std_dtor(&channel->std); -} - -/* Initializes an instance of wrapped_grpc_channel to be associated with an - * object of a class specified by class_type */ -zend_object *create_wrapped_grpc_channel(zend_class_entry *class_type) { - wrapped_grpc_channel *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_channel) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &channel_ce_handlers; - return &intern->std; -} - -void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) { - HashTable *array_hash; - int args_index; - zval *data; - zend_string *key; - array_hash = HASH_OF(args_array); if (!array_hash) { zend_throw_exception(spl_ce_InvalidArgumentException, - "array_hash is NULL", 1); + "array_hash is NULL", 1 TSRMLS_CC); return; } args->num_args = zend_hash_num_elements(array_hash); args->args = ecalloc(args->num_args, sizeof(grpc_arg)); args_index = 0; - ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, data) { - if (key == NULL) { + + char *key = NULL; + zval *data; + int key_type; + + PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(array_hash, key, key_type, data) + if (key_type != HASH_KEY_IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, - "args keys must be strings", 1); + "args keys must be strings", 1 TSRMLS_CC); + return; } - args->args[args_index].key = ZSTR_VAL(key); + args->args[args_index].key = key; switch (Z_TYPE_P(data)) { case IS_LONG: args->args[args_index].value.integer = (int)Z_LVAL_P(data); @@ -184,15 +113,13 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) { break; default: zend_throw_exception(spl_ce_InvalidArgumentException, - "args values must be int or string", 1); + "args values must be int or string", 1 TSRMLS_CC); return; } args_index++; - } ZEND_HASH_FOREACH_END(); + PHP_GRPC_HASH_FOREACH_END() } -#endif - /** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel @@ -201,18 +128,10 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) { * @param array $args The arguments to pass to the Channel (optional) */ PHP_METHOD(Channel, __construct) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object( - getThis() TSRMLS_CC); - zval **creds_obj = NULL; - int target_length; -#else wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); zval *creds_obj = NULL; - size_t target_length; -#endif char *target; + php_grpc_int target_length; zval *args_array = NULL; grpc_channel_args args; HashTable *array_hash; @@ -225,43 +144,23 @@ PHP_METHOD(Channel, __construct) { "Channel expects a string and an array", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 array_hash = Z_ARRVAL_P(args_array); - if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), + if (php_grpc_zend_hash_find(array_hash, "credentials", sizeof("credentials"), (void **)&creds_obj) == SUCCESS) { - if (Z_TYPE_P(*creds_obj) == IS_NULL) { - creds = NULL; - zend_hash_del(array_hash, "credentials", 12); - } else if (zend_get_class_entry(*creds_obj TSRMLS_CC) != - grpc_ce_channel_credentials) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "credentials must be a ChannelCredentials object", - 1 TSRMLS_CC); - return; - } else { - creds = (wrapped_grpc_channel_credentials *)zend_object_store_get_object( - *creds_obj TSRMLS_CC); - zend_hash_del(array_hash, "credentials", 12); - } - } -#else - array_hash = HASH_OF(args_array); - if ((creds_obj = zend_hash_str_find(array_hash, "credentials", - sizeof("credentials") - 1)) != NULL) { if (Z_TYPE_P(creds_obj) == IS_NULL) { creds = NULL; - zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); - } else if (Z_OBJ_P(creds_obj)->ce != grpc_ce_channel_credentials) { + php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials")); + } else if (PHP_GRPC_GET_CLASS_ENTRY(creds_obj) != + grpc_ce_channel_credentials) { zend_throw_exception(spl_ce_InvalidArgumentException, "credentials must be a ChannelCredentials object", - 1); + 1 TSRMLS_CC); return; } else { creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj); - zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); + php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials")); } } -#endif php_grpc_read_args_array(args_array, &args TSRMLS_CC); if (creds == NULL) { channel->wrapped = grpc_insecure_channel_create(target, &args, NULL); @@ -277,14 +176,8 @@ PHP_METHOD(Channel, __construct) { * @return string The URI of the endpoint */ PHP_METHOD(Channel, getTarget) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); - RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1); -#else wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); - RETURN_STRING(grpc_channel_get_target(channel->wrapped)); -#endif + PHP_GRPC_RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1); } /** @@ -293,12 +186,7 @@ PHP_METHOD(Channel, getTarget) { * @return long The grpc connectivity state */ PHP_METHOD(Channel, getConnectivityState) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); -#endif bool try_to_connect = false; /* "|b" == 1 optional bool */ @@ -320,32 +208,19 @@ PHP_METHOD(Channel, getConnectivityState) { * before deadline */ PHP_METHOD(Channel, watchConnectivityState) { -#if PHP_MAJOR_VERSION < 7 - long last_state; - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else - zend_long last_state; wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); -#endif + php_grpc_long last_state; zval *deadline_obj; /* "lO" == 1 long 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO", &last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, - "watchConnectivityState expects 1 long 1 timeval", - 1 TSRMLS_CC); + "watchConnectivityState expects 1 long 1 timeval", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *deadline = - (wrapped_grpc_timeval *)zend_object_store_get_object( - deadline_obj TSRMLS_CC); -#else wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); -#endif grpc_channel_watch_connectivity_state(channel->wrapped, (grpc_connectivity_state)last_state, deadline->wrapped, completion_queue, @@ -360,12 +235,7 @@ PHP_METHOD(Channel, watchConnectivityState) { * Close the channel */ PHP_METHOD(Channel, close) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); -#endif if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); channel->wrapped = NULL; @@ -386,11 +256,5 @@ void grpc_init_channel(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods); ce.create_object = create_wrapped_grpc_channel; grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&channel_ce_handlers, zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - channel_ce_handlers.offset = - XtOffsetOf(wrapped_grpc_channel, std); - channel_ce_handlers.free_obj = free_wrapped_grpc_channel; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers); } diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h index ea5efeaf86..0b815657d3 100755 --- a/src/php/ext/grpc/channel.h +++ b/src/php/ext/grpc/channel.h @@ -48,21 +48,17 @@ /* Class entry for the PHP Channel class */ extern zend_class_entry *grpc_ce_channel; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_channel that can be associated with a PHP object */ -typedef struct wrapped_grpc_channel { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel) grpc_channel *wrapped; -} wrapped_grpc_channel; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel) -#else +#if PHP_MAJOR_VERSION < 7 -/* Wrapper struct for grpc_channel that can be associated with a PHP object */ -typedef struct wrapped_grpc_channel { - grpc_channel *wrapped; - zend_object std; -} wrapped_grpc_channel; +#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ + (wrapped_grpc_channel *)zend_object_store_get_object(zv TSRMLS_CC) + +#else static inline wrapped_grpc_channel *wrapped_grpc_channel_from_obj(zend_object *obj) { @@ -70,7 +66,7 @@ static inline wrapped_grpc_channel XtOffsetOf(wrapped_grpc_channel, std)); } -#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ +#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ wrapped_grpc_channel_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index 16ba0368eb..0b356aa25f 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -52,6 +52,9 @@ #include <grpc/grpc_security.h> zend_class_entry *grpc_ce_channel_credentials; +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers channel_credentials_ce_handlers; +#endif static char *default_pem_root_certs = NULL; static grpc_ssl_roots_override_result get_ssl_roots_override( @@ -63,88 +66,35 @@ static grpc_ssl_roots_override_result get_ssl_roots_override( return GRPC_SSL_ROOTS_OVERRIDE_OK; } -#if PHP_MAJOR_VERSION < 7 - /* Frees and destroys an instance of wrapped_grpc_channel_credentials */ -void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) { - wrapped_grpc_channel_credentials *creds = - (wrapped_grpc_channel_credentials *)object; - if (creds->wrapped != NULL) { - grpc_channel_credentials_release(creds->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel_credentials) + if (p->wrapped != NULL) { + grpc_channel_credentials_release(p->wrapped); } - zend_object_std_dtor(&creds->std TSRMLS_CC); - efree(creds); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_channel_credentials to be * associated with an object of a class specified by class_type */ -zend_object_value create_wrapped_grpc_channel_credentials( +php_grpc_zend_object create_wrapped_grpc_channel_credentials( zend_class_entry *class_type TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_channel_credentials *intern; - - intern = (wrapped_grpc_channel_credentials *)emalloc( - sizeof(wrapped_grpc_channel_credentials)); - memset(intern, 0, sizeof(wrapped_grpc_channel_credentials)); - + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_channel_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_channel_credentials, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel_credentials, + channel_credentials_ce_handlers); } zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) { zval *credentials_object; - MAKE_STD_ZVAL(credentials_object); - object_init_ex(credentials_object, grpc_ce_channel_credentials); - wrapped_grpc_channel_credentials *credentials = - (wrapped_grpc_channel_credentials *)zend_object_store_get_object( - credentials_object TSRMLS_CC); - credentials->wrapped = wrapped; - return credentials_object; -} - -#else - -static zend_object_handlers channel_credentials_ce_handlers; - -/* Frees and destroys an instance of wrapped_grpc_channel_credentials */ -static void free_wrapped_grpc_channel_credentials(zend_object *object) { - wrapped_grpc_channel_credentials *creds = - wrapped_grpc_channel_creds_from_obj(object); - if (creds->wrapped != NULL) { - grpc_channel_credentials_release(creds->wrapped); - } - zend_object_std_dtor(&creds->std); -} - -/* Initializes an instance of wrapped_grpc_channel_credentials to be - * associated with an object of a class specified by class_type */ -zend_object *create_wrapped_grpc_channel_credentials(zend_class_entry - *class_type) { - wrapped_grpc_channel_credentials *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_channel_credentials) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &channel_credentials_ce_handlers; - return &intern->std; -} - -void grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped, - zval *credentials_object) { + PHP_GRPC_MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_channel_credentials); wrapped_grpc_channel_credentials *credentials = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object); credentials->wrapped = wrapped; + return credentials_object; } -#endif - /** * Set default roots pem. * @param string pem_roots PEM encoding of the server root certificates @@ -152,11 +102,7 @@ void grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped, */ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { char *pem_roots; -#if PHP_MAJOR_VERSION < 7 - int pem_roots_length; -#else - size_t pem_roots_length; -#endif + php_grpc_int pem_roots_length; /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pem_roots, @@ -175,13 +121,10 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); -#if PHP_MAJOR_VERSION < 7 - zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - grpc_php_wrap_channel_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -197,11 +140,9 @@ PHP_METHOD(ChannelCredentials, createSsl) { char *pem_root_certs = NULL; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; -#if PHP_MAJOR_VERSION < 7 - int root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; -#else - size_t root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; -#endif + php_grpc_int root_certs_length = 0; + php_grpc_int private_key_length = 0; + php_grpc_int cert_chain_length = 0; pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL; @@ -219,13 +160,10 @@ PHP_METHOD(ChannelCredentials, createSsl) { grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); -#if PHP_MAJOR_VERSION < 7 - zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - grpc_php_wrap_channel_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -246,29 +184,17 @@ PHP_METHOD(ChannelCredentials, createComposite) { "createComposite expects 2 Credentials", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel_credentials *cred1 = - (wrapped_grpc_channel_credentials *)zend_object_store_get_object( - cred1_obj TSRMLS_CC); + Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj); wrapped_grpc_call_credentials *cred2 = - (wrapped_grpc_call_credentials *)zend_object_store_get_object( - cred2_obj TSRMLS_CC); + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - wrapped_grpc_channel_credentials *cred1 = - Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj); - wrapped_grpc_call_credentials *cred2 = - Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); - grpc_channel_credentials *creds = - grpc_composite_channel_credentials_create(cred1->wrapped, - cred2->wrapped, NULL); - grpc_php_wrap_channel_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -300,13 +226,6 @@ void grpc_init_channel_credentials(TSRMLS_D) { grpc_set_ssl_roots_override_callback(get_ssl_roots_override); ce.create_object = create_wrapped_grpc_channel_credentials; grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&channel_credentials_ce_handlers, - zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - channel_credentials_ce_handlers.offset = - XtOffsetOf(wrapped_grpc_channel_credentials, std); - channel_credentials_ce_handlers.free_obj = - free_wrapped_grpc_channel_credentials; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel_credentials, + channel_credentials_ce_handlers); } diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h index 44071b10f1..b043d91fa6 100755 --- a/src/php/ext/grpc/channel_credentials.h +++ b/src/php/ext/grpc/channel_credentials.h @@ -49,34 +49,27 @@ /* Class entry for the ChannelCredentials PHP class */ extern zend_class_entry *grpc_ce_channel_credentials; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_channel_credentials that can be associated * with a PHP object */ -typedef struct wrapped_grpc_channel_credentials { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel_credentials) grpc_channel_credentials *wrapped; -} wrapped_grpc_channel_credentials; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel_credentials) -#else +#if PHP_MAJOR_VERSION < 7 -/* Wrapper struct for grpc_channel_credentials that can be associated - * with a PHP object */ -typedef struct wrapped_grpc_channel_credentials { - grpc_channel_credentials *wrapped; - zend_object std; -} wrapped_grpc_channel_credentials; +#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ + (wrapped_grpc_channel_credentials *)zend_object_store_get_object(zv TSRMLS_CC) + +#else static inline wrapped_grpc_channel_credentials -*wrapped_grpc_channel_creds_from_obj(zend_object *obj) { - return - (wrapped_grpc_channel_credentials *) - ((char*)(obj) - - XtOffsetOf(wrapped_grpc_channel_credentials, std)); +*wrapped_grpc_channel_credentials_from_obj(zend_object *obj) { + return (wrapped_grpc_channel_credentials *)( + (char*)(obj) - XtOffsetOf(wrapped_grpc_channel_credentials, std)); } -#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ - wrapped_grpc_channel_creds_from_obj(Z_OBJ_P((zv))) +#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ + wrapped_grpc_channel_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml deleted file mode 100644 index daf2ee5a53..0000000000 --- a/src/php/ext/grpc/package.xml +++ /dev/null @@ -1,156 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<package packagerversion="1.9.5" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> - <name>grpc</name> - <channel>pecl.php.net</channel> - <summary>A high performance, open source, general RPC framework that puts mobile and HTTP/2 first.</summary> - <description>Remote Procedure Calls (RPCs) provide a useful abstraction for building distributed applications and services. The libraries in this repository provide a concrete implementation of the gRPC protocol, layered over HTTP/2. These libraries enable communication between clients and servers using any combination of the supported languages.</description> - <lead> - <name>Stanley Cheung</name> - <user>stanleycheung</user> - <email>grpc-packages@google.com</email> - <active>yes</active> - </lead> - <date>2016-01-13</date> - <time>16:06:07</time> - <version> - <release>0.7.0</release> - <api>0.7.0</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <license>BSD</license> - <notes> -- Breaking change to Credentials class (removed) #3765 -- Replaced by ChannelCredentials and CallCredentials class #3765 -- New plugin based metadata auth API #4394 -- Explicit ChannelCredentials::createInsecure() call - </notes> - <contents> - <dir baseinstalldir="/" name="/"> - <file baseinstalldir="/" md5sum="f201d644fdbd8228ffd1d4a69cc44f1f" name="tests/grpc-basic.phpt" role="test" /> - <file baseinstalldir="/" md5sum="6f19828fb869b7b8a590cbb76b4f996d" name="byte_buffer.c" role="src" /> - <file baseinstalldir="/" md5sum="c8de0f819499c48adfc8d7f472c0196b" name="byte_buffer.h" role="src" /> - <file baseinstalldir="/" md5sum="ee7eb7757f9e6f0e36f8f616b6bd0af5" name="call.c" role="src" /> - <file baseinstalldir="/" md5sum="44c56bd9912d2538cbd6059e3e0452b6" name="call.h" role="src" /> - <file baseinstalldir="/" md5sum="ff90f6c03ed44b5f4170bf3259a6704e" name="call_credentials.c" role="src" /> - <file baseinstalldir="/" md5sum="3c3860e1d84f43cb6b2fbaa8d2ae1ab7" name="call_credentials.h" role="src" /> - <file baseinstalldir="/" md5sum="aee9b63f790522aec2c682055240cc61" name="channel.c" role="src" /> - <file baseinstalldir="/" md5sum="ed4b00c0cf3702b115d0cfa87450dc09" name="channel.h" role="src" /> - <file baseinstalldir="/" md5sum="1a51c76d0b7b7d3ab570ed7d60c2ea46" name="channel_credentials.c" role="src" /> - <file baseinstalldir="/" md5sum="a86250e03f610ce6c2c7595a84e08821" name="channel_credentials.h" role="src" /> - <file baseinstalldir="/" md5sum="55ab7a42f9dd9bfc7e28a61cfc5fca63" name="completion_queue.c" role="src" /> - <file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" /> - <file baseinstalldir="/" md5sum="cafed254127007ff2271dad7d56a06c8" name="config.m4" role="src" /> - <file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" /> - <file baseinstalldir="/" md5sum="8847cf67b1b54c981d47ecbb0d139a0c" name="LICENSE" role="doc" /> - <file baseinstalldir="/" md5sum="3131a8af38fe5918e5409016b89d6cdb" name="php_grpc.c" role="src" /> - <file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" /> - <file baseinstalldir="/" md5sum="7533a6d3ea02c78cad23a9651de0825d" name="README.md" role="doc" /> - <file baseinstalldir="/" md5sum="3e4e960454ebb2fc7b78a840493f5315" name="server.c" role="src" /> - <file baseinstalldir="/" md5sum="4b730f06d14cbbb0642bdbd194749595" name="server.h" role="src" /> - <file baseinstalldir="/" md5sum="34ea881f1fe960d190d0713422cf8916" name="server_credentials.c" role="src" /> - <file baseinstalldir="/" md5sum="9c4b4cc06356a8a39a16a085a9b85996" name="server_credentials.h" role="src" /> - <file baseinstalldir="/" md5sum="7646ec78cb133f66ba59e03c6f451e39" name="timeval.c" role="src" /> - <file baseinstalldir="/" md5sum="496e27a100b4d93ca3fb35c924c5e163" name="timeval.h" role="src" /> - </dir> - </contents> - <dependencies> - <required> - <php> - <min>5.5.0</min> - </php> - <pearinstaller> - <min>1.4.0</min> - </pearinstaller> - </required> - </dependencies> - <providesextension>grpc</providesextension> - <extsrcrelease /> - <changelog> - <release> - <version> - <release>0.5.0</release> - <api>0.5.0</api> - </version> - <stability> - <release>alpha</release> - <api>alpha</api> - </stability> - <date>2015-06-16</date> - <license>BSD</license> - <notes> -First alpha release - </notes> - </release> - <release> - <version> - <release>0.5.1</release> - <api>0.5.1</api> - </version> - <stability> - <release>alpha</release> - <api>alpha</api> - </stability> - <date>2015-07-09</date> - <license>BSD</license> - <notes> -Update to wrap gRPC C Core version 0.10.0 - </notes> - </release> - <release> - <version> - <release>0.6.0</release> - <api>0.6.0</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2015-09-24</date> - <license>BSD</license> - <notes> -- support per message compression disable -- expose per-call host override option -- expose connectivity API -- expose channel target and call peer -- add user-agent -- update to wrap gRPC C core library beta version 0.11.0 - </notes> - </release> - <release> - <version> - <release>0.6.1</release> - <api>0.6.0</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2015-10-21</date> - <license>BSD</license> - <notes> -- fixed undefined constant fatal error when run with apache/nginx #2275 - </notes> - </release> - <release> - <version> - <release>0.7.0</release> - <api>0.7.0</api> - </version> - <stability> - <release>beta</release> - <api>beta</api> - </stability> - <date>2016-01-13</date> - <license>BSD</license> - <notes> -- Breaking change to Credentials class (removed) #3765 -- Replaced by ChannelCredentials and CallCredentials class #3765 -- New plugin based metadata auth API #4394 -- Explicit ChannelCredentials::createInsecure() call - </notes> - </release> - </changelog> -</package> diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h new file mode 100644 index 0000000000..fd8d35636f --- /dev/null +++ b/src/php/ext/grpc/php7_wrapper.h @@ -0,0 +1,218 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef PHP7_WRAPPER_GRPC_H +#define PHP7_WRAPPER_GRPC_H + +#if PHP_MAJOR_VERSION < 7 + +#define php_grpc_int int +#define php_grpc_long long +#define php_grpc_ulong ulong +#define php_grpc_zend_object zend_object_value +#define php_grpc_add_property_string(arg, name, context, b) \ + add_property_string(arg, name, context, b) +#define php_grpc_add_property_stringl(res, name, str, len, b) \ + add_property_stringl(res, name, str, len, b) +#define php_grpc_add_next_index_stringl(data, str, len, b) \ + add_next_index_stringl(data, str, len, b) + +#define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup) +#define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv) +#define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv) + +#define PHP_GRPC_WRAP_OBJECT_START(name) \ + typedef struct name { \ + zend_object std; +#define PHP_GRPC_WRAP_OBJECT_END(name) \ + } name; + +#define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \ + void free_##class_object(void *object TSRMLS_DC) { \ + class_object *p = (class_object *)object; +#define PHP_GRPC_FREE_WRAPPED_FUNC_END() \ + zend_object_std_dtor(&p->std TSRMLS_CC); \ + efree(p); \ + } + +#define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \ + class_object *intern; \ + zend_object_value retval; \ + intern = (class_object *)emalloc(sizeof(class_object)); \ + memset(intern, 0, sizeof(class_object)); + +#define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \ + retval.handle = zend_objects_store_put( \ + intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \ + free_##class_object, NULL TSRMLS_CC); \ + retval.handlers = zend_get_std_object_handlers(); \ + return retval; + +#define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \ + zval **tmp_data = NULL; \ + for (zend_hash_internal_pointer_reset(ht); \ + zend_hash_get_current_data(ht, (void**)&tmp_data) == SUCCESS; \ + zend_hash_move_forward(ht)) { \ + data = *tmp_data; + +#define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \ + zval **tmp##key = NULL; \ + ulong index##key; \ + uint len##key; \ + for (zend_hash_internal_pointer_reset(ht); \ + zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \ + zend_hash_move_forward(ht)) { \ + key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index##key,\ + 0, NULL); \ + data = *tmp##key; + +#define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index,\ + data) \ + zval **tmp##key = NULL; \ + uint len##key; \ + for (zend_hash_internal_pointer_reset(ht); \ + zend_hash_get_current_data(ht, (void**)&tmp##key) == SUCCESS; \ + zend_hash_move_forward(ht)) { \ + key_type = zend_hash_get_current_key_ex(ht, &key, &len##key, &index,\ + 0, NULL); \ + data = *tmp##key; + +#define PHP_GRPC_HASH_FOREACH_END() } + +static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, + void **value) { + zval **data = NULL; + if (zend_hash_find(ht, key, len, (void **)&data) == SUCCESS) { + *value = *data; + return SUCCESS; + } else { + *value = NULL; + return FAILURE; + } +} + +#define php_grpc_zend_hash_del zend_hash_del + +#define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC) + +#define PHP_GRPC_INIT_HANDLER(class_object, handler_name) + +#else + +#define php_grpc_int size_t +#define php_grpc_long zend_long +#define php_grpc_ulong zend_ulong +#define php_grpc_zend_object zend_object* +#define php_grpc_add_property_string(arg, name, context, b) \ + add_property_string(arg, name, context) +#define php_grpc_add_property_stringl(res, name, str, len, b) \ + add_property_stringl(res, name, str, len) +#define php_grpc_add_next_index_stringl(data, str, len, b) \ + add_next_index_stringl(data, str, len) + +#define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val) +#define PHP_GRPC_MAKE_STD_ZVAL(pzv) \ + zval _stack_zval_##pzv; \ + pzv = &(_stack_zval_##pzv) +#define PHP_GRPC_DELREF(zv) + +#define PHP_GRPC_WRAP_OBJECT_START(name) \ + typedef struct name { +#define PHP_GRPC_WRAP_OBJECT_END(name) \ + zend_object std; \ + } name; + +#define WRAPPED_OBJECT_FROM_OBJ(class_object, obj) \ + class_object##_from_obj(obj); + +#define PHP_GRPC_FREE_WRAPPED_FUNC_START(class_object) \ + static void free_##class_object(zend_object *object) { \ + class_object *p = WRAPPED_OBJECT_FROM_OBJ(class_object, object) +#define PHP_GRPC_FREE_WRAPPED_FUNC_END() \ + zend_object_std_dtor(&p->std); \ + } + +#define PHP_GRPC_ALLOC_CLASS_OBJECT(class_object) \ + class_object *intern; \ + intern = ecalloc(1, sizeof(class_object) + \ + zend_object_properties_size(class_type)); + +#define PHP_GRPC_FREE_CLASS_OBJECT(class_object, handler) \ + intern->std.handlers = &handler; \ + return &intern->std; + +#define PHP_GRPC_HASH_FOREACH_VAL_START(ht, data) \ + ZEND_HASH_FOREACH_VAL(ht, data) { + +#define PHP_GRPC_HASH_FOREACH_STR_KEY_VAL_START(ht, key, key_type, data) \ + zend_string *(zs_##key); \ + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, (zs_##key), data) { \ + if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \ + else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;} + +#define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index, \ + data) \ + zend_string *(zs_##key); \ + ZEND_HASH_FOREACH_KEY_VAL(ht, index, zs_##key, data) { \ + if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \ + else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;} + +#define PHP_GRPC_HASH_FOREACH_END() } ZEND_HASH_FOREACH_END(); + +static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, + void **value) { + zval *value_tmp = zend_hash_str_find(ht, key, len -1); + if (value_tmp == NULL) { + return FAILURE; + } else { + *value = (void *)value_tmp; + return SUCCESS; + } +} + +static inline int php_grpc_zend_hash_del(HashTable *ht, char *key, int len) { + return zend_hash_str_del(ht, key, len - 1); +} + +#define PHP_GRPC_GET_CLASS_ENTRY(object) Z_OBJ_P(object)->ce + +#define PHP_GRPC_INIT_HANDLER(class_object, handler_name) \ + memcpy(&handler_name, zend_get_std_object_handlers(), \ + sizeof(zend_object_handlers)); \ + handler_name.offset = XtOffsetOf(class_object, std); \ + handler_name.free_obj = free_##class_object + +#endif /* PHP_MAJOR_VERSION */ + +#endif /* PHP7_WRAPPER_GRPC_H */ diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index bd7ee75a6f..e57a06545e 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -57,6 +57,8 @@ extern zend_module_entry grpc_module_entry; #include "php.h" +#include "php7_wrapper.h" + #include "grpc/grpc.h" #define RETURN_DESTROY_ZVAL(val) \ diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index 50fb2d0cf9..fc20c42b16 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -57,84 +57,37 @@ #include "timeval.h" zend_class_entry *grpc_ce_server; - -#if PHP_MAJOR_VERSION < 7 - -/* Frees and destroys an instance of wrapped_grpc_server */ -void free_wrapped_grpc_server(void *object TSRMLS_DC) { - wrapped_grpc_server *server = (wrapped_grpc_server *)object; - if (server->wrapped != NULL) { - grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL); - grpc_server_cancel_all_calls(server->wrapped); - grpc_completion_queue_pluck(completion_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_server_destroy(server->wrapped); - } - zend_object_std_dtor(&server->std TSRMLS_CC); - efree(server); -} - -/* Initializes an instance of wrapped_grpc_call to be associated with an object - * of a class specified by class_type */ -zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type - TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_server *intern; - - intern = (wrapped_grpc_server *)emalloc(sizeof(wrapped_grpc_server)); - memset(intern, 0, sizeof(wrapped_grpc_server)); - - zend_object_std_init(&intern->std, class_type TSRMLS_CC); - object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_server, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; -} - -#else - +#if PHP_MAJOR_VERSION >= 7 static zend_object_handlers server_ce_handlers; +#endif /* Frees and destroys an instance of wrapped_grpc_server */ -static void free_wrapped_grpc_server(zend_object *object) { - wrapped_grpc_server *server = wrapped_grpc_server_from_obj(object); - if (server->wrapped != NULL) { - grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL); - grpc_server_cancel_all_calls(server->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server) + if (p->wrapped != NULL) { + grpc_server_shutdown_and_notify(p->wrapped, completion_queue, NULL); + grpc_server_cancel_all_calls(p->wrapped); grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_server_destroy(server->wrapped); + grpc_server_destroy(p->wrapped); } - zend_object_std_dtor(&server->std); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_call to be associated with an object * of a class specified by class_type */ -zend_object *create_wrapped_grpc_server(zend_class_entry *class_type) { - wrapped_grpc_server *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_server) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); +php_grpc_zend_object create_wrapped_grpc_server(zend_class_entry *class_type + TSRMLS_DC) { + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server); + zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - intern->std.handlers = &server_ce_handlers; - return &intern->std; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server, server_ce_handlers); } -#endif - /** * Constructs a new instance of the Server class * @param array $args The arguments to pass to the server (optional) */ PHP_METHOD(Server, __construct) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); -#endif zval *args_array = NULL; grpc_channel_args args; @@ -172,16 +125,10 @@ PHP_METHOD(Server, requestCall) { grpc_metadata_array metadata; grpc_event event; -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); zval *result; - MAKE_STD_ZVAL(result); + PHP_GRPC_MAKE_STD_ZVAL(result); object_init(result); -#else - wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); - object_init(return_value); -#endif grpc_call_details_init(&details); grpc_metadata_array_init(&metadata); @@ -202,40 +149,32 @@ PHP_METHOD(Server, requestCall) { 1 TSRMLS_CC); goto cleanup; } + php_grpc_add_property_string(result, "method", details.method, true); + php_grpc_add_property_string(result, "host", details.host, true); #if PHP_MAJOR_VERSION < 7 add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC)); - add_property_string(result, "method", details.method, true); - add_property_string(result, "host", details.host, true); add_property_zval(result, "absolute_deadline", grpc_php_wrap_timeval(details.deadline TSRMLS_CC)); add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC)); - -cleanup: - grpc_call_details_destroy(&details); - grpc_metadata_array_destroy(&metadata); - RETURN_DESTROY_ZVAL(result); - #else - zval zv_call; zval zv_timeval; zval zv_md; - grpc_php_wrap_call(call, true, &zv_call); - grpc_php_wrap_timeval(details.deadline, &zv_timeval); - grpc_parse_metadata_array(&metadata, &zv_md); - - add_property_zval(return_value, "call", &zv_call); - add_property_string(return_value, "method", details.method); - add_property_string(return_value, "host", details.host); - add_property_zval(return_value, "absolute_deadline", &zv_timeval); - add_property_zval(return_value, "metadata", &zv_md); + //TODO(thinkerou): why use zval* to unit test error? + zv_call = *grpc_php_wrap_call(call, true); + zv_timeval = *grpc_php_wrap_timeval(details.deadline); + zv_md = *grpc_parse_metadata_array(&metadata); + + add_property_zval(result, "call", &zv_call); + add_property_zval(result, "absolute_deadline", &zv_timeval); + add_property_zval(result, "metadata", &zv_md); +#endif cleanup: grpc_call_details_destroy(&details); grpc_metadata_array_destroy(&metadata); - RETURN_DESTROY_ZVAL(return_value); -#endif + RETURN_DESTROY_ZVAL(result); } /** @@ -245,14 +184,8 @@ cleanup: */ PHP_METHOD(Server, addHttp2Port) { const char *addr; -#if PHP_MAJOR_VERSION < 7 - int addr_len; - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else - size_t addr_len; + php_grpc_int addr_len; wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); -#endif /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) @@ -266,15 +199,9 @@ PHP_METHOD(Server, addHttp2Port) { PHP_METHOD(Server, addSecureHttp2Port) { const char *addr; + php_grpc_int addr_len; zval *creds_obj; -#if PHP_MAJOR_VERSION < 7 - int addr_len; - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else - size_t addr_len; wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); -#endif /* "sO" == 1 string, 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len, @@ -285,14 +212,8 @@ PHP_METHOD(Server, addSecureHttp2Port) { "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_server_credentials *creds = - (wrapped_grpc_server_credentials *)zend_object_store_get_object( - creds_obj TSRMLS_CC); -#else wrapped_grpc_server_credentials *creds = Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj); -#endif RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr, creds->wrapped)); } @@ -302,12 +223,7 @@ PHP_METHOD(Server, addSecureHttp2Port) { * @return Void */ PHP_METHOD(Server, start) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); -#endif grpc_server_start(server->wrapped); } @@ -317,7 +233,7 @@ static zend_function_entry server_methods[] = { PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC) PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC) PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) - PHP_FE_END + PHP_FE_END }; void grpc_init_server(TSRMLS_D) { @@ -325,10 +241,5 @@ void grpc_init_server(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods); ce.create_object = create_wrapped_grpc_server; grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&server_ce_handlers, zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - server_ce_handlers.offset = XtOffsetOf(wrapped_grpc_server, std); - server_ce_handlers.free_obj = free_wrapped_grpc_server; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_server, server_ce_handlers); } diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h index a7df456a11..a635bc11df 100755 --- a/src/php/ext/grpc/server.h +++ b/src/php/ext/grpc/server.h @@ -48,21 +48,17 @@ /* Class entry for the Server PHP class */ extern zend_class_entry *grpc_ce_server; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_server that can be associated with a PHP object */ -typedef struct wrapped_grpc_server { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server) grpc_server *wrapped; -} wrapped_grpc_server; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server) -#else +#if PHP_MAJOR_VERSION < 7 -/* Wrapper struct for grpc_server that can be associated with a PHP object */ -typedef struct wrapped_grpc_server { - grpc_server *wrapped; - zend_object std; -} wrapped_grpc_server; +#define Z_WRAPPED_GRPC_SERVER_P(zv) \ + (wrapped_grpc_server *)zend_object_store_get_object(zv TSRMLS_CC) + +#else static inline wrapped_grpc_server *wrapped_grpc_server_from_obj(zend_object *obj) { @@ -70,8 +66,7 @@ static inline wrapped_grpc_server XtOffsetOf(wrapped_grpc_server, std)); } -#define Z_WRAPPED_GRPC_SERVER_P(zv) \ - wrapped_grpc_server_from_obj(Z_OBJ_P((zv))) +#define Z_WRAPPED_GRPC_SERVER_P(zv) wrapped_grpc_server_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 296632d5bd..b05896af4a 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -50,89 +50,39 @@ #include <grpc/grpc_security.h> zend_class_entry *grpc_ce_server_credentials; - -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers server_credentials_ce_handlers; +#endif /* Frees and destroys an instace of wrapped_grpc_server_credentials */ -void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { - wrapped_grpc_server_credentials *creds = - (wrapped_grpc_server_credentials *)object; - if (creds->wrapped != NULL) { - grpc_server_credentials_release(creds->wrapped); +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_server_credentials) + if (p->wrapped != NULL) { + grpc_server_credentials_release(p->wrapped); } - zend_object_std_dtor(&creds->std TSRMLS_CC); - efree(creds); -} +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instace of wrapped_grpc_server_credentials to be associated * with an object of a class specified by class_type */ -zend_object_value create_wrapped_grpc_server_credentials( +php_grpc_zend_object create_wrapped_grpc_server_credentials( zend_class_entry *class_type TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_server_credentials *intern; - - intern = (wrapped_grpc_server_credentials *)emalloc( - sizeof(wrapped_grpc_server_credentials)); - memset(intern, 0, sizeof(wrapped_grpc_server_credentials)); - + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_server_credentials); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_server_credentials, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_server_credentials, + server_credentials_ce_handlers); } zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) { zval *server_credentials_object; - MAKE_STD_ZVAL(server_credentials_object); - object_init_ex(server_credentials_object, grpc_ce_server_credentials); - wrapped_grpc_server_credentials *server_credentials = - (wrapped_grpc_server_credentials *)zend_object_store_get_object( - server_credentials_object TSRMLS_CC); - server_credentials->wrapped = wrapped; - return server_credentials_object; -} - -#else - -static zend_object_handlers server_credentials_ce_handlers; - -/* Frees and destroys an instace of wrapped_grpc_server_credentials */ -static void free_wrapped_grpc_server_credentials(zend_object *object) { - wrapped_grpc_server_credentials *creds = - wrapped_grpc_server_creds_from_obj(object); - if (creds->wrapped != NULL) { - grpc_server_credentials_release(creds->wrapped); - } - zend_object_std_dtor(&creds->std); -} - -/* Initializes an instace of wrapped_grpc_server_credentials to be associated - * with an object of a class specified by class_type */ -zend_object *create_wrapped_grpc_server_credentials(zend_class_entry - *class_type) { - wrapped_grpc_server_credentials *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_server_credentials) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &server_credentials_ce_handlers; - return &intern->std; -} - -void grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped, - zval *server_credentials_object) { + PHP_GRPC_MAKE_STD_ZVAL(server_credentials_object); object_init_ex(server_credentials_object, grpc_ce_server_credentials); wrapped_grpc_server_credentials *server_credentials = Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object); server_credentials->wrapped = wrapped; + return server_credentials_object; } -#endif - /** * Create SSL credentials. * @param string pem_root_certs PEM encoding of the server root certificates @@ -144,11 +94,9 @@ PHP_METHOD(ServerCredentials, createSsl) { char *pem_root_certs = 0; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; -#if PHP_MAJOR_VERSION < 7 - int root_certs_length = 0, private_key_length, cert_chain_length; -#else - size_t root_certs_length = 0, private_key_length, cert_chain_length; -#endif + php_grpc_int root_certs_length = 0; + php_grpc_int private_key_length; + php_grpc_int cert_chain_length; /* "s!ss" == 1 nullable string, 2 strings */ /* TODO: support multiple key cert pairs. */ @@ -165,19 +113,16 @@ PHP_METHOD(ServerCredentials, createSsl) { grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); -#if PHP_MAJOR_VERSION < 7 - zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); + zval *creds_object; + PHP_GRPC_MAKE_STD_ZVAL(creds_object); + creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); -#else - grpc_php_wrap_server_credentials(creds, return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } static zend_function_entry server_credentials_methods[] = { PHP_ME(ServerCredentials, createSsl, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_FE_END + PHP_FE_END }; void grpc_init_server_credentials(TSRMLS_D) { @@ -185,13 +130,6 @@ void grpc_init_server_credentials(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\ServerCredentials", server_credentials_methods); ce.create_object = create_wrapped_grpc_server_credentials; grpc_ce_server_credentials = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&server_credentials_ce_handlers, - zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - server_credentials_ce_handlers.offset = - XtOffsetOf(wrapped_grpc_server_credentials, std); - server_credentials_ce_handlers.free_obj = - free_wrapped_grpc_server_credentials; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_server_credentials, + server_credentials_ce_handlers); } diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h index d37fafc0dc..6781a614b1 100755 --- a/src/php/ext/grpc/server_credentials.h +++ b/src/php/ext/grpc/server_credentials.h @@ -49,31 +49,27 @@ /* Class entry for the Server_Credentials PHP class */ extern zend_class_entry *grpc_ce_server_credentials; -#if PHP_MAJOR_VERSION < 7 - /* Wrapper struct for grpc_server_credentials that can be associated with a PHP * object */ -typedef struct wrapped_grpc_server_credentials { - zend_object std; +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_server_credentials) grpc_server_credentials *wrapped; -} wrapped_grpc_server_credentials; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_server_credentials) -#else +#if PHP_MAJOR_VERSION < 7 -typedef struct wrapped_grpc_server_credentials { - grpc_server_credentials *wrapped; - zend_object std; -} wrapped_grpc_server_credentials; +#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ + (wrapped_grpc_server_credentials *)zend_object_store_get_object(zv TSRMLS_CC) + +#else static inline wrapped_grpc_server_credentials -*wrapped_grpc_server_creds_from_obj(zend_object *obj) { - return (wrapped_grpc_server_credentials*) - ((char*)(obj) - - XtOffsetOf(wrapped_grpc_server_credentials, std)); +*wrapped_grpc_server_credentials_from_obj(zend_object *obj) { + return (wrapped_grpc_server_credentials*)( + (char*)(obj) - XtOffsetOf(wrapped_grpc_server_credentials, std)); } -#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ - wrapped_grpc_server_creds_from_obj(Z_OBJ_P((zv))) +#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ + wrapped_grpc_server_credentials_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 8dc997c2dd..e145d96772 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -51,87 +51,40 @@ #include <grpc/support/time.h> zend_class_entry *grpc_ce_timeval; - -#if PHP_MAJOR_VERSION < 7 +#if PHP_MAJOR_VERSION >= 7 +static zend_object_handlers timeval_ce_handlers; +#endif /* Frees and destroys an instance of wrapped_grpc_call */ -void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { - wrapped_grpc_timeval *timeval = (wrapped_grpc_timeval *)object; - zend_object_std_dtor(&timeval->std TSRMLS_CC); - efree(timeval); -} +PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval) +PHP_GRPC_FREE_WRAPPED_FUNC_END() /* Initializes an instance of wrapped_grpc_timeval to be associated with an * object of a class specified by class_type */ -zend_object_value create_wrapped_grpc_timeval(zend_class_entry *class_type - TSRMLS_DC) { - zend_object_value retval; - wrapped_grpc_timeval *intern; - intern = (wrapped_grpc_timeval *)emalloc(sizeof(wrapped_grpc_timeval)); - memset(intern, 0, sizeof(wrapped_grpc_timeval)); +php_grpc_zend_object create_wrapped_grpc_timeval(zend_class_entry *class_type + TSRMLS_DC) { + PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_timeval); zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - retval.handle = zend_objects_store_put( - intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, - free_wrapped_grpc_timeval, NULL TSRMLS_CC); - retval.handlers = zend_get_std_object_handlers(); - return retval; + PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_timeval, timeval_ce_handlers); } zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) { zval *timeval_object; - MAKE_STD_ZVAL(timeval_object); - object_init_ex(timeval_object, grpc_ce_timeval); - wrapped_grpc_timeval *timeval = - (wrapped_grpc_timeval *)zend_object_store_get_object( - timeval_object TSRMLS_CC); - memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec)); - return timeval_object; -} - -#else - -static zend_object_handlers timeval_ce_handlers; - -/* Frees and destroys an instance of wrapped_grpc_call */ -static void free_wrapped_grpc_timeval(zend_object *object) { - wrapped_grpc_timeval *timeval = wrapped_grpc_timeval_from_obj(object); - zend_object_std_dtor(&timeval->std); -} - -/* Initializes an instance of wrapped_grpc_timeval to be associated with an - * object of a class specified by class_type */ -zend_object *create_wrapped_grpc_timeval(zend_class_entry *class_type) { - wrapped_grpc_timeval *intern; - intern = ecalloc(1, sizeof(wrapped_grpc_timeval) + - zend_object_properties_size(class_type)); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &timeval_ce_handlers; - return &intern->std; -} - -void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object) { + PHP_GRPC_MAKE_STD_ZVAL(timeval_object); object_init_ex(timeval_object, grpc_ce_timeval); wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object); memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec)); + return timeval_object; } -#endif - /** * Constructs a new instance of the Timeval class * @param long $usec The number of microseconds in the interval */ PHP_METHOD(Timeval, __construct) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *timeval = - (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); - long microseconds; -#else wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); - zend_long microseconds; -#endif + php_grpc_long microseconds; /* "l" == 1 long */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", µseconds) == @@ -160,23 +113,14 @@ PHP_METHOD(Timeval, add) { "add expects a Timeval", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *self = - (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); - wrapped_grpc_timeval *other = - (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); - zval *sum = + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + zval *sum; + PHP_GRPC_MAKE_STD_ZVAL(sum); + sum = grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); -#else - wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); - wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - - grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped), - return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -195,22 +139,14 @@ PHP_METHOD(Timeval, subtract) { "subtract expects a Timeval", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *self = - (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); - wrapped_grpc_timeval *other = - (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); - zval *diff = + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + zval *diff; + PHP_GRPC_MAKE_STD_ZVAL(diff); + diff = grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); -#else - wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); - wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped), - return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -232,15 +168,8 @@ PHP_METHOD(Timeval, compare) { "compare expects two Timevals", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *a = - (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); - wrapped_grpc_timeval *b = - (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC); -#else wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); -#endif long result = gpr_time_cmp(a->wrapped, b->wrapped); RETURN_LONG(result); } @@ -265,19 +194,9 @@ PHP_METHOD(Timeval, similar) { "compare expects three Timevals", 1 TSRMLS_CC); return; } -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *a = - (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); - wrapped_grpc_timeval *b = - (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC); - wrapped_grpc_timeval *thresh = - (wrapped_grpc_timeval *)zend_object_store_get_object( - thresh_obj TSRMLS_CC); -#else wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj); -#endif int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped); RETURN_BOOL(result); } @@ -287,13 +206,10 @@ PHP_METHOD(Timeval, similar) { * @return Timeval The current time */ PHP_METHOD(Timeval, now) { -#if PHP_MAJOR_VERSION < 7 - zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *now; + PHP_GRPC_MAKE_STD_ZVAL(now); + now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); -#else - grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME), return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -301,18 +217,13 @@ PHP_METHOD(Timeval, now) { * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { -#if PHP_MAJOR_VERSION < 7 - zval *grpc_php_timeval_zero = + zval *grpc_php_timeval_zero; + PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_zero); + grpc_php_timeval_zero = grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_ZVAL(grpc_php_timeval_zero, false, /* Copy original before returning? */ true /* Destroy original before returning */); -#else - grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME), return_value); - RETURN_ZVAL(return_value, - false, /* Copy original before returning? */ - true /* Destroy original before returning */); -#endif } /** @@ -320,14 +231,11 @@ PHP_METHOD(Timeval, zero) { * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { -#if PHP_MAJOR_VERSION < 7 - zval *grpc_php_timeval_inf_future = + zval *grpc_php_timeval_inf_future; + PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_future); + grpc_php_timeval_inf_future = grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); -#else - grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME), return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -335,14 +243,11 @@ PHP_METHOD(Timeval, infFuture) { * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { -#if PHP_MAJOR_VERSION < 7 - zval *grpc_php_timeval_inf_past = + zval *grpc_php_timeval_inf_past; + PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_past); + grpc_php_timeval_inf_past = grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); -#else - grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME), return_value); - RETURN_DESTROY_ZVAL(return_value); -#endif } /** @@ -350,12 +255,7 @@ PHP_METHOD(Timeval, infPast) { * @return void */ PHP_METHOD(Timeval, sleepUntil) { -#if PHP_MAJOR_VERSION < 7 - wrapped_grpc_timeval *this = - (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); -#else wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); -#endif gpr_sleep_until(this->wrapped); } @@ -378,13 +278,7 @@ void grpc_init_timeval(TSRMLS_D) { INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods); ce.create_object = create_wrapped_grpc_timeval; grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC); -#if PHP_MAJOR_VERSION >= 7 - memcpy(&timeval_ce_handlers, zend_get_std_object_handlers(), - sizeof(zend_object_handlers)); - timeval_ce_handlers.offset = - XtOffsetOf(wrapped_grpc_timeval, std); - timeval_ce_handlers.free_obj = free_wrapped_grpc_timeval; -#endif + PHP_GRPC_INIT_HANDLER(wrapped_grpc_timeval, timeval_ce_handlers); } void grpc_shutdown_timeval(TSRMLS_D) {} diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h index d4eb2facde..63a1d702f3 100755 --- a/src/php/ext/grpc/timeval.h +++ b/src/php/ext/grpc/timeval.h @@ -50,27 +50,24 @@ extern zend_class_entry *grpc_ce_timeval; /* Wrapper struct for timeval that can be associated with a PHP object */ +PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_timeval) + gpr_timespec wrapped; +PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_timeval) + #if PHP_MAJOR_VERSION < 7 -typedef struct wrapped_grpc_timeval { - zend_object std; - gpr_timespec wrapped; -} wrapped_grpc_timeval; +#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ + (wrapped_grpc_timeval *)zend_object_store_get_object(zv TSRMLS_CC) #else -typedef struct wrapped_grpc_timeval { - gpr_timespec wrapped; - zend_object std; -} wrapped_grpc_timeval; - static inline wrapped_grpc_timeval *wrapped_grpc_timeval_from_obj(zend_object *obj) { return (wrapped_grpc_timeval*)((char*)(obj) - XtOffsetOf(wrapped_grpc_timeval, std)); } -#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ +#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv))) #endif /* PHP_MAJOR_VERSION */ @@ -82,10 +79,6 @@ void grpc_init_timeval(TSRMLS_D); void grpc_shutdown_timeval(TSRMLS_D); /* Creates a Timeval object that wraps the given timeval struct */ -#if PHP_MAJOR_VERSION < 7 zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC); -#else -void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object); -#endif /* PHP_MAJOR_VERSION */ #endif /* NET_GRPC_PHP_GRPC_TIMEVAL_H_ */ diff --git a/src/proto/census/census.proto b/src/proto/census/census.proto index c869d851ff..c2a594b641 100644 --- a/src/proto/census/census.proto +++ b/src/proto/census/census.proto @@ -33,12 +33,12 @@ package google.census; // All the census protos. // -// Nomenclature note: capitalized names below (like Metric) are protos. +// Nomenclature note: capitalized names below (like Resource) are protos. // -// Census lets you define a Metric - something which can be measured, like the +// Census lets you define a Resource - something which can be measured, like the // latency of an RPC, the number of CPU cycles spent on an operation, or // anything else you care to measure. You can record individual instances of -// measurements (a double value) for every metric of interest. These +// measurements (a double value) for every Resource of interest. These // individual measurements are aggregated together into an Aggregation. There // are two Aggregation types available: Distribution (describes the // distribution of all measurements, possibly with a histogram) and @@ -47,8 +47,8 @@ package google.census; // // You can define how your stats are broken down by Tag values and which // Aggregations to use through a View. The corresponding combination of -// Metric/View/Aggregation which is available to census clients is called a -// ViewAggregation. +// Resource/View/Aggregation which is available to census clients is called a +// Metric. // The following two types are copied from @@ -85,26 +85,23 @@ message Timestamp { int32 nanos = 2; } -// Describes a metric -message Metric { - // name of metric, e.g. rpc_latency, cpu. +// Describes a Resource. +message Resource { + // name of resource, e.g. rpc_latency, cpu. Must be unique. string name = 1; - // More detailed description of the metric, used in documentation. + // More detailed description of the resource, used in documentation. string description = 2; // Fundamental units of measurement supported by Census // TODO(aveitch): expand this to include other S.I. units? - message BasicUnit { - enum Measure { - UNKNOWN = 0; - BITS = 1; - BYTES = 2; - SECS = 3; - CORES = 4; - MAX_UNITS = 5; - } - Measure type = 1; + enum BasicUnit { + UNKNOWN = 0; + BITS = 1; + BYTES = 2; + SECS = 3; + CORES = 4; + MAX_UNITS = 5; } // MeasurementUnit lets you build compound units of the form @@ -124,7 +121,7 @@ message Metric { // denominator: SECS // denominator: SECS // - // To specify multiples (in power of 10) units, specify a non-zero prefix + // To specify multiples (in power of 10) of units, specify a non-zero prefix // value, for example: // // - MB/s (i.e. megabytes / s): @@ -141,32 +138,40 @@ message Metric { repeated BasicUnit denominator = 3; } - // The units in which the Metric value is reported. + // The units in which Resource values are measured. MeasurementUnit unit = 3; - - // Metrics will be assigned an ID when registered. Invalid if <= 0. - int32 id = 4; } -// An Aggregation summarizes a series of individual Metric measurements, an +// An Aggregation summarizes a series of individual Resource measurements, an // AggregationDescriptor describes an Aggregation. message AggregationDescriptor { - // At most one set of options. If neither option is set, a default type - // of Distribution (without a histogram component) will be used. + enum AggregationType { + // Unspecified. Should not be used. + UNKNOWN = 0; + // A count of measurements made. + COUNT = 1; + // A Distribution. + DISTRIBUTION = 2; + // Counts over fixed time intervals. + INTERVAL = 3; + } + // The type of Aggregation. + AggregationType type = 1; + + // At most one set of options. It is illegal to specifiy an option for + // COUNT Aggregations. interval_boundaries must be set for INTERVAL types. + // bucket_boundaries are optional for DISTRIBUTION types. oneof options { - // Defines the histogram bucket boundaries for Distributions. - BucketBoundaries bucket_boundaries = 1; + // Defines histogram bucket boundaries for Distributions. + BucketBoundaries bucket_boundaries = 2; // Defines the time windows to record for IntervalStats. - IntervalBoundaries interval_boundaries = 2; + IntervalBoundaries interval_boundaries = 3; } // A Distribution may optionally contain a histogram of the values in the - // population. The bucket boundaries for that histogram is described by - // `bucket_boundaries`. - // - // Describes histogram bucket boundaries. Defines `size(bounds) + 1` (= N) - // buckets (for size(bounds) >= 1; if size(bounds) == 0, then no histogram - // will be defined. The boundaries for bucket index i are: + // population. The bucket boundaries for that histogram are described by + // `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The + // boundaries for bucket index i are: // // [-infinity, bounds[i]) for i == 0 // [bounds[i-1], bounds[i]) for 0 < i < N-2 @@ -196,8 +201,8 @@ message AggregationDescriptor { // a specified set of histogram buckets, as defined in // Aggregation.bucket_options. // -// The summary statistics are the count, mean, sum of the squared deviation from -// the mean, the minimum, and the maximum of the set of population of values. +// The summary statistics are the count, mean, minimum, and the maximum of the +// set of population of values. // // Although it is not forbidden, it is generally a bad idea to include // non-finite values (infinities or NaNs) in the population of values, as this @@ -243,7 +248,7 @@ message Distribution { message IntervalStats { // Summary statistic over a single time window. message Window { - // The window duration. + // The window duration. Must be positive. Duration window_size = 1; // The number of measurements in this window. int64 count = 2; @@ -251,7 +256,7 @@ message IntervalStats { double mean = 3; } - // Full set of windows for this metric. + // Full set of windows for this aggregation. repeated Window window = 1; } @@ -264,24 +269,24 @@ message Tag { // A View specifies an Aggregation and a set of tag keys. The Aggregation will // be broken down by the unique set of matching tag values for each measurement. message View { - // Name of view. + // Name of view. Must be unique. string name = 1; // More detailed description, for documentation purposes. string description = 2; - // ID of Metric to associate with this View. - int32 metric_id = 3; + // Name of Resource to be broken down for this view. + string resource_name = 3; // Aggregation type to associate with this View. AggregationDescriptor aggregation = 4; - // Tag keys to match with a given Metric. If no keys are specified, then all - // stats for the Metric are recorded. Keys must be unique. + // Tag keys to match with a given Resource measurement. If no keys are + // specified, then all stats are recorded. Keys must be unique. repeated string tag_key = 5; } -// An Aggregation summarizes a series of individual Metric measures. +// An Aggregation summarizes a series of individual Resource measurements. message Aggregation { // Name of this aggregation. string name = 1; @@ -291,23 +296,27 @@ message Aggregation { // The data for this Aggregation. oneof data { - Distribution distribution = 3; - IntervalStats interval_stats = 4; + uint64 count = 3; + Distribution distribution = 4; + IntervalStats interval_stats = 5; } // Tags associated with this Aggregation. - repeated Tag tag = 5; + repeated Tag tag = 6; } -// A ViewAggregations represents all the Aggregations for a particular view. -message ViewAggregations { +// A Metric represents all the Aggregations for a particular view. +message Metric { + // View associated with this Metric. + string view_name = 1; + // Aggregations - each will have a unique set of tag values for the tag_keys // associated with the corresponding View. - repeated Aggregation aggregation = 1; + repeated Aggregation aggregation = 2; - // Start and end timestamps over which the value was accumulated. These + // Start and end timestamps over which the metric was accumulated. These // values are not relevant/defined for IntervalStats aggregations, which are // always accumulated over a fixed time period. - Timestamp start = 2; - Timestamp end = 3; + Timestamp start = 3; + Timestamp end = 4; } diff --git a/src/python/grpcio/.gitignore b/src/python/grpcio/.gitignore index 7cd8fab273..3309795948 100644 --- a/src/python/grpcio/.gitignore +++ b/src/python/grpcio/.gitignore @@ -14,3 +14,4 @@ doc/ _grpcio_metadata.py htmlcov/ grpc/_cython/_credentials +poison.c diff --git a/src/python/grpcio/_unixccompiler_patch.py b/src/python/grpcio/_unixccompiler_patch.py index 0ce5d63e98..894c3ef395 100644 --- a/src/python/grpcio/_unixccompiler_patch.py +++ b/src/python/grpcio/_unixccompiler_patch.py @@ -34,6 +34,7 @@ from distutils import errors from distutils import unixccompiler import os import os.path +import shlex import shutil import sys import tempfile @@ -47,6 +48,9 @@ def _unix_commandfile_spawn(self, command): Some commands like `gcc` (and friends like `clang`) support command files to work around shell command length limits. """ + # Sometimes distutils embeds the executables as full strings including some + # hard-coded flags rather than as lists. + command = list(shlex.split(command[0])) + list(command[1:]) command_base = os.path.basename(command[0].strip()) if command_base == 'ccache': command_base = command[:2] diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index 86a73fa836..d36ac23305 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -184,6 +184,71 @@ class BuildPy(build_py.build_py): build_py.build_py.run(self) +def _poison_extensions(extensions, message): + """Includes a file that will always fail to compile in all extensions.""" + poison_filename = os.path.join(PYTHON_STEM, 'poison.c') + with open(poison_filename, 'w') as poison: + poison.write('#error {}'.format(message)) + for extension in extensions: + extension.sources = [poison_filename] + +def check_and_update_cythonization(extensions): + """Replace .pyx files with their generated counterparts and return whether or + not cythonization still needs to occur.""" + for extension in extensions: + generated_pyx_sources = [] + other_sources = [] + for source in extension.sources: + base, file_ext = os.path.splitext(source) + if file_ext == '.pyx': + generated_pyx_source = next( + (base + gen_ext for gen_ext in ('.c', '.cpp',) + if os.path.isfile(base + gen_ext)), None) + if generated_pyx_source: + generated_pyx_sources.append(generated_pyx_source) + else: + sys.stderr.write('Cython-generated files are missing...\n') + return False + else: + other_sources.append(source) + extension.sources = generated_pyx_sources + other_sources + sys.stderr.write('Found cython-generated files...\n') + return True + +def try_cythonize(extensions, linetracing=False, mandatory=True): + """Attempt to cythonize the extensions. + + Args: + extensions: A list of `distutils.extension.Extension`. + linetracing: A bool indicating whether or not to enable linetracing. + mandatory: Whether or not having Cython-generated files is mandatory. If it + is, extensions will be poisoned when they can't be fully generated. + """ + try: + # Break import style to ensure we have access to Cython post-setup_requires + import Cython.Build + except ImportError: + if mandatory: + sys.stderr.write( + "This package needs to generate C files with Cython but it cannot. " + "Poisoning extension sources to disallow extension commands...") + _poison_extensions( + extensions, + "Extensions have been poisoned due to missing Cython-generated code.") + return extensions + cython_compiler_directives = {} + if linetracing: + additional_define_macros = [('CYTHON_TRACE_NOGIL', '1')] + cython_compiler_directives['linetrace'] = True + return Cython.Build.cythonize( + extensions, + include_path=[ + include_dir for extension in extensions for include_dir in extension.include_dirs + ], + compiler_directives=cython_compiler_directives + ) + + class BuildExt(build_ext.build_ext): """Custom build_ext command to enable compiler-specific flags.""" @@ -201,6 +266,8 @@ class BuildExt(build_ext.build_ext): if compiler in BuildExt.LINK_OPTIONS: for extension in self.extensions: extension.extra_link_args += list(BuildExt.LINK_OPTIONS[compiler]) + if not check_and_update_cythonization(self.extensions): + self.extensions = try_cythonize(self.extensions) try: build_ext.build_ext.build_extensions(self) except Exception as error: diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index fd015129f0..513839df7d 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -345,7 +345,7 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): This method blocks until the value is available. Returns: - The bytes of the details of the RPC. + The details string of the RPC. """ raise NotImplementedError() @@ -764,7 +764,7 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): details to transmit. Args: - details: The details bytes of the RPC to be transmitted to + details: The details string of the RPC to be transmitted to the invocation side of the RPC. """ raise NotImplementedError() diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index 29dbc3a668..3117dd1cb3 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -353,12 +353,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): else: return max(self._deadline - time.time(), 0) - def add_cancellation_callback(self, callback): + def add_callback(self, callback): with self._state.condition: if self._state.callbacks is None: return False else: - self._state.callbacks.append(lambda unused_future: callback()) + self._state.callbacks.append(lambda: callback()) return True def initial_metadata(self): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 7714504d1b..42fced6545 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -30,19 +30,29 @@ cimport libc.time -cdef extern from "grpc/_cython/loader.h": +# Typedef types with approximately the same semantics to provide their names to +# Cython +ctypedef int int32_t +ctypedef unsigned uint32_t +ctypedef long int64_t - ctypedef int int32_t - ctypedef unsigned uint32_t - ctypedef long int64_t - int pygrpc_load_core(char*) - int pygrpc_initialize_core() +cdef extern from "grpc/support/alloc.h": void *gpr_malloc(size_t size) nogil void gpr_free(void *ptr) nogil void *gpr_realloc(void *p, size_t size) nogil + +cdef extern from "grpc/byte_buffer_reader.h": + + struct grpc_byte_buffer_reader: + # We don't care about the internals + pass + + +cdef extern from "grpc/grpc.h": + ctypedef struct gpr_slice: # don't worry about writing out the members of gpr_slice; we never access # them directly. @@ -86,7 +96,22 @@ cdef extern from "grpc/_cython/loader.h": gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) nogil int gpr_time_cmp(gpr_timespec a, gpr_timespec b) nogil - + + ctypedef struct grpc_byte_buffer: + # We don't care about the internals. + pass + + grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, + size_t nslices) nogil + size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil + void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil + + int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, + grpc_byte_buffer *buffer) nogil + int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, + gpr_slice *slice) nogil + void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil + ctypedef enum grpc_status_code: GRPC_STATUS_OK GRPC_STATUS_CANCELLED @@ -107,37 +132,6 @@ cdef extern from "grpc/_cython/loader.h": GRPC_STATUS_DATA_LOSS GRPC_STATUS__DO_NOT_USE - ctypedef enum grpc_ssl_roots_override_result: - GRPC_SSL_ROOTS_OVERRIDE_OK - GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY - GRPC_SSL_ROOTS_OVERRIDE_FAILED - - ctypedef enum grpc_ssl_client_certificate_request_type: - GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, - GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY - GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY - GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY - GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - - struct grpc_byte_buffer_reader: - # We don't care about the internals - pass - - ctypedef struct grpc_byte_buffer: - # We don't care about the internals. - pass - - grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, - size_t nslices) nogil - size_t grpc_byte_buffer_length(grpc_byte_buffer *bb) nogil - void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer) nogil - - int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, - grpc_byte_buffer *buffer) nogil - int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, - gpr_slice *slice) nogil - void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) nogil - const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING const char *GRPC_ARG_ENABLE_CENSUS const char *GRPC_ARG_MAX_CONCURRENT_STREAMS @@ -353,6 +347,21 @@ cdef extern from "grpc/_cython/loader.h": void grpc_server_cancel_all_calls(grpc_server *server) nogil void grpc_server_destroy(grpc_server *server) nogil + +cdef extern from "grpc/grpc_security.h": + + ctypedef enum grpc_ssl_roots_override_result: + GRPC_SSL_ROOTS_OVERRIDE_OK + GRPC_SSL_ROOTS_OVERRIDE_FAILED_PERMANENTLY + GRPC_SSL_ROOTS_OVERRIDE_FAILED + + ctypedef enum grpc_ssl_client_certificate_request_type: + GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, + GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY + GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY + GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY + ctypedef struct grpc_ssl_pem_key_cert_pair: const char *private_key const char *certificate_chain "cert_chain" @@ -438,6 +447,9 @@ cdef extern from "grpc/_cython/loader.h": grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) nogil + +cdef extern from "grpc/compression.h": + ctypedef enum grpc_compression_algorithm: GRPC_COMPRESS_NONE GRPC_COMPRESS_DEFLATE @@ -472,3 +484,4 @@ cdef extern from "grpc/_cython/loader.h": int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options *opts, grpc_compression_algorithm algorithm) nogil + diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx index e055d321bc..a9520b9c0f 100644 --- a/src/python/grpcio/grpc/_cython/cygrpc.pyx +++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx @@ -49,11 +49,18 @@ include "grpc/_cython/_cygrpc/server.pyx.pxi" # -def _initialize(): - if not pygrpc_initialize_core(): - raise ImportError('failed to initialize core gRPC library') +cdef extern from "Python.h": + + int Py_AtExit(void(*func)()) + +def _initialize(): + grpc_init() grpc_set_ssl_roots_override_callback( <grpc_ssl_roots_override_callback>ssl_roots_override_callback) + if Py_AtExit(grpc_shutdown) != 0: + raise ImportError('failed to register gRPC library shutdown callbacks') + + _initialize() diff --git a/src/python/grpcio/grpc/_cython/loader.h b/src/python/grpcio/grpc/_cython/loader.h deleted file mode 100644 index 62fd225204..0000000000 --- a/src/python/grpcio/grpc/_cython/loader.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef PYGRPC_LOADER_H_ -#define PYGRPC_LOADER_H_ - -#include "imports.generated.h" - -/* Additional inclusions not covered by "imports.generated.h" */ -#include <grpc/byte_buffer_reader.h> - -/* TODO(atash) remove cruft */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cpluslus */ - -/* Attempts to load the core if necessary, and return non-zero upon succes. */ -int pygrpc_load_core(char *path); - -/* Initializes grpc and registers grpc_shutdown() to be called right before - * interpreter exit. Returns non-zero upon success. - */ -int pygrpc_initialize_core(void); - -#ifdef __cplusplus -} -#endif /* __cpluslus */ - -#endif /* GRPC_RB_BYTE_BUFFER_H_ */ - diff --git a/src/python/grpcio/grpc/beta/_client_adaptations.py b/src/python/grpcio/grpc/beta/_client_adaptations.py index 73415e0be7..e4ee44d7a3 100644 --- a/src/python/grpcio/grpc/beta/_client_adaptations.py +++ b/src/python/grpcio/grpc/beta/_client_adaptations.py @@ -67,7 +67,7 @@ def _abortion(rpc_error_call): error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0] return face.Abortion( error_kind, rpc_error_call.initial_metadata(), - rpc_error_call.trailing_metadata(), code, rpc_error_code.details()) + rpc_error_call.trailing_metadata(), code, rpc_error_call.details()) def _abortion_error(rpc_error_call): @@ -159,9 +159,11 @@ class _Rendezvous(future.Future, face.Call): return self._call.time_remaining() def add_abortion_callback(self, abortion_callback): - registered = self._call.add_callback( - lambda: abortion_callback(_abortion(self._call))) - return None if registered else _abortion(self._call) + def done_callback(): + if self.code() is not grpc.StatusCode.OK: + abortion_callback(_abortion(self._call)) + registered = self._call.add_callback(done_callback) + return None if registered else done_callback() def protocol_context(self): return _InvocationProtocolContext() diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 5441af4c66..5e59851a08 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -82,6 +82,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', + 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', 'src/core/lib/compression/compression.c', @@ -163,6 +164,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/static_metadata.c', + 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', @@ -185,7 +187,6 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/transport/status_conversion.c', 'src/core/ext/transport/chttp2/transport/stream_lists.c', 'src/core/ext/transport/chttp2/transport/stream_map.c', - 'src/core/ext/transport/chttp2/transport/timeout_encoding.c', 'src/core/ext/transport/chttp2/transport/varint.c', 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', @@ -241,6 +242,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', + 'src/core/ext/lb_policy/grpclb/grpclb.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -252,6 +254,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/resolver/sockaddr/sockaddr_resolver.c', 'src/core/ext/load_reporting/load_reporting.c', 'src/core/ext/load_reporting/load_reporting_filter.c', + 'src/core/ext/census/base_resources.c', 'src/core/ext/census/context.c', 'src/core/ext/census/gen/census.pb.c', 'src/core/ext/census/grpc_context.c', @@ -261,6 +264,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/census/mlog.c', 'src/core/ext/census/operation.c', 'src/core/ext/census/placeholders.c', + 'src/core/ext/census/resource.c', 'src/core/ext/census/tracing.c', 'src/core/plugin_registry/grpc_plugin_registry.c', 'src/boringssl/err_data.c', diff --git a/src/python/grpcio_health_checking/MANIFEST.in b/src/python/grpcio_health_checking/MANIFEST.in index 7d26647697..7407f646d1 100644 --- a/src/python/grpcio_health_checking/MANIFEST.in +++ b/src/python/grpcio_health_checking/MANIFEST.in @@ -1,3 +1,4 @@ +include grpc_version.py include health_commands.py -graft grpc_health +graft grpc global-exclude *.pyc diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc/__init__.py index 7086519106..fcc7048815 100644 --- a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py +++ b/src/python/grpcio_health_checking/grpc/__init__.py @@ -27,4 +27,4 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +__import__('pkg_resources').declare_namespace(__name__) diff --git a/src/python/grpcio_health_checking/grpc_health/__init__.py b/src/python/grpcio_health_checking/grpc/health/__init__.py index 7086519106..7086519106 100644 --- a/src/python/grpcio_health_checking/grpc_health/__init__.py +++ b/src/python/grpcio_health_checking/grpc/health/__init__.py diff --git a/src/python/grpcio_health_checking/grpc_health/health/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py index 7086519106..7086519106 100644 --- a/src/python/grpcio_health_checking/grpc_health/health/__init__.py +++ b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py index 8da60c70cb..8108ac1096 100644 --- a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc/health/v1/health.py @@ -31,10 +31,12 @@ import threading -from grpc_health.health.v1 import health_pb2 +import grpc +from grpc.health.v1 import health_pb2 -class HealthServicer(health_pb2.BetaHealthServicer): + +class HealthServicer(health_pb2.HealthServicer): """Servicer handling RPCs for service statuses.""" def __init__(self): @@ -43,14 +45,12 @@ class HealthServicer(health_pb2.BetaHealthServicer): def Check(self, request, context): with self._server_status_lock: - if request.service not in self._server_status: - # TODO(atash): once the Python API has a way of setting the server - # status, bring us into conformance with the health check spec by - # returning the NOT_FOUND status here. - raise NotImplementedError() + status = self._server_status.get(request.service) + if status is None: + context.set_code(grpc.StatusCode.NOT_FOUND) + return health_pb2.HealthCheckResponse() else: - return health_pb2.HealthCheckResponse( - status=self._server_status[request.service]) + return health_pb2.HealthCheckResponse(status=status) def set(self, service, status): """Sets the status of a service. @@ -63,4 +63,3 @@ class HealthServicer(health_pb2.BetaHealthServicer): """ with self._server_status_lock: self._server_status[service] = status - diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc.rb b/src/python/grpcio_health_checking/grpc_version.py index 3a2a5b8dc9..be0d0ced3c 100755..100644 --- a/src/ruby/tools/bin/grpc_tools_ruby_protoc.rb +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby # Copyright 2016, Google Inc. # All rights reserved. # @@ -28,14 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require 'rbconfig' +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -require_relative '../os_check' - -protoc_name = 'protoc' + RbConfig::CONFIG['EXEEXT'] - -protoc_path = File.join(File.dirname(__FILE__), - RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name, - protoc_name) - -exec([ protoc_path, protoc_path ], *ARGV) +VERSION='1.1.0.dev0' diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py index a7a59f6974..66df25da63 100644 --- a/src/python/grpcio_health_checking/health_commands.py +++ b/src/python/grpcio_health_checking/health_commands.py @@ -29,16 +29,10 @@ """Provides distutils command classes for the GRPC Python setup process.""" -import distutils -import glob import os -import os.path import shutil -import subprocess -import sys import setuptools -from setuptools.command import build_py ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') @@ -60,12 +54,25 @@ class CopyProtoModules(setuptools.Command): if os.path.isfile(HEALTH_PROTO): shutil.copyfile( HEALTH_PROTO, - os.path.join(ROOT_DIR, 'grpc_health/health/v1/health.proto')) + os.path.join(ROOT_DIR, 'grpc/health/v1/health.proto')) -class BuildPy(build_py.build_py): - """Custom project build command.""" +class BuildPackageProtos(setuptools.Command): + """Command to generate project *_pb2.py modules from proto files.""" + + description = 'build grpc protobuf modules' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass def run(self): - self.run_command('build_proto_modules') - build_py.build_py.run(self) + # due to limitations of the proto generator, we require that only *one* + # directory is provided as an 'include' directory. We assume it's the '' key + # to `self.distribution.package_dir` (and get a key error if it's not + # there). + from grpc.tools import command + command.build_package_protos(self.distribution.package_dir['']) diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 70b4575bf5..727d628885 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -30,49 +30,42 @@ """Setup module for the GRPC Python package's optional health checking.""" import os -import os.path import sys -from distutils import core as _core import setuptools -import grpc.tools.command - # Ensure we're in the proper directory whether or not we're being used by pip. os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our commands module. import health_commands - -PACKAGES = ( - setuptools.find_packages('.') -) +import grpc_version PACKAGE_DIRECTORIES = { '': '.', } SETUP_REQUIRES = ( - 'grpcio-tools>=0.14.0', + 'grpcio-tools>=0.15.0', ) INSTALL_REQUIRES = ( - 'grpcio>=0.13.1', + 'grpcio>=0.15.0', ) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! 'preprocess': health_commands.CopyProtoModules, - - 'build_proto_modules': grpc.tools.command.BuildProtoModules, - 'build_py': health_commands.BuildPy, + 'build_package_protos': health_commands.BuildPackageProtos, } setuptools.setup( name='grpcio-health-checking', - version='0.14.0', - packages=list(PACKAGES), + version=grpc_version.VERSION, + license='3-clause BSD', package_dir=PACKAGE_DIRECTORIES, + packages=setuptools.find_packages('.'), + namespace_packages=['grpc'], install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, cmdclass=COMMAND_CLASS diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index 171829b62f..5ee551cfe1 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -138,7 +138,7 @@ class BuildPy(build_py.build_py): def run(self): try: - self.run_command('build_proto_modules') + self.run_command('build_package_protos') except CommandError as error: sys.stderr.write('warning: %s\n' % error.message) build_py.build_py.run(self) diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index 7eef420bdb..0afaf7dfa2 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -75,7 +75,7 @@ COMMAND_CLASS = { # Run `preprocess` *before* doing any packaging! 'preprocess': commands.GatherProto, - 'build_proto_modules': grpc.tools.command.BuildProtoModules, + 'build_package_protos': grpc.tools.command.BuildPackageProtos, 'build_py': commands.BuildPy, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index 1b63388663..80300d13df 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -27,48 +27,68 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Tests of grpc_health.health.v1.health.""" +"""Tests of grpc.health.v1.health.""" import unittest -from grpc_health.health.v1 import health -from grpc_health.health.v1 import health_pb2 +import grpc +from grpc.framework.foundation import logging_pool +from grpc.health.v1 import health +from grpc.health.v1 import health_pb2 + +from tests.unit.framework.common import test_constants class HealthServicerTest(unittest.TestCase): def setUp(self): - self.servicer = health.HealthServicer() - self.servicer.set('', health_pb2.HealthCheckResponse.SERVING) - self.servicer.set('grpc.test.TestServiceServing', - health_pb2.HealthCheckResponse.SERVING) - self.servicer.set('grpc.test.TestServiceUnknown', - health_pb2.HealthCheckResponse.UNKNOWN) - self.servicer.set('grpc.test.TestServiceNotServing', - health_pb2.HealthCheckResponse.NOT_SERVING) + servicer = health.HealthServicer() + servicer.set('', health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceServing', + health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceUnknown', + health_pb2.HealthCheckResponse.UNKNOWN) + servicer.set('grpc.test.TestServiceNotServing', + health_pb2.HealthCheckResponse.NOT_SERVING) + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server(server_pool) + port = self._server.add_insecure_port('[::]:0') + health_pb2.add_HealthServicer_to_server(servicer, self._server) + self._server.start() + + channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = health_pb2.HealthStub(channel) def test_empty_service(self): request = health_pb2.HealthCheckRequest() - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceServing') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) def test_unknown_serivce(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceUnknown') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.UNKNOWN) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) def test_not_serving_service(self): request = health_pb2.HealthCheckRequest( service='grpc.test.TestServiceNotServing') - resp = self.servicer.Check(request, None) - self.assertEqual(resp.status, health_pb2.HealthCheckResponse.NOT_SERVING) + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status) + + def test_not_found_service(self): + request = health_pb2.HealthCheckRequest( + service='not-found') + with self.assertRaises(grpc.RpcError) as context: + resp = self._stub.Check(request) + + self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py index d32208f9eb..df620b19ba 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py @@ -434,11 +434,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. for test_messages in test_messages_sequence: request = test_messages.request() callback = _Callback() + abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( request, _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the @@ -450,6 +452,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) def testFailedUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -472,11 +475,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. for test_messages in test_messages_sequence: requests = test_messages.requests() callback = _Callback() + abortion_callback = _Callback() with self._control.fail(): response_future = self._invoker.future(group, method)( iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) self.assertIs(callback.future(), response_future) # Because the servicer fails outside of the thread from which the @@ -488,6 +493,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. with self.assertRaises(face.ExpirationError): response_future.result() self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) def testFailedStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( diff --git a/src/ruby/.rubocop.yml b/src/ruby/.rubocop.yml index 34bb477543..0f61ccfa81 100644 --- a/src/ruby/.rubocop.yml +++ b/src/ruby/.rubocop.yml @@ -5,8 +5,8 @@ inherit_from: .rubocop_todo.yml AllCops: Exclude: - 'bin/apis/**/*' - - 'bin/math.rb' - - 'bin/math_services.rb' + - 'bin/math_pb.rb' + - 'bin/math_services_pb.rb' - 'pb/grpc/health/v1/*' - 'pb/test/**/*' diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index d7e00e4293..1f238a798b 100755 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -40,7 +40,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir) $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' -require 'math_services' +require 'math_services_pb' require 'optparse' include GRPC::Core::TimeConsts diff --git a/src/ruby/bin/math.rb b/src/ruby/bin/math_pb.rb index 60429a1505..60429a1505 100755..100644 --- a/src/ruby/bin/math.rb +++ b/src/ruby/bin/math_pb.rb diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index 1ee4c5632d..751a6ebcab 100755 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -42,7 +42,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'forwardable' require 'grpc' require 'logger' -require 'math_services' +require 'math_services_pb' require 'optparse' # RubyLogger defines a logger for gRPC based on the standard ruby logger. diff --git a/src/ruby/bin/math_services.rb b/src/ruby/bin/math_services_pb.rb index 2b97602b6f..2ba1825d4f 100755..100644 --- a/src/ruby/bin/math_services.rb +++ b/src/ruby/bin/math_services_pb.rb @@ -32,7 +32,7 @@ # require 'grpc' -require 'math' +require 'math_pb' module Math module Math diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 18a15d0125..e6d30a174b 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -40,6 +40,7 @@ #include <grpc/grpc_security.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/time.h> #include "rb_grpc.h" #include "rb_call.h" #include "rb_channel_args.h" @@ -71,6 +72,7 @@ typedef struct grpc_rb_channel { /* The actual channel */ grpc_channel *wrapped; + grpc_completion_queue *queue; } grpc_rb_channel; /* Destroys Channel instances. */ @@ -83,6 +85,7 @@ static void grpc_rb_channel_free(void *p) { if (ch->wrapped != NULL) { grpc_channel_destroy(ch->wrapped); + grpc_rb_completion_queue_destroy(ch->queue); } xfree(p); @@ -165,6 +168,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { } rb_ivar_set(self, id_target, target); wrapper->wrapped = ch; + wrapper->queue = grpc_completion_queue_create(NULL); return self; } @@ -203,16 +207,18 @@ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, the completion queue with success=0 */ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, - VALUE cqueue, - VALUE deadline, - VALUE tag) { + VALUE deadline) { grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; grpc_completion_queue *cq = NULL; - cq = grpc_rb_get_wrapped_completion_queue(cqueue); + void *tag = wrapper; + + grpc_event event; + TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; + cq = wrapper->queue; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; @@ -222,9 +228,16 @@ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, (grpc_connectivity_state)NUM2LONG(last_state), grpc_rb_time_timeval(deadline, /* absolute time */ 0), cq, - ROBJECT(tag)); + tag); - return Qnil; + event = rb_completion_queue_pluck(cq, tag, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + if (event.success) { + return Qtrue; + } else { + return Qfalse; + } } /* Create a call given a grpc_channel, in order to call method. The request diff --git a/src/ruby/ext/grpc/rb_completion_queue.h b/src/ruby/ext/grpc/rb_completion_queue.h index 9f8f6aa5ff..aa9dc6416a 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.h +++ b/src/ruby/ext/grpc/rb_completion_queue.h @@ -38,9 +38,6 @@ #include <grpc/grpc.h> -/* Gets the wrapped completion queue from the ruby wrapper */ -grpc_completion_queue *grpc_rb_get_wrapped_completion_queue(VALUE v); - void grpc_rb_completion_queue_destroy(grpc_completion_queue *cq); /** diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index d7f862cd9c..aee57b11aa 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -61,15 +61,10 @@ census_trace_print_type census_trace_print_import; census_trace_scan_start_type census_trace_scan_start_import; census_get_trace_record_type census_get_trace_record_import; census_trace_scan_end_type census_trace_scan_end_import; +census_define_resource_type census_define_resource_import; +census_delete_resource_type census_delete_resource_import; +census_resource_id_type census_resource_id_import; census_record_values_type census_record_values_import; -census_view_create_type census_view_create_import; -census_view_delete_type census_view_delete_import; -census_view_metric_type census_view_metric_import; -census_view_naggregations_type census_view_naggregations_import; -census_view_tags_type census_view_tags_import; -census_view_aggregrations_type census_view_aggregrations_import; -census_view_get_data_type census_view_get_data_import; -census_view_reset_type census_view_reset_import; grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import; grpc_compression_algorithm_name_type grpc_compression_algorithm_name_import; grpc_compression_algorithm_for_level_type grpc_compression_algorithm_for_level_import; @@ -334,15 +329,10 @@ void grpc_rb_load_imports(HMODULE library) { census_trace_scan_start_import = (census_trace_scan_start_type) GetProcAddress(library, "census_trace_scan_start"); census_get_trace_record_import = (census_get_trace_record_type) GetProcAddress(library, "census_get_trace_record"); census_trace_scan_end_import = (census_trace_scan_end_type) GetProcAddress(library, "census_trace_scan_end"); + census_define_resource_import = (census_define_resource_type) GetProcAddress(library, "census_define_resource"); + census_delete_resource_import = (census_delete_resource_type) GetProcAddress(library, "census_delete_resource"); + census_resource_id_import = (census_resource_id_type) GetProcAddress(library, "census_resource_id"); census_record_values_import = (census_record_values_type) GetProcAddress(library, "census_record_values"); - census_view_create_import = (census_view_create_type) GetProcAddress(library, "census_view_create"); - census_view_delete_import = (census_view_delete_type) GetProcAddress(library, "census_view_delete"); - census_view_metric_import = (census_view_metric_type) GetProcAddress(library, "census_view_metric"); - census_view_naggregations_import = (census_view_naggregations_type) GetProcAddress(library, "census_view_naggregations"); - census_view_tags_import = (census_view_tags_type) GetProcAddress(library, "census_view_tags"); - census_view_aggregrations_import = (census_view_aggregrations_type) GetProcAddress(library, "census_view_aggregrations"); - census_view_get_data_import = (census_view_get_data_type) GetProcAddress(library, "census_view_get_data"); - census_view_reset_import = (census_view_reset_type) GetProcAddress(library, "census_view_reset"); grpc_compression_algorithm_parse_import = (grpc_compression_algorithm_parse_type) GetProcAddress(library, "grpc_compression_algorithm_parse"); grpc_compression_algorithm_name_import = (grpc_compression_algorithm_name_type) GetProcAddress(library, "grpc_compression_algorithm_name"); grpc_compression_algorithm_for_level_import = (grpc_compression_algorithm_for_level_type) GetProcAddress(library, "grpc_compression_algorithm_for_level"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 14da63780c..3bb76fbb97 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -134,33 +134,18 @@ extern census_get_trace_record_type census_get_trace_record_import; typedef void(*census_trace_scan_end_type)(); extern census_trace_scan_end_type census_trace_scan_end_import; #define census_trace_scan_end census_trace_scan_end_import +typedef int32_t(*census_define_resource_type)(const uint8_t *resource_pb, size_t resource_pb_size); +extern census_define_resource_type census_define_resource_import; +#define census_define_resource census_define_resource_import +typedef void(*census_delete_resource_type)(int32_t resource_id); +extern census_delete_resource_type census_delete_resource_import; +#define census_delete_resource census_delete_resource_import +typedef int32_t(*census_resource_id_type)(const char *name); +extern census_resource_id_type census_resource_id_import; +#define census_resource_id census_resource_id_import typedef void(*census_record_values_type)(census_context *context, census_value *values, size_t nvalues); extern census_record_values_type census_record_values_import; #define census_record_values census_record_values_import -typedef census_view *(*census_view_create_type)(uint32_t metric_id, const census_context *tags, const census_aggregation *aggregations, size_t naggregations); -extern census_view_create_type census_view_create_import; -#define census_view_create census_view_create_import -typedef void(*census_view_delete_type)(census_view *view); -extern census_view_delete_type census_view_delete_import; -#define census_view_delete census_view_delete_import -typedef size_t(*census_view_metric_type)(const census_view *view); -extern census_view_metric_type census_view_metric_import; -#define census_view_metric census_view_metric_import -typedef size_t(*census_view_naggregations_type)(const census_view *view); -extern census_view_naggregations_type census_view_naggregations_import; -#define census_view_naggregations census_view_naggregations_import -typedef const census_context *(*census_view_tags_type)(const census_view *view); -extern census_view_tags_type census_view_tags_import; -#define census_view_tags census_view_tags_import -typedef const census_aggregation *(*census_view_aggregrations_type)(const census_view *view); -extern census_view_aggregrations_type census_view_aggregrations_import; -#define census_view_aggregrations census_view_aggregrations_import -typedef const census_view_data *(*census_view_get_data_type)(const census_view *view); -extern census_view_get_data_type census_view_get_data_import; -#define census_view_get_data census_view_get_data_import -typedef void(*census_view_reset_type)(census_view *view); -extern census_view_reset_type census_view_reset_import; -#define census_view_reset census_view_reset_import typedef int(*grpc_compression_algorithm_parse_type)(const char *name, size_t name_length, grpc_compression_algorithm *algorithm); extern grpc_compression_algorithm_parse_type grpc_compression_algorithm_parse_import; #define grpc_compression_algorithm_parse grpc_compression_algorithm_parse_import diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index 425dc3e519..c2ac3c4daf 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -76,7 +76,7 @@ module GRPC # block that can be invoked with each response. # # @param requests the Enumerable of requests to send - # @op_notifier a Notifier used to signal completion + # @param op_notifier a Notifier used to signal completion # @return an Enumerator of requests to yield def run_on_client(requests, op_notifier, &blk) @op_notifier = op_notifier diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index 9d6bd3bf59..0d7c1f7805 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -34,7 +34,8 @@ require_relative '../version' module GRPC # rubocop:disable Metrics/ParameterLists - # ClientStub represents an endpoint used to send requests to GRPC servers. + # ClientStub represents a client connection to a gRPC server, and can be used + # to send requests. class ClientStub include Core::StatusCodes include Core::TimeConsts @@ -75,8 +76,9 @@ module GRPC # my_stub = ClientStub.new(example.host.com:50505, # :this_channel_is_insecure) # - # Any arbitrary keyword arguments are treated as channel arguments used to - # configure the RPC connection to the host. + # If a channel_override argument is passed, it will be used as the + # underlying channel. Otherwise, the channel_args argument will be used + # to construct a new underlying channel. # # There are some specific keyword args that are not used to configure the # channel: @@ -91,10 +93,17 @@ module GRPC # # @param host [String] the host the stub connects to # @param creds [Core::ChannelCredentials|Symbol] the channel credentials, or - # :this_channel_is_insecure + # :this_channel_is_insecure, which explicitly indicates that the client + # should be created with an insecure connection. Note: this argument is + # ignored if the channel_override argument is provided. # @param channel_override [Core::Channel] a pre-created channel # @param timeout [Number] the default timeout to use in requests - # @param channel_args [Hash] the channel arguments + # @param propagate_mask [Number] A bitwise combination of flags in + # GRPC::Core::PropagateMasks. Indicates how data should be propagated + # from parent server calls to child client calls if this client is being + # used within a gRPC server. + # @param channel_args [Hash] the channel arguments. Note: this argument is + # ignored if the channel_override argument is provided. def initialize(host, creds, channel_override: nil, timeout: nil, @@ -389,11 +398,11 @@ module GRPC # @param marshal [Function] f(obj)->string that marshals requests # @param unmarshal [Function] f(string)->obj that unmarshals responses # @param deadline [Time] (optional) the time the request should complete + # @param return_op [true|false] return an Operation if true # @param parent [Core::Call] a prior call whose reserved metadata # will be propagated by this one. # @param credentials [Core::CallCredentials] credentials to use when making # the call - # @param return_op [true|false] return an Operation if true # @param metadata [Hash] metadata to be sent to the server # @param blk [Block] when provided, is executed for each response # @return [Enumerator|nil|Operation] as discussed above @@ -430,7 +439,8 @@ module GRPC # @param unmarshal [Function] f(string)->obj that unmarshals responses # @param parent [Grpc::Call] a parent call, available when calls are # made from server - # @param timeout [TimeConst] + # @param credentials [Core::CallCredentials] credentials to use when making + # the call def new_active_call(method, marshal, unmarshal, deadline: nil, parent: nil, diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index c92a532a50..7ea2371365 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -172,22 +172,18 @@ module GRPC # The RPC server is configured using keyword arguments. # # There are some specific keyword args used to configure the RpcServer - # instance, however other arbitrary are allowed and when present are used - # to configure the listeninng connection set up by the RpcServer. - # - # * poll_period: when present, the server polls for new events with this - # period + # instance. # # * pool_size: the size of the thread pool the server uses to run its # threads # - # * creds: [GRPC::Core::ServerCredentials] - # the credentials used to secure the server - # # * max_waiting_requests: the maximum number of requests that are not # being handled to allow. When this limit is exceeded, the server responds # with not available to new requests # + # * poll_period: when present, the server polls for new events with this + # period + # # * connect_md_proc: # when non-nil is a proc for determining metadata to to send back the client # on receiving an invocation req. The proc signature is: diff --git a/src/ruby/pb/grpc/health/checker.rb b/src/ruby/pb/grpc/health/checker.rb index f7310d9289..4bce1744c4 100644 --- a/src/ruby/pb/grpc/health/checker.rb +++ b/src/ruby/pb/grpc/health/checker.rb @@ -28,7 +28,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'grpc' -require 'grpc/health/v1/health_services' +require 'grpc/health/v1/health_services_pb' require 'thread' module Grpc diff --git a/src/ruby/pb/grpc/health/v1/health.rb b/src/ruby/pb/grpc/health/v1/health_pb.rb index aa87a93918..aa87a93918 100644 --- a/src/ruby/pb/grpc/health/v1/health.rb +++ b/src/ruby/pb/grpc/health/v1/health_pb.rb diff --git a/src/ruby/pb/grpc/health/v1/health_services.rb b/src/ruby/pb/grpc/health/v1/health_services_pb.rb index 68a3956f54..8cc01e91dc 100644 --- a/src/ruby/pb/grpc/health/v1/health_services.rb +++ b/src/ruby/pb/grpc/health/v1/health_services_pb.rb @@ -32,7 +32,7 @@ # require 'grpc' -require 'grpc/health/v1/health' +require 'grpc/health/v1/health_pb' module Grpc module Health diff --git a/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb index eb523ffa6f..e51c2f087a 100644 --- a/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb +++ b/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb @@ -1,5 +1,5 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! -# Source: grpc/testing/duplicate/echo_duplicate.proto for package 'grpc.testing.duplicate' +# Source: src/proto/grpc/testing/duplicate/echo_duplicate.proto for package 'grpc.testing.duplicate' # Original file comments: # Copyright 2015, Google Inc. # All rights reserved. @@ -34,7 +34,7 @@ # require 'grpc' -require 'grpc/testing/duplicate/echo_duplicate' +require 'src/proto/grpc/testing/duplicate/echo_duplicate_pb' module Grpc module Testing diff --git a/src/ruby/pb/grpc/testing/metrics.rb b/src/ruby/pb/grpc/testing/metrics_pb.rb index 3b3c8cd61b..77b6c90970 100644 --- a/src/ruby/pb/grpc/testing/metrics.rb +++ b/src/ruby/pb/grpc/testing/metrics_pb.rb @@ -1,5 +1,5 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: grpc/testing/metrics.proto +# source: src/proto/grpc/testing/metrics.proto require 'google/protobuf' diff --git a/src/ruby/pb/grpc/testing/metrics_services.rb b/src/ruby/pb/grpc/testing/metrics_services_pb.rb index 467b7b3ee5..e46366b1fb 100644 --- a/src/ruby/pb/grpc/testing/metrics_services.rb +++ b/src/ruby/pb/grpc/testing/metrics_services_pb.rb @@ -1,5 +1,5 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! -# Source: grpc/testing/metrics.proto for package 'grpc.testing' +# Source: src/proto/grpc/testing/metrics.proto for package 'grpc.testing' # Original file comments: # Copyright 2015-2016, Google Inc. # All rights reserved. @@ -38,7 +38,7 @@ # service. require 'grpc' -require 'grpc/testing/metrics' +require 'src/proto/grpc/testing/metrics_pb' module Grpc module Testing diff --git a/src/ruby/pb/src/proto/grpc/testing/empty.rb b/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb index 9c2568d605..9c2568d605 100644 --- a/src/ruby/pb/src/proto/grpc/testing/empty.rb +++ b/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb diff --git a/src/ruby/pb/src/proto/grpc/testing/messages.rb b/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb index e27ccd0dc0..e27ccd0dc0 100644 --- a/src/ruby/pb/src/proto/grpc/testing/messages.rb +++ b/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb diff --git a/src/ruby/pb/src/proto/grpc/testing/test.rb b/src/ruby/pb/src/proto/grpc/testing/test_pb.rb index 245b5ce00c..2cc9863031 100644 --- a/src/ruby/pb/src/proto/grpc/testing/test.rb +++ b/src/ruby/pb/src/proto/grpc/testing/test_pb.rb @@ -3,8 +3,8 @@ require 'google/protobuf' -require 'src/proto/grpc/testing/empty' -require 'src/proto/grpc/testing/messages' +require 'src/proto/grpc/testing/empty_pb' +require 'src/proto/grpc/testing/messages_pb' Google::Protobuf::DescriptorPool.generated_pool.build do end diff --git a/src/ruby/pb/src/proto/grpc/testing/test_services.rb b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb index 2652de5e6d..fde328e4c5 100644 --- a/src/ruby/pb/src/proto/grpc/testing/test_services.rb +++ b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb @@ -35,7 +35,7 @@ # require 'grpc' -require 'src/proto/grpc/testing/test' +require 'src/proto/grpc/testing/test_pb' module Grpc module Testing diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb index 4c6d441dcb..1e3ae65630 100755 --- a/src/ruby/pb/test/client.rb +++ b/src/ruby/pb/test/client.rb @@ -52,9 +52,9 @@ require_relative '../../lib/grpc' require 'googleauth' require 'google/protobuf' -require_relative '../src/proto/grpc/testing/empty' -require_relative '../src/proto/grpc/testing/messages' -require_relative '../src/proto/grpc/testing/test_services' +require_relative '../src/proto/grpc/testing/empty_pb' +require_relative '../src/proto/grpc/testing/messages_pb' +require_relative '../src/proto/grpc/testing/test_services_pb' AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb index 11ee3d465d..0808121661 100755 --- a/src/ruby/pb/test/server.rb +++ b/src/ruby/pb/test/server.rb @@ -50,9 +50,9 @@ require 'optparse' require 'grpc' -require_relative '../src/proto/grpc/testing/empty' -require_relative '../src/proto/grpc/testing/messages' -require_relative '../src/proto/grpc/testing/test_services' +require_relative '../src/proto/grpc/testing/empty_pb' +require_relative '../src/proto/grpc/testing/messages_pb' +require_relative '../src/proto/grpc/testing/test_services_pb' # DebugIsTruncated extends the default Logger to truncate debug messages class DebugIsTruncated < Logger diff --git a/src/ruby/qps/client.rb b/src/ruby/qps/client.rb index 917b01271e..7ed648acef 100644 --- a/src/ruby/qps/client.rb +++ b/src/ruby/qps/client.rb @@ -38,7 +38,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'histogram' -require 'src/proto/grpc/testing/services_services' +require 'src/proto/grpc/testing/services_services_pb' class Poisson def interarrival diff --git a/src/ruby/qps/server.rb b/src/ruby/qps/server.rb index 52a89ce847..cd98ee1fd9 100644 --- a/src/ruby/qps/server.rb +++ b/src/ruby/qps/server.rb @@ -38,9 +38,9 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'grpc' require 'qps-common' -require 'src/proto/grpc/testing/messages' -require 'src/proto/grpc/testing/services_services' -require 'src/proto/grpc/testing/stats' +require 'src/proto/grpc/testing/messages_pb' +require 'src/proto/grpc/testing/services_services_pb' +require 'src/proto/grpc/testing/stats_pb' class BenchmarkServiceImpl < Grpc::Testing::BenchmarkService::Service def unary_call(req, _call) diff --git a/src/ruby/qps/src/proto/grpc/testing/control.rb b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb index 958fca320b..02207a2b5d 100644 --- a/src/ruby/qps/src/proto/grpc/testing/control.rb +++ b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb @@ -3,8 +3,8 @@ require 'google/protobuf' -require 'src/proto/grpc/testing/payloads' -require 'src/proto/grpc/testing/stats' +require 'src/proto/grpc/testing/payloads_pb' +require 'src/proto/grpc/testing/stats_pb' Google::Protobuf::DescriptorPool.generated_pool.build do add_message "grpc.testing.PoissonParams" do optional :offered_load, :double, 1 @@ -109,6 +109,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do repeated :server_stats, :message, 4, "grpc.testing.ServerStats" repeated :server_cores, :int32, 5 optional :summary, :message, 6, "grpc.testing.ScenarioResultSummary" + repeated :client_success, :bool, 7 + repeated :server_success, :bool, 8 end add_enum "grpc.testing.ClientType" do value :SYNC_CLIENT, 0 diff --git a/src/ruby/qps/src/proto/grpc/testing/messages.rb b/src/ruby/qps/src/proto/grpc/testing/messages_pb.rb index e27ccd0dc0..e27ccd0dc0 100644 --- a/src/ruby/qps/src/proto/grpc/testing/messages.rb +++ b/src/ruby/qps/src/proto/grpc/testing/messages_pb.rb diff --git a/src/ruby/qps/src/proto/grpc/testing/payloads.rb b/src/ruby/qps/src/proto/grpc/testing/payloads_pb.rb index ae8855f685..ae8855f685 100644 --- a/src/ruby/qps/src/proto/grpc/testing/payloads.rb +++ b/src/ruby/qps/src/proto/grpc/testing/payloads_pb.rb diff --git a/src/ruby/qps/src/proto/grpc/testing/services.rb b/src/ruby/qps/src/proto/grpc/testing/services_pb.rb index b2675c2afe..5ce13bf8b0 100644 --- a/src/ruby/qps/src/proto/grpc/testing/services.rb +++ b/src/ruby/qps/src/proto/grpc/testing/services_pb.rb @@ -3,8 +3,8 @@ require 'google/protobuf' -require 'src/proto/grpc/testing/messages' -require 'src/proto/grpc/testing/control' +require 'src/proto/grpc/testing/messages_pb' +require 'src/proto/grpc/testing/control_pb' Google::Protobuf::DescriptorPool.generated_pool.build do end diff --git a/src/ruby/qps/src/proto/grpc/testing/services_services.rb b/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb index 94b9a1e164..bdbb9c86d0 100644 --- a/src/ruby/qps/src/proto/grpc/testing/services_services.rb +++ b/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb @@ -34,7 +34,7 @@ # of unary/streaming requests/responses. require 'grpc' -require 'src/proto/grpc/testing/services' +require 'src/proto/grpc/testing/services_pb' module Grpc module Testing diff --git a/src/ruby/qps/src/proto/grpc/testing/stats.rb b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb index 41f75bedf0..41f75bedf0 100644 --- a/src/ruby/qps/src/proto/grpc/testing/stats.rb +++ b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb diff --git a/src/ruby/qps/worker.rb b/src/ruby/qps/worker.rb index 665fb86352..12b8087ca0 100755 --- a/src/ruby/qps/worker.rb +++ b/src/ruby/qps/worker.rb @@ -44,7 +44,7 @@ require 'facter' require 'client' require 'qps-common' require 'server' -require 'src/proto/grpc/testing/services_services' +require 'src/proto/grpc/testing/services_services_pb' class WorkerServiceImpl < Grpc::Testing::WorkerService::Service def cpu_cores diff --git a/src/ruby/spec/pb/duplicate/codegen_spec.rb b/src/ruby/spec/pb/duplicate/codegen_spec.rb index 54c136c510..ea0240965c 100644 --- a/src/ruby/spec/pb/duplicate/codegen_spec.rb +++ b/src/ruby/spec/pb/duplicate/codegen_spec.rb @@ -44,7 +44,7 @@ describe 'Ping protobuf code generation' do # Get the current content service_path = File.join(root_dir, 'src', 'ruby', 'pb', 'grpc', 'testing', 'duplicate', - 'echo_duplicate_services.rb') + 'echo_duplicate_services_pb.rb') want = nil File.open(service_path) { |f| want = f.read } @@ -54,7 +54,7 @@ describe 'Ping protobuf code generation' do got = nil Dir.mktmpdir do |tmp_dir| gen_out = File.join(tmp_dir, 'src', 'proto', 'grpc', 'testing', - 'duplicate', 'echo_duplicate_services.rb') + 'duplicate', 'echo_duplicate_services_pb.rb') pid = spawn( 'protoc', '-I.', diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb index de11c9fedf..1b2fa96827 100644 --- a/src/ruby/spec/pb/health/checker_spec.rb +++ b/src/ruby/spec/pb/health/checker_spec.rb @@ -28,7 +28,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'grpc' -require 'grpc/health/v1/health' +require 'grpc/health/v1/health_pb' require 'grpc/health/checker' require 'open3' require 'tmpdir' @@ -43,7 +43,7 @@ describe 'Health protobuf code generation' do skip 'protoc || grpc_ruby_plugin missing, cannot verify health code-gen' else it 'should already be loaded indirectly i.e, used by the other specs' do - expect(require('grpc/health/v1/health_services')).to be(false) + expect(require('grpc/health/v1/health_services_pb')).to be(false) end it 'should have the same content as created by code generation' do @@ -52,7 +52,7 @@ describe 'Health protobuf code generation' do # Get the current content service_path = File.join(root_dir, 'ruby', 'pb', 'grpc', - 'health', 'v1', 'health_services.rb') + 'health', 'v1', 'health_services_pb.rb') want = nil File.open(service_path) { |f| want = f.read } @@ -62,7 +62,7 @@ describe 'Health protobuf code generation' do got = nil Dir.mktmpdir do |tmp_dir| gen_out = File.join(tmp_dir, 'grpc', 'health', 'v1', - 'health_services.rb') + 'health_services_pb.rb') pid = spawn( 'protoc', '-I.', diff --git a/src/ruby/stress/metrics_server.rb b/src/ruby/stress/metrics_server.rb index 13638c4d21..2b7f78577d 100644 --- a/src/ruby/stress/metrics_server.rb +++ b/src/ruby/stress/metrics_server.rb @@ -27,8 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require_relative '../pb/grpc/testing/metrics.rb' -require_relative '../pb/grpc/testing/metrics_services.rb' +require_relative '../pb/grpc/testing/metrics_pb.rb' +require_relative '../pb/grpc/testing/metrics_services_pb.rb' class Gauge def get_name diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc b/src/ruby/tools/bin/grpc_tools_ruby_protoc new file mode 100755 index 0000000000..dab06e7958 --- /dev/null +++ b/src/ruby/tools/bin/grpc_tools_ruby_protoc @@ -0,0 +1,48 @@ +#!/usr/bin/env ruby +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 'rbconfig' + +require_relative '../os_check' + +ext = RbConfig::CONFIG['EXEEXT'] + +protoc_name = 'protoc' + ext + +plugin_name = 'grpc_ruby_plugin' + ext + +protoc_dir = File.join(File.dirname(__FILE__), + RbConfig::CONFIG['host_cpu'] + '-' + OS.os_name) + +protoc_path = File.join(protoc_dir, protoc_name) + +plugin_path = File.join(protoc_dir, plugin_name) + +exec([ protoc_path, protoc_path ], "--plugin=protoc-gen-grpc=#{plugin_path}", *ARGV) diff --git a/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb b/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin index 4b296dedc7..4b296dedc7 100755 --- a/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin.rb +++ b/src/ruby/tools/bin/grpc_tools_ruby_protoc_plugin diff --git a/src/ruby/tools/grpc-tools.gemspec b/src/ruby/tools/grpc-tools.gemspec index 9fa4b66392..68e2a7a113 100644 --- a/src/ruby/tools/grpc-tools.gemspec +++ b/src/ruby/tools/grpc-tools.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY - s.executables = %w( grpc_tools_ruby_protoc.rb grpc_tools_ruby_protoc_plugin.rb ) + s.executables = %w( grpc_tools_ruby_protoc grpc_tools_ruby_protoc_plugin ) end |