Merge branch 'master' into epollerr

pull/15092/head
Yash Tibrewal 7 years ago
commit dddf207932
  1. 11
      .pylintrc
  2. 11
      .pylintrc-tests
  3. 19
      BUILD
  4. 3
      CMakeLists.txt
  5. 21
      Makefile
  6. 15
      bazel/cc_grpc_library.bzl
  7. 8
      bazel/grpc_deps.bzl
  8. 13
      build.yaml
  9. 15
      examples/ruby/pubsub/.gitignore
  10. 4
      examples/ruby/pubsub/Gemfile
  11. 0
      examples/ruby/pubsub/google/protobuf/empty.rb
  12. 0
      examples/ruby/pubsub/pubsub_demo.rb
  13. 0
      examples/ruby/pubsub/tech/pubsub/proto/pubsub.rb
  14. 0
      examples/ruby/pubsub/tech/pubsub/proto/pubsub_services.rb
  15. 19
      gRPC-Core.podspec
  16. 23
      gRPC-ProtoRPC.podspec
  17. 10
      gRPC.podspec
  18. 6
      grpc.gemspec
  19. 2
      grpc.gyp
  20. 2
      include/grpc/impl/codegen/grpc_types.h
  21. 3
      include/grpc/impl/codegen/port_platform.h
  22. 7
      include/grpcpp/impl/codegen/call.h
  23. 41
      setup.py
  24. 19
      src/compiler/csharp_generator.cc
  25. 404
      src/core/ext/filters/client_channel/client_channel.cc
  26. 4
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  27. 12
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  28. 16
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  29. 7
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  30. 183
      src/core/lib/iomgr/cfstream_handle.cc
  31. 80
      src/core/lib/iomgr/cfstream_handle.h
  32. 372
      src/core/lib/iomgr/endpoint_cfstream.cc
  33. 49
      src/core/lib/iomgr/endpoint_cfstream.h
  34. 12
      src/core/lib/iomgr/error.cc
  35. 5
      src/core/lib/iomgr/error.h
  36. 52
      src/core/lib/iomgr/error_cfstream.cc
  37. 31
      src/core/lib/iomgr/error_cfstream.h
  38. 4
      src/core/lib/iomgr/ev_epoll1_linux.cc
  39. 4
      src/core/lib/iomgr/ev_epollex_linux.cc
  40. 2
      src/core/lib/iomgr/ev_epollsig_linux.cc
  41. 4
      src/core/lib/iomgr/ev_poll_posix.cc
  42. 4
      src/core/lib/iomgr/ev_posix.cc
  43. 4
      src/core/lib/iomgr/iomgr_posix.cc
  44. 11
      src/core/lib/iomgr/polling_entity.cc
  45. 39
      src/core/lib/iomgr/port.h
  46. 2
      src/core/lib/iomgr/resolve_address.h
  47. 2
      src/core/lib/iomgr/resolve_address_posix.cc
  48. 2
      src/core/lib/iomgr/sockaddr_posix.h
  49. 2
      src/core/lib/iomgr/socket_factory_posix.cc
  50. 2
      src/core/lib/iomgr/socket_utils_common_posix.cc
  51. 216
      src/core/lib/iomgr/tcp_client_cfstream.cc
  52. 6
      src/core/lib/iomgr/tcp_client_custom.cc
  53. 2
      src/core/lib/iomgr/tcp_client_posix.cc
  54. 24
      src/core/lib/iomgr/tcp_posix.cc
  55. 4
      src/core/lib/iomgr/tcp_server_posix.cc
  56. 4
      src/core/lib/iomgr/tcp_server_utils_posix_common.cc
  57. 16
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  58. 2
      src/core/lib/security/credentials/oauth2/oauth2_credentials.h
  59. 4
      src/core/lib/security/util/json_util.cc
  60. 12
      src/core/lib/slice/slice_buffer.cc
  61. 1
      src/core/lib/surface/call.cc
  62. 3
      src/core/lib/transport/transport.cc
  63. 12
      src/core/lib/transport/transport.h
  64. 8
      src/cpp/server/server_builder.cc
  65. 25
      src/csharp/Grpc.Core.NativeDebug.nuspec
  66. 2
      src/csharp/Grpc.Examples/MathGrpc.cs
  67. 2
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  68. 2
      src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs
  69. 38
      src/csharp/Grpc.IntegrationTesting/EmptyService.cs
  70. 85
      src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs
  71. 2
      src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
  72. 2
      src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs
  73. 2
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  74. 2
      src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs
  75. 2
      src/csharp/Grpc.Reflection/ReflectionGrpc.cs
  76. 1
      src/csharp/build_packages_dotnetcli.bat
  77. 1
      src/csharp/build_packages_dotnetcli.sh
  78. 2
      src/csharp/generate_proto_csharp.sh
  79. 5
      src/objective-c/BoringSSL.podspec
  80. 30
      src/objective-c/GRPCClient/GRPCCall+MobileLog.h
  81. 33
      src/objective-c/GRPCClient/GRPCCall+MobileLog.m
  82. 11
      src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
  83. 1
      src/objective-c/GRPCClient/private/GRPCHost.h
  84. 7
      src/objective-c/GRPCClient/private/GRPCHost.m
  85. 2
      src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
  86. 2
      src/objective-c/examples/Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme
  87. 29
      src/objective-c/tests/Podfile
  88. 773
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  89. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
  90. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme
  91. 63
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartextCFStream.xcscheme
  92. 63
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalSSLCFStream.xcscheme
  93. 2
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme
  94. 61
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemoteCFStream.xcscheme
  95. 78
      src/objective-c/tests/analyze_link_map.py
  96. 5
      src/objective-c/tests/build_one_example.sh
  97. 41
      src/objective-c/tests/run_tests.sh
  98. 193
      src/php/README.md
  99. 1
      src/php/tests/unit_tests/CallCredentials2Test.php
  100. 1
      src/php/tests/unit_tests/CallCredentialsTest.php
  101. Some files were not shown because too many files have changed in this diff Show More

@ -72,6 +72,13 @@ disable=
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have # TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions... # this one if we extracted just a few more helper functions...
too-many-nested-blocks, too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from # TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary
# the beginning and will continue to do so until it goes away for good. # super-init requirement for abstract class implementations for now.
super-init-not-called,
# NOTE(nathaniel): A single statement that always returns program
# control is better than two statements the first of which sometimes
# returns program control and the second of which always returns
# program control. Probably generally, but definitely in the cases of
# if:/else: and for:/else:.
useless-else-on-loop, useless-else-on-loop,
no-else-return,

@ -103,6 +103,13 @@ disable=
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have # TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions... # this one if we extracted just a few more helper functions...
too-many-nested-blocks, too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from # TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary
# the beginning and will continue to do so until it goes away for good. # super-init requirement for abstract class implementations for now.
super-init-not-called,
# NOTE(nathaniel): A single statement that always returns program
# control is better than two statements the first of which sometimes
# returns program control and the second of which always returns
# program control. Probably generally, but definitely in the cases of
# if:/else: and for:/else:.
useless-else-on-loop, useless-else-on-loop,
no-else-return,

19
BUILD

@ -1003,6 +1003,25 @@ grpc_cc_library(
], ],
) )
grpc_cc_library(
name = "grpc_cfstream",
srcs = [
"src/core/lib/iomgr/cfstream_handle.cc",
"src/core/lib/iomgr/endpoint_cfstream.cc",
"src/core/lib/iomgr/error_cfstream.cc",
"src/core/lib/iomgr/tcp_client_cfstream.cc",
],
hdrs = [
"src/core/lib/iomgr/cfstream_handle.h",
"src/core/lib/iomgr/endpoint_cfstream.h",
"src/core/lib/iomgr/error_cfstream.h",
],
deps = [
":gpr_base",
":grpc_base",
],
)
grpc_cc_library( grpc_cc_library(
name = "grpc_client_channel", name = "grpc_client_channel",
srcs = [ srcs = [

@ -700,6 +700,7 @@ target_include_directories(address_sorting
) )
target_link_libraries(address_sorting target_link_libraries(address_sorting
${_gRPC_BASELIB_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES}
) )
@ -5297,6 +5298,7 @@ add_library(end2end_tests
test/core/end2end/tests/max_message_length.cc test/core/end2end/tests/max_message_length.cc
test/core/end2end/tests/negative_deadline.cc test/core/end2end/tests/negative_deadline.cc
test/core/end2end/tests/network_status_change.cc test/core/end2end/tests/network_status_change.cc
test/core/end2end/tests/no_error_on_hotpath.cc
test/core/end2end/tests/no_logging.cc test/core/end2end/tests/no_logging.cc
test/core/end2end/tests/no_op.cc test/core/end2end/tests/no_op.cc
test/core/end2end/tests/payload.cc test/core/end2end/tests/payload.cc
@ -5415,6 +5417,7 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/max_message_length.cc test/core/end2end/tests/max_message_length.cc
test/core/end2end/tests/negative_deadline.cc test/core/end2end/tests/negative_deadline.cc
test/core/end2end/tests/network_status_change.cc test/core/end2end/tests/network_status_change.cc
test/core/end2end/tests/no_error_on_hotpath.cc
test/core/end2end/tests/no_logging.cc test/core/end2end/tests/no_logging.cc
test/core/end2end/tests/no_op.cc test/core/end2end/tests/no_op.cc
test/core/end2end/tests/payload.cc test/core/end2end/tests/payload.cc

@ -501,7 +501,6 @@ endif
ifeq ($(HAS_PKG_CONFIG),true) ifeq ($(HAS_PKG_CONFIG),true)
OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
@ -514,7 +513,6 @@ OPENSSL_LIBS = ssl crypto
endif endif
OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS) OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare -Wno-implicit-fallthrough $(NO_W_EXTRA_SEMI) -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS) BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare -Wno-implicit-fallthrough $(NO_W_EXTRA_SEMI) -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS)
ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS) ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS) PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
@ -542,13 +540,7 @@ HAS_SYSTEM_PROTOBUF_VERIFY = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true) ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
HAS_SYSTEM_OPENSSL_NPN = true
CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true, CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true,
else
HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
endif
ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true,
endif endif
HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false) HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_ZLIB),true) ifeq ($(HAS_SYSTEM_ZLIB),true)
@ -565,7 +557,6 @@ endif
else else
# override system libraries if the config requires a custom compiled library # override system libraries if the config requires a custom compiled library
HAS_SYSTEM_OPENSSL_ALPN = false HAS_SYSTEM_OPENSSL_ALPN = false
HAS_SYSTEM_OPENSSL_NPN = false
HAS_SYSTEM_ZLIB = false HAS_SYSTEM_ZLIB = false
HAS_SYSTEM_PROTOBUF = false HAS_SYSTEM_PROTOBUF = false
HAS_SYSTEM_CARES = false HAS_SYSTEM_CARES = false
@ -712,12 +703,7 @@ ifneq ($(HAS_EMBEDDED_OPENSSL_ALPN),false)
EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN) EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
NO_SECURE ?= false NO_SECURE ?= false
else # HAS_EMBEDDED_OPENSSL_ALPN=false else # HAS_EMBEDDED_OPENSSL_ALPN=false
ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
EMBED_OPENSSL ?= false
NO_SECURE ?= false
else
NO_SECURE ?= true NO_SECURE ?= true
endif # HAS_SYSTEM_OPENSSL_NPN=true
endif # HAS_EMBEDDED_OPENSSL_ALPN endif # HAS_EMBEDDED_OPENSSL_ALPN
endif # HAS_SYSTEM_OPENSSL_ALPN endif # HAS_SYSTEM_OPENSSL_ALPN
@ -751,10 +737,10 @@ LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS)
else # HAS_PKG_CONFIG=false else # HAS_PKG_CONFIG=false
LIBS_SECURE = $(OPENSSL_LIBS) LIBS_SECURE = $(OPENSSL_LIBS)
endif # HAS_PKG_CONFIG endif # HAS_PKG_CONFIG
ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true) ifeq ($(DISABLE_ALPN),true)
CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0 CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
LIBS_SECURE = $(OPENSSL_LIBS) LIBS_SECURE = $(OPENSSL_LIBS)
endif # HAS_SYSTEM_OPENSSL_NPN endif # DISABLE_ALPN
PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE)) PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE))
endif # EMBED_OPENSSL endif # EMBED_OPENSSL
endif # NO_SECURE endif # NO_SECURE
@ -1347,7 +1333,6 @@ uri_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry
run_dep_checks: run_dep_checks:
$(OPENSSL_ALPN_CHECK_CMD) || true $(OPENSSL_ALPN_CHECK_CMD) || true
$(OPENSSL_NPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true $(ZLIB_CHECK_CMD) || true
$(PERFTOOLS_CHECK_CMD) || true $(PERFTOOLS_CHECK_CMD) || true
$(PROTOBUF_CHECK_CMD) || true $(PROTOBUF_CHECK_CMD) || true
@ -10006,6 +9991,7 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/max_message_length.cc \ test/core/end2end/tests/max_message_length.cc \
test/core/end2end/tests/negative_deadline.cc \ test/core/end2end/tests/negative_deadline.cc \
test/core/end2end/tests/network_status_change.cc \ test/core/end2end/tests/network_status_change.cc \
test/core/end2end/tests/no_error_on_hotpath.cc \
test/core/end2end/tests/no_logging.cc \ test/core/end2end/tests/no_logging.cc \
test/core/end2end/tests/no_op.cc \ test/core/end2end/tests/no_op.cc \
test/core/end2end/tests/payload.cc \ test/core/end2end/tests/payload.cc \
@ -10122,6 +10108,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/max_message_length.cc \ test/core/end2end/tests/max_message_length.cc \
test/core/end2end/tests/negative_deadline.cc \ test/core/end2end/tests/negative_deadline.cc \
test/core/end2end/tests/network_status_change.cc \ test/core/end2end/tests/network_status_change.cc \
test/core/end2end/tests/no_error_on_hotpath.cc \
test/core/end2end/tests/no_logging.cc \ test/core/end2end/tests/no_logging.cc \
test/core/end2end/tests/no_op.cc \ test/core/end2end/tests/no_op.cc \
test/core/end2end/tests/payload.cc \ test/core/end2end/tests/payload.cc \

@ -43,12 +43,7 @@ def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mo
) )
if not proto_only: if not proto_only:
if use_external: plugin = "@com_github_grpc_grpc//:grpc_cpp_plugin"
# when this file is used by non-grpc projects
plugin = "//external:grpc_cpp_plugin"
else:
plugin = "//:grpc_cpp_plugin"
generate_cc( generate_cc(
name = codegen_grpc_target, name = codegen_grpc_target,
srcs = [proto_target], srcs = [proto_target],
@ -57,14 +52,8 @@ def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mo
generate_mocks = generate_mocks, generate_mocks = generate_mocks,
**kwargs **kwargs
) )
grpc_deps = ["@com_github_grpc_grpc//:grpc++_codegen_proto",
if use_external:
# when this file is used by non-grpc projects
grpc_deps = ["//external:grpc++_codegen_proto",
"//external:protobuf"] "//external:protobuf"]
else:
grpc_deps = ["//:grpc++_codegen_proto", "//external:protobuf"]
native.cc_library( native.cc_library(
name = name, name = name,
srcs = [":" + codegen_grpc_target, ":" + codegen_target], srcs = [":" + codegen_grpc_target, ":" + codegen_target],

@ -130,12 +130,12 @@ def grpc_deps():
if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules(): if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules():
native.http_archive( native.http_archive(
name = "com_github_bazelbuild_bazeltoolchains", name = "com_github_bazelbuild_bazeltoolchains",
strip_prefix = "bazel-toolchains-09c850dbb8e785ded3d23a7003e9a0168fe1fb2f", strip_prefix = "bazel-toolchains-4653c01284d8a4a536f8f9bb47b7d10f94c549e7",
urls = [ urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/09c850dbb8e785ded3d23a7003e9a0168fe1fb2f.tar.gz", "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/4653c01284d8a4a536f8f9bb47b7d10f94c549e7.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/09c850dbb8e785ded3d23a7003e9a0168fe1fb2f.tar.gz", "https://github.com/bazelbuild/bazel-toolchains/archive/4653c01284d8a4a536f8f9bb47b7d10f94c549e7.tar.gz",
], ],
sha256 = "08e521cf2d0998e3d27a16c2e2542ebf4d3857b3ddadcfd145d128140754d7bd", sha256 = "1c4a532b396c698e6467a1548554571cb85fa091e472b05e398ebc836c315d77",
) )
# TODO: move some dependencies from "grpc_deps" here? # TODO: move some dependencies from "grpc_deps" here?

@ -536,6 +536,19 @@ filegroups:
uses: uses:
- grpc_codegen - grpc_codegen
- grpc_trace_headers - grpc_trace_headers
- name: grpc_cfstream
headers:
- src/core/lib/iomgr/cfstream_handle.h
- src/core/lib/iomgr/endpoint_cfstream.h
- src/core/lib/iomgr/error_cfstream.h
src:
- src/core/lib/iomgr/cfstream_handle.cc
- src/core/lib/iomgr/endpoint_cfstream.cc
- src/core/lib/iomgr/error_cfstream.cc
- src/core/lib/iomgr/tcp_client_cfstream.cc
uses:
- grpc_base_headers
- gpr_base_headers
- name: grpc_client_authority_filter - name: grpc_client_authority_filter
headers: headers:
- src/core/ext/filters/http/client_authority_filter.h - src/core/ext/filters/http/client_authority_filter.h

@ -0,0 +1,15 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
*.bundle
*.so
*.o
*.a
mkmf.log
vendor

@ -0,0 +1,4 @@
source 'https://rubygems.org/'
gem 'grpc', '~> 1.0'
gem 'googleauth', '>= 0.5.1', '< 0.7'

@ -1080,6 +1080,24 @@ Pod::Spec.new do |s|
'src/core/ext/filters/workarounds/workaround_utils.h' 'src/core/ext/filters/workarounds/workaround_utils.h'
end end
s.subspec 'CFStream-Implementation' do |ss|
ss.header_mappings_dir = '.'
ss.dependency "#{s.name}/Implementation", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
ss.source_files = 'src/core/lib/iomgr/cfstream_handle.cc',
'src/core/lib/iomgr/endpoint_cfstream.cc',
'src/core/lib/iomgr/error_cfstream.cc',
'src/core/lib/iomgr/tcp_client_cfstream.cc',
'src/core/lib/iomgr/cfstream_handle.h',
'src/core/lib/iomgr/endpoint_cfstream.h',
'src/core/lib/iomgr/error_cfstream.h'
ss.private_header_files = 'src/core/lib/iomgr/cfstream_handle.h',
'src/core/lib/iomgr/endpoint_cfstream.h',
'src/core/lib/iomgr/error_cfstream.h'
end
s.subspec 'Cronet-Interface' do |ss| s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc' ss.header_mappings_dir = 'include/grpc'
ss.source_files = 'include/grpc/grpc_cronet.h' ss.source_files = 'include/grpc/grpc_cronet.h'
@ -1198,6 +1216,7 @@ Pod::Spec.new do |s|
'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc', 'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc', 'test/core/end2end/tests/no_op.cc',
'test/core/end2end/tests/payload.cc', 'test/core/end2end/tests/payload.cc',

@ -41,12 +41,25 @@ Pod::Spec.new do |s|
s.header_dir = name s.header_dir = name
src_dir = 'src/objective-c/ProtoRPC' src_dir = 'src/objective-c/ProtoRPC'
s.source_files = "#{src_dir}/*.{h,m}"
s.header_mappings_dir = "#{src_dir}"
s.dependency 'gRPC', version s.default_subspec = 'Main'
s.dependency 'gRPC-RxLibrary', version
s.dependency 'Protobuf', '~> 3.0' s.subspec 'Main' do |ss|
ss.header_mappings_dir = "#{src_dir}"
ss.dependency 'gRPC', version
ss.dependency 'gRPC-RxLibrary', version
ss.dependency 'Protobuf', '~> 3.0'
ss.source_files = "#{src_dir}/*.{h,m}"
end
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC/CFStream', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.pod_target_xcconfig = { s.pod_target_xcconfig = {
# This is needed by all pods that depend on Protobuf: # This is needed by all pods that depend on Protobuf:
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',

@ -63,6 +63,16 @@ Pod::Spec.new do |s|
ss.dependency 'gRPC-Core', version ss.dependency 'gRPC-Core', version
end end
# This subspec is mutually exclusive with the `Main` subspec
s.subspec 'CFStream' do |ss|
ss.dependency 'gRPC-Core/CFStream-Implementation', version
ss.dependency "#{s.name}/Main", version
ss.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1'
}
end
s.subspec 'GID' do |ss| s.subspec 'GID' do |ss|
ss.ios.deployment_target = '7.0' ss.ios.deployment_target = '7.0'

