Merge remote-tracking branch 'origin/master' into py_proto_library

pull/19822/head
Richard Belleville 6 years ago
commit e1980a7a5a
  1. 5
      BUILD
  2. 1
      BUILD.gn
  3. 47
      CMakeLists.txt
  4. 56
      Makefile
  5. 7
      WORKSPACE
  6. 215
      bazel/generate_objc.bzl
  7. 50
      bazel/grpc_build_system.bzl
  8. 8
      bazel/grpc_deps.bzl
  9. 46
      bazel/grpc_util.bzl
  10. 68
      bazel/objc_grpc_library.bzl
  11. 17
      build.yaml
  12. 3
      doc/g_stands_for.md
  13. 75
      examples/python/cancellation/BUILD.bazel
  14. 127
      examples/python/cancellation/README.md
  15. 104
      examples/python/cancellation/client.py
  16. 56
      examples/python/cancellation/hash_name.proto
  17. 148
      examples/python/cancellation/search.py
  18. 134
      examples/python/cancellation/server.py
  19. 87
      examples/python/cancellation/test/_cancellation_example_test.py
  20. 5
      gRPC-C++.podspec
  21. 2
      gRPC-Core.podspec
  22. 2
      gRPC-ProtoRPC.podspec
  23. 2
      gRPC-RxLibrary.podspec
  24. 2
      gRPC.podspec
  25. 5
      include/grpcpp/impl/codegen/channel_interface.h
  26. 87
      include/grpcpp/impl/codegen/delegating_channel.h
  27. 4
      package.xml
  28. 3
      src/core/ext/transport/chttp2/transport/incoming_metadata.cc
  29. 28
      src/core/ext/transport/chttp2/transport/parsing.cc
  30. 11
      src/core/lib/slice/slice_internal.h
  31. 2
      src/core/lib/surface/version.cc
  32. 2
      src/core/lib/transport/metadata_batch.cc
  33. 1321
      src/core/lib/transport/static_metadata.cc
  34. 24
      src/core/lib/transport/static_metadata.h
  35. 2
      src/cpp/common/version_cc.cc
  36. 4
      src/csharp/Grpc.Core.Api/VersionInfo.cs
  37. 2
      src/csharp/build/dependencies.props
  38. 2
      src/csharp/build_unitypackage.bat
  39. 2
      src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec
  40. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  41. 96
      src/objective-c/BUILD
  42. 2
      src/objective-c/GRPCClient/private/version.h
  43. 69
      src/objective-c/examples/BUILD
  44. 31
      src/objective-c/examples/BazelBuildSamples/ios-sample/Podfile
  45. 413
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample.xcodeproj/project.pbxproj
  46. 25
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/AppDelegate.h
  47. 63
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/AppDelegate.m
  48. 98
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/Assets.xcassets/AppIcon.appiconset/Contents.json
  49. 6
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/Assets.xcassets/Contents.json
  50. 25
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/Base.lproj/LaunchScreen.storyboard
  51. 38
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/Base.lproj/Main.storyboard
  52. 45
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/Info.plist
  53. 23
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/ViewController.h
  54. 86
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/ViewController.m
  55. 26
      src/objective-c/examples/BazelBuildSamples/ios-sample/ios-sample/main.m
  56. 118
      src/objective-c/examples/BazelBuildSamples/messages.proto
  57. 28
      src/objective-c/examples/BazelBuildSamples/rmt/BUILD
  58. 57
      src/objective-c/examples/BazelBuildSamples/rmt/test.proto
  59. 4
      src/objective-c/manual_tests/ViewController.m
  60. 2
      src/objective-c/tests/version.h
  61. 2
      src/php/composer.json
  62. 2
      src/php/ext/grpc/version.h
  63. 151
      src/python/grpcio/grpc/_channel.py
  64. 50
      src/python/grpcio/grpc/_common.py
  65. 2
      src/python/grpcio/grpc/_grpcio_metadata.py
  66. 2
      src/python/grpcio/grpc_version.py
  67. 2
      src/python/grpcio_channelz/grpc_version.py
  68. 2
      src/python/grpcio_health_checking/grpc_version.py
  69. 2
      src/python/grpcio_reflection/grpc_version.py
  70. 2
      src/python/grpcio_status/grpc_version.py
  71. 2
      src/python/grpcio_testing/grpc_version.py
  72. 2
      src/python/grpcio_tests/commands.py
  73. 2
      src/python/grpcio_tests/grpc_version.py
  74. 1
      src/python/grpcio_tests/tests/tests.json
  75. 8
      src/python/grpcio_tests/tests/unit/BUILD.bazel
  76. 84
      src/python/grpcio_tests/tests/unit/_signal_client.py
  77. 172
      src/python/grpcio_tests/tests/unit/_signal_handling_test.py
  78. 2
      src/ruby/lib/grpc/version.rb
  79. 2
      src/ruby/tools/version.rb
  80. 18
      test/cpp/end2end/BUILD
  81. 100
      test/cpp/end2end/delegating_channel_test.cc
  82. 37
      tools/codegen/core/gen_static_metadata.py
  83. 2
      tools/distrib/python/grpcio_tools/grpc_version.py
  84. 3
      tools/doxygen/Doxyfile.c++
  85. 3
      tools/doxygen/Doxyfile.c++.internal
  86. 20
      tools/run_tests/generated/sources_and_headers.json
  87. 24
      tools/run_tests/generated/tests.json
  88. 11
      tools/run_tests/sanity/check_bazel_workspace.py