@ -20,7 +20,9 @@ Gem::Specification.new do |s|
s.files += Dir.glob('src/ruby/bin/**/*') s.files += Dir.glob('src/ruby/bin/**/*')
s.files += Dir.glob('src/ruby/ext/**/*') s.files += Dir.glob('src/ruby/ext/**/*')
s.files += Dir.glob('src/ruby/lib/**/*') s.files += Dir.glob('src/ruby/lib/**/*')
s.files += Dir.glob('src/ruby/pb/**/*') s.files += Dir.glob('src/ruby/pb/**/*').reject do |f|
f.match(%r{^src/ruby/pb/test})
end
s.files += Dir.glob('include/grpc/**/*') s.files += Dir.glob('include/grpc/**/*')
s.test_files = Dir.glob('src/ruby/spec/**/*') s.test_files = Dir.glob('src/ruby/spec/**/*')
s.bindir = 'src/ruby/bin' s.bindir = 'src/ruby/bin'
@ -28,7 +30,6 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.1' s.add_dependency 'google-protobuf', '~> 3.1'
s.add_dependency 'googleauth', '>= 0.5.1', '< 0.7'
s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0'
s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'bundler', '~> 1.9'
@ -41,6 +42,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rspec', '~> 3.6' s.add_development_dependency 'rspec', '~> 3.6'
s.add_development_dependency 'rubocop', '~> 0.49.1' s.add_development_dependency 'rubocop', '~> 0.49.1'
s.add_development_dependency 'signet', '~> 0.7.0' s.add_development_dependency 'signet', '~> 0.7.0'
s.add_development_dependency 'googleauth', '>= 0.5.1', '< 0.7'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb) s.extensions = %w(src/ruby/ext/grpc/extconf.rb)

@ -2630,6 +2630,7 @@
'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc', 'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc', 'test/core/end2end/tests/no_op.cc',
'test/core/end2end/tests/payload.cc', 'test/core/end2end/tests/payload.cc',
@ -2720,6 +2721,7 @@
'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc', 'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc', 'test/core/end2end/tests/no_op.cc',
'test/core/end2end/tests/payload.cc', 'test/core/end2end/tests/payload.cc',

@ -332,7 +332,7 @@ typedef struct {
#define GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE "grpc.per_rpc_retry_buffer_size" #define GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE "grpc.per_rpc_retry_buffer_size"
/** Channel arg that carries the bridged objective c object for custom metrics /** Channel arg that carries the bridged objective c object for custom metrics
* logging filter. */ * logging filter. */
#define GRPC_ARG_MOBILE_LOG_CONFIG "grpc.mobile_log_config" #define GRPC_ARG_MOBILE_LOG_CONTEXT "grpc.mobile_log_context"
/** If non-zero, client authority filter is disabled for the channel */ /** If non-zero, client authority filter is disabled for the channel */
#define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \ #define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \
"grpc.disable_client_authority_filter" "grpc.disable_client_authority_filter"

@ -227,7 +227,10 @@
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1 #define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1 #define GPR_GETPID_IN_UNISTD_H 1
/* TODO(mxyan): Remove when CFStream becomes default */
#ifndef GRPC_CFSTREAM
#define GPR_SUPPORT_CHANNELS_FROM_FD 1 #define GPR_SUPPORT_CHANNELS_FROM_FD 1
#endif
#ifdef _LP64 #ifdef _LP64
#define GPR_ARCH_64 1 #define GPR_ARCH_64 1
#else /* _LP64 */ #else /* _LP64 */

@ -573,8 +573,11 @@ class CallOpClientRecvStatus {
binary_error_details = binary_error_details =
grpc::string(iter->second.begin(), iter->second.length()); grpc::string(iter->second.begin(), iter->second.length());
} }
*recv_status_ = Status(static_cast<StatusCode>(status_code_), *recv_status_ =
grpc::string(GRPC_SLICE_START_PTR(error_message_), Status(static_cast<StatusCode>(status_code_),
GRPC_SLICE_IS_EMPTY(error_message_)
? grpc::string()
: grpc::string(GRPC_SLICE_START_PTR(error_message_),
GRPC_SLICE_END_PTR(error_message_)), GRPC_SLICE_END_PTR(error_message_)),
binary_error_details); binary_error_details);
client_context_->set_debug_error_string( client_context_->set_debug_error_string(

@ -35,7 +35,7 @@ egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
PY3 = sys.version_info.major == 3 PY3 = sys.version_info.major == 3
PYTHON_STEM = os.path.join('src', 'python', 'grpcio') PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
CORE_INCLUDE = ('include', '.',) CORE_INCLUDE = ('include', '.',)
BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),) SSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),)
ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),) ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
CARES_INCLUDE = ( CARES_INCLUDE = (
os.path.join('third_party', 'cares'), os.path.join('third_party', 'cares'),
@ -84,6 +84,24 @@ CLASSIFIERS = [
# present, then it will still attempt to use Cython. # present, then it will still attempt to use Cython.
BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False) BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
# Export this variable to use the system installation of openssl. You need to
# have the header files installed (in /usr/include/openssl) and during
# runtime, the shared libary must be installed
BUILD_WITH_SYSTEM_OPENSSL = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL',
False)
# Export this variable to use the system installation of zlib. You need to
# have the header files installed (in /usr/include/) and during
# runtime, the shared libary must be installed
BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB',
False)
# Export this variable to use the system installation of cares. You need to
# have the header files installed (in /usr/include/) and during
# runtime, the shared libary must be installed
BUILD_WITH_SYSTEM_CARES = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_CARES',
False)
# Environment variable to determine whether or not to enable coverage analysis # Environment variable to determine whether or not to enable coverage analysis
# in Cython modules. # in Cython modules.
ENABLE_CYTHON_TRACING = os.environ.get( ENABLE_CYTHON_TRACING = os.environ.get(
@ -148,8 +166,21 @@ CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
if "win32" in sys.platform: if "win32" in sys.platform:
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES) CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
if BUILD_WITH_SYSTEM_OPENSSL:
CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x, CORE_C_FILES)
CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
if BUILD_WITH_SYSTEM_ZLIB:
CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
if BUILD_WITH_SYSTEM_CARES:
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
CARES_INCLUDE = (os.path.join('/usr', 'include'),)
EXTENSION_INCLUDE_DIRECTORIES = ( EXTENSION_INCLUDE_DIRECTORIES = (
(PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE + (PYTHON_STEM,) + CORE_INCLUDE + SSL_INCLUDE + ZLIB_INCLUDE +
CARES_INCLUDE + ADDRESS_SORTING_INCLUDE) CARES_INCLUDE + ADDRESS_SORTING_INCLUDE)
EXTENSION_LIBRARIES = () EXTENSION_LIBRARIES = ()
@ -159,6 +190,12 @@ if not "win32" in sys.platform:
EXTENSION_LIBRARIES += ('m',) EXTENSION_LIBRARIES += ('m',)
if "win32" in sys.platform: if "win32" in sys.platform:
EXTENSION_LIBRARIES += ('advapi32', 'ws2_32',) EXTENSION_LIBRARIES += ('advapi32', 'ws2_32',)
if BUILD_WITH_SYSTEM_OPENSSL:
EXTENSION_LIBRARIES += ('ssl', 'crypto',)
if BUILD_WITH_SYSTEM_ZLIB:
EXTENSION_LIBRARIES += ('z',)
if BUILD_WITH_SYSTEM_CARES:
EXTENSION_LIBRARIES += ('cares',)
DEFINE_MACROS = ( DEFINE_MACROS = (
('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600), ('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),

@ -590,19 +590,16 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor* service) {
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
out->Print("return grpc::ServerServiceDefinition.CreateBuilder()\n"); out->Print("return grpc::ServerServiceDefinition.CreateBuilder()");
out->Indent(); out->Indent();
out->Indent(); out->Indent();
for (int i = 0; i < service->method_count(); i++) { for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor* method = service->method(i); const MethodDescriptor* method = service->method(i);
out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)", out->Print("\n.AddMethod($methodfield$, serviceImpl.$methodname$)",
"methodfield", GetMethodFieldName(method), "methodname", "methodfield", GetMethodFieldName(method), "methodname",
method->name()); method->name());
if (i == service->method_count() - 1) {
out->Print(".Build();");
}
out->Print("\n");
} }
out->Print(".Build();\n");
out->Outdent(); out->Outdent();
out->Outdent(); out->Outdent();
@ -676,20 +673,26 @@ grpc::string GetServices(const FileDescriptor* file, bool generate_client,
out.PrintRaw(leading_comments.c_str()); out.PrintRaw(leading_comments.c_str());
} }
out.Print("#pragma warning disable 1591\n"); out.Print("#pragma warning disable 0414, 1591\n");
out.Print("#region Designer generated code\n"); out.Print("#region Designer generated code\n");
out.Print("\n"); out.Print("\n");
out.Print("using grpc = global::Grpc.Core;\n"); out.Print("using grpc = global::Grpc.Core;\n");
out.Print("\n"); out.Print("\n");
out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file)); grpc::string file_namespace = GetFileNamespace(file);
if (file_namespace != "") {
out.Print("namespace $namespace$ {\n", "namespace", file_namespace);
out.Indent(); out.Indent();
}
for (int i = 0; i < file->service_count(); i++) { for (int i = 0; i < file->service_count(); i++) {
GenerateService(&out, file->service(i), generate_client, generate_server, GenerateService(&out, file->service(i), generate_client, generate_server,
internal_access); internal_access);
} }
if (file_namespace != "") {
out.Outdent(); out.Outdent();
out.Print("}\n"); out.Print("}\n");
}
out.Print("#endregion\n"); out.Print("#endregion\n");
} }
return output; return output;

@ -891,6 +891,7 @@ typedef struct client_channel_call_data {
grpc_closure pick_cancel_closure; grpc_closure pick_cancel_closure;
grpc_polling_entity* pollent; grpc_polling_entity* pollent;
bool pollent_added_to_interested_parties;
// Batches are added to this list when received from above. // Batches are added to this list when received from above.
// They are removed when we are done handling the batch (i.e., when // They are removed when we are done handling the batch (i.e., when
@ -949,7 +950,6 @@ static void retry_commit(grpc_call_element* elem,
static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void start_internal_recv_trailing_metadata(grpc_call_element* elem);
static void on_complete(void* arg, grpc_error* error); static void on_complete(void* arg, grpc_error* error);
static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored);
static void pick_after_resolver_result_start_locked(grpc_call_element* elem);
static void start_pick_locked(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored);
// //
@ -2684,59 +2684,133 @@ static void pick_done(void* arg, grpc_error* error) {
} }
} }
static void maybe_add_call_to_channel_interested_parties_locked(
grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (!calld->pollent_added_to_interested_parties) {
calld->pollent_added_to_interested_parties = true;
grpc_polling_entity_add_to_pollset_set(calld->pollent,
chand->interested_parties);
}
}
static void maybe_del_call_from_channel_interested_parties_locked(
grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (calld->pollent_added_to_interested_parties) {
calld->pollent_added_to_interested_parties = false;
grpc_polling_entity_del_from_pollset_set(calld->pollent,
chand->interested_parties);
}
}
// Invoked when a pick is completed to leave the client_channel combiner // Invoked when a pick is completed to leave the client_channel combiner
// and continue processing in the call combiner. // and continue processing in the call combiner.
// If needed, removes the call's polling entity from chand->interested_parties.
static void pick_done_locked(grpc_call_element* elem, grpc_error* error) { static void pick_done_locked(grpc_call_element* elem, grpc_error* error) {
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
maybe_del_call_from_channel_interested_parties_locked(elem);
GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem, GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(&calld->pick_closure, error); GRPC_CLOSURE_SCHED(&calld->pick_closure, error);
} }
// A wrapper around pick_done_locked() that is used in cases where namespace grpc_core {
// either (a) the pick was deferred pending a resolver result or (b) the
// pick was done asynchronously. Removes the call's polling entity from // Performs subchannel pick via LB policy.
// chand->interested_parties before invoking pick_done_locked(). class LbPicker {
static void async_pick_done_locked(grpc_call_element* elem, grpc_error* error) { public:
// Starts a pick on chand->lb_policy.
static void StartLocked(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_polling_entity_del_from_pollset_set(calld->pollent, if (grpc_client_channel_trace.enabled()) {
chand->interested_parties); gpr_log(GPR_INFO, "chand=%p calld=%p: starting pick on lb_policy=%p",
pick_done_locked(elem, error); chand, calld, chand->lb_policy.get());
} }
// If this is a retry, use the send_initial_metadata payload that
// we've cached; otherwise, use the pending batch. The
// send_initial_metadata batch will be the first pending batch in the
// list, as set by get_batch_index() above.
calld->pick.initial_metadata =
calld->seen_send_initial_metadata
? &calld->send_initial_metadata
: calld->pending_batches[0]
.batch->payload->send_initial_metadata.send_initial_metadata;
calld->pick.initial_metadata_flags =
calld->seen_send_initial_metadata
? calld->send_initial_metadata_flags
: calld->pending_batches[0]
.batch->payload->send_initial_metadata
.send_initial_metadata_flags;
GRPC_CLOSURE_INIT(&calld->pick_closure, &LbPicker::DoneLocked, elem,
grpc_combiner_scheduler(chand->combiner));
calld->pick.on_complete = &calld->pick_closure;
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback");
const bool pick_done = chand->lb_policy->PickLocked(&calld->pick);
if (GPR_LIKELY(pick_done)) {
// Pick completed synchronously.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed synchronously",
chand, calld);
}
pick_done_locked(elem, GRPC_ERROR_NONE);
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
} else {
// Pick will be returned asynchronously.
// Add the polling entity from call_data to the channel_data's
// interested_parties, so that the I/O of the LB policy can be done
// under it. It will be removed in pick_done_locked().
maybe_add_call_to_channel_interested_parties_locked(elem);
// Request notification on call cancellation.
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback_cancel");
grpc_call_combiner_set_notify_on_cancel(
calld->call_combiner,
GRPC_CLOSURE_INIT(&calld->pick_cancel_closure,
&LbPicker::CancelLocked, elem,
grpc_combiner_scheduler(chand->combiner)));
}
}
// Note: This runs under the client_channel combiner, but will NOT be private:
// holding the call combiner. // Callback invoked by LoadBalancingPolicy::PickLocked() for async picks.
static void pick_callback_cancel_locked(void* arg, grpc_error* error) { // Unrefs the LB policy and invokes pick_done_locked().
static void DoneLocked(void* arg, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
// Note: chand->lb_policy may have changed since we started our pick,
// in which case we will be cancelling the pick on a policy other than
// the one we started it on. However, this will just be a no-op.
if (GPR_LIKELY(error != GRPC_ERROR_NONE && chand->lb_policy != nullptr)) {
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling pick from LB policy %p", gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed asynchronously",
chand, calld, chand->lb_policy.get()); chand, calld);
} }
chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error)); pick_done_locked(elem, GRPC_ERROR_REF(error));
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
} }
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback_cancel");
}
// Callback invoked by LoadBalancingPolicy::PickLocked() for async picks. // Note: This runs under the client_channel combiner, but will NOT be
// Unrefs the LB policy and invokes async_pick_done_locked(). // holding the call combiner.
static void pick_callback_done_locked(void* arg, grpc_error* error) { static void CancelLocked(void* arg, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
// Note: chand->lb_policy may have changed since we started our pick,
// in which case we will be cancelling the pick on a policy other than
// the one we started it on. However, this will just be a no-op.
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE && chand->lb_policy != nullptr)) {
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed asynchronously", chand, gpr_log(GPR_INFO,
calld); "chand=%p calld=%p: cancelling pick from LB policy %p", chand,
calld, chand->lb_policy.get());
} }
async_pick_done_locked(elem, GRPC_ERROR_REF(error)); chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error));
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback"); }
} GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback_cancel");
}
};
} // namespace grpc_core
// Applies service config to the call. Must be invoked once we know // Applies service config to the call. Must be invoked once we know
// that the resolver has returned results to the channel. // that the resolver has returned results to the channel.
@ -2766,6 +2840,24 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) {
grpc_deadline_state_reset(elem, calld->deadline); grpc_deadline_state_reset(elem, calld->deadline);
} }
} }
// If the service config set wait_for_ready and the application
// did not explicitly set it, use the value from the service config.
uint32_t* send_initial_metadata_flags =
&calld->pending_batches[0]
.batch->payload->send_initial_metadata
.send_initial_metadata_flags;
if (GPR_UNLIKELY(
calld->method_params->wait_for_ready() !=
ClientChannelMethodParams::WAIT_FOR_READY_UNSET &&
!(*send_initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET))) {
if (calld->method_params->wait_for_ready() ==
ClientChannelMethodParams::WAIT_FOR_READY_TRUE) {
*send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
*send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
}
}
} }
} }
// If no retry policy, disable retries. // If no retry policy, disable retries.
@ -2776,132 +2868,66 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) {
} }
} }
// Starts a pick on chand->lb_policy. // Invoked once resolver results are available.
// Returns true if pick is completed synchronously. static void process_service_config_and_start_lb_pick_locked(
static bool pick_callback_start_locked(grpc_call_element* elem) { grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: starting pick on lb_policy=%p", chand,
calld, chand->lb_policy.get());
}
// Only get service config data on the first attempt. // Only get service config data on the first attempt.
if (GPR_LIKELY(calld->num_attempts_completed == 0)) { if (GPR_LIKELY(calld->num_attempts_completed == 0)) {
apply_service_config_to_call_locked(elem); apply_service_config_to_call_locked(elem);
} }
// If the application explicitly set wait_for_ready, use that. // Start LB pick.
// Otherwise, if the service config specified a value for this grpc_core::LbPicker::StartLocked(elem);
// method, use that.
//
// The send_initial_metadata batch will be the first one in the list,
// as set by get_batch_index() above.
calld->pick.initial_metadata =
calld->seen_send_initial_metadata
? &calld->send_initial_metadata
: calld->pending_batches[0]
.batch->payload->send_initial_metadata.send_initial_metadata;
uint32_t send_initial_metadata_flags =
calld->seen_send_initial_metadata
? calld->send_initial_metadata_flags
: calld->pending_batches[0]
.batch->payload->send_initial_metadata
.send_initial_metadata_flags;
const bool wait_for_ready_set_from_api =
send_initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
const bool wait_for_ready_set_from_service_config =
calld->method_params != nullptr &&
calld->method_params->wait_for_ready() !=
ClientChannelMethodParams::WAIT_FOR_READY_UNSET;
if (GPR_UNLIKELY(!wait_for_ready_set_from_api &&
wait_for_ready_set_from_service_config)) {
if (calld->method_params->wait_for_ready() ==
ClientChannelMethodParams::WAIT_FOR_READY_TRUE) {
send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
}
}
calld->pick.initial_metadata_flags = send_initial_metadata_flags;
GRPC_CLOSURE_INIT(&calld->pick_closure, pick_callback_done_locked, elem,
grpc_combiner_scheduler(chand->combiner));
calld->pick.on_complete = &calld->pick_closure;
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback");
const bool pick_done = chand->lb_policy->PickLocked(&calld->pick);
if (GPR_LIKELY(pick_done)) {
// Pick completed synchronously.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed synchronously",
chand, calld);
}
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
} else {
GRPC_CALL_STACK_REF(calld->owning_call, "pick_callback_cancel");
grpc_call_combiner_set_notify_on_cancel(
calld->call_combiner,
GRPC_CLOSURE_INIT(&calld->pick_cancel_closure,
pick_callback_cancel_locked, elem,
grpc_combiner_scheduler(chand->combiner)));
}
return pick_done;
} }
typedef struct { namespace grpc_core {
grpc_call_element* elem;
bool finished;
grpc_closure closure;
grpc_closure cancel_closure;
} pick_after_resolver_result_args;
// Note: This runs under the client_channel combiner, but will NOT be // Handles waiting for a resolver result.
// holding the call combiner. // Used only for the first call on an idle channel.
static void pick_after_resolver_result_cancel_locked(void* arg, class ResolverResultWaiter {
grpc_error* error) { public:
pick_after_resolver_result_args* args = explicit ResolverResultWaiter(grpc_call_element* elem) : elem_(elem) {
static_cast<pick_after_resolver_result_args*>(arg);
if (GPR_LIKELY(args->finished)) {
gpr_free(args);
return;
}
// If we don't yet have a resolver result, then a closure for
// pick_after_resolver_result_done_locked() will have been added to
// chand->waiting_for_resolver_result_closures, and it may not be invoked
// until after this call has been destroyed. We mark the operation as
// finished, so that when pick_after_resolver_result_done_locked()
// is called, it will be a no-op. We also immediately invoke
// async_pick_done_locked() to propagate the error back to the caller.
args->finished = true;
grpc_call_element* elem = args->elem;
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"chand=%p calld=%p: cancelling pick waiting for resolver result", "chand=%p calld=%p: deferring pick pending resolver result",
chand, calld); chand, calld);
} }
// Note: Although we are not in the call combiner here, we are // Add closure to be run when a resolver result is available.
// basically stealing the call combiner from the pending pick, so GRPC_CLOSURE_INIT(&done_closure_, &ResolverResultWaiter::DoneLocked, this,
// it's safe to call async_pick_done_locked() here -- we are grpc_combiner_scheduler(chand->combiner));
// essentially calling it here instead of calling it in AddToWaitingList();
// pick_after_resolver_result_done_locked(). // Set cancellation closure, so that we abort if the call is cancelled.
async_pick_done_locked(elem, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( GRPC_CLOSURE_INIT(&cancel_closure_, &ResolverResultWaiter::CancelLocked,
"Pick cancelled", &error, 1)); this, grpc_combiner_scheduler(chand->combiner));
} grpc_call_combiner_set_notify_on_cancel(calld->call_combiner,
&cancel_closure_);
}
private:
// Adds closure_ to chand->waiting_for_resolver_result_closures.
void AddToWaitingList() {
channel_data* chand = static_cast<channel_data*>(elem_->channel_data);
grpc_closure_list_append(&chand->waiting_for_resolver_result_closures,
&done_closure_, GRPC_ERROR_NONE);
}
static void pick_after_resolver_result_done_locked(void* arg, // Invoked when a resolver result is available.
grpc_error* error) { static void DoneLocked(void* arg, grpc_error* error) {
pick_after_resolver_result_args* args = ResolverResultWaiter* self = static_cast<ResolverResultWaiter*>(arg);
static_cast<pick_after_resolver_result_args*>(arg); // If CancelLocked() has already run, delete ourselves without doing
if (GPR_UNLIKELY(args->finished)) { // anything. Note that the call stack may have already been destroyed,
/* cancelled, do nothing */ // so it's not safe to access anything in elem_.
if (GPR_UNLIKELY(self->finished_)) {
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "call cancelled before resolver result"); gpr_log(GPR_INFO, "call cancelled before resolver result");
} }
gpr_free(args); Delete(self);
return; return;
} }
args->finished = true; // Otherwise, process the resolver result.
grpc_call_element* elem = args->elem; grpc_call_element* elem = self->elem_;
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
@ -2909,15 +2935,15 @@ static void pick_after_resolver_result_done_locked(void* arg,
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data", gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data",
chand, calld); chand, calld);
} }
async_pick_done_locked(elem, GRPC_ERROR_REF(error)); pick_done_locked(elem, GRPC_ERROR_REF(error));
} else if (GPR_UNLIKELY(chand->resolver == nullptr)) { } else if (GPR_UNLIKELY(chand->resolver == nullptr)) {
// Shutting down. // Shutting down.
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand, gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand,
calld); calld);
} }
async_pick_done_locked( pick_done_locked(elem,
elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
} else if (GPR_UNLIKELY(chand->lb_policy == nullptr)) { } else if (GPR_UNLIKELY(chand->lb_policy == nullptr)) {
// Transient resolver failure. // Transient resolver failure.
// If call has wait_for_ready=true, try again; otherwise, fail. // If call has wait_for_ready=true, try again; otherwise, fail.
@ -2934,7 +2960,10 @@ static void pick_after_resolver_result_done_locked(void* arg,
"wait_for_ready=true; trying again", "wait_for_ready=true; trying again",
chand, calld); chand, calld);
} }
pick_after_resolver_result_start_locked(elem); // Re-add ourselves to the waiting list.
self->AddToWaitingList();
// Return early so that we don't set finished_ to true below.
return;
} else { } else {
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
@ -2942,7 +2971,7 @@ static void pick_after_resolver_result_done_locked(void* arg,
"wait_for_ready=false; failing", "wait_for_ready=false; failing",
chand, calld); chand, calld);
} }
async_pick_done_locked( pick_done_locked(
elem, elem,
grpc_error_set_int( grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"),
@ -2950,41 +2979,53 @@ static void pick_after_resolver_result_done_locked(void* arg,
} }
} else { } else {
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing pick", gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing LB pick",
chand, calld); chand, calld);
} }
if (GPR_LIKELY(pick_callback_start_locked(elem))) { process_service_config_and_start_lb_pick_locked(elem);
// Even if the LB policy returns a result synchronously, we have
// already added our polling entity to chand->interested_parties
// in order to wait for the resolver result, so we need to
// remove it here. Therefore, we call async_pick_done_locked()
// instead of pick_done_locked().
async_pick_done_locked(elem, GRPC_ERROR_NONE);
} }
self->finished_ = true;
} }
}
static void pick_after_resolver_result_start_locked(grpc_call_element* elem) { // Invoked when the call is cancelled.
// Note: This runs under the client_channel combiner, but will NOT be
// holding the call combiner.
static void CancelLocked(void* arg, grpc_error* error) {
ResolverResultWaiter* self = static_cast<ResolverResultWaiter*>(arg);
// If DoneLocked() has already run, delete ourselves without doing anything.
if (GPR_LIKELY(self->finished_)) {
Delete(self);
return;
}
// If we are being cancelled, immediately invoke pick_done_locked()
// to propagate the error back to the caller.
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
grpc_call_element* elem = self->elem_;
channel_data* chand = static_cast<channel_data*>(elem->channel_data); channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) { if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring pick pending resolver result", chand, "chand=%p calld=%p: cancelling call waiting for name "
calld); "resolution",
chand, calld);
}
// Note: Although we are not in the call combiner here, we are
// basically stealing the call combiner from the pending pick, so
// it's safe to call pick_done_locked() here -- we are essentially
// calling it here instead of calling it in DoneLocked().
pick_done_locked(elem, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1));
}
self->finished_ = true;
} }
pick_after_resolver_result_args* args =
static_cast<pick_after_resolver_result_args*>(gpr_zalloc(sizeof(*args))); grpc_call_element* elem_;
args->elem = elem; grpc_closure done_closure_;
GRPC_CLOSURE_INIT(&args->closure, pick_after_resolver_result_done_locked, grpc_closure cancel_closure_;
args, grpc_combiner_scheduler(chand->combiner)); bool finished_ = false;
grpc_closure_list_append(&chand->waiting_for_resolver_result_closures, };
&args->closure, GRPC_ERROR_NONE);
grpc_call_combiner_set_notify_on_cancel( } // namespace grpc_core
calld->call_combiner,
GRPC_CLOSURE_INIT(&args->cancel_closure,
pick_after_resolver_result_cancel_locked, args,
grpc_combiner_scheduler(chand->combiner)));
}
static void start_pick_locked(void* arg, grpc_error* ignored) { static void start_pick_locked(void* arg, grpc_error* ignored) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
@ -2993,31 +3034,24 @@ static void start_pick_locked(void* arg, grpc_error* ignored) {
GPR_ASSERT(calld->pick.connected_subchannel == nullptr); GPR_ASSERT(calld->pick.connected_subchannel == nullptr);
GPR_ASSERT(calld->subchannel_call == nullptr); GPR_ASSERT(calld->subchannel_call == nullptr);
if (GPR_LIKELY(chand->lb_policy != nullptr)) { if (GPR_LIKELY(chand->lb_policy != nullptr)) {
// We already have an LB policy, so ask it for a pick. // We already have resolver results, so process the service config
if (GPR_LIKELY(pick_callback_start_locked(elem))) { // and start an LB pick.
// Pick completed synchronously. process_service_config_and_start_lb_pick_locked(elem);
pick_done_locked(elem, GRPC_ERROR_NONE); } else if (GPR_UNLIKELY(chand->resolver == nullptr)) {
return;
}
} else {
// We do not yet have an LB policy, so wait for a resolver result.
if (GPR_UNLIKELY(chand->resolver == nullptr)) {
pick_done_locked(elem, pick_done_locked(elem,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected")); GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
return; } else {
} // We do not yet have an LB policy, so wait for a resolver result.
if (GPR_UNLIKELY(!chand->started_resolving)) { if (GPR_UNLIKELY(!chand->started_resolving)) {
start_resolving_locked(chand); start_resolving_locked(chand);
} }
pick_after_resolver_result_start_locked(elem); // Create a new waiter, which will delete itself when done.
grpc_core::New<grpc_core::ResolverResultWaiter>(elem);
// Add the polling entity from call_data to the channel_data's
// interested_parties, so that the I/O of the resolver can be done
// under it. It will be removed in pick_done_locked().
maybe_add_call_to_channel_interested_parties_locked(elem);
} }
// We need to wait for either a resolver result or for an async result
// from the LB policy. Add the polling entity from call_data to the
// channel_data's interested_parties, so that the I/O of the LB policy
// and resolver can be done under it. The polling entity will be
// removed in async_pick_done_locked().
grpc_polling_entity_add_to_pollset_set(calld->pollent,
chand->interested_parties);
} }
// //

@ -18,7 +18,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) #if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER)
#include <ares.h> #include <ares.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -348,4 +348,4 @@ void grpc_ares_ev_driver_start(grpc_ares_ev_driver* ev_driver) {
gpr_mu_unlock(&ev_driver->mu); gpr_mu_unlock(&ev_driver->mu);
} }
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */ #endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */

@ -1451,10 +1451,8 @@ static void perform_stream_op_locked(void* stream_op,
} }
} }
if (op_payload->send_initial_metadata.peer_string != nullptr) { if (op_payload->send_initial_metadata.peer_string != nullptr) {
char* old_peer_string = (char*)gpr_atm_full_xchg( gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
op_payload->send_initial_metadata.peer_string, (gpr_atm)t->peer_string);
(gpr_atm)gpr_strdup(t->peer_string));
gpr_free(old_peer_string);
} }
} }
@ -1569,10 +1567,8 @@ static void perform_stream_op_locked(void* stream_op,
s->trailing_metadata_available = s->trailing_metadata_available =
op_payload->recv_initial_metadata.trailing_metadata_available; op_payload->recv_initial_metadata.trailing_metadata_available;
if (op_payload->recv_initial_metadata.peer_string != nullptr) { if (op_payload->recv_initial_metadata.peer_string != nullptr) {
char* old_peer_string = (char*)gpr_atm_full_xchg( gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string,
op_payload->recv_initial_metadata.peer_string, (gpr_atm)t->peer_string);
(gpr_atm)gpr_strdup(t->peer_string));
gpr_free(old_peer_string);
} }
grpc_chttp2_maybe_complete_recv_initial_metadata(t, s); grpc_chttp2_maybe_complete_recv_initial_metadata(t, s);
} }

@ -41,14 +41,18 @@
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/timeout_encoding.h"
#define HASH_FRAGMENT_1(x) ((x)&255) #define HASH_FRAGMENT_MASK (GRPC_CHTTP2_HPACKC_NUM_VALUES - 1)
#define HASH_FRAGMENT_2(x) ((x >> 8) & 255) #define HASH_FRAGMENT_1(x) ((x)&HASH_FRAGMENT_MASK)
#define HASH_FRAGMENT_3(x) ((x >> 16) & 255) #define HASH_FRAGMENT_2(x) \
#define HASH_FRAGMENT_4(x) ((x >> 24) & 255) (((x) >> GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS) & HASH_FRAGMENT_MASK)
#define HASH_FRAGMENT_3(x) \
(((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 2)) & HASH_FRAGMENT_MASK)
#define HASH_FRAGMENT_4(x) \
(((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 3)) & HASH_FRAGMENT_MASK)
/* if the probability of this item being seen again is < 1/x then don't add /* if the probability of this item being seen again is < 1/x then don't add
it to the table */ it to the table */
#define ONE_ON_ADD_PROBABILITY 128 #define ONE_ON_ADD_PROBABILITY (GRPC_CHTTP2_HPACKC_NUM_VALUES >> 1)
/* don't consider adding anything bigger than this to the hpack table */ /* don't consider adding anything bigger than this to the hpack table */
#define MAX_DECODER_SPACE_USAGE 512 #define MAX_DECODER_SPACE_USAGE 512
@ -135,7 +139,7 @@ static void inc_filter(uint8_t idx, uint32_t* sum, uint8_t* elems) {
} else { } else {
int i; int i;
*sum = 0; *sum = 0;
for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) { for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
elems[i] /= 2; elems[i] /= 2;
(*sum) += elems[i]; (*sum) += elems[i];
} }

@ -28,8 +28,9 @@
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256 // This should be <= 8. We use 6 to save space.
#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256 #define GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS 6
#define GRPC_CHTTP2_HPACKC_NUM_VALUES (1 << GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS)
/* initial table size, per spec */ /* initial table size, per spec */
#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096 #define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
/* maximum table size we'll actually use */ /* maximum table size we'll actually use */
@ -58,7 +59,7 @@ typedef struct {
a new literal should be added to the compression table or not. a new literal should be added to the compression table or not.
They track a single integer that counts how often a particular value has They track a single integer that counts how often a particular value has
been seen. When that count reaches max (255), all values are halved. */ been seen. When that count reaches max (255), all values are halved. */
uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS]; uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
/* entry tables for keys & elems: these tables track values that have been /* entry tables for keys & elems: these tables track values that have been
seen and *may* be in the decompressor table */ seen and *may* be in the decompressor table */

@ -0,0 +1,183 @@
/*
*
* 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 <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM
#import <CoreFoundation/CoreFoundation.h>
#import "src/core/lib/iomgr/cfstream_handle.h"
#include <grpc/support/atm.h>
#include <grpc/support/sync.h>
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/exec_ctx.h"
extern grpc_core::TraceFlag grpc_tcp_trace;
void* CFStreamHandle::Retain(void* info) {
CFStreamHandle* handle = static_cast<CFStreamHandle*>(info);
CFSTREAM_HANDLE_REF(handle, "retain");
return info;
}
void CFStreamHandle::Release(void* info) {
CFStreamHandle* handle = static_cast<CFStreamHandle*>(info);
CFSTREAM_HANDLE_UNREF(handle, "release");
}
CFStreamHandle* CFStreamHandle::CreateStreamHandle(
CFReadStreamRef read_stream, CFWriteStreamRef write_stream) {
return new CFStreamHandle(read_stream, write_stream);
}
void CFStreamHandle::ReadCallback(CFReadStreamRef stream,
CFStreamEventType type,
void* client_callback_info) {
CFStreamHandle* handle = static_cast<CFStreamHandle*>(client_callback_info);
CFSTREAM_HANDLE_REF(handle, "read callback");
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
grpc_core::ExecCtx exec_ctx;
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle,
stream, type, client_callback_info);
}
switch (type) {
case kCFStreamEventOpenCompleted:
handle->open_event_.SetReady();
break;
case kCFStreamEventHasBytesAvailable:
case kCFStreamEventEndEncountered:
handle->read_event_.SetReady();
break;
case kCFStreamEventErrorOccurred:
handle->open_event_.SetReady();
handle->read_event_.SetReady();
break;
default:
GPR_UNREACHABLE_CODE(return );
}
CFSTREAM_HANDLE_UNREF(handle, "read callback");
});
}
void CFStreamHandle::WriteCallback(CFWriteStreamRef stream,
CFStreamEventType type,
void* clientCallBackInfo) {
CFStreamHandle* handle = static_cast<CFStreamHandle*>(clientCallBackInfo);
CFSTREAM_HANDLE_REF(handle, "write callback");
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
grpc_core::ExecCtx exec_ctx;
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle,
stream, type, clientCallBackInfo);
}
switch (type) {
case kCFStreamEventOpenCompleted:
handle->open_event_.SetReady();
break;
case kCFStreamEventCanAcceptBytes:
case kCFStreamEventEndEncountered:
handle->write_event_.SetReady();
break;
case kCFStreamEventErrorOccurred:
handle->open_event_.SetReady();
handle->write_event_.SetReady();
break;
default:
GPR_UNREACHABLE_CODE(return );
}
CFSTREAM_HANDLE_UNREF(handle, "write callback");
});
}
CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream,
CFWriteStreamRef write_stream) {
gpr_ref_init(&refcount_, 1);
open_event_.InitEvent();
read_event_.InitEvent();
write_event_.InitEvent();
CFStreamClientContext ctx = {0, static_cast<void*>(this), nil, nil, nil};
CFReadStreamSetClient(
read_stream,
kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
CFStreamHandle::ReadCallback, &ctx);
CFWriteStreamSetClient(
write_stream,
kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
CFStreamHandle::WriteCallback, &ctx);
CFReadStreamScheduleWithRunLoop(read_stream, CFRunLoopGetMain(),
kCFRunLoopCommonModes);
CFWriteStreamScheduleWithRunLoop(write_stream, CFRunLoopGetMain(),
kCFRunLoopCommonModes);
}
CFStreamHandle::~CFStreamHandle() {
open_event_.DestroyEvent();
read_event_.DestroyEvent();
write_event_.DestroyEvent();
}
void CFStreamHandle::NotifyOnOpen(grpc_closure* closure) {
open_event_.NotifyOn(closure);
}
void CFStreamHandle::NotifyOnRead(grpc_closure* closure) {
read_event_.NotifyOn(closure);
}
void CFStreamHandle::NotifyOnWrite(grpc_closure* closure) {
write_event_.NotifyOn(closure);
}
void CFStreamHandle::Shutdown(grpc_error* error) {
open_event_.SetShutdown(GRPC_ERROR_REF(error));
read_event_.SetShutdown(GRPC_ERROR_REF(error));
write_event_.SetShutdown(GRPC_ERROR_REF(error));
GRPC_ERROR_UNREF(error);
}
void CFStreamHandle::Ref(const char* file, int line, const char* reason) {
if (grpc_tcp_trace.enabled()) {
gpr_atm val = gpr_atm_no_barrier_load(&refcount_.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"CFStream Handle ref %p : %s %" PRIdPTR " -> %" PRIdPTR, this,
reason, val, val + 1);
}
gpr_ref(&refcount_);
}
void CFStreamHandle::Unref(const char* file, int line, const char* reason) {
if (grpc_tcp_trace.enabled()) {
gpr_atm val = gpr_atm_no_barrier_load(&refcount_.count);
gpr_log(GPR_ERROR,
"CFStream Handle unref %p : %s %" PRIdPTR " -> %" PRIdPTR, this,
reason, val, val - 1);
}
if (gpr_unref(&refcount_)) {
delete this;
}
}
#endif

@ -0,0 +1,80 @@
/*
*
* 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.
*
*/
/* The CFStream handle acts as an event synchronization entity for
* read/write/open/error/eos events happening on CFStream streams. */
#ifndef GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H
#define GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM
#import <CoreFoundation/CoreFoundation.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/lockfree_event.h"
class CFStreamHandle final {
public:
static CFStreamHandle* CreateStreamHandle(CFReadStreamRef read_stream,
CFWriteStreamRef write_stream);
~CFStreamHandle();
CFStreamHandle(const CFReadStreamRef& ref) = delete;
CFStreamHandle(CFReadStreamRef&& ref) = delete;
CFStreamHandle& operator=(const CFStreamHandle& rhs) = delete;
void NotifyOnOpen(grpc_closure* closure);
void NotifyOnRead(grpc_closure* closure);
void NotifyOnWrite(grpc_closure* closure);
void Shutdown(grpc_error* error);
void Ref(const char* file = "", int line = 0, const char* reason = nullptr);
void Unref(const char* file = "", int line = 0, const char* reason = nullptr);
private:
CFStreamHandle(CFReadStreamRef read_stream, CFWriteStreamRef write_stream);
static void ReadCallback(CFReadStreamRef stream, CFStreamEventType type,
void* client_callback_info);
static void WriteCallback(CFWriteStreamRef stream, CFStreamEventType type,
void* client_callback_info);
static void* Retain(void* info);
static void Release(void* info);
grpc_core::LockfreeEvent open_event_;
grpc_core::LockfreeEvent read_event_;
grpc_core::LockfreeEvent write_event_;
gpr_refcount refcount_;
};
#ifdef DEBUG
#define CFSTREAM_HANDLE_REF(handle, reason) \
(handle)->Ref(__FILE__, __LINE__, (reason))
#define CFSTREAM_HANDLE_UNREF(handle, reason) \
(handle)->Unref(__FILE__, __LINE__, (reason))
#else
#define CFSTREAM_HANDLE_REF(handle, reason) (handle)->Ref()
#define CFSTREAM_HANDLE_UNREF(handle, reason) (handle)->Unref()
#endif
#endif
#endif /* GRPC_CORE_LIB_IOMGR_CFSTREAM_HANDLE_H */