@ -74,11 +74,11 @@ config_setting(
)
# This should be updated along with build.yaml
g_stands_for = "gangnam"
g_stands_for = "ganges"
core_version = "7.0.0"
version = "1.23.0-dev"
version = "1.24.0-dev"
GPR_PUBLIC_HDRS = [
"include/grpc/support/alloc.h",
@ -2077,6 +2077,7 @@ grpc_cc_library(
"include/grpcpp/impl/codegen/config.h",
"include/grpcpp/impl/codegen/core_codegen_interface.h",
"include/grpcpp/impl/codegen/create_auth_context.h",
"include/grpcpp/impl/codegen/delegating_channel.h",
"include/grpcpp/impl/codegen/grpc_library.h",
"include/grpcpp/impl/codegen/intercepted_channel.h",
"include/grpcpp/impl/codegen/interceptor.h",

@ -1076,6 +1076,7 @@ config("grpc_config") {
"include/grpcpp/impl/codegen/core_codegen.h",
"include/grpcpp/impl/codegen/core_codegen_interface.h",
"include/grpcpp/impl/codegen/create_auth_context.h",
"include/grpcpp/impl/codegen/delegating_channel.h",
"include/grpcpp/impl/codegen/grpc_library.h",
"include/grpcpp/impl/codegen/intercepted_channel.h",
"include/grpcpp/impl/codegen/interceptor.h",

@ -24,7 +24,7 @@
cmake_minimum_required(VERSION 3.5.1)
set(PACKAGE_NAME "grpc")
set(PACKAGE_VERSION "1.23.0-dev")
set(PACKAGE_VERSION "1.24.0-dev")
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@ -627,6 +627,7 @@ add_dependencies(buildtests_cxx cxx_byte_buffer_test)
add_dependencies(buildtests_cxx cxx_slice_test)
add_dependencies(buildtests_cxx cxx_string_ref_test)
add_dependencies(buildtests_cxx cxx_time_test)
add_dependencies(buildtests_cxx delegating_channel_test)
add_dependencies(buildtests_cxx end2end_test)
add_dependencies(buildtests_cxx error_details_test)
add_dependencies(buildtests_cxx exception_test)
@ -3373,6 +3374,7 @@ foreach(_hdr
include/grpcpp/impl/codegen/config.h
include/grpcpp/impl/codegen/core_codegen_interface.h
include/grpcpp/impl/codegen/create_auth_context.h
include/grpcpp/impl/codegen/delegating_channel.h
include/grpcpp/impl/codegen/grpc_library.h
include/grpcpp/impl/codegen/intercepted_channel.h
include/grpcpp/impl/codegen/interceptor.h
@ -3873,6 +3875,7 @@ foreach(_hdr
include/grpcpp/impl/codegen/config.h
include/grpcpp/impl/codegen/core_codegen_interface.h
include/grpcpp/impl/codegen/create_auth_context.h
include/grpcpp/impl/codegen/delegating_channel.h
include/grpcpp/impl/codegen/grpc_library.h
include/grpcpp/impl/codegen/intercepted_channel.h
include/grpcpp/impl/codegen/interceptor.h
@ -4079,6 +4082,7 @@ foreach(_hdr
include/grpcpp/impl/codegen/config.h
include/grpcpp/impl/codegen/core_codegen_interface.h
include/grpcpp/impl/codegen/create_auth_context.h
include/grpcpp/impl/codegen/delegating_channel.h
include/grpcpp/impl/codegen/grpc_library.h
include/grpcpp/impl/codegen/intercepted_channel.h
include/grpcpp/impl/codegen/interceptor.h
@ -4451,6 +4455,7 @@ foreach(_hdr
include/grpcpp/impl/codegen/config.h
include/grpcpp/impl/codegen/core_codegen_interface.h
include/grpcpp/impl/codegen/create_auth_context.h
include/grpcpp/impl/codegen/delegating_channel.h
include/grpcpp/impl/codegen/grpc_library.h
include/grpcpp/impl/codegen/intercepted_channel.h
include/grpcpp/impl/codegen/interceptor.h
@ -13073,6 +13078,46 @@ target_link_libraries(cxx_time_test
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(delegating_channel_test
test/cpp/end2end/delegating_channel_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(delegating_channel_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(delegating_channel_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++_test_util
grpc_test_util
grpc++
grpc
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -461,8 +461,8 @@ Q = @
endif
CORE_VERSION = 7.0.0
CPP_VERSION = 1.23.0-dev
CSHARP_VERSION = 2.23.0-dev
CPP_VERSION = 1.24.0-dev
CSHARP_VERSION = 2.24.0-dev
CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@ -1208,6 +1208,7 @@ cxx_byte_buffer_test: $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test
cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test
cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test
cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test
delegating_channel_test: $(BINDIR)/$(CONFIG)/delegating_channel_test
end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
error_details_test: $(BINDIR)/$(CONFIG)/error_details_test
exception_test: $(BINDIR)/$(CONFIG)/exception_test
@ -1688,6 +1689,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/cxx_slice_test \
$(BINDIR)/$(CONFIG)/cxx_string_ref_test \
$(BINDIR)/$(CONFIG)/cxx_time_test \
$(BINDIR)/$(CONFIG)/delegating_channel_test \
$(BINDIR)/$(CONFIG)/end2end_test \
$(BINDIR)/$(CONFIG)/error_details_test \
$(BINDIR)/$(CONFIG)/exception_test \
@ -1855,6 +1857,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/cxx_slice_test \
$(BINDIR)/$(CONFIG)/cxx_string_ref_test \
$(BINDIR)/$(CONFIG)/cxx_time_test \
$(BINDIR)/$(CONFIG)/delegating_channel_test \
$(BINDIR)/$(CONFIG)/end2end_test \
$(BINDIR)/$(CONFIG)/error_details_test \
$(BINDIR)/$(CONFIG)/exception_test \
@ -2354,6 +2357,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/cxx_string_ref_test || ( echo test cxx_string_ref_test failed ; exit 1 )
$(E) "[RUN] Testing cxx_time_test"
$(Q) $(BINDIR)/$(CONFIG)/cxx_time_test || ( echo test cxx_time_test failed ; exit 1 )
$(E) "[RUN] Testing delegating_channel_test"
$(Q) $(BINDIR)/$(CONFIG)/delegating_channel_test || ( echo test delegating_channel_test failed ; exit 1 )
$(E) "[RUN] Testing end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 )
$(E) "[RUN] Testing error_details_test"
@ -5738,6 +5743,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/impl/codegen/config.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \
@ -6208,6 +6214,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/impl/codegen/config.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \
@ -6385,6 +6392,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/impl/codegen/config.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \
@ -6763,6 +6771,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/impl/codegen/config.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \
@ -16089,6 +16098,49 @@ endif
endif
DELEGATING_CHANNEL_TEST_SRC = \
test/cpp/end2end/delegating_channel_test.cc \
DELEGATING_CHANNEL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DELEGATING_CHANNEL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/delegating_channel_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/delegating_channel_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/delegating_channel_test: $(PROTOBUF_DEP) $(DELEGATING_CHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(DELEGATING_CHANNEL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/delegating_channel_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/end2end/delegating_channel_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_delegating_channel_test: $(DELEGATING_CHANNEL_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(DELEGATING_CHANNEL_TEST_OBJS:.o=.dep)
endif
endif
END2END_TEST_SRC = \
test/cpp/end2end/end2end_test.cc \
test/cpp/end2end/interceptors_util.cc \

@ -64,3 +64,10 @@ api_dependencies()
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains()
load("@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies")
apple_rules_dependencies()
load("@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies")
apple_support_dependencies()

@ -0,0 +1,215 @@
load(
"//bazel:protobuf.bzl",
"get_include_protoc_args",
"get_plugin_args",
"proto_path_to_generated_filename",
)
load(":grpc_util.bzl", "to_upper_camel_with_extension",)
_GRPC_PROTO_HEADER_FMT = "{}.pbrpc.h"
_GRPC_PROTO_SRC_FMT = "{}.pbrpc.m"
_PROTO_HEADER_FMT = "{}.pbobjc.h"
_PROTO_SRC_FMT = "{}.pbobjc.m"
_GENERATED_PROTOS_DIR = "_generated_protos"
_GENERATE_HDRS = 1
_GENERATE_SRCS = 2
_GENERATE_NON_ARC_SRCS = 3
def _generate_objc_impl(ctx):
"""Implementation of the generate_objc rule."""
protos = [
f
for src in ctx.attr.deps
for f in src[ProtoInfo].transitive_imports.to_list()
]
target_package = _join_directories([ctx.label.workspace_root, ctx.label.package])
files_with_rpc = [_label_to_full_file_path(f, target_package) for f in ctx.attr.srcs]
outs = []
for proto in protos:
outs += [_get_output_file_name_from_proto(proto, _PROTO_HEADER_FMT)]
outs += [_get_output_file_name_from_proto(proto, _PROTO_SRC_FMT)]
file_path = _get_full_path_from_file(proto)
if file_path in files_with_rpc:
outs += [_get_output_file_name_from_proto(proto, _GRPC_PROTO_HEADER_FMT)]
outs += [_get_output_file_name_from_proto(proto, _GRPC_PROTO_SRC_FMT)]
out_files = [ctx.actions.declare_file(out) for out in outs]
dir_out = _join_directories([
str(ctx.genfiles_dir.path), target_package, _GENERATED_PROTOS_DIR
])
arguments = []
if ctx.executable.plugin:
arguments += get_plugin_args(
ctx.executable.plugin,
[],
dir_out,
False,
)
tools = [ctx.executable.plugin]
arguments += ["--objc_out=" + dir_out]
arguments += ["--proto_path=."]
arguments += get_include_protoc_args(protos)
# Include the output directory so that protoc puts the generated code in the
# right directory.
arguments += ["--proto_path={}".format(dir_out)]
arguments += ["--proto_path={}".format(_get_directory_from_proto(proto)) for proto in protos]
arguments += [_get_full_path_from_file(proto) for proto in protos]
# create a list of well known proto files if the argument is non-None
well_known_proto_files = []
if ctx.attr.use_well_known_protos:
f = ctx.attr.well_known_protos.files.to_list()[0].dirname
# go two levels up so that #import "google/protobuf/..." is correct
arguments += ["-I{0}".format(f + "/../..")]
well_known_proto_files = ctx.attr.well_known_protos.files.to_list()
ctx.actions.run(
inputs = protos + well_known_proto_files,
tools = tools,
outputs = out_files,
executable = ctx.executable._protoc,
arguments = arguments,
)
return struct(files = depset(out_files))
def _label_to_full_file_path(src, package):
if not src.startswith("//"):
# Relative from current package
if not src.startswith(":"):
# "a.proto" -> ":a.proto"
src = ":" + src
src = "//" + package + src
# Converts //path/to/package:File.ext to path/to/package/File.ext.
src = src.replace("//", "")
src = src.replace(":", "/")
if src.startswith("/"):
# "//:a.proto" -> "/a.proto" so remove the initial slash
return src[1:]
else:
return src
def _get_output_file_name_from_proto(proto, fmt):
return proto_path_to_generated_filename(
_GENERATED_PROTOS_DIR + "/" +
_get_directory_from_proto(proto) + _get_slash_or_null_from_proto(proto) +
to_upper_camel_with_extension(_get_file_name_from_proto(proto), "proto"),
fmt,
)
def _get_file_name_from_proto(proto):
return proto.path.rpartition("/")[2]
def _get_slash_or_null_from_proto(proto):
"""Potentially returns empty (if the file is in the root directory)"""
return proto.path.rpartition("/")[1]
def _get_directory_from_proto(proto):
return proto.path.rpartition("/")[0]
def _get_full_path_from_file(file):
gen_dir_length = 0
# if file is generated, then prepare to remote its root
# (including CPU architecture...)
if not file.is_source:
gen_dir_length = len(file.root.path) + 1
return file.path[gen_dir_length:]
def _join_directories(directories):
massaged_directories = [directory for directory in directories if len(directory) != 0]
return "/".join(massaged_directories)
generate_objc = rule(
attrs = {
"deps": attr.label_list(
mandatory = True,
allow_empty = False,
providers = [ProtoInfo],
),
"plugin": attr.label(
default = "@com_github_grpc_grpc//src/compiler:grpc_objective_c_plugin",
executable = True,
providers = ["files_to_run"],
cfg = "host",
),
"srcs": attr.string_list(
mandatory = False,
allow_empty = True
),
"use_well_known_protos": attr.bool(
mandatory = False,
default = False
),
"well_known_protos": attr.label(
default = "@com_google_protobuf//:well_known_protos"
),
"_protoc": attr.label(
default = Label("//external:protocol_compiler"),
executable = True,
cfg = "host",
),
},
output_to_genfiles = True,
implementation = _generate_objc_impl
)
def _group_objc_files_impl(ctx):
suffix = ""
if ctx.attr.gen_mode == _GENERATE_HDRS:
suffix = "h"
elif ctx.attr.gen_mode == _GENERATE_SRCS:
suffix = "pbrpc.m"
elif ctx.attr.gen_mode == _GENERATE_NON_ARC_SRCS:
suffix = "pbobjc.m"
else:
fail("Undefined gen_mode")
out_files = [
file
for file in ctx.attr.src.files.to_list()
if file.basename.endswith(suffix)
]
return struct(files = depset(out_files))
generate_objc_hdrs = rule(
attrs = {
"src": attr.label(
mandatory = True,
),
"gen_mode": attr.int(
default = _GENERATE_HDRS,
)
},
implementation = _group_objc_files_impl
)
generate_objc_srcs = rule(
attrs = {
"src": attr.label(
mandatory = True,
),
"gen_mode": attr.int(
default = _GENERATE_SRCS,
)
},
implementation = _group_objc_files_impl
)
generate_objc_non_arc_srcs = rule(
attrs = {
"src": attr.label(
mandatory = True,
),
"gen_mode": attr.int(
default = _GENERATE_NON_ARC_SRCS,
)
},
implementation = _group_objc_files_impl
)

@ -24,6 +24,7 @@
#
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library")
# The set of pollers to test against if a test exercises polling
@ -198,6 +199,19 @@ def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], da
)
def grpc_generate_one_off_targets():
apple_resource_bundle(
# The choice of name is signicant here, since it determines the bundle name.
name = "gRPCCertificates",
resources = ["etc/roots.pem"],
)
# In open-source, grpc_objc* libraries depend directly on //:grpc
native.alias(
name = "grpc_objc",
actual = "//:grpc",
)
def grpc_objc_use_cronet_config():
pass
def grpc_sh_test(name, srcs, args = [], data = []):
@ -240,6 +254,42 @@ def grpc_package(name, visibility = "private", features = []):
features = features,
)
def grpc_objc_library(
name,
srcs,
hdrs = [],
textual_hdrs = [],
data = [],
deps = [],
defines = [],
includes = [],
visibility = ["//visibility:public"]):
"""The grpc version of objc_library, only used for the Objective-C library compilation
Args:
name: name of target
hdrs: public headers
srcs: all source files (.m)
textual_hdrs: private headers
data: any other bundle resources
defines: preprocessors
includes: added to search path, always [the path to objc directory]
deps: dependencies
visibility: visibility, default to public
"""
native.objc_library(
name = name,
hdrs = hdrs,
srcs = srcs,
textual_hdrs = textual_hdrs,
data = data,
deps = deps,
defines = defines,
includes = includes,
visibility = visibility,
)
def grpc_upb_proto_library(name, deps):
upb_proto_library(name = name, deps = deps)

@ -224,6 +224,14 @@ def grpc_deps():
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz"],
sha256 = "a82a352bffae6bee4e95f68a8d80a70e87f42c4741e6a448bec11998fcc82329",
)
if "build_bazel_rules_apple" not in native.existing_rules():
git_repository(
name = "build_bazel_rules_apple",
remote = "https://github.com/bazelbuild/rules_apple.git",
tag = "0.17.2",
)
# TODO: move some dependencies from "grpc_deps" here?
def grpc_test_only_deps():
"""Internal, not intended for use by packages that are consuming grpc.

@ -0,0 +1,46 @@
# Follows convention set in objectivec_helpers.cc in the protobuf ObjC compiler.
_upper_segments_list = ["url", "http", "https"]
def strip_extension(str):
return str.rpartition(".")[0]
def capitalize(word):
if word in _upper_segments_list:
return word.upper()
else:
return word.capitalize()
def lower_underscore_to_upper_camel(str):
str = strip_extension(str)
camel_case_str = ""
word = ""
for c in str.elems(): # NB: assumes ASCII!
if c.isalpha():
word += c.lower()
else:
# Last word is finished.
if len(word):
camel_case_str += capitalize(word)
word = ""
if c.isdigit():
camel_case_str += c
# Otherwise, drop the character. See UnderscoresToCamelCase in:
# third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
if len(word):
camel_case_str += capitalize(word)
return camel_case_str
def file_to_upper_camel(src):
elements = src.rpartition("/")
upper_camel = lower_underscore_to_upper_camel(elements[-1])
return "".join(list(elements[:-1]) + [upper_camel])
def file_with_extension(src, ext):
elements = src.rpartition("/")
return "".join(list(elements[:-1]) + [elements[-1], "." + ext])
def to_upper_camel_with_extension(src, ext):
src = file_to_upper_camel(src)
return file_with_extension(src, ext)

@ -0,0 +1,68 @@
load(
"//bazel:generate_objc.bzl",
"generate_objc",
"generate_objc_hdrs",
"generate_objc_srcs",
"generate_objc_non_arc_srcs"
)
load("//bazel:protobuf.bzl", "well_known_proto_libs")
def objc_grpc_library(name, deps, srcs = [], use_well_known_protos = False, **kwargs):
"""Generates messages and/or service stubs for given proto_library and all transitively dependent proto files
Args:
name: name of target
deps: a list of proto_library targets that needs to be compiled
srcs: a list of labels to proto files with service stubs to be generated,
labels specified must include service stubs; otherwise Bazel will complain about srcs being empty
use_well_known_protos: whether to use the well known protos defined in
@com_google_protobuf//src/google/protobuf, default to false
**kwargs: other arguments
"""
objc_grpc_library_name = "_" + name + "_objc_grpc_library"
generate_objc(
name = objc_grpc_library_name,
srcs = srcs,
deps = deps,
use_well_known_protos = use_well_known_protos,
**kwargs
)
generate_objc_hdrs(
name = objc_grpc_library_name + "_hdrs",
src = ":" + objc_grpc_library_name,
)
generate_objc_non_arc_srcs(
name = objc_grpc_library_name + "_non_arc_srcs",
src = ":" + objc_grpc_library_name,
)
arc_srcs = None
if len(srcs) > 0:
generate_objc_srcs(
name = objc_grpc_library_name + "_srcs",
src = ":" + objc_grpc_library_name,
)
arc_srcs = [":" + objc_grpc_library_name + "_srcs"]
native.objc_library(
name = name,
hdrs = [":" + objc_grpc_library_name + "_hdrs"],
non_arc_srcs = [":" + objc_grpc_library_name + "_non_arc_srcs"],
srcs = arc_srcs,
defines = [
"GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=0",
"GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO=0",
],
includes = [
"_generated_protos",
"src/objective-c",
],
deps = [
"@com_github_grpc_grpc//src/objective-c:proto_objc_rpc",
"@com_google_protobuf//:protobuf_objc",
],
)

@ -14,8 +14,8 @@ settings:
'#10': See the expand_version.py for all the quirks here
core_version: 7.0.0
csharp_major_version: 2
g_stands_for: gangnam
version: 1.23.0-dev
g_stands_for: ganges
version: 1.24.0-dev
filegroups:
- name: alts_proto
headers:
@ -1323,6 +1323,7 @@ filegroups:
- include/grpcpp/impl/codegen/config.h
- include/grpcpp/impl/codegen/core_codegen_interface.h
- include/grpcpp/impl/codegen/create_auth_context.h
- include/grpcpp/impl/codegen/delegating_channel.h
- include/grpcpp/impl/codegen/grpc_library.h
- include/grpcpp/impl/codegen/intercepted_channel.h
- include/grpcpp/impl/codegen/interceptor.h
@ -4855,6 +4856,18 @@ targets:
- grpc
- gpr
uses_polling: false
- name: delegating_channel_test
gtest: true
build: test
language: c++
src:
- test/cpp/end2end/delegating_channel_test.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr
- name: end2end_test
gtest: true
cpu_cost: 0.5

@ -22,4 +22,5 @@
- 1.20 'g' stands for ['godric'](https://github.com/grpc/grpc/tree/v1.20.x)
- 1.21 'g' stands for ['gandalf'](https://github.com/grpc/grpc/tree/v1.21.x)
- 1.22 'g' stands for ['gale'](https://github.com/grpc/grpc/tree/v1.22.x)
- 1.23 'g' stands for ['gangnam'](https://github.com/grpc/grpc/tree/master)
- 1.23 'g' stands for ['gangnam'](https://github.com/grpc/grpc/tree/v1.23.x)
- 1.24 'g' stands for ['ganges'](https://github.com/grpc/grpc/tree/master)

@ -0,0 +1,75 @@
# gRPC Bazel BUILD file.
#
# Copyright 2019 The gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("@grpc_python_dependencies//:requirements.bzl", "requirement")
load("//bazel:python_rules.bzl", "py_proto_library")
package(default_testonly = 1)
proto_library(
name = "hash_name_proto",
srcs = ["hash_name.proto"],
)
py_proto_library(
name = "hash_name_proto_pb2",
deps = [":hash_name_proto"],
well_known_protos = False,
)
py_binary(
name = "client",
srcs = ["client.py"],
deps = [
"//src/python/grpcio/grpc:grpcio",
":hash_name_proto_pb2",
requirement("six"),
],
srcs_version = "PY2AND3",
)
py_library(
name = "search",
srcs = ["search.py"],
srcs_version = "PY2AND3",
deps = [
":hash_name_proto_pb2",
],
)
py_binary(
name = "server",
srcs = ["server.py"],
deps = [
"//src/python/grpcio/grpc:grpcio",
":hash_name_proto_pb2",
":search",
] + select({
"//conditions:default": [requirement("futures")],
"//:python3": [],
}),
srcs_version = "PY2AND3",
)
py_test(
name = "test/_cancellation_example_test",
srcs = ["test/_cancellation_example_test.py"],
data = [
":client",
":server"
],
size = "small",
)

@ -0,0 +1,127 @@
### Cancellation
In the example, we implement a silly algorithm. We search for bytestrings whose
hashes are similar to a given search string. For example, say we're looking for
the string "doctor". Our algorithm may return `JrqhZVkTDoctYrUlXDbL6pfYQHU=` or
`RC9/7mlM3ldy4TdoctOc6WzYbO4=`. This is a brute force algorithm, so the server
performing the search must be conscious of the resources it allows to each client
and each client must be conscientious of the resources it demands of the server.
In particular, we ensure that client processes cancel the stream explicitly
before terminating and we ensure that server processes cancel RPCs that have gone on longer
than a certain number of iterations.
#### Cancellation on the Client Side
A client may cancel an RPC for several reasons. Perhaps the data it requested
has been made irrelevant. Perhaps you, as the client, want to be a good citizen
of the server and are conserving compute resources.
##### Cancelling a Server-Side Unary RPC from the Client
The default RPC methods on a stub will simply return the result of an RPC.
```python
>>> stub = hash_name_pb2_grpc.HashFinderStub(channel)
>>> stub.Find(hash_name_pb2.HashNameRequest(desired_name=name))
<hash_name_pb2.HashNameResponse object at 0x7fe2eb8ce2d0>
```
But you may use the `future()` method to receive an instance of `grpc.Future`.
This interface allows you to wait on a response with a timeout, add a callback
to be executed when the RPC completes, or to cancel the RPC before it has
completed.
In the example, we use this interface to cancel our in-progress RPC when the
user interrupts the process with ctrl-c.
```python
stub = hash_name_pb2_grpc.HashFinderStub(channel)
future = stub.Find.future(hash_name_pb2.HashNameRequest(desired_name=name))
def cancel_request(unused_signum, unused_frame):
future.cancel()
sys.exit(0)
signal.signal(signal.SIGINT, cancel_request)
result = future.result()
print(result)
```
We also call `sys.exit(0)` to terminate the process. If we do not do this, then
`future.result()` with throw an `RpcError`. Alternatively, you may catch this
exception.
##### Cancelling a Server-Side Streaming RPC from the Client
Cancelling a Server-side streaming RPC is even simpler from the perspective of
the gRPC API. The default stub method is already an instance of `grpc.Future`,
so the methods outlined above still apply. It is also a generator, so we may
iterate over it to yield the results of our RPC.
```python
stub = hash_name_pb2_grpc.HashFinderStub(channel)
result_generator = stub.FindRange(hash_name_pb2.HashNameRequest(desired_name=name))
def cancel_request(unused_signum, unused_frame):
result_generator.cancel()
sys.exit(0)
signal.signal(signal.SIGINT, cancel_request)
for result in result_generator:
print(result)
```
We also call `sys.exit(0)` here to terminate the process. Alternatively, you may
catch the `RpcError` raised by the for loop upon cancellation.
#### Cancellation on the Server Side
A server is reponsible for cancellation in two ways. It must respond in some way
when a client initiates a cancellation, otherwise long-running computations
could continue indefinitely.
It may also decide to cancel the RPC for its own reasons. In our example, the
server can be configured to cancel an RPC after a certain number of hashes has
been computed in order to conserve compute resources.
##### Responding to Cancellations from a Servicer Thread
It's important to remember that a gRPC Python server is backed by a thread pool
with a fixed size. When an RPC is cancelled, the library does *not* terminate
your servicer thread. It is your responsibility as the application author to
ensure that your servicer thread terminates soon after the RPC has been
cancelled.
In this example, we use the `ServicerContext.add_callback` method to set a
`threading.Event` object when the RPC is terminated. We pass this `Event` object
down through our hashing algorithm and ensure to check that the RPC is still
ongoing before each iteration.
```python
stop_event = threading.Event()
def on_rpc_done():
# Regain servicer thread.
stop_event.set()
context.add_callback(on_rpc_done)
secret = _find_secret(stop_event)
```
##### Initiating a Cancellation on the Server Side
Initiating a cancellation from the server side is simpler. Just call
`ServicerContext.cancel()`.
In our example, we ensure that no single client is monopolizing the server by
cancelling after a configurable number of hashes have been checked.
```python
try:
for candidate in secret_generator:
yield candidate
except ResourceLimitExceededError:
print("Cancelling RPC due to exhausted resources.")
context.cancel()
```
In this type of situation, you may also consider returning a more specific error
using the [`grpcio-status`](https://pypi.org/project/grpcio-status/) package.

@ -0,0 +1,104 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""An example of cancelling requests in gRPC."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import logging
import signal
import sys
import grpc
from examples.python.cancellation import hash_name_pb2
from examples.python.cancellation import hash_name_pb2_grpc
_DESCRIPTION = "A client for finding hashes similar to names."
_LOGGER = logging.getLogger(__name__)
def run_unary_client(server_target, name, ideal_distance):
with grpc.insecure_channel(server_target) as channel:
stub = hash_name_pb2_grpc.HashFinderStub(channel)
future = stub.Find.future(
hash_name_pb2.HashNameRequest(
desired_name=name, ideal_hamming_distance=ideal_distance),
wait_for_ready=True)
def cancel_request(unused_signum, unused_frame):
future.cancel()
sys.exit(0)
signal.signal(signal.SIGINT, cancel_request)
result = future.result()
print(result)
def run_streaming_client(server_target, name, ideal_distance,
interesting_distance):
with grpc.insecure_channel(server_target) as channel:
stub = hash_name_pb2_grpc.HashFinderStub(channel)
result_generator = stub.FindRange(
hash_name_pb2.HashNameRequest(
desired_name=name,
ideal_hamming_distance=ideal_distance,
interesting_hamming_distance=interesting_distance),
wait_for_ready=True)
def cancel_request(unused_signum, unused_frame):
result_generator.cancel()
sys.exit(0)
signal.signal(signal.SIGINT, cancel_request)
for result in result_generator:
print(result)
def main():
parser = argparse.ArgumentParser(description=_DESCRIPTION)
parser.add_argument("name", type=str, help='The desired name.')
parser.add_argument(
"--ideal-distance",
default=0,
nargs='?',
type=int,
help="The desired Hamming distance.")
parser.add_argument(
'--server',
default='localhost:50051',
type=str,
nargs='?',
help='The host-port pair at which to reach the server.')
parser.add_argument(
'--show-inferior',
default=None,
type=int,
nargs='?',
help='Also show candidates with a Hamming distance less than this value.'
)
args = parser.parse_args()
if args.show_inferior is not None:
run_streaming_client(args.server, args.name, args.ideal_distance,
args.show_inferior)
else:
run_unary_client(args.server, args.name, args.ideal_distance)
if __name__ == "__main__":
logging.basicConfig()
main()

@ -0,0 +1,56 @@
// Copyright 2019 the gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package hash_name;
// A request for a single secret whose hash is similar to a desired name.
message HashNameRequest {
// The string that is desired in the secret's hash.
string desired_name = 1;
// The ideal Hamming distance betwen desired_name and the secret that will
// be searched for.
int32 ideal_hamming_distance = 2;
// A Hamming distance greater than the ideal Hamming distance. Search results
// with a Hamming distance less than this value but greater than the ideal
// distance will be returned back to the client but will not terminate the
// search.
int32 interesting_hamming_distance = 3;
}
message HashNameResponse {
// The search result.
string secret = 1;
// The hash of the search result. A substring of this is of
// ideal_hamming_distance Hamming distance or less from desired_name.
string hashed_name = 2;
// The Hamming distance between hashed_name and desired_name.
int32 hamming_distance = 3;
}
service HashFinder {
// Search for a single string whose hash is similar to the specified
// desired_name. interesting_hamming_distance is ignored.
rpc Find (HashNameRequest) returns (HashNameResponse) {}
// Search for a string whose hash is similar to the specified desired_name,
// but also stream back less-than-ideal candidates.
rpc FindRange (HashNameRequest) returns (stream HashNameResponse) {}
}

@ -0,0 +1,148 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A search algorithm over the space of all bytestrings."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import base64
import hashlib
import itertools
import logging
import struct
from examples.python.cancellation import hash_name_pb2
_LOGGER = logging.getLogger(__name__)
_BYTE_MAX = 255
def _get_hamming_distance(a, b):
"""Calculates hamming distance between strings of equal length."""
distance = 0
for char_a, char_b in zip(a, b):
if char_a != char_b:
distance += 1
return distance
def _get_substring_hamming_distance(candidate, target):
"""Calculates the minimum hamming distance between between the target
and any substring of the candidate.
Args:
candidate: The string whose substrings will be tested.
target: The target string.
Returns:
The minimum Hamming distance between candidate and target.
"""
min_distance = None
if len(target) > len(candidate):
raise ValueError("Candidate must be at least as long as target.")
for i in range(len(candidate) - len(target) + 1):
distance = _get_hamming_distance(candidate[i:i + len(target)].lower(),
target.lower())
if min_distance is None or distance < min_distance:
min_distance = distance
return min_distance
def _get_hash(secret):
hasher = hashlib.sha1()
hasher.update(secret)
return base64.b64encode(hasher.digest()).decode('ascii')
class ResourceLimitExceededError(Exception):
"""Signifies the request has exceeded configured limits."""
def _bytestrings_of_length(length):
"""Generates a stream containing all bytestrings of a given length.
Args:
length: A positive integer length.
Yields:
All bytestrings of length `length`.
"""
for digits in itertools.product(range(_BYTE_MAX), repeat=length):
yield b''.join(struct.pack('B', i) for i in digits)
def _all_bytestrings():
"""Generates a stream containing all possible bytestrings.
This generator does not terminate.
Yields:
All bytestrings in ascending order of length.
"""
for bytestring in itertools.chain.from_iterable(
_bytestrings_of_length(length) for length in itertools.count()):
yield bytestring
def search(target,
ideal_distance,
stop_event,
maximum_hashes,
interesting_hamming_distance=None):
"""Find candidate strings.
Search through the space of all bytestrings, in order of increasing length,
indefinitely, until a hash with a Hamming distance of `maximum_distance` or
less has been found.
Args:
target: The search string.
ideal_distance: The desired Hamming distance.
stop_event: An event indicating whether the RPC should terminate.
maximum_hashes: The maximum number of hashes to check before stopping.
interesting_hamming_distance: If specified, strings with a Hamming
distance from the target below this value will be yielded.
Yields:
Instances of HashNameResponse. The final entry in the stream will be of
`maximum_distance` Hamming distance or less from the target string,
while all others will be of less than `interesting_hamming_distance`.
Raises:
ResourceLimitExceededError: If the computation exceeds `maximum_hashes`
iterations.
"""
hashes_computed = 0
for secret in _all_bytestrings():
if stop_event.is_set():
raise StopIteration() # pylint: disable=stop-iteration-return
candidate_hash = _get_hash(secret)
distance = _get_substring_hamming_distance(candidate_hash, target)
if interesting_hamming_distance is not None and distance <= interesting_hamming_distance:
# Surface interesting candidates, but don't stop.
yield hash_name_pb2.HashNameResponse(
secret=base64.b64encode(secret),
hashed_name=candidate_hash,
hamming_distance=distance)
elif distance <= ideal_distance:
# Yield ideal candidate and end the stream.
yield hash_name_pb2.HashNameResponse(
secret=base64.b64encode(secret),
hashed_name=candidate_hash,
hamming_distance=distance)
raise StopIteration() # pylint: disable=stop-iteration-return
hashes_computed += 1
if hashes_computed == maximum_hashes:
raise ResourceLimitExceededError()

@ -0,0 +1,134 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""An example of cancelling requests in gRPC."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from concurrent import futures
import argparse
import contextlib
import logging
import time
import threading
import grpc
import search
from examples.python.cancellation import hash_name_pb2
from examples.python.cancellation import hash_name_pb2_grpc
_LOGGER = logging.getLogger(__name__)
_SERVER_HOST = 'localhost'
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_DESCRIPTION = "A server for finding hashes similar to names."
class HashFinder(hash_name_pb2_grpc.HashFinderServicer):
def __init__(self, maximum_hashes):
super(HashFinder, self).__init__()
self._maximum_hashes = maximum_hashes
def Find(self, request, context):
stop_event = threading.Event()
def on_rpc_done():
_LOGGER.debug("Attempting to regain servicer thread.")
stop_event.set()
context.add_callback(on_rpc_done)
candidates = []
try:
candidates = list(
search.search(request.desired_name,
request.ideal_hamming_distance, stop_event,
self._maximum_hashes))
except search.ResourceLimitExceededError:
_LOGGER.info("Cancelling RPC due to exhausted resources.")
context.cancel()
_LOGGER.debug("Servicer thread returning.")
if not candidates:
return hash_name_pb2.HashNameResponse()
return candidates[-1]
def FindRange(self, request, context):
stop_event = threading.Event()
def on_rpc_done():
_LOGGER.debug("Attempting to regain servicer thread.")
stop_event.set()
context.add_callback(on_rpc_done)
secret_generator = search.search(
request.desired_name,
request.ideal_hamming_distance,
stop_event,
self._maximum_hashes,
interesting_hamming_distance=request.interesting_hamming_distance)
try:
for candidate in secret_generator:
yield candidate
except search.ResourceLimitExceededError:
_LOGGER.info("Cancelling RPC due to exhausted resources.")
context.cancel()
_LOGGER.debug("Regained servicer thread.")
@contextlib.contextmanager
def _running_server(port, maximum_hashes):
# We use only a single servicer thread here to demonstrate that, if managed
# carefully, cancelled RPCs can need not continue occupying servicers
# threads.
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=1), maximum_concurrent_rpcs=1)
hash_name_pb2_grpc.add_HashFinderServicer_to_server(
HashFinder(maximum_hashes), server)
address = '{}:{}'.format(_SERVER_HOST, port)
actual_port = server.add_insecure_port(address)
server.start()
print("Server listening at '{}'".format(address))
try:
yield actual_port
except KeyboardInterrupt:
pass
finally:
server.stop(None)
def main():
parser = argparse.ArgumentParser(description=_DESCRIPTION)
parser.add_argument(
'--port',
type=int,
default=50051,
nargs='?',
help='The port on which the server will listen.')
parser.add_argument(
'--maximum-hashes',
type=int,
default=1000000,
nargs='?',
help='The maximum number of hashes to search before cancelling.')
args = parser.parse_args()
with _running_server(args.port, args.maximum_hashes):
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
if __name__ == "__main__":
logging.basicConfig()
main()

@ -0,0 +1,87 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test for cancellation example."""
import contextlib
import os
import signal
import socket
import subprocess
import unittest
_BINARY_DIR = os.path.realpath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
_SERVER_PATH = os.path.join(_BINARY_DIR, 'server')
_CLIENT_PATH = os.path.join(_BINARY_DIR, 'client')
@contextlib.contextmanager
def _get_port():
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0:
raise RuntimeError("Failed to set SO_REUSEPORT.")
sock.bind(('', 0))
try:
yield sock.getsockname()[1]
finally:
sock.close()
def _start_client(server_port,
desired_string,
ideal_distance,
interesting_distance=None):
interesting_distance_args = () if interesting_distance is None else (
'--show-inferior', interesting_distance)
return subprocess.Popen((_CLIENT_PATH, desired_string, '--server',
'localhost:{}'.format(server_port),
'--ideal-distance',
str(ideal_distance)) + interesting_distance_args)
class CancellationExampleTest(unittest.TestCase):
def test_successful_run(self):
with _get_port() as test_port:
server_process = subprocess.Popen((_SERVER_PATH, '--port',
str(test_port)))
try:
client_process = _start_client(test_port, 'aa', 0)
client_return_code = client_process.wait()
self.assertEqual(0, client_return_code)
self.assertIsNone(server_process.poll())
finally:
server_process.kill()
server_process.wait()
def test_graceful_sigint(self):
with _get_port() as test_port:
server_process = subprocess.Popen((_SERVER_PATH, '--port',
str(test_port)))
try:
client_process1 = _start_client(test_port, 'aaaaaaaaaa', 0)
client_process1.send_signal(signal.SIGINT)
client_process1.wait()
client_process2 = _start_client(test_port, 'aa', 0)
client_return_code = client_process2.wait()
self.assertEqual(0, client_return_code)
self.assertIsNone(server_process.poll())
finally:
server_process.kill()
server_process.wait()
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -23,7 +23,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-C++'
# TODO (mxyan): use version that match gRPC version when pod is stabilized
# version = '1.23.0-dev'
# version = '1.24.0-dev'
version = '0.0.9-dev'
s.version = version
s.summary = 'gRPC C++ library'
@ -31,7 +31,7 @@ Pod::Spec.new do |s|
s.license = 'Apache License, Version 2.0'
s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
grpc_version = '1.23.0-dev'
grpc_version = '1.24.0-dev'
s.source = {
:git => 'https://github.com/grpc/grpc.git',
@ -179,6 +179,7 @@ Pod::Spec.new do |s|
'include/grpcpp/impl/codegen/config.h',
'include/grpcpp/impl/codegen/core_codegen_interface.h',
'include/grpcpp/impl/codegen/create_auth_context.h',
'include/grpcpp/impl/codegen/delegating_channel.h',
'include/grpcpp/impl/codegen/grpc_library.h',
'include/grpcpp/impl/codegen/intercepted_channel.h',
'include/grpcpp/impl/codegen/interceptor.h',

@ -22,7 +22,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.23.0-dev'
version = '1.24.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.23.0-dev'
version = '1.24.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.23.0-dev'
version = '1.24.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'https://grpc.io'

@ -20,7 +20,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.23.0-dev'
version = '1.24.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'https://grpc.io'

@ -57,6 +57,10 @@ class ClientCallbackUnaryFactory;
namespace grpc {
class ChannelInterface;
namespace experimental {
class DelegatingChannel;
}
namespace internal {
class Call;
class CallOpSetInterface;
@ -128,6 +132,7 @@ class ChannelInterface {
template <class InputMessage, class OutputMessage>
friend class ::grpc_impl::internal::CallbackUnaryCallImpl;
friend class ::grpc::internal::RpcMethod;
friend class ::grpc::experimental::DelegatingChannel;
friend class ::grpc::internal::InterceptedChannel;
virtual internal::Call CreateCall(const internal::RpcMethod& method,
::grpc_impl::ClientContext* context,

@ -0,0 +1,87 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPCPP_IMPL_CODEGEN_DELEGATING_CHANNEL_H
#define GRPCPP_IMPL_CODEGEN_DELEGATING_CHANNEL_H
namespace grpc {
namespace experimental {
class DelegatingChannel : public ::grpc::ChannelInterface {
public:
virtual ~DelegatingChannel() {}
DelegatingChannel(std::shared_ptr<::grpc::ChannelInterface> delegate_channel)
: delegate_channel_(delegate_channel) {}
grpc_connectivity_state GetState(bool try_to_connect) override {
return delegate_channel()->GetState(try_to_connect);
}
std::shared_ptr<::grpc::ChannelInterface> delegate_channel() {
return delegate_channel_;
}
private:
internal::Call CreateCall(const internal::RpcMethod& method,
ClientContext* context,
::grpc_impl::CompletionQueue* cq) final {
return delegate_channel()->CreateCall(method, context, cq);
}
void PerformOpsOnCall(internal::CallOpSetInterface* ops,
internal::Call* call) final {
delegate_channel()->PerformOpsOnCall(ops, call);
}
void* RegisterMethod(const char* method) final {
return delegate_channel()->RegisterMethod(method);
}
void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
gpr_timespec deadline,
::grpc_impl::CompletionQueue* cq,
void* tag) override {
delegate_channel()->NotifyOnStateChangeImpl(last_observed, deadline, cq,
tag);
}
bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
gpr_timespec deadline) override {
return delegate_channel()->WaitForStateChangeImpl(last_observed, deadline);
}
internal::Call CreateCallInternal(const internal::RpcMethod& method,
ClientContext* context,
::grpc_impl::CompletionQueue* cq,
size_t interceptor_pos) final {
return delegate_channel()->CreateCallInternal(method, context, cq,
interceptor_pos);
}
::grpc_impl::CompletionQueue* CallbackCQ() final {
return delegate_channel()->CallbackCQ();
}
std::shared_ptr<::grpc::ChannelInterface> delegate_channel_;
};
} // namespace experimental
} // namespace grpc
#endif // GRPCPP_IMPL_CODEGEN_DELEGATING_CHANNEL_H

@ -13,8 +13,8 @@
<date>2018-01-19</date>
<time>16:06:07</time>
<version>
<release>1.23.0dev</release>
<api>1.23.0dev</api>
<release>1.24.0dev</release>
<api>1.24.0dev</api>
</version>
<stability>
<release>beta</release>

@ -38,7 +38,8 @@ grpc_error* grpc_chttp2_incoming_metadata_buffer_add(
storage = static_cast<grpc_linked_mdelem*>(
buffer->arena->Alloc(sizeof(grpc_linked_mdelem)));
}
return grpc_metadata_batch_add_tail(&buffer->batch, storage, elem);
storage->md = elem;
return grpc_metadata_batch_link_tail(&buffer->batch, storage);
}
grpc_error* grpc_chttp2_incoming_metadata_buffer_replace_or_add(

@ -108,7 +108,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
/* fallthrough */
dts_fh_0:
case GRPC_DTS_FH_0:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_frame_size = (static_cast<uint32_t>(*cur)) << 16;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_1;
@ -116,7 +116,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_1:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_frame_size |= (static_cast<uint32_t>(*cur)) << 8;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_2;
@ -124,7 +124,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_2:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_frame_size |= *cur;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_3;
@ -132,7 +132,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_3:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_frame_type = *cur;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_4;
@ -140,7 +140,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_4:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_frame_flags = *cur;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_5;
@ -148,7 +148,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_5:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_stream_id = ((static_cast<uint32_t>(*cur)) & 0x7f) << 24;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_6;
@ -156,7 +156,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_6:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 16;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_7;
@ -164,7 +164,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_7:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_stream_id |= (static_cast<uint32_t>(*cur)) << 8;
if (++cur == end) {
t->deframe_state = GRPC_DTS_FH_8;
@ -172,7 +172,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FH_8:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
t->incoming_stream_id |= (static_cast<uint32_t>(*cur));
t->deframe_state = GRPC_DTS_FRAME;
err = init_frame_parser(t);
@ -208,7 +208,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t,
}
/* fallthrough */
case GRPC_DTS_FRAME:
GPR_ASSERT(cur < end);
GPR_DEBUG_ASSERT(cur < end);
if (static_cast<uint32_t>(end - cur) == t->incoming_frame_size) {
err = parse_frame_slice(
t,
@ -425,7 +425,7 @@ static void on_initial_header(void* tp, grpc_mdelem md) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
grpc_chttp2_stream* s = t->incoming_stream;
GPR_ASSERT(s != nullptr);
GPR_DEBUG_ASSERT(s != nullptr);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
@ -473,7 +473,7 @@ static void on_initial_header(void* tp, grpc_mdelem md) {
const size_t metadata_size_limit =
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
if (new_size > metadata_size_limit) {
if (GPR_UNLIKELY(new_size > metadata_size_limit)) {
gpr_log(GPR_DEBUG,
"received initial metadata size exceeds limit (%" PRIuPTR
" vs. %" PRIuPTR ")",
@ -504,7 +504,7 @@ static void on_trailing_header(void* tp, grpc_mdelem md) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
grpc_chttp2_stream* s = t->incoming_stream;
GPR_ASSERT(s != nullptr);
GPR_DEBUG_ASSERT(s != nullptr);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* key = grpc_slice_to_c_string(GRPC_MDKEY(md));
@ -627,7 +627,7 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
} else {
t->incoming_stream = s;
}
GPR_ASSERT(s != nullptr);
GPR_DEBUG_ASSERT(s != nullptr);
s->stats.incoming.framing_bytes += 9;
if (GPR_UNLIKELY(s->read_closed)) {
GRPC_CHTTP2_IF_TRACING(gpr_log(

@ -174,6 +174,17 @@ struct grpc_slice_refcount {
namespace grpc_core {
struct StaticSliceRefcount {
static grpc_slice_refcount kStaticSubRefcount;
StaticSliceRefcount(uint32_t index)
: base(&kStaticSubRefcount, grpc_slice_refcount::Type::STATIC),
index(index) {}
grpc_slice_refcount base;
uint32_t index;
};
extern grpc_slice_refcount kNoopRefcount;
struct InternedSliceRefcount {

@ -25,4 +25,4 @@
const char* grpc_version_string(void) { return "7.0.0"; }
const char* grpc_g_stands_for(void) { return "gangnam"; }
const char* grpc_g_stands_for(void) { return "ganges"; }

@ -104,7 +104,7 @@ static grpc_error* maybe_link_callout(grpc_metadata_batch* batch,
if (idx == GRPC_BATCH_CALLOUTS_COUNT) {
return GRPC_ERROR_NONE;
}
if (batch->idx.array[idx] == nullptr) {
if (GPR_LIKELY(batch->idx.array[idx] == nullptr)) {
++batch->list.default_count;
batch->idx.array[idx] = storage;
return GRPC_ERROR_NONE;

File diff suppressed because it is too large Load Diff

@ -260,15 +260,18 @@ extern const grpc_core::StaticMetadataSlice
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
(grpc_static_slice_table[105])
extern grpc_slice_refcount
namespace grpc_core {
struct StaticSliceRefcount;
}
extern grpc_core::StaticSliceRefcount
grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT];
#define GRPC_IS_STATIC_METADATA_STRING(slice) \
((slice).refcount != NULL && \
(slice).refcount->GetType() == grpc_slice_refcount::Type::STATIC)
#define GRPC_STATIC_METADATA_INDEX(static_slice) \
(static_cast<intptr_t>( \
((static_slice).refcount - grpc_static_metadata_refcounts)))
#define GRPC_STATIC_METADATA_INDEX(static_slice) \
(reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount) \
->index)
#define GRPC_STATIC_MDELEM_COUNT 85
extern grpc_core::StaticMetadata
@ -519,11 +522,14 @@ typedef union {
} named;
} grpc_metadata_batch_callouts;
#define GRPC_BATCH_INDEX_OF(slice) \
(GRPC_IS_STATIC_METADATA_STRING((slice)) \
? static_cast<grpc_metadata_batch_callouts_index>( \
GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, \
static_cast<intptr_t>(GRPC_BATCH_CALLOUTS_COUNT))) \
#define GRPC_BATCH_INDEX_OF(slice) \
(GRPC_IS_STATIC_METADATA_STRING((slice)) && \
reinterpret_cast<grpc_core::StaticSliceRefcount*>((slice).refcount) \
->index <= static_cast<uint32_t>(GRPC_BATCH_CALLOUTS_COUNT) \
? static_cast<grpc_metadata_batch_callouts_index>( \
reinterpret_cast<grpc_core::StaticSliceRefcount*>( \
(slice).refcount) \
->index) \
: GRPC_BATCH_CALLOUTS_COUNT)
extern const uint8_t grpc_static_accept_encoding_metadata[8];

@ -22,5 +22,5 @@
#include <grpcpp/grpcpp.h>
namespace grpc {
grpc::string Version() { return "1.23.0-dev"; }
grpc::string Version() { return "1.24.0-dev"; }
} // namespace grpc

@ -33,11 +33,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
public const string CurrentAssemblyFileVersion = "2.23.0.0";
public const string CurrentAssemblyFileVersion = "2.24.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
public const string CurrentVersion = "2.23.0-dev";
public const string CurrentVersion = "2.24.0-dev";
}
}

@ -1,7 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
<GrpcCsharpVersion>2.23.0-dev</GrpcCsharpVersion>
<GrpcCsharpVersion>2.24.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.8.0</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -13,7 +13,7 @@
@rem limitations under the License.
@rem Current package versions
set VERSION=2.23.0-dev
set VERSION=2.24.0-dev
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe

@ -42,7 +42,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCCppPlugin'
v = '1.23.0-dev'
v = '1.24.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates C++ files from .proto services.'
s.description = <<-DESC

@ -42,7 +42,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCPlugin'
v = '1.23.0-dev'
v = '1.24.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC

@ -0,0 +1,96 @@
# gRPC Bazel BUILD file.
#
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
licenses(["notice"]) # Apache v2
package(default_visibility = ["//visibility:public"])
load("//bazel:grpc_build_system.bzl", "grpc_objc_library", "grpc_objc_use_cronet_config")
exports_files(["LICENSE"])
grpc_objc_use_cronet_config()
grpc_objc_library(
name = "rx_library",
srcs = glob([
"RxLibrary/*.m",
"RxLibrary/transformations/*.m",
]),
hdrs = glob([
"RxLibrary/*.h",
"RxLibrary/transformations/*.h",
]),
includes = ["."],
deps = [":rx_library_private"],
)
grpc_objc_library(
name = "rx_library_private",
srcs = glob([
"RxLibrary/private/*.m",
]),
textual_hdrs = glob([
"RxLibrary/private/*.h",
]),
visibility = ["//visibility:private"],
)
grpc_objc_library(
name = "grpc_objc_client",
srcs = glob(
[
"GRPCClient/*.m",
"GRPCClient/private/*.m",
],
exclude = ["GRPCClient/GRPCCall+GID.m"],
),
hdrs = glob(
[
"GRPCClient/*.h",
"GRPCClient/internal/*.h",
],
exclude = ["GRPCClient/GRPCCall+GID.h"],
),
data = ["//:gRPCCertificates"],
includes = ["."],
textual_hdrs = glob([
"GRPCClient/private/*.h",
]),
deps = [
":rx_library",
"//:grpc_objc",
],
)
grpc_objc_library(
name = "proto_objc_rpc",
srcs = glob(
["ProtoRPC/*.m"],
),
hdrs = glob(
["ProtoRPC/*.h"],
),
# Different from Cocoapods, do not import as if @com_google_protobuf//:protobuf_objc is a framework,
# use the real paths of @com_google_protobuf//:protobuf_objc instead
defines = ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=0"],
includes = ["src/objective-c"],
deps = [
":grpc_objc_client",
":rx_library",
"@com_google_protobuf//:protobuf_objc",
],
)

@ -22,4 +22,4 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.23.0-dev"
#define GRPC_OBJC_VERSION_STRING @"1.24.0-dev"

@ -0,0 +1,69 @@
# gRPC Bazel BUILD file.
#
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load(
"@com_github_grpc_grpc//bazel:objc_grpc_library.bzl",
"objc_grpc_library",
)
proto_library(
name = "messages_proto",
srcs = ["BazelBuildSamples/messages.proto"],
visibility = ["//visibility:public"],
)
objc_grpc_library(
name = "test_grpc_objc",
srcs = ["BazelBuildSamples/rmt/test.proto"],
use_well_known_protos = True,
deps = [
"//src/objective-c/examples/BazelBuildSamples/rmt:test_proto",
],
)
# Proof that without this works without srcs
objc_grpc_library(
name = "test_objc",
use_well_known_protos = True,
deps = [
"//src/objective-c/examples/BazelBuildSamples/rmt:test_proto",
]
)
objc_library(
name = "ios-sample-lib",
srcs = glob(["BazelBuildSamples/ios-sample/ios-sample/**/*.m"]),
hdrs = glob(["BazelBuildSamples/ios-sample/ios-sample/**/*.h"]),
data = glob([
"BazelBuildSamples/ios-sample/ios-sample/Assets.xcassets/**/*",
"BazelBuildSamples/ios-sample/ios-sample/Base.lproj/**/*"
]),
deps = [
":test_grpc_objc",
]
)
ios_application(
name = "ios-sample",
bundle_id = "com.google.ios-sample-objc-bazel",
families = ["iphone"],
minimum_os_version = "9.0",
infoplists = ["BazelBuildSamples/ios-sample/ios-sample/Info.plist"],
visibility = ["//visibility:public"],
deps = [":ios-sample-lib"],
)

@ -0,0 +1,31 @@
platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
ROOT_DIR = '../../../../..'
target 'ios-sample' do
pod 'gRPC-ProtoRPC', :path => ROOT_DIR
pod 'gRPC', :path => ROOT_DIR
pod 'gRPC-Core', :path => ROOT_DIR
pod 'gRPC-RxLibrary', :path => ROOT_DIR
pod 'RemoteTest', :path => "../../RemoteTestClient"
pod '!ProtoCompiler-gRPCPlugin', :path => "#{ROOT_DIR}/src/objective-c"
end
pre_install do |installer|
grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
src_root = "$(PODS_TARGET_SRCROOT)"
grpc_core_spec.pod_target_xcconfig = {
'GRPC_SRC_ROOT' => src_root,
'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
# If we don't set these two settings, `include/grpc/support/time.h` and
# `src/core/lib/gpr/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
# build.
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
end

@ -0,0 +1,413 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
AB433CC922D7E38000D579CC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AB433CC822D7E38000D579CC /* AppDelegate.m */; };
AB433CCC22D7E38000D579CC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB433CCB22D7E38000D579CC /* ViewController.m */; };
AB433CCF22D7E38000D579CC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB433CCD22D7E38000D579CC /* Main.storyboard */; };
AB433CD122D7E38100D579CC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AB433CD022D7E38100D579CC /* Assets.xcassets */; };
AB433CD422D7E38100D579CC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB433CD222D7E38100D579CC /* LaunchScreen.storyboard */; };
AB433CD722D7E38100D579CC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AB433CD622D7E38100D579CC /* main.m */; };
ED11F6CDF54788FC7CFD87B1 /* libPods-ios-sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5AF80A181E30BD84FA56BE33 /* libPods-ios-sample.a */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
112D4595FA3E81552DA9E877 /* Pods-ios-sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-sample.release.xcconfig"; path = "Target Support Files/Pods-ios-sample/Pods-ios-sample.release.xcconfig"; sourceTree = "<group>"; };
5AF80A181E30BD84FA56BE33 /* libPods-ios-sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios-sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
72599BE4AC5785D3368D40DD /* Pods-ios-sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-sample.debug.xcconfig"; path = "Target Support Files/Pods-ios-sample/Pods-ios-sample.debug.xcconfig"; sourceTree = "<group>"; };
AB433CC422D7E38000D579CC /* ios-sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ios-sample.app"; sourceTree = BUILT_PRODUCTS_DIR; };
AB433CC722D7E38000D579CC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
AB433CC822D7E38000D579CC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
AB433CCA22D7E38000D579CC /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
AB433CCB22D7E38000D579CC /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
AB433CCE22D7E38000D579CC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
AB433CD022D7E38100D579CC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
AB433CD322D7E38100D579CC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
AB433CD522D7E38100D579CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AB433CD622D7E38100D579CC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
AB433CC122D7E38000D579CC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
ED11F6CDF54788FC7CFD87B1 /* libPods-ios-sample.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2A170580B60E92B1A65525D4 /* Pods */ = {
isa = PBXGroup;
children = (
72599BE4AC5785D3368D40DD /* Pods-ios-sample.debug.xcconfig */,
112D4595FA3E81552DA9E877 /* Pods-ios-sample.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
AB433CBB22D7E38000D579CC = {
isa = PBXGroup;
children = (
AB433CC622D7E38000D579CC /* ios-sample */,
AB433CC522D7E38000D579CC /* Products */,
2A170580B60E92B1A65525D4 /* Pods */,
FD148AE940967C50DB2C12CB /* Frameworks */,
);
sourceTree = "<group>";
};
AB433CC522D7E38000D579CC /* Products */ = {
isa = PBXGroup;
children = (
AB433CC422D7E38000D579CC /* ios-sample.app */,
);
name = Products;
sourceTree = "<group>";
};
AB433CC622D7E38000D579CC /* ios-sample */ = {
isa = PBXGroup;
children = (
AB433CC722D7E38000D579CC /* AppDelegate.h */,
AB433CC822D7E38000D579CC /* AppDelegate.m */,
AB433CCA22D7E38000D579CC /* ViewController.h */,
AB433CCB22D7E38000D579CC /* ViewController.m */,
AB433CCD22D7E38000D579CC /* Main.storyboard */,
AB433CD022D7E38100D579CC /* Assets.xcassets */,
AB433CD222D7E38100D579CC /* LaunchScreen.storyboard */,
AB433CD522D7E38100D579CC /* Info.plist */,
AB433CD622D7E38100D579CC /* main.m */,
);
path = "ios-sample";
sourceTree = "<group>";
};
FD148AE940967C50DB2C12CB /* Frameworks */ = {
isa = PBXGroup;
children = (
5AF80A181E30BD84FA56BE33 /* libPods-ios-sample.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
AB433CC322D7E38000D579CC /* ios-sample */ = {
isa = PBXNativeTarget;
buildConfigurationList = AB433CDA22D7E38100D579CC /* Build configuration list for PBXNativeTarget "ios-sample" */;
buildPhases = (
9DD34A50D448CD3F464D4A3C /* [CP] Check Pods Manifest.lock */,
AB433CC022D7E38000D579CC /* Sources */,
AB433CC122D7E38000D579CC /* Frameworks */,
AB433CC222D7E38000D579CC /* Resources */,
630985F7228D41528084692C /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = "ios-sample";
productName = "ios-sample";
productReference = AB433CC422D7E38000D579CC /* ios-sample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
AB433CBC22D7E38000D579CC /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1010;
ORGANIZATIONNAME = "Tony Lu";
TargetAttributes = {
AB433CC322D7E38000D579CC = {
CreatedOnToolsVersion = 10.1;
};
};
};
buildConfigurationList = AB433CBF22D7E38000D579CC /* Build configuration list for PBXProject "ios-sample" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = AB433CBB22D7E38000D579CC;
productRefGroup = AB433CC522D7E38000D579CC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
AB433CC322D7E38000D579CC /* ios-sample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
AB433CC222D7E38000D579CC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AB433CD422D7E38100D579CC /* LaunchScreen.storyboard in Resources */,
AB433CD122D7E38100D579CC /* Assets.xcassets in Resources */,
AB433CCF22D7E38000D579CC /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
630985F7228D41528084692C /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ios-sample/Pods-ios-sample-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ios-sample/Pods-ios-sample-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios-sample/Pods-ios-sample-resources.sh\"\n";
showEnvVarsInLog = 0;
};
9DD34A50D448CD3F464D4A3C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ios-sample-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
AB433CC022D7E38000D579CC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AB433CCC22D7E38000D579CC /* ViewController.m in Sources */,
AB433CD722D7E38100D579CC /* main.m in Sources */,
AB433CC922D7E38000D579CC /* AppDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
AB433CCD22D7E38000D579CC /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
AB433CCE22D7E38000D579CC /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
AB433CD222D7E38100D579CC /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
AB433CD322D7E38100D579CC /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
AB433CD822D7E38100D579CC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
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 = 12.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
AB433CD922D7E38100D579CC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = 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 = 12.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
AB433CDB22D7E38100D579CC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 72599BE4AC5785D3368D40DD /* Pods-ios-sample.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 6T98ZJNPG5;
INFOPLIST_FILE = "ios-sample/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.google.ios-sample-objc-bazel";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
AB433CDC22D7E38100D579CC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 112D4595FA3E81552DA9E877 /* Pods-ios-sample.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 6T98ZJNPG5;
INFOPLIST_FILE = "ios-sample/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.google.ios-sample-objc-bazel";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
AB433CBF22D7E38000D579CC /* Build configuration list for PBXProject "ios-sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
AB433CD822D7E38100D579CC /* Debug */,
AB433CD922D7E38100D579CC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
AB433CDA22D7E38100D579CC /* Build configuration list for PBXNativeTarget "ios-sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
AB433CDB22D7E38100D579CC /* Debug */,
AB433CDC22D7E38100D579CC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = AB433CBC22D7E38000D579CC /* Project object */;
}

@ -0,0 +1,25 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder<UIApplicationDelegate>
@property(strong, nonatomic) UIWindow* window;
@end

@ -0,0 +1,63 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for
// certain types of temporary interruptions (such as an incoming phone call or SMS message) or
// when the user quits the application and it begins the transition to the background state. Use
// this method to pause ongoing tasks, disable timers, and invalidate graphics rendering
// callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store
// enough application state information to restore your application to its current state in case
// it is terminated later. If your application supports background execution, this method is
// called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo
// many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If
// the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also
// applicationDidEnterBackground:.
}
@end

@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iTL-zv-YSZ">
<rect key="frame" x="164" y="318" width="46" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Button"/>
<connections>
<action selector="tapCall:" destination="BYZ-38-t0r" eventType="touchUpInside" id="c5c-m5-SGC"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

@ -0,0 +1,45 @@
<?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_US</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>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

@ -0,0 +1,23 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

@ -0,0 +1,86 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import "ViewController.h"
#import <GRPCClient/GRPCCall.h>
#if COCOAPODS
#import <RemoteTest/Messages.pbobjc.h>
#import <RemoteTest/Test.pbrpc.h>
#else
#import "src/objective-c/examples/BazelBuildSamples/Messages.pbobjc.h"
#import "src/objective-c/examples/BazelBuildSamples/rmt/Test.pbrpc.h"
#endif
static NSString *const kPackage = @"grpc.testing";
static NSString *const kService = @"TestService";
@interface ViewController ()<GRPCResponseHandler>
@end
@implementation ViewController {
GRPCCallOptions *_options;
}
- (void)viewDidLoad {
[super viewDidLoad];
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
// optionally modify options
_options = options;
}
- (IBAction)tapCall:(id)sender {
GRPCProtoMethod *kUnaryCallMethod =
[[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"UnaryCall"];
GRPCRequestOptions *requestOptions =
[[GRPCRequestOptions alloc] initWithHost:@"grpc-test.sandbox.googleapis.com"
path:kUnaryCallMethod.HTTPPath
safety:GRPCCallSafetyCacheableRequest];
GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions
responseHandler:self
callOptions:_options];
RMTSimpleRequest *request = [RMTSimpleRequest message];
request.responseSize = 100;
[call start];
[call writeData:[request data]];
[call finish];
}
- (dispatch_queue_t)dispatchQueue {
return dispatch_get_main_queue();
}
- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata {
NSLog(@"Header: %@", initialMetadata);
}
- (void)didReceiveData:(id)data {
NSLog(@"Message: %@", data);
}
- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
NSLog(@"Trailer: %@\nError: %@", trailingMetadata, error);
}
@end

@ -0,0 +1,26 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

@ -0,0 +1,118 @@
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Message definitions to be used by integration test service definitions.
syntax = "proto3";
package grpc.testing;
option objc_class_prefix = "RMT";
// The type of payload that should be returned.
enum PayloadType {
// Compressable text format.
COMPRESSABLE = 0;
// Uncompressable binary format.
UNCOMPRESSABLE = 1;
// Randomly chosen from all other formats defined in this enum.
RANDOM = 2;
}
// A block of data, to simply increase gRPC message size.
message Payload {
// The type of data in body.
PayloadType type = 1;
// Primary contents of payload.
bytes body = 2;
}
// Unary request.
message SimpleRequest {
// Desired payload type in the response from the server.
// If response_type is RANDOM, server randomly chooses one from other formats.
PayloadType response_type = 1;
// Desired payload size in the response from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
int32 response_size = 2;
// Optional input payload sent along with the request.
Payload payload = 3;
// Whether SimpleResponse should include username.
bool fill_username = 4;
// Whether SimpleResponse should include OAuth scope.
bool fill_oauth_scope = 5;
}
// Unary response, as configured by the request.
message SimpleResponse {
// Payload to increase message size.
Payload payload = 1;
// The user the request came from, for verifying authentication was
// successful when the client expected it.
string username = 2;
// OAuth scope.
string oauth_scope = 3;
}
// Client-streaming request.
message StreamingInputCallRequest {
// Optional input payload sent along with the request.
Payload payload = 1;
// Not expecting any payload from the response.
}
// Client-streaming response.
message StreamingInputCallResponse {
// Aggregated size of payloads received from the client.
int32 aggregated_payload_size = 1;
}
// Configuration for a particular response.
message ResponseParameters {
// Desired payload sizes in responses from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
int32 size = 1;
// Desired interval between consecutive responses in the response stream in
// microseconds.
int32 interval_us = 2;
}
// Server-streaming request.
message StreamingOutputCallRequest {
// Desired payload type in the response from the server.
// If response_type is RANDOM, the payload from each response in the stream
// might be of different types. This is to simulate a mixed type of payload
// stream.
PayloadType response_type = 1;
// Configuration for each expected response message.
repeated ResponseParameters response_parameters = 2;
// Optional input payload sent along with the request.
Payload payload = 3;
}
// Server-streaming response, as configured by the request and parameters.
message StreamingOutputCallResponse {
// Payload to increase response size.
Payload payload = 1;
}

@ -0,0 +1,28 @@
# gRPC Bazel BUILD file.
#
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
licenses(["notice"]) # Apache v2
package(default_visibility = ["//visibility:public"])
exports_files(["LICENSE"])
proto_library(
name = "test_proto",
srcs = ["test.proto"],
deps = ["//src/objective-c/examples:messages_proto"],
visibility = ["//visibility:public"],
)

@ -0,0 +1,57 @@
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses.
syntax = "proto3";
import "google/protobuf/empty.proto";
import "src/objective-c/examples/BazelBuildSamples/messages.proto";
package grpc.testing;
option objc_class_prefix = "RMT";
// A simple service to test the various types of RPCs and experiment with
// performance with various types of payload.
service TestService {
// One empty request followed by one empty response.
rpc EmptyCall(google.protobuf.Empty) returns (google.protobuf.Empty);
// One request followed by one response.
rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
rpc StreamingOutputCall(StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
rpc StreamingInputCall(stream StreamingInputCallRequest)
returns (StreamingInputCallResponse);
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
rpc FullDuplexCall(stream StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
rpc HalfDuplexCall(stream StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
}

@ -20,8 +20,8 @@
#import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCCallOptions.h>
#import <RemoteTest/Messages.pbobjc.h>
#import <RemoteTest/Test.pbrpc.h>
#import "src/objective-c/tests/RemoteTestClient/Messages.pbobjc.h"
#import "src/objective-c/tests/RemoteTestClient/Test.pbrpc.h"
NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com";
const int32_t kMessageSize = 100;

@ -22,5 +22,5 @@
// instead. This file can be regenerated from the template by running
// `tools/buildgen/generate_projects.sh`.
#define GRPC_OBJC_VERSION_STRING @"1.23.0-dev"
#define GRPC_OBJC_VERSION_STRING @"1.24.0-dev"
#define GRPC_C_VERSION_STRING @"7.0.0"

@ -2,7 +2,7 @@
"name": "grpc/grpc-dev",
"description": "gRPC library for PHP - for Developement use only",
"license": "Apache-2.0",
"version": "1.23.0",
"version": "1.24.0",
"require": {
"php": ">=5.5.0",
"google/protobuf": "^v3.3.0"

@ -20,6 +20,6 @@
#ifndef VERSION_H
#define VERSION_H
#define PHP_GRPC_VERSION "1.23.0dev"
#define PHP_GRPC_VERSION "1.24.0dev"
#endif /* VERSION_H */

@ -13,6 +13,7 @@
# limitations under the License.
"""Invocation-side implementation of gRPC Python."""
import functools
import logging
import sys
import threading
@ -81,17 +82,6 @@ def _unknown_code_details(unknown_cygrpc_code, details):
unknown_cygrpc_code, details)
def _wait_once_until(condition, until):
if until is None:
condition.wait()
else:
remaining = until - time.time()
if remaining < 0:
raise grpc.FutureTimeoutError()
else:
condition.wait(timeout=remaining)
class _RPCState(object):
def __init__(self, due, initial_metadata, trailing_metadata, code, details):
@ -178,12 +168,11 @@ def _event_handler(state, response_deserializer):
#pylint: disable=too-many-statements
def _consume_request_iterator(request_iterator, state, call, request_serializer,
event_handler):
if cygrpc.is_fork_support_enabled():
condition_wait_timeout = 1.0
else:
condition_wait_timeout = None
"""Consume a request iterator supplied by the user."""
def consume_request_iterator(): # pylint: disable=too-many-branches
# Iterate over the request iterator until it is exhausted or an error
# condition is encountered.
while True:
return_from_user_request_generator_invoked = False
try:
@ -224,14 +213,19 @@ def _consume_request_iterator(request_iterator, state, call, request_serializer,
state.due.add(cygrpc.OperationType.send_message)
else:
return
while True:
state.condition.wait(condition_wait_timeout)
cygrpc.block_if_fork_in_progress(state)
if state.code is None:
if cygrpc.OperationType.send_message not in state.due:
break
else:
return
def _done():
return (state.code is not None or
cygrpc.OperationType.send_message not in
state.due)
_common.wait(
state.condition.wait,
_done,
spin_cb=functools.partial(
cygrpc.block_if_fork_in_progress, state))
if state.code is not None:
return
else:
return
with state.condition:
@ -281,13 +275,21 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too
with self._state.condition:
return self._state.code is not None
def _is_complete(self):
return self._state.code is not None
def result(self, timeout=None):
until = None if timeout is None else time.time() + timeout
"""Returns the result of the computation or raises its exception.
See grpc.Future.result for the full API contract.
"""
with self._state.condition:
while True:
if self._state.code is None:
_wait_once_until(self._state.condition, until)
elif self._state.code is grpc.StatusCode.OK:
timed_out = _common.wait(
self._state.condition.wait, self._is_complete, timeout=timeout)
if timed_out:
raise grpc.FutureTimeoutError()
else:
if self._state.code is grpc.StatusCode.OK:
return self._state.response
elif self._state.cancelled:
raise grpc.FutureCancelledError()
@ -295,12 +297,17 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too
raise self
def exception(self, timeout=None):
until = None if timeout is None else time.time() + timeout
"""Return the exception raised by the computation.
See grpc.Future.exception for the full API contract.
"""
with self._state.condition:
while True:
if self._state.code is None:
_wait_once_until(self._state.condition, until)
elif self._state.code is grpc.StatusCode.OK:
timed_out = _common.wait(
self._state.condition.wait, self._is_complete, timeout=timeout)
if timed_out:
raise grpc.FutureTimeoutError()
else:
if self._state.code is grpc.StatusCode.OK:
return None
elif self._state.cancelled:
raise grpc.FutureCancelledError()
@ -308,12 +315,17 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too
return self
def traceback(self, timeout=None):
until = None if timeout is None else time.time() + timeout
"""Access the traceback of the exception raised by the computation.
See grpc.future.traceback for the full API contract.
"""
with self._state.condition:
while True:
if self._state.code is None:
_wait_once_until(self._state.condition, until)
elif self._state.code is grpc.StatusCode.OK:
timed_out = _common.wait(
self._state.condition.wait, self._is_complete, timeout=timeout)
if timed_out:
raise grpc.FutureTimeoutError()
else:
if self._state.code is grpc.StatusCode.OK:
return None
elif self._state.cancelled:
raise grpc.FutureCancelledError()
@ -345,17 +357,23 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too
raise StopIteration()
else:
raise self
while True:
self._state.condition.wait()
if self._state.response is not None:
response = self._state.response
self._state.response = None
return response
elif cygrpc.OperationType.receive_message not in self._state.due:
if self._state.code is grpc.StatusCode.OK:
raise StopIteration()
elif self._state.code is not None:
raise self
def _response_ready():
return (
self._state.response is not None or
(cygrpc.OperationType.receive_message not in self._state.due
and self._state.code is not None))
_common.wait(self._state.condition.wait, _response_ready)
if self._state.response is not None:
response = self._state.response
self._state.response = None
return response
elif cygrpc.OperationType.receive_message not in self._state.due:
if self._state.code is grpc.StatusCode.OK:
raise StopIteration()
elif self._state.code is not None:
raise self
def __iter__(self):
return self
@ -386,32 +404,47 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too
def initial_metadata(self):
with self._state.condition:
while self._state.initial_metadata is None:
self._state.condition.wait()
def _done():
return self._state.initial_metadata is not None
_common.wait(self._state.condition.wait, _done)
return self._state.initial_metadata
def trailing_metadata(self):
with self._state.condition:
while self._state.trailing_metadata is None:
self._state.condition.wait()
def _done():
return self._state.trailing_metadata is not None
_common.wait(self._state.condition.wait, _done)
return self._state.trailing_metadata
def code(self):
with self._state.condition:
while self._state.code is None:
self._state.condition.wait()
def _done():
return self._state.code is not None
_common.wait(self._state.condition.wait, _done)
return self._state.code
def details(self):
with self._state.condition:
while self._state.details is None:
self._state.condition.wait()
def _done():
return self._state.details is not None
_common.wait(self._state.condition.wait, _done)
return _common.decode(self._state.details)
def debug_error_string(self):
with self._state.condition:
while self._state.debug_error_string is None:
self._state.condition.wait()
def _done():
return self._state.debug_error_string is not None
_common.wait(self._state.condition.wait, _done)
return _common.decode(self._state.debug_error_string)
def _repr(self):

@ -15,6 +15,7 @@
import logging
import time
import six
import grpc
@ -60,6 +61,8 @@ STATUS_CODE_TO_CYGRPC_STATUS_CODE = {
CYGRPC_STATUS_CODE_TO_STATUS_CODE)
}
MAXIMUM_WAIT_TIMEOUT = 0.1
def encode(s):
if isinstance(s, bytes):
@ -96,3 +99,50 @@ def deserialize(serialized_message, deserializer):
def fully_qualified_method(group, method):
return '/{}/{}'.format(group, method)
def _wait_once(wait_fn, timeout, spin_cb):
wait_fn(timeout=timeout)
if spin_cb is not None:
spin_cb()
def wait(wait_fn, wait_complete_fn, timeout=None, spin_cb=None):
"""Blocks waiting for an event without blocking the thread indefinitely.
See https://github.com/grpc/grpc/issues/19464 for full context. CPython's
`threading.Event.wait` and `threading.Condition.wait` methods, if invoked
without a timeout kwarg, may block the calling thread indefinitely. If the
call is made from the main thread, this means that signal handlers may not
run for an arbitrarily long period of time.
This wrapper calls the supplied wait function with an arbitrary short
timeout to ensure that no signal handler has to wait longer than
MAXIMUM_WAIT_TIMEOUT before executing.
Args:
wait_fn: A callable acceptable a single float-valued kwarg named
`timeout`. This function is expected to be one of `threading.Event.wait`
or `threading.Condition.wait`.
wait_complete_fn: A callable taking no arguments and returning a bool.
When this function returns true, it indicates that waiting should cease.
timeout: An optional float-valued number of seconds after which the wait
should cease.
spin_cb: An optional Callable taking no arguments and returning nothing.
This callback will be called on each iteration of the spin. This may be
used for, e.g. work related to forking.
Returns:
True if a timeout was supplied and it was reached. False otherwise.
"""
if timeout is None:
while not wait_complete_fn():
_wait_once(wait_fn, MAXIMUM_WAIT_TIMEOUT, spin_cb)
else:
end = time.time() + timeout
while not wait_complete_fn():
remaining = min(end - time.time(), MAXIMUM_WAIT_TIMEOUT)
if remaining < 0:
return True
_wait_once(wait_fn, remaining, spin_cb)
return False

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
__version__ = """1.23.0.dev0"""
__version__ = """1.24.0.dev0"""

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -145,6 +145,8 @@ class TestGevent(setuptools.Command):
'unit._exit_test.ExitTest.test_in_flight_partial_unary_stream_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_unary_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_stream_call',
# TODO(https://github.com/grpc/grpc/issues/18980): Reenable.
'unit._signal_handling_test.SignalHandlingTest',
'unit._metadata_flags_test',
'health_check._health_servicer_test.HealthServicerTest.test_cancelled_watch_removed_from_watch_list',
# TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -67,6 +67,7 @@
"unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithoutClientAuth",
"unit._server_test.ServerTest",
"unit._session_cache_test.SSLSessionCacheTest",
"unit._signal_handling_test.SignalHandlingTest",
"unit._version_test.VersionTest",
"unit.beta._beta_features_test.BetaFeaturesTest",
"unit.beta._beta_features_test.ContextManagementAndLifecycleTest",

@ -14,6 +14,7 @@ GRPCIO_TESTS_UNIT = [
"_credentials_test.py",
"_dns_resolver_test.py",
"_empty_message_test.py",
"_error_message_encoding_test.py",
"_exit_test.py",
"_interceptor_test.py",
"_invalid_metadata_test.py",
@ -25,6 +26,7 @@ GRPCIO_TESTS_UNIT = [
# "_reconnect_test.py",
"_resource_exhausted_test.py",
"_rpc_test.py",
"_signal_handling_test.py",
# TODO(ghostwriternr): To be added later.
# "_server_ssl_cert_config_test.py",
"_server_test.py",
@ -37,6 +39,11 @@ py_library(
srcs = ["_tcp_proxy.py"],
)
py_library(
name = "_signal_client",
srcs = ["_signal_client.py"],
)
py_library(
name = "resources",
srcs = ["resources.py"],
@ -85,6 +92,7 @@ py_library(
":_server_shutdown_scenarios",
":_from_grpc_import_star",
":_tcp_proxy",
":_signal_client",
"//src/python/grpcio_tests/tests/unit/framework/common",
"//src/python/grpcio_tests/tests/testing",
"//external:six"

@ -0,0 +1,84 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Client for testing responsiveness to signals."""
from __future__ import print_function
import argparse
import functools
import logging
import signal
import sys
import grpc
SIGTERM_MESSAGE = "Handling sigterm!"
UNARY_UNARY = "/test/Unary"
UNARY_STREAM = "/test/ServerStreaming"
_MESSAGE = b'\x00\x00\x00'
_ASSERTION_MESSAGE = "Control flow should never reach here."
# NOTE(gnossen): We use a global variable here so that the signal handler can be
# installed before the RPC begins. If we do not do this, then we may receive the
# SIGINT before the signal handler is installed. I'm not happy with per-process
# global state, but the per-process global state that is signal handlers
# somewhat forces my hand.
per_process_rpc_future = None
def handle_sigint(unused_signum, unused_frame):
print(SIGTERM_MESSAGE)
if per_process_rpc_future is not None:
per_process_rpc_future.cancel()
sys.stderr.flush()
sys.exit(0)
def main_unary(server_target):
"""Initiate a unary RPC to be interrupted by a SIGINT."""
global per_process_rpc_future # pylint: disable=global-statement
with grpc.insecure_channel(server_target) as channel:
multicallable = channel.unary_unary(UNARY_UNARY)
signal.signal(signal.SIGINT, handle_sigint)
per_process_rpc_future = multicallable.future(
_MESSAGE, wait_for_ready=True)
result = per_process_rpc_future.result()
assert False, _ASSERTION_MESSAGE
def main_streaming(server_target):
"""Initiate a streaming RPC to be interrupted by a SIGINT."""
global per_process_rpc_future # pylint: disable=global-statement
with grpc.insecure_channel(server_target) as channel:
signal.signal(signal.SIGINT, handle_sigint)
per_process_rpc_future = channel.unary_stream(UNARY_STREAM)(
_MESSAGE, wait_for_ready=True)
for result in per_process_rpc_future:
pass
assert False, _ASSERTION_MESSAGE
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Signal test client.')
parser.add_argument('server', help='Server target')
parser.add_argument(
'arity', help='RPC arity', choices=('unary', 'streaming'))
args = parser.parse_args()
if args.arity == 'unary':
main_unary(args.server)
else:
main_streaming(args.server)

@ -0,0 +1,172 @@
# Copyright 2019 the gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test of responsiveness to signals."""
import logging
import os
import signal
import subprocess
import tempfile
import threading
import unittest
import sys
import grpc
from tests.unit import test_common
from tests.unit import _signal_client
_CLIENT_PATH = None
if sys.executable is not None:
_CLIENT_PATH = os.path.abspath(os.path.realpath(_signal_client.__file__))
else:
# NOTE(rbellevi): For compatibility with internal testing.
if len(sys.argv) != 2:
raise RuntimeError("Must supply path to executable client.")
client_name = sys.argv[1].split("/")[-1]
del sys.argv[1] # For compatibility with test runner.
_CLIENT_PATH = os.path.realpath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), client_name))
_HOST = 'localhost'
class _GenericHandler(grpc.GenericRpcHandler):
def __init__(self):
self._connected_clients_lock = threading.RLock()
self._connected_clients_event = threading.Event()
self._connected_clients = 0
self._unary_unary_handler = grpc.unary_unary_rpc_method_handler(
self._handle_unary_unary)
self._unary_stream_handler = grpc.unary_stream_rpc_method_handler(
self._handle_unary_stream)
def _on_client_connect(self):
with self._connected_clients_lock:
self._connected_clients += 1
self._connected_clients_event.set()
def _on_client_disconnect(self):
with self._connected_clients_lock:
self._connected_clients -= 1
if self._connected_clients == 0:
self._connected_clients_event.clear()
def await_connected_client(self):
"""Blocks until a client connects to the server."""
self._connected_clients_event.wait()
def _handle_unary_unary(self, request, servicer_context):
"""Handles a unary RPC.
Blocks until the client disconnects and then echoes.
"""
stop_event = threading.Event()
def on_rpc_end():
self._on_client_disconnect()
stop_event.set()
servicer_context.add_callback(on_rpc_end)
self._on_client_connect()
stop_event.wait()
return request
def _handle_unary_stream(self, request, servicer_context):
"""Handles a server streaming RPC.
Blocks until the client disconnects and then echoes.
"""
stop_event = threading.Event()
def on_rpc_end():
self._on_client_disconnect()
stop_event.set()
servicer_context.add_callback(on_rpc_end)
self._on_client_connect()
stop_event.wait()
yield request
def service(self, handler_call_details):
if handler_call_details.method == _signal_client.UNARY_UNARY:
return self._unary_unary_handler
elif handler_call_details.method == _signal_client.UNARY_STREAM:
return self._unary_stream_handler
else:
return None
def _read_stream(stream):
stream.seek(0)
return stream.read()
def _start_client(args, stdout, stderr):
invocation = None
if sys.executable is not None:
invocation = (sys.executable, _CLIENT_PATH) + tuple(args)
else:
invocation = (_CLIENT_PATH,) + tuple(args)
return subprocess.Popen(invocation, stdout=stdout, stderr=stderr)
class SignalHandlingTest(unittest.TestCase):
def setUp(self):
self._server = test_common.test_server()
self._port = self._server.add_insecure_port('{}:0'.format(_HOST))
self._handler = _GenericHandler()
self._server.add_generic_rpc_handlers((self._handler,))
self._server.start()
def tearDown(self):
self._server.stop(None)
@unittest.skipIf(os.name == 'nt', 'SIGINT not supported on windows')
def testUnary(self):
"""Tests that the server unary code path does not stall signal handlers."""
server_target = '{}:{}'.format(_HOST, self._port)
with tempfile.TemporaryFile(mode='r') as client_stdout:
with tempfile.TemporaryFile(mode='r') as client_stderr:
client = _start_client((server_target, 'unary'), client_stdout,
client_stderr)
self._handler.await_connected_client()
client.send_signal(signal.SIGINT)
self.assertFalse(client.wait(), msg=_read_stream(client_stderr))
client_stdout.seek(0)
self.assertIn(_signal_client.SIGTERM_MESSAGE,
client_stdout.read())
@unittest.skipIf(os.name == 'nt', 'SIGINT not supported on windows')
def testStreaming(self):
"""Tests that the server streaming code path does not stall signal handlers."""
server_target = '{}:{}'.format(_HOST, self._port)
with tempfile.TemporaryFile(mode='r') as client_stdout:
with tempfile.TemporaryFile(mode='r') as client_stderr:
client = _start_client((server_target, 'streaming'),
client_stdout, client_stderr)
self._handler.await_connected_client()
client.send_signal(signal.SIGINT)
self.assertFalse(client.wait(), msg=_read_stream(client_stderr))
client_stdout.seek(0)
self.assertIn(_signal_client.SIGTERM_MESSAGE,
client_stdout.read())
if __name__ == '__main__':
logging.basicConfig()
unittest.main(verbosity=2)

@ -14,5 +14,5 @@
# GRPC contains the General RPC module.
module GRPC
VERSION = '1.23.0.dev'
VERSION = '1.24.0.dev'
end

@ -14,6 +14,6 @@
module GRPC
module Tools
VERSION = '1.23.0.dev'
VERSION = '1.24.0.dev'
end
end

@ -165,6 +165,24 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "delegating_channel_test",
srcs = ["delegating_channel_test.cc"],
external_deps = [
"gtest",
],
deps = [
":test_service_impl",
"//:gpr",
"//:grpc",
"//:grpc++",
"//src/proto/grpc/testing:echo_messages_proto",
"//src/proto/grpc/testing:echo_proto",
"//test/core/util:grpc_test_util",
"//test/cpp/util:test_util",
],
)
grpc_cc_test(
name = "client_interceptors_end2end_test",
srcs = ["client_interceptors_end2end_test.cc"],

@ -0,0 +1,100 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <memory>
#include <vector>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/generic/generic_stub.h>
#include <grpcpp/impl/codegen/delegating_channel.h>
#include <grpcpp/impl/codegen/proto_utils.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include <grpcpp/support/client_interceptor.h>
#include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/end2end/test_service_impl.h"
#include "test/cpp/util/byte_buffer_proto_helper.h"
#include "test/cpp/util/string_ref_helper.h"
#include <gtest/gtest.h>
namespace grpc {
namespace testing {
namespace {
class TestChannel : public experimental::DelegatingChannel {
public:
TestChannel(const std::shared_ptr<ChannelInterface>& delegate_channel)
: experimental::DelegatingChannel(delegate_channel) {}
// Always returns GRPC_CHANNEL_READY
grpc_connectivity_state GetState(bool try_to_connect) override {
return GRPC_CHANNEL_READY;
}
};
class DelegatingChannelTest : public ::testing::Test {
protected:
DelegatingChannelTest() {
int port = grpc_pick_unused_port_or_die();
ServerBuilder builder;
server_address_ = "localhost:" + std::to_string(port);
builder.AddListeningPort(server_address_, InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
}
~DelegatingChannelTest() { server_->Shutdown(); }
std::string server_address_;
TestServiceImpl service_;
std::unique_ptr<Server> server_;
};
TEST_F(DelegatingChannelTest, SimpleTest) {
auto channel = CreateChannel(server_address_, InsecureChannelCredentials());
std::shared_ptr<TestChannel> test_channel =
std::make_shared<TestChannel>(channel);
// gRPC channel should be in idle state at this point but our test channel
// will return ready.
EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE);
EXPECT_EQ(test_channel->GetState(false), GRPC_CHANNEL_READY);
auto stub = grpc::testing::EchoTestService::NewStub(test_channel);
ClientContext ctx;
EchoRequest req;
req.set_message("Hello");
EchoResponse resp;
Status s = stub->Echo(&ctx, req, &resp);
EXPECT_EQ(s.ok(), true);
EXPECT_EQ(resp.message(), "Hello");
}
} // namespace
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -393,7 +393,7 @@ for i, elem in enumerate(all_strs):
def slice_def(i):
return (
'grpc_core::StaticMetadataSlice(&grpc_static_metadata_refcounts[%d], %d, g_bytes+%d)'
'grpc_core::StaticMetadataSlice(&grpc_static_metadata_refcounts[%d].base, %d, g_bytes+%d)'
) % (i, len(all_strs[i]), id2strofs[i])
@ -416,14 +416,14 @@ print >> H
print >> C, 'static uint8_t g_bytes[] = {%s};' % (','.join(
'%d' % ord(c) for c in ''.join(all_strs)))
print >> C
print >> C, ('static grpc_slice_refcount static_sub_refcnt;')
print >> H, ('extern grpc_slice_refcount '
print >> H, ('namespace grpc_core { struct StaticSliceRefcount; }')
print >> H, ('extern grpc_core::StaticSliceRefcount '
'grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT];')
print >> C, ('grpc_slice_refcount '
print >> C, 'grpc_slice_refcount grpc_core::StaticSliceRefcount::kStaticSubRefcount;'
print >> C, ('grpc_core::StaticSliceRefcount '
'grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = {')
for i, elem in enumerate(all_strs):
print >> C, (' grpc_slice_refcount(&static_sub_refcnt, '
'grpc_slice_refcount::Type::STATIC), ')
print >> C, ' grpc_core::StaticSliceRefcount(%d), ' % i
print >> C, '};'
print >> C
print >> H, '#define GRPC_IS_STATIC_METADATA_STRING(slice) \\'
@ -438,8 +438,7 @@ for i, elem in enumerate(all_strs):
print >> C, '};'
print >> C
print >> H, '#define GRPC_STATIC_METADATA_INDEX(static_slice) \\'
print >> H, (' (static_cast<intptr_t>(((static_slice).refcount - '
'grpc_static_metadata_refcounts)))')
print >> H, '(reinterpret_cast<grpc_core::StaticSliceRefcount*>((static_slice).refcount)->index)'
print >> H
print >> D, '# hpack fuzzing dictionary'
@ -598,8 +597,26 @@ for elem in METADATA_BATCH_CALLOUTS:
print >> H, ' } named;'
print >> H, '} grpc_metadata_batch_callouts;'
print >> H
print >> H, '#define GRPC_BATCH_INDEX_OF(slice) \\'
print >> H, ' (GRPC_IS_STATIC_METADATA_STRING((slice)) ? static_cast<grpc_metadata_batch_callouts_index>(GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, static_cast<intptr_t>(GRPC_BATCH_CALLOUTS_COUNT))) : GRPC_BATCH_CALLOUTS_COUNT)'
batch_idx_of_hdr = '#define GRPC_BATCH_INDEX_OF(slice) \\'
static_slice = 'GRPC_IS_STATIC_METADATA_STRING((slice))'
slice_to_slice_ref = '(slice).refcount'
static_slice_ref_type = 'grpc_core::StaticSliceRefcount*'
slice_ref_as_static = ('reinterpret_cast<' + static_slice_ref_type + '>(' +
slice_to_slice_ref + ')')
slice_ref_idx = slice_ref_as_static + '->index'
batch_idx_type = 'grpc_metadata_batch_callouts_index'
slice_ref_idx_to_batch_idx = (
'static_cast<' + batch_idx_type + '>(' + slice_ref_idx + ')')
batch_invalid_idx = 'GRPC_BATCH_CALLOUTS_COUNT'
batch_invalid_u32 = 'static_cast<uint32_t>(' + batch_invalid_idx + ')'
# Assemble GRPC_BATCH_INDEX_OF(slice) macro as a join for ease of reading.
batch_idx_of_pieces = [
batch_idx_of_hdr, '\n', '(', static_slice, '&&', slice_ref_idx, '<=',
batch_invalid_u32, '?', slice_ref_idx_to_batch_idx, ':', batch_invalid_idx,
')'
]
print >> H, ''.join(batch_idx_of_pieces)
print >> H
print >> H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (

@ -14,4 +14,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
VERSION = '1.23.0.dev0'
VERSION = '1.24.0.dev0'

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.23.0-dev
PROJECT_NUMBER = 1.24.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -972,6 +972,7 @@ include/grpcpp/impl/codegen/config_protobuf.h \
include/grpcpp/impl/codegen/core_codegen.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \

@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.23.0-dev
PROJECT_NUMBER = 1.24.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -974,6 +974,7 @@ include/grpcpp/impl/codegen/core_codegen.h \
include/grpcpp/impl/codegen/core_codegen.h \
include/grpcpp/impl/codegen/core_codegen_interface.h \
include/grpcpp/impl/codegen/create_auth_context.h \
include/grpcpp/impl/codegen/delegating_channel.h \
include/grpcpp/impl/codegen/grpc_library.h \
include/grpcpp/impl/codegen/intercepted_channel.h \
include/grpcpp/impl/codegen/interceptor.h \

@ -3686,6 +3686,24 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c++",
"name": "delegating_channel_test",
"src": [
"test/cpp/end2end/delegating_channel_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -10400,6 +10418,7 @@
"include/grpcpp/impl/codegen/config.h",
"include/grpcpp/impl/codegen/core_codegen_interface.h",
"include/grpcpp/impl/codegen/create_auth_context.h",
"include/grpcpp/impl/codegen/delegating_channel.h",
"include/grpcpp/impl/codegen/grpc_library.h",
"include/grpcpp/impl/codegen/intercepted_channel.h",
"include/grpcpp/impl/codegen/interceptor.h",
@ -10485,6 +10504,7 @@
"include/grpcpp/impl/codegen/config.h",
"include/grpcpp/impl/codegen/core_codegen_interface.h",
"include/grpcpp/impl/codegen/create_auth_context.h",
"include/grpcpp/impl/codegen/delegating_channel.h",
"include/grpcpp/impl/codegen/grpc_library.h",
"include/grpcpp/impl/codegen/intercepted_channel.h",
"include/grpcpp/impl/codegen/interceptor.h",

@ -4545,6 +4545,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "delegating_channel_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

@ -63,6 +63,7 @@ _GRPC_DEP_NAMES = [
_ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
_TWISTED_CONSTANTLY_DEP_NAME,
'io_bazel_rules_go',
'build_bazel_rules_apple',
]
_GRPC_BAZEL_ONLY_DEPS = [
@ -76,6 +77,7 @@ _GRPC_BAZEL_ONLY_DEPS = [
_ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
_TWISTED_CONSTANTLY_DEP_NAME,
'io_bazel_rules_go',
'build_bazel_rules_apple',
]
@ -106,6 +108,13 @@ class BazelEvalState(object):
return
self.names_and_urls[args['name']] = args['url']
def git_repository(self, **args):
assert self.names_and_urls.get(args['name']) is None
if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
self.names_and_urls[args['name']] = 'dont care'
return
self.names_and_urls[args['name']] = args['remote']
# Parse git hashes from bazel/grpc_deps.bzl {new_}http_archive rules
with open(os.path.join('bazel', 'grpc_deps.bzl'), 'r') as f:
@ -121,6 +130,7 @@ build_rules = {
'native': eval_state,
'http_archive': lambda **args: eval_state.http_archive(**args),
'load': lambda a, b: None,
'git_repository': lambda **args: eval_state.git_repository(**args),
}
exec bazel_file in build_rules
for name in _GRPC_DEP_NAMES:
@ -162,6 +172,7 @@ for name in _GRPC_DEP_NAMES:
'native': state,
'http_archive': lambda **args: state.http_archive(**args),
'load': lambda a, b: None,
'git_repository': lambda **args: state.git_repository(**args),
}
exec bazel_file in rules
assert name not in names_and_urls_with_overridden_name.keys()

Loading…
Cancel
Save