@ -0,0 +1,372 @@
/*
*
* 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 <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM_ENDPOINT
#import <CoreFoundation/CoreFoundation.h>
#import "src/core/lib/iomgr/endpoint_cfstream.h"
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/cfstream_handle.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/error_cfstream.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
extern grpc_core::TraceFlag grpc_tcp_trace;
typedef struct {
grpc_endpoint base;
gpr_refcount refcount;
CFReadStreamRef read_stream;
CFWriteStreamRef write_stream;
CFStreamHandle* stream_sync;
grpc_closure* read_cb;
grpc_closure* write_cb;
grpc_slice_buffer* read_slices;
grpc_slice_buffer* write_slices;
grpc_closure read_action;
grpc_closure write_action;
char* peer_string;
grpc_resource_user* resource_user;
grpc_resource_user_slice_allocator slice_allocator;
} CFStreamEndpoint;
static void CFStreamFree(CFStreamEndpoint* ep) {
grpc_resource_user_unref(ep->resource_user);
CFRelease(ep->read_stream);
CFRelease(ep->write_stream);
CFSTREAM_HANDLE_UNREF(ep->stream_sync, "free");
gpr_free(ep->peer_string);
gpr_free(ep);
}
#ifndef NDEBUG
#define EP_REF(ep, reason) CFStreamRef((ep), (reason), __FILE__, __LINE__)
#define EP_UNREF(ep, reason) CFStreamUnref((ep), (reason), __FILE__, __LINE__)
static void CFStreamUnref(CFStreamEndpoint* ep, const char* reason,
const char* file, int line) {
if (grpc_tcp_trace.enabled()) {
gpr_atm val = gpr_atm_no_barrier_load(&ep->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"CFStream endpoint unref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep,
reason, val, val - 1);
}
if (gpr_unref(&ep->refcount)) {
CFStreamFree(ep);
}
}
static void CFStreamRef(CFStreamEndpoint* ep, const char* reason,
const char* file, int line) {
if (grpc_tcp_trace.enabled()) {
gpr_atm val = gpr_atm_no_barrier_load(&ep->refcount.count);
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
"CFStream endpoint ref %p : %s %" PRIdPTR " -> %" PRIdPTR, ep,
reason, val, val + 1);
}
gpr_ref(&ep->refcount);
}
#else
#define EP_REF(ep, reason) CFStreamRef((ep))
#define EP_UNREF(ep, reason) CFStreamUnref((ep))
static void CFStreamUnref(CFStreamEndpoint* ep) {
if (gpr_unref(&ep->refcount)) {
CFStreamFree(ep);
}
}
static void CFStreamRef(CFStreamEndpoint* ep) { gpr_ref(&ep->refcount); }
#endif
static grpc_error* CFStreamAnnotateError(grpc_error* src_error,
CFStreamEndpoint* ep) {
return grpc_error_set_str(
grpc_error_set_int(src_error, GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_UNAVAILABLE),
GRPC_ERROR_STR_TARGET_ADDRESS,
grpc_slice_from_copied_string(ep->peer_string));
}
static void CallReadCb(CFStreamEndpoint* ep, grpc_error* error) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_read_cb %p %p:%p", ep,
ep->read_cb, ep->read_cb->cb, ep->read_cb->cb_arg);
size_t i;
const char* str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "read: error=%s", str);
for (i = 0; i < ep->read_slices->count; i++) {
char* dump = grpc_dump_slice(ep->read_slices->slices[i],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", ep, ep->peer_string, dump);
gpr_free(dump);
}
}
grpc_closure* cb = ep->read_cb;
ep->read_cb = nullptr;
ep->read_slices = nullptr;
GRPC_CLOSURE_SCHED(cb, error);
}
static void CallWriteCb(CFStreamEndpoint* ep, grpc_error* error) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_write_cb %p %p:%p", ep,
ep->write_cb, ep->write_cb->cb, ep->write_cb->cb_arg);
const char* str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "write: error=%s", str);
}
grpc_closure* cb = ep->write_cb;
ep->write_cb = nullptr;
ep->write_slices = nullptr;
GRPC_CLOSURE_SCHED(cb, error);
}
static void ReadAction(void* arg, grpc_error* error) {
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg);
GPR_ASSERT(ep->read_cb != nullptr);
if (error) {
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices);
CallReadCb(ep, GRPC_ERROR_REF(error));
EP_UNREF(ep, "read");
return;
}
GPR_ASSERT(ep->read_slices->count == 1);
grpc_slice slice = ep->read_slices->slices[0];
size_t len = GRPC_SLICE_LENGTH(slice);
CFIndex read_size =
CFReadStreamRead(ep->read_stream, GRPC_SLICE_START_PTR(slice), len);
if (read_size == -1) {
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices);
CFErrorRef stream_error = CFReadStreamCopyError(ep->read_stream);
if (stream_error != nullptr) {
error = CFStreamAnnotateError(
GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "Read error"), ep);
CFRelease(stream_error);
} else {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Read error");
}
CallReadCb(ep, error);
EP_UNREF(ep, "read");
} else if (read_size == 0) {
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices);
CallReadCb(ep,
CFStreamAnnotateError(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Socket closed"), ep));
EP_UNREF(ep, "read");
} else {
if (read_size < len) {
grpc_slice_buffer_trim_end(ep->read_slices, len - read_size, nullptr);
}
CallReadCb(ep, GRPC_ERROR_NONE);
EP_UNREF(ep, "read");
}
}
static void WriteAction(void* arg, grpc_error* error) {
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg);
GPR_ASSERT(ep->write_cb != nullptr);
if (error) {
grpc_slice_buffer_reset_and_unref_internal(ep->write_slices);
CallWriteCb(ep, GRPC_ERROR_REF(error));
EP_UNREF(ep, "write");
return;
}
grpc_slice slice = grpc_slice_buffer_take_first(ep->write_slices);
size_t slice_len = GRPC_SLICE_LENGTH(slice);
CFIndex write_size = CFWriteStreamWrite(
ep->write_stream, GRPC_SLICE_START_PTR(slice), slice_len);
if (write_size == -1) {
grpc_slice_buffer_reset_and_unref_internal(ep->write_slices);
CFErrorRef stream_error = CFWriteStreamCopyError(ep->write_stream);
if (stream_error != nullptr) {
error = CFStreamAnnotateError(
GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "write failed."), ep);
CFRelease(stream_error);
} else {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("write failed.");
}
CallWriteCb(ep, error);
EP_UNREF(ep, "write");
} else {
if (write_size < GRPC_SLICE_LENGTH(slice)) {
grpc_slice_buffer_undo_take_first(
ep->write_slices, grpc_slice_sub(slice, write_size, slice_len));
}
if (ep->write_slices->length > 0) {
ep->stream_sync->NotifyOnWrite(&ep->write_action);
} else {
CallWriteCb(ep, GRPC_ERROR_NONE);
EP_UNREF(ep, "write");
}
if (grpc_tcp_trace.enabled()) {
grpc_slice trace_slice = grpc_slice_sub(slice, 0, write_size);
char* dump = grpc_dump_slice(trace_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", ep, ep->peer_string, dump);
gpr_free(dump);
grpc_slice_unref_internal(trace_slice);
}
}
grpc_slice_unref_internal(slice);
}
static void CFStreamReadAllocationDone(void* arg, grpc_error* error) {
CFStreamEndpoint* ep = static_cast<CFStreamEndpoint*>(arg);
if (error == GRPC_ERROR_NONE) {
ep->stream_sync->NotifyOnRead(&ep->read_action);
} else {
grpc_slice_buffer_reset_and_unref_internal(ep->read_slices);
CallReadCb(ep, error);
EP_UNREF(ep, "read");
}
}
static void CFStreamRead(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p read (%p, %p) length:%zu", ep_impl,
slices, cb, slices->length);
}
GPR_ASSERT(ep_impl->read_cb == nullptr);
ep_impl->read_cb = cb;
ep_impl->read_slices = slices;
grpc_slice_buffer_reset_and_unref_internal(slices);
grpc_resource_user_alloc_slices(&ep_impl->slice_allocator,
GRPC_TCP_DEFAULT_READ_SLICE_SIZE, 1,
ep_impl->read_slices);
EP_REF(ep_impl, "read");
}
static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices,
grpc_closure* cb) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p write (%p, %p) length:%zu",
ep_impl, slices, cb, slices->length);
}
GPR_ASSERT(ep_impl->write_cb == nullptr);
ep_impl->write_cb = cb;
ep_impl->write_slices = slices;
EP_REF(ep_impl, "write");
ep_impl->stream_sync->NotifyOnWrite(&ep_impl->write_action);
}
void CFStreamShutdown(grpc_endpoint* ep, grpc_error* why) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown (%p)", ep_impl, why);
}
CFReadStreamClose(ep_impl->read_stream);
CFWriteStreamClose(ep_impl->write_stream);
ep_impl->stream_sync->Shutdown(why);
grpc_resource_user_shutdown(ep_impl->resource_user);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown DONE (%p)", ep_impl, why);
}
}
void CFStreamDestroy(grpc_endpoint* ep) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p destroy", ep_impl);
}
EP_UNREF(ep_impl, "destroy");
}
grpc_resource_user* CFStreamGetResourceUser(grpc_endpoint* ep) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
return ep_impl->resource_user;
}
char* CFStreamGetPeer(grpc_endpoint* ep) {
CFStreamEndpoint* ep_impl = reinterpret_cast<CFStreamEndpoint*>(ep);
return gpr_strdup(ep_impl->peer_string);
}
int CFStreamGetFD(grpc_endpoint* ep) { return 0; }
void CFStreamAddToPollset(grpc_endpoint* ep, grpc_pollset* pollset) {}
void CFStreamAddToPollsetSet(grpc_endpoint* ep, grpc_pollset_set* pollset) {}
void CFStreamDeleteFromPollsetSet(grpc_endpoint* ep,
grpc_pollset_set* pollset) {}
static const grpc_endpoint_vtable vtable = {CFStreamRead,
CFStreamWrite,
CFStreamAddToPollset,
CFStreamAddToPollsetSet,
CFStreamDeleteFromPollsetSet,
CFStreamShutdown,
CFStreamDestroy,
CFStreamGetResourceUser,
CFStreamGetPeer,
CFStreamGetFD};
grpc_endpoint* grpc_cfstream_endpoint_create(
CFReadStreamRef read_stream, CFWriteStreamRef write_stream,
const char* peer_string, grpc_resource_quota* resource_quota,
CFStreamHandle* stream_sync) {
CFStreamEndpoint* ep_impl =
static_cast<CFStreamEndpoint*>(gpr_malloc(sizeof(CFStreamEndpoint)));
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG,
"CFStream endpoint:%p create readStream:%p writeStream: %p",
ep_impl, read_stream, write_stream);
}
ep_impl->base.vtable = &vtable;
gpr_ref_init(&ep_impl->refcount, 1);
ep_impl->read_stream = read_stream;
ep_impl->write_stream = write_stream;
CFRetain(read_stream);
CFRetain(write_stream);
ep_impl->stream_sync = stream_sync;
CFSTREAM_HANDLE_REF(ep_impl->stream_sync, "endpoint create");
ep_impl->peer_string = gpr_strdup(peer_string);
ep_impl->read_cb = nil;
ep_impl->write_cb = nil;
ep_impl->read_slices = nil;
ep_impl->write_slices = nil;
GRPC_CLOSURE_INIT(&ep_impl->read_action, ReadAction,
static_cast<void*>(ep_impl), grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&ep_impl->write_action, WriteAction,
static_cast<void*>(ep_impl), grpc_schedule_on_exec_ctx);
ep_impl->resource_user =
grpc_resource_user_create(resource_quota, peer_string);
grpc_resource_user_slice_allocator_init(&ep_impl->slice_allocator,
ep_impl->resource_user,
CFStreamReadAllocationDone, ep_impl);
return &ep_impl->base;
}
#endif /* GRPC_CFSTREAM_ENDPOINT */

@ -0,0 +1,49 @@
/*
*
* 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.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H
#define GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H
/*
Low level TCP "bottom half" implementation, for use by transports built on
top of a TCP connection.
Note that this file does not (yet) include APIs for creating the socket in
the first place.
All calls passing slice transfer ownership of a slice refcount unless
otherwise specified.
*/
#include <grpc/support/port_platform.h>
#ifdef GRPC_CFSTREAM
#import <CoreFoundation/CoreFoundation.h>
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/cfstream_handle.h"
#include "src/core/lib/iomgr/endpoint.h"
grpc_endpoint* grpc_cfstream_endpoint_create(
CFReadStreamRef read_stream, CFWriteStreamRef write_stream,
const char* peer_string, grpc_resource_quota* resource_quota,
CFStreamHandle* stream_sync);
#endif /* GRPC_CFSTREAM */
#endif /* GRPC_CORE_LIB_IOMGR_ENDPOINT_CFSTREAM_H */

@ -312,6 +312,12 @@ static void internal_add_error(grpc_error** err, grpc_error* new_err) {
// It is very common to include and extra int and string in an error // It is very common to include and extra int and string in an error
#define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME)
static bool g_error_creation_allowed = true;
void grpc_disable_error_creation() { g_error_creation_allowed = false; }
void grpc_enable_error_creation() { g_error_creation_allowed = true; }
grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc,
grpc_error** referencing, grpc_error** referencing,
size_t num_referencing) { size_t num_referencing) {
@ -326,6 +332,12 @@ grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc,
return GRPC_ERROR_OOM; return GRPC_ERROR_OOM;
} }
#ifndef NDEBUG #ifndef NDEBUG
if (!g_error_creation_allowed) {
gpr_log(GPR_ERROR,
"Error creation occurred when error creation was disabled [%s:%d]",
file, line);
abort();
}
if (grpc_trace_error_refcount.enabled()) { if (grpc_trace_error_refcount.enabled()) {
gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line); gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line);
} }

@ -123,6 +123,11 @@ typedef enum {
#define GRPC_ERROR_OOM ((grpc_error*)2) #define GRPC_ERROR_OOM ((grpc_error*)2)
#define GRPC_ERROR_CANCELLED ((grpc_error*)4) #define GRPC_ERROR_CANCELLED ((grpc_error*)4)
// debug only toggles that allow for a sanity to check that ensures we will
// never create any errors in the per-RPC hotpath.
void grpc_disable_error_creation();
void grpc_enable_error_creation();
const char* grpc_error_string(grpc_error* error); const char* grpc_error_string(grpc_error* error);
/// Create an error - but use GRPC_ERROR_CREATE instead /// Create an error - but use GRPC_ERROR_CREATE instead

@ -0,0 +1,52 @@
/*
*
* 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 <grpc/support/port_platform.h>
#ifdef GRPC_CFSTREAM
#include <CoreFoundation/CoreFoundation.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/iomgr/error.h"
#define MAX_ERROR_DESCRIPTION 256
grpc_error* grpc_error_create_from_cferror(const char* file, int line,
void* arg, const char* custom_desc) {
CFErrorRef error = static_cast<CFErrorRef>(arg);
char buf_domain[MAX_ERROR_DESCRIPTION];
char buf_desc[MAX_ERROR_DESCRIPTION];
char* error_msg;
CFErrorDomain domain = CFErrorGetDomain((error));
CFIndex code = CFErrorGetCode((error));
CFStringRef desc = CFErrorCopyDescription((error));
CFStringGetCString(domain, buf_domain, MAX_ERROR_DESCRIPTION,
kCFStringEncodingUTF8);
CFStringGetCString(desc, buf_desc, MAX_ERROR_DESCRIPTION,
kCFStringEncodingUTF8);
gpr_asprintf(&error_msg, "%s (error domain:%s, code:%ld, description:%s)",
custom_desc, buf_domain, code, buf_desc);
CFRelease(desc);
grpc_error* return_error = grpc_error_create(
file, line, grpc_slice_from_copied_string(error_msg), NULL, 0);
gpr_free(error_msg);
return return_error;
}
#endif /* GRPC_CFSTREAM */

@ -0,0 +1,31 @@
/*
*
* 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.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H
#define GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H
#ifdef GRPC_CFSTREAM
// Create an error from Apple Core Foundation CFError object
#define GRPC_ERROR_CREATE_FROM_CFERROR(error, desc) \
grpc_error_create_from_cferror(__FILE__, __LINE__, \
static_cast<void*>((error)), (desc))
grpc_error* grpc_error_create_from_cferror(const char* file, int line,
void* arg, const char* desc);
#endif /* GRPC_CFSTREAM */
#endif /* GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H */

@ -1264,12 +1264,12 @@ const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
} }
#else /* defined(GRPC_LINUX_EPOLL) */ #else /* defined(GRPC_LINUX_EPOLL) */
#if defined(GRPC_POSIX_SOCKET) #if defined(GRPC_POSIX_SOCKET_EV_EPOLL1)
#include "src/core/lib/iomgr/ev_epoll1_linux.h" #include "src/core/lib/iomgr/ev_epoll1_linux.h"
/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return /* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
* NULL */ * NULL */
const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) { const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
return nullptr; return nullptr;
} }
#endif /* defined(GRPC_POSIX_SOCKET) */ #endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLL1) */
#endif /* !defined(GRPC_LINUX_EPOLL) */ #endif /* !defined(GRPC_LINUX_EPOLL) */

@ -1586,7 +1586,7 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux(
} }
#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */ #else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
#if defined(GRPC_POSIX_SOCKET) #if defined(GRPC_POSIX_SOCKET_EV_EPOLLEX)
#include "src/core/lib/iomgr/ev_epollex_linux.h" #include "src/core/lib/iomgr/ev_epollex_linux.h"
/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means /* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means
epoll_create1 is not available. Return NULL */ epoll_create1 is not available. Return NULL */
@ -1594,6 +1594,6 @@ const grpc_event_engine_vtable* grpc_init_epollex_linux(
bool explicitly_requested) { bool explicitly_requested) {
return nullptr; return nullptr;
} }
#endif /* defined(GRPC_POSIX_SOCKET) */ #endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLLEX) */
#endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */ #endif /* !defined(GRPC_LINUX_EPOLL_CREATE1) */

@ -1750,7 +1750,7 @@ const grpc_event_engine_vtable* grpc_init_epollsig_linux(
} }
#else /* defined(GRPC_LINUX_EPOLL_CREATE1) */ #else /* defined(GRPC_LINUX_EPOLL_CREATE1) */
#if defined(GRPC_POSIX_SOCKET) #if defined(GRPC_POSIX_SOCKET_EV_EPOLLSIG)
#include "src/core/lib/iomgr/ev_epollsig_linux.h" #include "src/core/lib/iomgr/ev_epollsig_linux.h"
/* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means /* If GRPC_LINUX_EPOLL_CREATE1 is not defined, it means
epoll_create1 is not available. Return NULL */ epoll_create1 is not available. Return NULL */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_EV_POLL
#include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/iomgr/ev_poll_posix.h"
@ -1769,4 +1769,4 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(bool explicit_request) {
return &vtable; return &vtable;
} }
#endif #endif /* GRPC_POSIX_SOCKET_EV_POLL */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_EV
#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/ev_posix.h"
@ -343,4 +343,4 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
g_event_engine->pollset_set_del_fd(pollset_set, fd); g_event_engine->pollset_set_del_fd(pollset_set, fd);
} }
#endif // GRPC_POSIX_SOCKET #endif // GRPC_POSIX_SOCKET_EV

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_IOMGR
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/ev_posix.h"
@ -64,4 +64,4 @@ void grpc_set_default_iomgr_platform() {
grpc_set_iomgr_platform_vtable(&vtable); grpc_set_iomgr_platform_vtable(&vtable);
} }
#endif /* GRPC_POSIX_SOCKET */ #endif /* GRPC_POSIX_SOCKET_IOMGR */

@ -61,8 +61,11 @@ bool grpc_polling_entity_is_empty(const grpc_polling_entity* pollent) {
void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent, void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent,
grpc_pollset_set* pss_dst) { grpc_pollset_set* pss_dst) {
if (pollent->tag == GRPC_POLLS_POLLSET) { if (pollent->tag == GRPC_POLLS_POLLSET) {
GPR_ASSERT(pollent->pollent.pollset != nullptr); // CFStream does not use file destriptors. When CFStream is used, the fd
// pollset is possible to be null.
if (pollent->pollent.pollset != nullptr) {
grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset); grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset);
}
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) { } else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr); GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
grpc_pollset_set_add_pollset_set(pss_dst, pollent->pollent.pollset_set); grpc_pollset_set_add_pollset_set(pss_dst, pollent->pollent.pollset_set);
@ -75,8 +78,14 @@ void grpc_polling_entity_add_to_pollset_set(grpc_polling_entity* pollent,
void grpc_polling_entity_del_from_pollset_set(grpc_polling_entity* pollent, void grpc_polling_entity_del_from_pollset_set(grpc_polling_entity* pollent,
grpc_pollset_set* pss_dst) { grpc_pollset_set* pss_dst) {
if (pollent->tag == GRPC_POLLS_POLLSET) { if (pollent->tag == GRPC_POLLS_POLLSET) {
#ifdef GRPC_CFSTREAM
if (pollent->pollent.pollset != nullptr) {
grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset);
}
#else
GPR_ASSERT(pollent->pollent.pollset != nullptr); GPR_ASSERT(pollent->pollent.pollset != nullptr);
grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset); grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset);
#endif
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) { } else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr); GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
grpc_pollset_set_del_pollset_set(pss_dst, pollent->pollent.pollset_set); grpc_pollset_set_del_pollset_set(pss_dst, pollent->pollent.pollset_set);

@ -97,7 +97,26 @@
#define GRPC_MSG_IOVLEN_TYPE int #define GRPC_MSG_IOVLEN_TYPE int
#define GRPC_POSIX_FORK 1 #define GRPC_POSIX_FORK 1
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
#ifdef GRPC_CFSTREAM
#define GRPC_POSIX_SOCKET_IOMGR 1
#define GRPC_CFSTREAM_ENDPOINT 1
#define GRPC_CFSTREAM_CLIENT 1
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
#define GRPC_POSIX_SOCKET_SOCKADDR 1
#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1
#define GRPC_POSIX_SOCKET_TCP 1
#define GRPC_POSIX_SOCKET_TCP_SERVER 1
#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1
#define GRPC_POSIX_SOCKET_UTILS_COMMON 1
#else
#define GRPC_POSIX_SOCKET 1 #define GRPC_POSIX_SOCKET 1
#endif
#define GRPC_POSIX_SOCKETUTILS 1 #define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_SYSCONF 1 #define GRPC_POSIX_SYSCONF 1
#define GRPC_POSIX_WAKEUP_FD 1 #define GRPC_POSIX_WAKEUP_FD 1
@ -131,12 +150,30 @@
#endif #endif
#if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \ #if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \
defined(GRPC_CUSTOM_SOCKET) != \ defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_CFSTREAM) != \
1 1
#error \ #error \
"Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET" "Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET"
#endif #endif
#ifdef GRPC_POSIX_SOCKET
#define GRPC_POSIX_SOCKET_ARES_EV_DRIVER 1
#define GRPC_POSIX_SOCKET_EV 1
#define GRPC_POSIX_SOCKET_EV_EPOLLEX 1
#define GRPC_POSIX_SOCKET_EV_EPOLLSIG 1
#define GRPC_POSIX_SOCKET_EV_POLL 1
#define GRPC_POSIX_SOCKET_EV_EPOLL1 1
#define GRPC_POSIX_SOCKET_IOMGR 1
#define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1
#define GRPC_POSIX_SOCKET_SOCKADDR 1
#define GRPC_POSIX_SOCKET_SOCKET_FACTORY 1
#define GRPC_POSIX_SOCKET_TCP 1
#define GRPC_POSIX_SOCKET_TCP_CLIENT 1
#define GRPC_POSIX_SOCKET_TCP_SERVER 1
#define GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON 1
#define GRPC_POSIX_SOCKET_UTILS_COMMON 1
#endif
#if defined(GRPC_POSIX_HOST_NAME_MAX) && defined(GRPC_POSIX_SYSCONF) #if defined(GRPC_POSIX_HOST_NAME_MAX) && defined(GRPC_POSIX_SYSCONF)
#error "Cannot define both GRPC_POSIX_HOST_NAME_MAX and GRPC_POSIX_SYSCONF" #error "Cannot define both GRPC_POSIX_HOST_NAME_MAX and GRPC_POSIX_SYSCONF"
#endif #endif

@ -33,7 +33,7 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#ifdef GRPC_POSIX_SOCKET #if defined(GRPC_POSIX_SOCKET) || defined(GRPC_CFSTREAM)
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif

@ -19,7 +19,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_RESOLVE_ADDRESS
#include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr.h"

@ -23,7 +23,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_SOCKADDR
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_SOCKET_FACTORY
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
#include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/socket_utils_posix.h"

@ -0,0 +1,216 @@
/*
*
* 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 <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_CFSTREAM_CLIENT
#include <CoreFoundation/CoreFoundation.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <netinet/in.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/host_port.h"
#include "src/core/lib/iomgr/cfstream_handle.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/endpoint_cfstream.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/error_cfstream.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/timer.h"
extern grpc_core::TraceFlag grpc_tcp_trace;
typedef struct CFStreamConnect {
gpr_mu mu;
gpr_refcount refcount;
CFReadStreamRef read_stream;
CFWriteStreamRef write_stream;
CFStreamHandle* stream_sync;
grpc_timer alarm;
grpc_closure on_alarm;
grpc_closure on_open;
bool read_stream_open;
bool write_stream_open;
bool failed;
grpc_closure* closure;
grpc_endpoint** endpoint;
int refs;
char* addr_name;
grpc_resource_quota* resource_quota;
} CFStreamConnect;
static void CFStreamConnectCleanup(CFStreamConnect* connect) {
grpc_resource_quota_unref_internal(connect->resource_quota);
CFSTREAM_HANDLE_UNREF(connect->stream_sync, "async connect clean up");
CFRelease(connect->read_stream);
CFRelease(connect->write_stream);
gpr_mu_destroy(&connect->mu);
gpr_free(connect->addr_name);
gpr_free(connect);
}
static void OnAlarm(void* arg, grpc_error* error) {
CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnAlarm, error:%p", connect, error);
}
gpr_mu_lock(&connect->mu);
grpc_closure* closure = connect->closure;
connect->closure = nil;
const bool done = (--connect->refs == 0);
gpr_mu_unlock(&connect->mu);
// Only schedule a callback once, by either OnAlarm or OnOpen. The
// first one issues callback while the second one does cleanup.
if (done) {
CFStreamConnectCleanup(connect);
} else {
grpc_error* error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("connect() timed out");
GRPC_CLOSURE_SCHED(closure, error);
}
}
static void OnOpen(void* arg, grpc_error* error) {
CFStreamConnect* connect = static_cast<CFStreamConnect*>(arg);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnOpen, error:%p", connect, error);
}
gpr_mu_lock(&connect->mu);
grpc_timer_cancel(&connect->alarm);
grpc_closure* closure = connect->closure;
connect->closure = nil;
bool done = (--connect->refs == 0);
grpc_endpoint** endpoint = connect->endpoint;
// Only schedule a callback once, by either OnAlarm or OnOpen. The
// first one issues callback while the second one does cleanup.
if (done) {
gpr_mu_unlock(&connect->mu);
CFStreamConnectCleanup(connect);
} else {
if (error == GRPC_ERROR_NONE) {
CFErrorRef stream_error = CFReadStreamCopyError(connect->read_stream);
if (stream_error == NULL) {
stream_error = CFWriteStreamCopyError(connect->write_stream);
}
if (stream_error) {
error = GRPC_ERROR_CREATE_FROM_CFERROR(stream_error, "connect() error");
CFRelease(stream_error);
}
if (error == GRPC_ERROR_NONE) {
*endpoint = grpc_cfstream_endpoint_create(
connect->read_stream, connect->write_stream, connect->addr_name,
connect->resource_quota, connect->stream_sync);
}
} else {
GRPC_ERROR_REF(error);
}
gpr_mu_unlock(&connect->mu);
GRPC_CLOSURE_SCHED(closure, error);
}
}
static void ParseResolvedAddress(const grpc_resolved_address* addr,
CFStringRef* host, int* port) {
char *host_port, *host_string, *port_string;
grpc_sockaddr_to_string(&host_port, addr, 1);
gpr_split_host_port(host_port, &host_string, &port_string);
*host = CFStringCreateWithCString(NULL, host_string, kCFStringEncodingUTF8);
gpr_free(host_string);
gpr_free(port_string);
gpr_free(host_port);
*port = grpc_sockaddr_get_port(addr);
}
static void CFStreamClientConnect(grpc_closure* closure, grpc_endpoint** ep,
grpc_pollset_set* interested_parties,
const grpc_channel_args* channel_args,
const grpc_resolved_address* resolved_addr,
grpc_millis deadline) {
CFStreamConnect* connect;
connect = (CFStreamConnect*)gpr_zalloc(sizeof(CFStreamConnect));
connect->closure = closure;
connect->endpoint = ep;
connect->addr_name = grpc_sockaddr_to_uri(resolved_addr);
// connect->resource_quota = resource_quota;
connect->refs = 2; // One for the connect operation, one for the timer.
gpr_ref_init(&connect->refcount, 1);
gpr_mu_init(&connect->mu);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
connect->addr_name);
}
grpc_resource_quota* resource_quota = grpc_resource_quota_create(NULL);
if (channel_args != NULL) {
for (size_t i = 0; i < channel_args->num_args; i++) {
if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
grpc_resource_quota_unref_internal(resource_quota);
resource_quota = grpc_resource_quota_ref_internal(
(grpc_resource_quota*)channel_args->args[i].value.pointer.p);
}
}
}
connect->resource_quota = resource_quota;
CFReadStreamRef read_stream;
CFWriteStreamRef write_stream;
CFStringRef host;
int port;
ParseResolvedAddress(resolved_addr, &host, &port);
CFStreamCreatePairWithSocketToHost(NULL, host, port, &read_stream,
&write_stream);
CFRelease(host);
connect->read_stream = read_stream;
connect->write_stream = write_stream;
connect->stream_sync =
CFStreamHandle::CreateStreamHandle(read_stream, write_stream);
GRPC_CLOSURE_INIT(&connect->on_open, OnOpen, static_cast<void*>(connect),
grpc_schedule_on_exec_ctx);
connect->stream_sync->NotifyOnOpen(&connect->on_open);
GRPC_CLOSURE_INIT(&connect->on_alarm, OnAlarm, connect,
grpc_schedule_on_exec_ctx);
gpr_mu_lock(&connect->mu);
CFReadStreamOpen(read_stream);
CFWriteStreamOpen(write_stream);
grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm);
gpr_mu_unlock(&connect->mu);
}
grpc_tcp_client_vtable grpc_posix_tcp_client_vtable = {CFStreamClientConnect};
#endif /* GRPC_CFSTREAM_CLIENT */

@ -140,12 +140,12 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep,
socket, connect->addr_name); socket, connect->addr_name);
} }
grpc_custom_socket_vtable->connect(
socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len,
custom_connect_callback);
GRPC_CLOSURE_INIT(&connect->on_alarm, on_alarm, socket, GRPC_CLOSURE_INIT(&connect->on_alarm, on_alarm, socket,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm); grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm);
grpc_custom_socket_vtable->connect(
socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len,
custom_connect_callback);
} }
grpc_tcp_client_vtable custom_tcp_client_vtable = {tcp_connect}; grpc_tcp_client_vtable custom_tcp_client_vtable = {tcp_connect};

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_TCP_CLIENT
#include "src/core/lib/iomgr/tcp_client_posix.h" #include "src/core/lib/iomgr/tcp_client_posix.h"

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_TCP
#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/tcp_posix.h"
@ -70,7 +70,9 @@ struct grpc_tcp {
grpc_endpoint base; grpc_endpoint base;
grpc_fd* em_fd; grpc_fd* em_fd;
int fd; int fd;
bool finished_edge; /* Used by the endpoint read function to distinguish the very first read call
* from the rest */
bool is_first_read;
double target_length; double target_length;
double bytes_read_this_round; double bytes_read_this_round;
gpr_refcount refcount; gpr_refcount refcount;
@ -377,7 +379,6 @@ static void tcp_do_read(grpc_tcp* tcp) {
ssize_t read_bytes; ssize_t read_bytes;
size_t i; size_t i;
GPR_ASSERT(!tcp->finished_edge);
GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
for (i = 0; i < tcp->incoming_buffer->count; i++) { for (i = 0; i < tcp->incoming_buffer->count; i++) {
@ -473,7 +474,6 @@ static void tcp_continue_read(grpc_tcp* tcp) {
static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error) { static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error) {
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg); grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
GPR_ASSERT(!tcp->finished_edge);
if (grpc_tcp_trace.enabled()) { if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error)); gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error));
} }
@ -497,10 +497,17 @@ static void tcp_read(grpc_endpoint* ep, grpc_slice_buffer* incoming_buffer,
grpc_slice_buffer_reset_and_unref_internal(incoming_buffer); grpc_slice_buffer_reset_and_unref_internal(incoming_buffer);
grpc_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer); grpc_slice_buffer_swap(incoming_buffer, &tcp->last_read_buffer);
TCP_REF(tcp, "read"); TCP_REF(tcp, "read");
if (tcp->finished_edge) { if (tcp->is_first_read) {
tcp->finished_edge = false; /* Endpoint read called for the very first time. Register read callback with
* the polling engine */
tcp->is_first_read = false;
notify_on_read(tcp); notify_on_read(tcp);
} else { } else {
/* Not the first time. We may or may not have more bytes available. In any
* case call tcp->read_done_closure (i.e tcp_handle_read()) which does the
* right thing (i.e calls tcp_do_read() which either reads the available
* bytes or calls notify_on_read() to be notified when new bytes become
* available */
GRPC_CLOSURE_SCHED(&tcp->read_done_closure, GRPC_ERROR_NONE); GRPC_CLOSURE_SCHED(&tcp->read_done_closure, GRPC_ERROR_NONE);
} }
} }
@ -778,7 +785,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
tcp->min_read_chunk_size = tcp_min_read_chunk_size; tcp->min_read_chunk_size = tcp_min_read_chunk_size;
tcp->max_read_chunk_size = tcp_max_read_chunk_size; tcp->max_read_chunk_size = tcp_max_read_chunk_size;
tcp->bytes_read_this_round = 0; tcp->bytes_read_this_round = 0;
tcp->finished_edge = true; /* Will be set to false by the very first endpoint read function */
tcp->is_first_read = true;
/* paired with unref in grpc_tcp_destroy */ /* paired with unref in grpc_tcp_destroy */
gpr_ref_init(&tcp->refcount, 1); gpr_ref_init(&tcp->refcount, 1);
gpr_atm_no_barrier_store(&tcp->shutdown_count, 0); gpr_atm_no_barrier_store(&tcp->shutdown_count, 0);
@ -811,4 +819,4 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd,
TCP_UNREF(tcp, "destroy"); TCP_UNREF(tcp, "destroy");
} }
#endif #endif /* GRPC_POSIX_SOCKET_TCP */

@ -25,7 +25,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_TCP_SERVER
#include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/tcp_server.h"
@ -559,4 +559,4 @@ grpc_tcp_server_vtable grpc_posix_tcp_server_vtable = {
tcp_server_shutdown_starting_add, tcp_server_shutdown_starting_add,
tcp_server_unref, tcp_server_unref,
tcp_server_shutdown_listeners}; tcp_server_shutdown_listeners};
#endif #endif /* GRPC_POSIX_SOCKET_TCP_SERVER */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET #ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON
#include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include "src/core/lib/iomgr/tcp_server_utils_posix.h"
@ -217,4 +217,4 @@ error:
return ret; return ret;
} }
#endif /* GRPC_POSIX_SOCKET */ #endif /* GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON */

@ -219,9 +219,11 @@ static void on_oauth2_token_fetcher_http_response(void* user_data,
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->token_fetch_pending = false; c->token_fetch_pending = false;
c->access_token_md = GRPC_MDELEM_REF(access_token_md); c->access_token_md = GRPC_MDELEM_REF(access_token_md);
c->token_expiration = status == GRPC_CREDENTIALS_OK c->token_expiration =
? grpc_core::ExecCtx::Get()->Now() + token_lifetime status == GRPC_CREDENTIALS_OK
: 0; ? gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_millis(token_lifetime, GPR_TIMESPAN))
: gpr_inf_past(GPR_CLOCK_MONOTONIC);
grpc_oauth2_pending_get_request_metadata* pending_request = grpc_oauth2_pending_get_request_metadata* pending_request =
c->pending_requests; c->pending_requests;
c->pending_requests = nullptr; c->pending_requests = nullptr;
@ -259,8 +261,10 @@ static bool oauth2_token_fetcher_get_request_metadata(
grpc_mdelem cached_access_token_md = GRPC_MDNULL; grpc_mdelem cached_access_token_md = GRPC_MDNULL;
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
if (!GRPC_MDISNULL(c->access_token_md) && if (!GRPC_MDISNULL(c->access_token_md) &&
(c->token_expiration - grpc_core::ExecCtx::Get()->Now() > gpr_time_cmp(
refresh_threshold)) { gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_MONOTONIC)),
gpr_time_from_seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
GPR_TIMESPAN)) > 0) {
cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md); cached_access_token_md = GRPC_MDELEM_REF(c->access_token_md);
} }
if (!GRPC_MDISNULL(cached_access_token_md)) { if (!GRPC_MDISNULL(cached_access_token_md)) {
@ -333,7 +337,7 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials* c,
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
gpr_mu_init(&c->mu); gpr_mu_init(&c->mu);
c->token_expiration = 0; c->token_expiration = gpr_inf_past(GPR_CLOCK_MONOTONIC);
c->fetch_func = fetch_func; c->fetch_func = fetch_func;
c->pollent = c->pollent =
grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create()); grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());

@ -71,7 +71,7 @@ typedef struct {
grpc_call_credentials base; grpc_call_credentials base;
gpr_mu mu; gpr_mu mu;
grpc_mdelem access_token_md; grpc_mdelem access_token_md;
grpc_millis token_expiration; gpr_timespec token_expiration;
bool token_fetch_pending; bool token_fetch_pending;
grpc_oauth2_pending_get_request_metadata* pending_requests; grpc_oauth2_pending_get_request_metadata* pending_requests;
grpc_httpcli_context httpcli_context; grpc_httpcli_context httpcli_context;

@ -29,6 +29,10 @@ const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name) { const char* prop_name) {
grpc_json* child; grpc_json* child;
for (child = json->child; child != nullptr; child = child->next) { for (child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
gpr_log(GPR_ERROR, "Invalid (null) JSON key encountered");
return nullptr;
}
if (strcmp(child->key, prop_name) == 0) break; if (strcmp(child->key, prop_name) == 0) break;
} }
if (child == nullptr || child->type != GRPC_JSON_STRING) { if (child == nullptr || child->type != GRPC_JSON_STRING) {

@ -333,14 +333,26 @@ void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
size_t slice_len = GRPC_SLICE_LENGTH(slice); size_t slice_len = GRPC_SLICE_LENGTH(slice);
if (slice_len > n) { if (slice_len > n) {
sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n); sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice); grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
return; return;
} else if (slice_len == n) { } else if (slice_len == n) {
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice); grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
sb->count = idx; sb->count = idx;
return; return;
} else { } else {
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice); grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
n -= slice_len; n -= slice_len;
sb->count = idx; sb->count = idx;
} }

@ -516,7 +516,6 @@ static void release_call(void* call, grpc_error* error) {
grpc_call* c = static_cast<grpc_call*>(call); grpc_call* c = static_cast<grpc_call*>(call);
grpc_channel* channel = c->channel; grpc_channel* channel = c->channel;
grpc_call_combiner_destroy(&c->call_combiner); grpc_call_combiner_destroy(&c->call_combiner);
gpr_free((char*)c->peer_string);
grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena)); grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena));
GRPC_CHANNEL_INTERNAL_UNREF(channel, "call"); GRPC_CHANNEL_INTERNAL_UNREF(channel, "call");
} }

@ -184,7 +184,8 @@ void grpc_transport_set_pops(grpc_transport* transport, grpc_stream* stream,
nullptr) { nullptr) {
transport->vtable->set_pollset_set(transport, stream, pollset_set); transport->vtable->set_pollset_set(transport, stream, pollset_set);
} else { } else {
abort(); // No-op for empty pollset. Empty pollset is possible when using
// non-fd-based event engines such as CFStream.
} }
} }

@ -168,13 +168,11 @@ struct grpc_transport_stream_op_batch_payload {
/** Iff send_initial_metadata != NULL, flags associated with /** Iff send_initial_metadata != NULL, flags associated with
send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */ send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */
uint32_t send_initial_metadata_flags; uint32_t send_initial_metadata_flags;
// If non-NULL, will be set by the transport to the peer string // If non-NULL, will be set by the transport to the peer string (a char*).
// (a char*, which the caller takes ownership of). // The transport retains ownership of the string.
// Note: This pointer may be used by the transport after the // Note: This pointer may be used by the transport after the
// send_initial_metadata op is completed. It must remain valid // send_initial_metadata op is completed. It must remain valid
// until the call is destroyed. // until the call is destroyed.
// Note: When a transport sets this, it must free the previous
// value, if any.
gpr_atm* peer_string; gpr_atm* peer_string;
} send_initial_metadata; } send_initial_metadata;
@ -202,13 +200,11 @@ struct grpc_transport_stream_op_batch_payload {
// immediately available. This may be a signal that we received a // immediately available. This may be a signal that we received a
// Trailers-Only response. // Trailers-Only response.
bool* trailing_metadata_available; bool* trailing_metadata_available;
// If non-NULL, will be set by the transport to the peer string // If non-NULL, will be set by the transport to the peer string (a char*).
// (a char*, which the caller takes ownership of). // The transport retains ownership of the string.
// Note: This pointer may be used by the transport after the // Note: This pointer may be used by the transport after the
// recv_initial_metadata op is completed. It must remain valid // recv_initial_metadata op is completed. It must remain valid
// until the call is destroyed. // until the call is destroyed.
// Note: When a transport sets this, it must free the previous
// value, if any.
gpr_atm* peer_string; gpr_atm* peer_string;
} recv_initial_metadata; } recv_initial_metadata;

@ -39,8 +39,8 @@ static void do_plugin_list_init(void) {
} }
ServerBuilder::ServerBuilder() ServerBuilder::ServerBuilder()
: max_receive_message_size_(-1), : max_receive_message_size_(INT_MIN),
max_send_message_size_(-1), max_send_message_size_(INT_MIN),
sync_server_settings_(SyncServerSettings()), sync_server_settings_(SyncServerSettings()),
resource_quota_(nullptr), resource_quota_(nullptr),
generic_service_(nullptr) { generic_service_(nullptr) {
@ -186,10 +186,12 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
(*plugin)->UpdateChannelArguments(&args); (*plugin)->UpdateChannelArguments(&args);
} }
if (max_receive_message_size_ >= 0) { if (max_receive_message_size_ >= -1) {
args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_); args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_);
} }
// The default message size is -1 (max), so no need to explicitly set it for
// -1.
if (max_send_message_size_ >= 0) { if (max_send_message_size_ >= 0) {
args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_); args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_);
} }

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>Grpc.Core.NativeDebug</id>
<title>Grpc.Core: Native Debug Symbols</title>
<summary>Debug symbols for the native library contained in Grpc.Core</summary>
<description>Currently contains grpc_csharp_ext.pdb</description>
<version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release $version$</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
</metadata>
<files>
<!-- forward slashes in src path enable building on Linux -->
<file src="nativelibs/csharp_ext_windows_x86/grpc_csharp_ext.dll" target="runtimes/win/native/grpc_csharp_ext.x86.dll" />
<file src="nativelibs/csharp_ext_windows_x86/grpc_csharp_ext.pdb" target="runtimes/win/native/grpc_csharp_ext.x86.pdb" />
<file src="nativelibs/csharp_ext_windows_x64/grpc_csharp_ext.dll" target="runtimes/win/native/grpc_csharp_ext.x64.dll" />
<file src="nativelibs/csharp_ext_windows_x64/grpc_csharp_ext.pdb" target="runtimes/win/native/grpc_csharp_ext.x64.pdb" />
</files>
</package>

@ -17,7 +17,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -20,7 +20,7 @@
// The canonical version of this proto can be found at // The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto // https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
// //
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -19,7 +19,7 @@
// //
// An integration test service that covers all the method signature permutations // An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses. // of unary/streaming requests/responses.
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -0,0 +1,38 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/empty_service.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {
/// <summary>Holder for reflection information generated from src/proto/grpc/testing/empty_service.proto</summary>
public static partial class EmptyServiceReflection {
#region Descriptor
/// <summary>File descriptor for src/proto/grpc/testing/empty_service.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static EmptyServiceReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VtcHR5X3NlcnZpY2UucHJvdG8S",
"DGdycGMudGVzdGluZzIOCgxFbXB0eVNlcnZpY2ViBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null));
}
#endregion
}
}
#endregion Designer generated code

@ -0,0 +1,85 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/empty_service.proto
// </auto-generated>
// Original file comments:
// 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.
//
#pragma warning disable 0414, 1591
#region Designer generated code
using grpc = global::Grpc.Core;
namespace Grpc.Testing {
/// <summary>
/// A service that has zero methods.
/// See https://github.com/grpc/grpc/issues/15574
/// </summary>
public static partial class EmptyService
{
static readonly string __ServiceName = "grpc.testing.EmptyService";
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.EmptyServiceReflection.Descriptor.Services[0]; }
}
/// <summary>Base class for server-side implementations of EmptyService</summary>
public abstract partial class EmptyServiceBase
{
}
/// <summary>Client for EmptyService</summary>
public partial class EmptyServiceClient : grpc::ClientBase<EmptyServiceClient>
{
/// <summary>Creates a new client for EmptyService</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public EmptyServiceClient(grpc::Channel channel) : base(channel)
{
}
/// <summary>Creates a new client for EmptyService that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public EmptyServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected EmptyServiceClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected EmptyServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override EmptyServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new EmptyServiceClient(configuration);
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(EmptyServiceBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder().Build();
}
}
}
#endregion

@ -23,7 +23,7 @@
// Currently, 'Gauge' (i.e a metric that represents the measured value of // Currently, 'Gauge' (i.e a metric that represents the measured value of
// something at an instant of time) is the only metric type supported by the // something at an instant of time) is the only metric type supported by the
// service. // service.
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -19,7 +19,7 @@
// //
// An integration test service that covers all the method signature permutations // An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses. // of unary/streaming requests/responses.
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -20,7 +20,7 @@
// An integration test service that covers all the method signature permutations // An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses. // of unary/streaming requests/responses.
// //
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -19,7 +19,7 @@
// //
// An integration test service that covers all the method signature permutations // An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses. // of unary/streaming requests/responses.
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -19,7 +19,7 @@
// //
// Service exported by server reflection // Service exported by server reflection
// //
#pragma warning disable 1591 #pragma warning disable 0414, 1591
#region Designer generated code #region Designer generated code
using grpc = global::Grpc.Core; using grpc = global::Grpc.Core;

@ -47,6 +47,7 @@ xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\bu
%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error %NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
%NUGET% pack Grpc.Core.NativeDebug.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
@rem copy resulting nuget packages to artifacts directory @rem copy resulting nuget packages to artifacts directory

@ -46,6 +46,7 @@ dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts nuget pack Grpc.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Core.NativeDebug.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts nuget pack Grpc.Tools.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg) (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)

@ -42,4 +42,4 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR/CoreStats --grpc_out=$TESTING
# don't match the package names. Setting -I to the correct value src/proto # don't match the package names. Setting -I to the correct value src/proto
# breaks the code generation. # breaks the code generation.
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \ $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I . src/proto/grpc/testing/{control,echo_messages,empty,messages,metrics,payloads,benchmark_service,report_qps_scenario_service,worker_service,stats,test}.proto -I . src/proto/grpc/testing/{control,echo_messages,empty,empty_service,messages,metrics,payloads,benchmark_service,report_qps_scenario_service,worker_service,stats,test}.proto

@ -31,7 +31,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'BoringSSL' s.name = 'BoringSSL'
version = '10.0.4' version = '10.0.5'
s.version = version s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.' s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
# Adapted from the homepage: # Adapted from the homepage:
@ -61,8 +61,7 @@ Pod::Spec.new do |s|
Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it’s not part of the Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it’s not part of the
NDK) and a number of other apps/programs. NDK) and a number of other apps/programs.
DESC DESC
s.homepage = 'https://boringssl.googlesource.com/boringssl/' s.homepage = 'https://github.com/google/boringssl'
s.documentation_url = 'https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html'
s.license = { :type => 'Mixed', :file => 'LICENSE' } s.license = { :type => 'Mixed', :file => 'LICENSE' }
# "The name and email addresses of the library maintainers, not the Podspec maintainer." # "The name and email addresses of the library maintainers, not the Podspec maintainer."
s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite'

@ -1,30 +0,0 @@
/*
*
* Copyright 2017 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 "GRPCCall.h"
@interface GRPCCall (MobileLog)
// Set the object to be passed down along channel stack with channel arg
// GRPC_ARG_MOBILE_LOG_CONFIG. The setting may be used by custom channel
// filters for metrics logging.
+ (void)setLogConfig:(id)logConfig;
// Obtain the object to be passed down along channel stack with channel arg
// GRPC_ARG_MOBILE_LOG_CONFIG.
+ (id)logConfig;
@end

@ -1,33 +0,0 @@
/*
*
* Copyright 2017 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 "GRPCCall+MobileLog.h"
static id globalLogConfig = nil;
@implementation GRPCCall (MobileLog)
+ (void)setLogConfig:(id)logConfig {
globalLogConfig = logConfig;
}
+ (id)logConfig {
return globalLogConfig;
}
@end

@ -20,6 +20,14 @@
#import <grpc/grpc.h> #import <grpc/grpc.h>
#ifdef GRPC_CFSTREAM
const grpc_completion_queue_attributes kCompletionQueueAttr = {GRPC_CQ_CURRENT_VERSION,
GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING};
#else
const grpc_completion_queue_attributes kCompletionQueueAttr = {
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING};
#endif
@implementation GRPCCompletionQueue @implementation GRPCCompletionQueue
+ (instancetype)completionQueue { + (instancetype)completionQueue {
@ -33,7 +41,8 @@
- (instancetype)init { - (instancetype)init {
if ((self = [super init])) { if ((self = [super init])) {
_unmanagedQueue = grpc_completion_queue_create_for_next(NULL); _unmanagedQueue = grpc_completion_queue_create(
grpc_completion_queue_factory_lookup(&kCompletionQueueAttr), &kCompletionQueueAttr, NULL);
// This is for the following block to capture the pointer by value (instead // This is for the following block to capture the pointer by value (instead
// of retaining self and doing self->_unmanagedQueue). This is essential // of retaining self and doing self->_unmanagedQueue). This is essential

@ -37,6 +37,7 @@ struct grpc_channel_credentials;
@property(nonatomic) grpc_compression_algorithm compressAlgorithm; @property(nonatomic) grpc_compression_algorithm compressAlgorithm;
@property(nonatomic) int keepaliveInterval; @property(nonatomic) int keepaliveInterval;
@property(nonatomic) int keepaliveTimeout; @property(nonatomic) int keepaliveTimeout;
@property(nonatomic) id logContext;
/** The following properties should only be modified for testing: */ /** The following properties should only be modified for testing: */

@ -18,7 +18,6 @@
#import "GRPCHost.h" #import "GRPCHost.h"
#import <GRPCClient/GRPCCall+MobileLog.h>
#import <GRPCClient/GRPCCall.h> #import <GRPCClient/GRPCCall.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
@ -223,9 +222,9 @@ static NSMutableDictionary *kHostCache;
args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithInt:_keepaliveTimeout]; args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithInt:_keepaliveTimeout];
} }
id logConfig = [GRPCCall logConfig]; id logContext = self.logContext;
if (logConfig != nil) { if (logContext != nil) {
args[@GRPC_ARG_MOBILE_LOG_CONFIG] = logConfig; args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = logContext;
} }
if (useCronet) { if (useCronet) {

@ -325,6 +325,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist; INFOPLIST_FILE = Sample/Info.plist;
LD_GENERATE_MAP_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -337,6 +338,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = Sample/Info.plist; INFOPLIST_FILE = Sample/Info.plist;
LD_GENERATE_MAP_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "org.grpc.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";

@ -42,7 +42,7 @@
</AdditionalOptions> </AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"

@ -36,6 +36,27 @@ GRPC_LOCAL_SRC = '../../..'
end end
end end
%w(
InteropTestsRemoteCFStream
InteropTestsLocalSSLCFStream
InteropTestsLocalCleartextCFStream
).each do |target_name|
target target_name do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true
pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
pod 'gRPC/CFStream', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true
end
end
%w( %w(
CoreCronetEnd2EndTests CoreCronetEnd2EndTests
CronetUnitTests CronetUnitTests
@ -65,7 +86,7 @@ end
# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need. # TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
pre_install do |installer| pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file. # This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root: # Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
@ -96,15 +117,19 @@ post_install do |installer|
# GPR_UNREACHABLE_CODE causes "Control may reach end of non-void # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
# function" warning # function" warning
config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
if target.name.include?('CFStream')
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CFSTREAM=1'
else
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1'
end end
end end
end
# Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by # Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by
# the test target 'InteropTestsRemoteWithCronet' # the test target 'InteropTestsRemoteWithCronet'
# Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will # Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will
# be used by all test targets using it. # be used by all test targets using it.
if target.name == 'gRPC' if target.name == 'gRPC' || target.name.start_with?('gRPC.')
target.build_configurations.each do |config| target.build_configurations.each do |config|
if config.name == 'Cronet' if config.name == 'Cronet'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1 GRPC_TEST_OBJC=1' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1 GRPC_TEST_OBJC=1'

File diff suppressed because it is too large Load Diff

@ -26,6 +26,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
<TestableReference <TestableReference
@ -66,6 +67,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"

@ -26,6 +26,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
<TestableReference <TestableReference
@ -57,6 +58,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5EC5E4302081856B000EF4AD"
BuildableName = "InteropTestsLocalCleartextCFStream.xctest"
BlueprintName = "InteropTestsLocalCleartextCFStream"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "InteropTests">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5EC5E441208185CE000EF4AD"
BuildableName = "InteropTestsLocalSSLCFStream.xctest"
BlueprintName = "InteropTestsLocalSSLCFStream"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "InteropTests">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -26,6 +26,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
<TestableReference <TestableReference
@ -60,6 +61,7 @@
buildConfiguration = "Test" buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5EC5E420208177CC000EF4AD"
BuildableName = "InteropTestsRemoteCFStream.xctest"
BlueprintName = "InteropTestsRemoteCFStream"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "InteropTests">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -1,78 +0,0 @@
#!/usr/bin/python
# 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.
# This script analyzes link map file generated by Xcode. It calculates and
# prints out the sizes of each dependent library and the total sizes of the
# symbols.
# The script takes one parameter, which is the path to the link map file.
import sys
import re
table_tag = {}
state = "start"
table_stats_symbol = {}
table_stats_dead = {}
section_total_size = 0
symbol_total_size = 0
file_import = sys.argv[1]
lines = list(open(file_import))
for line in lines:
line_stripped = line[:-1]
if "# Object files:" == line_stripped:
state = "object"
continue
elif "# Sections:" == line_stripped:
state = "section"
continue
elif "# Symbols:" == line_stripped:
state = "symbol"
continue
elif "# Dead Stripped Symbols:" == line_stripped:
state = "dead"
continue
if state == "object":
segs = re.search('(\[ *[0-9]*\]) (.*)', line_stripped)
table_tag[segs.group(1)] = segs.group(2)
if state == "section":
if len(line_stripped) == 0 or line_stripped[0] == '#':
continue
segs = re.search('^(.+?)\s+(.+?)\s+.*', line_stripped)
section_total_size += int(segs.group(2), 16)
if state == "symbol":
if len(line_stripped) == 0 or line_stripped[0] == '#':
continue
segs = re.search('^.+?\s+(.+?)\s+(\[.+?\]).*', line_stripped)
target = table_tag[segs.group(2)]
target_stripped = re.search('^(.*?)(\(.+?\))?$', target).group(1)
size = int(segs.group(1), 16)
if not target_stripped in table_stats_symbol:
table_stats_symbol[target_stripped] = 0
table_stats_symbol[target_stripped] += size
print("Sections total size: %d" % section_total_size)
for target in table_stats_symbol:
print(target)
print(table_stats_symbol[target])
symbol_total_size += table_stats_symbol[target]
print("Symbols total size: %d" % symbol_total_size)

@ -42,6 +42,9 @@ xcodebuild \
build \ build \
-workspace *.xcworkspace \ -workspace *.xcworkspace \
-scheme $SCHEME \ -scheme $SCHEME \
-destination name="iPhone 6" \ -destination generic/platform=iOS \
-derivedDataPath Build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
| egrep -v "$XCODEBUILD_FILTER" \ | egrep -v "$XCODEBUILD_FILTER" \
| egrep -v "^$" - | egrep -v "^$" -

@ -53,7 +53,7 @@ while [ $retries -lt 3 ]; do
out=$(xcodebuild \ out=$(xcodebuild \
-workspace Tests.xcworkspace \ -workspace Tests.xcworkspace \
-scheme AllTests \ -scheme AllTests \
-destination name="iPhone 6" \ -destination name="iPhone 8" \
HOST_PORT_LOCALSSL=localhost:5051 \ HOST_PORT_LOCALSSL=localhost:5051 \
HOST_PORT_LOCAL=localhost:5050 \ HOST_PORT_LOCAL=localhost:5050 \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \ HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
@ -83,7 +83,7 @@ echo "TIME: $(date)"
xcodebuild \ xcodebuild \
-workspace Tests.xcworkspace \ -workspace Tests.xcworkspace \
-scheme CoreCronetEnd2EndTests \ -scheme CoreCronetEnd2EndTests \
-destination name="iPhone 6" \ -destination name="iPhone 8" \
test \ test \
| egrep -v "$XCODEBUILD_FILTER" \ | egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \ | egrep -v '^$' \
@ -113,7 +113,7 @@ echo "TIME: $(date)"
xcodebuild \ xcodebuild \
-workspace Tests.xcworkspace \ -workspace Tests.xcworkspace \
-scheme CronetUnitTests \ -scheme CronetUnitTests \
-destination name="iPhone 6" \ -destination name="iPhone 8" \
test \ test \
| egrep -v "$XCODEBUILD_FILTER" \ | egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \ | egrep -v '^$' \
@ -123,11 +123,44 @@ echo "TIME: $(date)"
xcodebuild \ xcodebuild \
-workspace Tests.xcworkspace \ -workspace Tests.xcworkspace \
-scheme InteropTestsRemoteWithCronet \ -scheme InteropTestsRemoteWithCronet \
-destination name="iPhone 6" \ -destination name="iPhone 8" \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsRemoteCFStream \
-destination name="iPhone 8" \
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \ HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \
test \ test \
| egrep -v "$XCODEBUILD_FILTER" \ | egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \ | egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" - | egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsLocalCleartextCFStream \
-destination name="iPhone 8" \
HOST_PORT_LOCAL=localhost:5050 \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme InteropTestsLocalSSLCFStream \
-destination name="iPhone 8" \
HOST_PORT_LOCALSSL=localhost:5051 \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
exit 0 exit 0

@ -2,11 +2,14 @@
# Overview # Overview
This directory contains source code for PHP implementation of gRPC layered on This directory contains source code for PHP implementation of gRPC layered on
shared C library. shared C library. The same installation guides with more examples and
tutorials can be seen at [grpc.io](https://grpc.io/docs/quickstart/php.html).
gRPC PHP installation instructions for Google Cloud Platform is in
[cloud.google.com](https://cloud.google.com/php/grpc).
## Environment ## Environment
**Prerequisite:** ###Prerequisite:
* `php` 5.5 or above, 7.0 or above * `php` 5.5 or above, 7.0 or above
* `pecl` * `pecl`
* `composer` * `composer`
@ -25,6 +28,10 @@ For PHP7:
```sh ```sh
$ sudo apt-get install php7.0 php7.0-dev php-pear phpunit $ sudo apt-get install php7.0 php7.0-dev php-pear phpunit
``` ```
or
```sh
$ sudo apt-get install php php-dev php-pear phpunit
```
**Install PHP and PECL on CentOS/RHEL 7:** **Install PHP and PECL on CentOS/RHEL 7:**
```sh ```sh
@ -33,8 +40,9 @@ $ sudo rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
$ sudo yum install php56w php56w-devel php-pear phpunit gcc zlib-devel $ sudo yum install php56w php56w-devel php-pear phpunit gcc zlib-devel
``` ```
**Install PECL on Mac:** **Install PHP and PECL on Mac:**
```sh ```sh
$ brew install homebrew/php/php56-grpc
$ curl -O http://pear.php.net/go-pear.phar $ curl -O http://pear.php.net/go-pear.phar
$ sudo php -d detect_unicode=0 go-pear.phar $ sudo php -d detect_unicode=0 go-pear.phar
``` ```
@ -52,50 +60,33 @@ $ chmod +x phpunit-old.phar
$ sudo mv phpunit-old.phar /usr/bin/phpunit $ sudo mv phpunit-old.phar /usr/bin/phpunit
``` ```
## Quick Install ## Install the gRPC PHP extension
There are two ways to install gRPC PHP extension.
* `pecl`
* `build from source`
**Install the gRPC PHP extension** ### Using PECL
```sh ```sh
sudo pecl install grpc sudo pecl install grpc
``` ```
This will compile and install the gRPC PHP extension into the standard PHP or specific version
extension directory. You should be able to run the [unit tests](#unit-tests),
with the PHP extension installed.
Note: For users on CentOS/RHEL 6, unfortunately this step won't work. Please
follow the instructions below to compile the extension from source.
**Update php.ini**
Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
```sh ```sh
extension=grpc.so sudo pecl install grpc-1.12.0
```
**Add the gRPC PHP library as a Composer dependency**
You need to add this to your project's `composer.json` file.
``` ```
"require": {
"grpc/grpc": "v1.1.0"
}
```
To run tests with generated stub code from `.proto` files, you will also need
the `composer` and `protoc` binaries. You can find out how to get these
[below](#generated-code-tests).
Note: for users on CentOS/RHEL 6, unfortunately this step won’t work.
Please follow the instructions below to compile the PECL extension from source.
## Build from Source #### Install on Windows
You can download the pre-compiled gRPC extension from the PECL
[website](https://pecl.php.net/package/grpc)
### gRPC C core library ### Build from Source with gRPC C core library
Clone this repository Clone this repository
@ -103,16 +94,16 @@ Clone this repository
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc $ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
``` ```
Build and install the gRPC C core library #### Build and install the gRPC C core library
```sh ```sh
$ cd grpc $ cd grpc
$ git pull --recurse-submodules && git submodule update --init --recursive $ git submodule update --init
$ make $ make
$ sudo make install $ sudo make install
``` ```
### gRPC PHP extension #### Build and install gRPC PHP extension
Compile the gRPC PHP extension Compile the gRPC PHP extension
@ -124,44 +115,69 @@ $ make
$ sudo make install $ sudo make install
``` ```
## Unit Tests This will compile and install the gRPC PHP extension into the
standard PHP extension directory. You should be able to run
the [unit tests](#unit-tests), with the PHP extension installed.
You will need the source code to run tests
### Update php.ini
After installing the gRPC extension, make sure you add this line
to your `php.ini` file, (e.g. `/etc/php5/cli/php.ini`,
`/etc/php5/apache2/php.ini`, or `/usr/local/etc/php/5.6/php.ini`),
depending on where your PHP installation is.
```sh ```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc extension=grpc.so
$ cd grpc
$ git pull --recurse-submodules && git submodule update --init --recursive
``` ```
Run unit tests **Add the gRPC PHP library as a Composer dependency**
You need to add this to your project's `composer.json` file.
```sh ```
$ cd grpc/src/php "require": {
$ ./bin/run_tests.sh "grpc/grpc": "v1.12.0"
}
``` ```
## Generated Code Tests To run tests with generated stub code from `.proto` files, you will also
need the `composer` and `protoc` binaries. You can find out how to get these below.
This section specifies the prerequisites for running the generated code tests, ## Install other prerequisites for both Mac OS X and Linux
as well as how to run the tests themselves.
### Composer * `protoc: protobuf compiler`
* `protobuf.so: protobuf runtime library`
* `grpc_php_plugin: Generates PHP gRPC service interface out of Protobuf IDL`
Install the runtime dependencies via `composer install`. ### Install Protobuf compiler
```sh If you don't have it already, you need to install the protobuf compiler
$ cd grpc/src/php `protoc`, version 3.5.0+ (the newer the better) for the current gRPC version.
$ composer install If you installed already, make the protobuf version is compatible to the
``` grpc version you installed. If you build grpc.so from the souce, you can check
the version of grpc inside package.xml file.
### Protobuf compiler The compatibility between the grpc and protobuf version is listed as table below:
Again if you don't have it already, you need to install the protobuf compiler grpc | protobuf
`protoc`, version 3.1.0+ (the newer the better). --- | ---
v1.0.0 | 3.0.0(GA)
v1.0.1 | 3.0.2
v1.1.0 | 3.1.0
v1.2.0 | 3.2.0
v1.2.0 | 3.2.0
v1.3.4 | 3.3.0
v1.3.5 | 3.2.0
v1.4.0 | 3.3.0
v1.6.0 | 3.4.0
v1.8.0 | 3.5.0
v1.12.0 | 3.5.2
If `protoc` hasn't been installed, you can download the `protoc` binaries from If `protoc` hasn't been installed, you can download the `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases). [the protocol buffers Github repository](https://github.com/google/protobuf/releases).
Then unzip this file and update the environment variable `PATH` to include the path to
the protoc binary file.
If you really must compile `protoc` from source, you can run the following If you really must compile `protoc` from source, you can run the following
commands, but this is risky because there is no easy way to uninstall / commands, but this is risky because there is no easy way to uninstall /
@ -173,32 +189,44 @@ $ ./autogen.sh && ./configure && make
$ sudo make install $ sudo make install
``` ```
### Protobuf Runtime library ### Protobuf Runtime library
There are two protobuf runtime libraries to choose from. They are idenfical in terms of APIs offered. There are two protobuf runtime libraries to choose from. They are identical
in terms of APIs offered. The C implementation provides better performance,
while the native implementation is easier to install. Make sure the installed
protobuf version works with grpc version.
1. C implementation (for better performance) #### 1. C implementation (for better performance)
``` sh ``` sh
$ sudo pecl install protobuf $ sudo pecl install protobuf
``` ```
or specific version
2. PHP implementation (for easier installation) ``` sh
$ sudo pecl install protobuf-3.5.1.1
```
Add this to your `php.ini` file:
```sh
extension=protobuf.so
```
#### 2. PHP implementation (for easier installation)
Add this to your `composer.json` file: Add this to your `composer.json` file:
``` ```
"require": { "require": {
"google/protobuf": "^v3.3.0" "google/protobuf": "^v3.5.0"
} }
``` ```
### PHP Protoc Plugin ### PHP Protoc Plugin
You need the gRPC PHP protoc plugin to generate the client stub classes. You need the gRPC PHP protoc plugin to generate the client stub classes.
It can generate server and client code from .proto service definitions.
It should already been compiled when you run `make` from the root directory It should already been compiled when you run `make` from the root directory
of this repo. The plugin can be found in the `bins/opt` directory. We are of this repo. The plugin can be found in the `bins/opt` directory. We are
@ -208,10 +236,47 @@ in the future.
You can also just build the gRPC PHP protoc plugin by running: You can also just build the gRPC PHP protoc plugin by running:
```sh ```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc $ cd grpc
$ git submodule update --init
$ make grpc_php_plugin $ make grpc_php_plugin
``` ```
Plugin may use the new feature of the new protobuf version, thus please also
make sure that the protobuf version installed is compatible with the grpc version
you build this plugin.
## Unit Tests
You will need the source code to run tests
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
```
Run unit tests
```sh
$ cd grpc/src/php
$ ./bin/run_tests.sh
```
## Generated Code Tests
This section specifies the prerequisites for running the generated code tests,
as well as how to run the tests themselves.
### Composer
Install the runtime dependencies via `composer install`.
```sh
$ cd grpc/src/php
$ composer install
```
### Client Stub ### Client Stub

@ -35,6 +35,7 @@ class CallCredentials2Test extends PHPUnit_Framework_TestCase
$this->channel = new Grpc\Channel( $this->channel = new Grpc\Channel(
'localhost:'.$this->port, 'localhost:'.$this->port,
[ [
'force_new' => true,
'grpc.ssl_target_name_override' => $this->host_override, 'grpc.ssl_target_name_override' => $this->host_override,
'grpc.default_authority' => $this->host_override, 'grpc.default_authority' => $this->host_override,
'credentials' => $credentials, 'credentials' => $credentials,

@ -41,6 +41,7 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
$this->channel = new Grpc\Channel( $this->channel = new Grpc\Channel(
'localhost:'.$this->port, 'localhost:'.$this->port,
[ [
'force_new' => true,
'grpc.ssl_target_name_override' => $this->host_override, 'grpc.ssl_target_name_override' => $this->host_override,
'grpc.default_authority' => $this->host_override, 'grpc.default_authority' => $this->host_override,
'credentials' => $this->credentials, 'credentials' => $this->credentials,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save