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. 17
      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. 11
      include/grpcpp/impl/codegen/call.h
  23. 41
      setup.py
  24. 25
      src/compiler/csharp_generator.cc
  25. 520
      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. 13
      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. 18
      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. 31
      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. 195
      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
# this one if we extracted just a few more helper functions...
too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from
# the beginning and will continue to do so until it goes away for good.
# TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary
# 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,
no-else-return,

@ -103,6 +103,13 @@ disable=
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions...
too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from
# the beginning and will continue to do so until it goes away for good.
# TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary
# 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,
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(
name = "grpc_client_channel",
srcs = [

@ -700,6 +700,7 @@ target_include_directories(address_sorting
)
target_link_libraries(address_sorting
${_gRPC_BASELIB_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
)
@ -5297,6 +5298,7 @@ add_library(end2end_tests
test/core/end2end/tests/max_message_length.cc
test/core/end2end/tests/negative_deadline.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_op.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/negative_deadline.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_op.cc
test/core/end2end/tests/payload.cc

@ -501,7 +501,6 @@ endif
ifeq ($(HAS_PKG_CONFIG),true)
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
PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
@ -514,7 +513,6 @@ OPENSSL_LIBS = ssl crypto
endif
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)
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)
@ -542,13 +540,7 @@ HAS_SYSTEM_PROTOBUF_VERIFY = $(shell $(PROTOBUF_CHECK_CMD) 2> /dev/null && echo
ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
HAS_SYSTEM_OPENSSL_NPN = 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
HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_SYSTEM_ZLIB),true)
@ -565,7 +557,6 @@ endif
else
# override system libraries if the config requires a custom compiled library
HAS_SYSTEM_OPENSSL_ALPN = false
HAS_SYSTEM_OPENSSL_NPN = false
HAS_SYSTEM_ZLIB = false
HAS_SYSTEM_PROTOBUF = false
HAS_SYSTEM_CARES = false
@ -712,12 +703,7 @@ ifneq ($(HAS_EMBEDDED_OPENSSL_ALPN),false)
EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
NO_SECURE ?= false
else # HAS_EMBEDDED_OPENSSL_ALPN=false
ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
EMBED_OPENSSL ?= false
NO_SECURE ?= false
else
NO_SECURE ?= true
endif # HAS_SYSTEM_OPENSSL_NPN=true
endif # HAS_EMBEDDED_OPENSSL_ALPN
endif # HAS_SYSTEM_OPENSSL_ALPN
@ -751,10 +737,10 @@ LDFLAGS := $(LDFLAGS_OPENSSL_PKG_CONFIG) $(LDFLAGS)
else # HAS_PKG_CONFIG=false
LIBS_SECURE = $(OPENSSL_LIBS)
endif # HAS_PKG_CONFIG
ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
ifeq ($(DISABLE_ALPN),true)
CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
LIBS_SECURE = $(OPENSSL_LIBS)
endif # HAS_SYSTEM_OPENSSL_NPN
endif # DISABLE_ALPN
PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE))
endif # EMBED_OPENSSL
endif # NO_SECURE
@ -1347,7 +1333,6 @@ uri_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/uri_fuzzer_test_one_entry
run_dep_checks:
$(OPENSSL_ALPN_CHECK_CMD) || true
$(OPENSSL_NPN_CHECK_CMD) || true
$(ZLIB_CHECK_CMD) || true
$(PERFTOOLS_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/negative_deadline.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_op.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/negative_deadline.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_op.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 use_external:
# when this file is used by non-grpc projects
plugin = "//external:grpc_cpp_plugin"
else:
plugin = "//:grpc_cpp_plugin"
plugin = "@com_github_grpc_grpc//:grpc_cpp_plugin"
generate_cc(
name = codegen_grpc_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,
**kwargs
)
if use_external:
# when this file is used by non-grpc projects
grpc_deps = ["//external:grpc++_codegen_proto",
"//external:protobuf"]
else:
grpc_deps = ["//:grpc++_codegen_proto", "//external:protobuf"]
grpc_deps = ["@com_github_grpc_grpc//:grpc++_codegen_proto",
"//external:protobuf"]
native.cc_library(
name = name,
srcs = [":" + codegen_grpc_target, ":" + codegen_target],

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

@ -536,6 +536,19 @@ filegroups:
uses:
- grpc_codegen
- 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
headers:
- 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'
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|
ss.header_mappings_dir = 'include/grpc'
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/negative_deadline.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_op.cc',
'test/core/end2end/tests/payload.cc',

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

@ -63,6 +63,16 @@ Pod::Spec.new do |s|
ss.dependency 'gRPC-Core', version
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|
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/ext/**/*')
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.test_files = Dir.glob('src/ruby/spec/**/*')
s.bindir = 'src/ruby/bin'
@ -28,7 +30,6 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
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_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 'rubocop', '~> 0.49.1'
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)

@ -2630,6 +2630,7 @@
'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.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_op.cc',
'test/core/end2end/tests/payload.cc',
@ -2720,6 +2721,7 @@
'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.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_op.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"
/** Channel arg that carries the bridged objective c object for custom metrics
* 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 */
#define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \
"grpc.disable_client_authority_filter"

@ -227,7 +227,10 @@
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 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
#endif
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */

@ -573,10 +573,13 @@ class CallOpClientRecvStatus {
binary_error_details =
grpc::string(iter->second.begin(), iter->second.length());
}
*recv_status_ = Status(static_cast<StatusCode>(status_code_),
grpc::string(GRPC_SLICE_START_PTR(error_message_),
GRPC_SLICE_END_PTR(error_message_)),
binary_error_details);
*recv_status_ =
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_)),
binary_error_details);
client_context_->set_debug_error_string(
debug_error_string_ != nullptr ? debug_error_string_ : "");
g_core_codegen_interface->grpc_slice_unref(error_message_);

@ -35,7 +35,7 @@ egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
PY3 = sys.version_info.major == 3
PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
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'),)
CARES_INCLUDE = (
os.path.join('third_party', 'cares'),
@ -84,6 +84,24 @@ CLASSIFIERS = [
# present, then it will still attempt to use Cython.
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
# in Cython modules.
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:
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 = (
(PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE +
(PYTHON_STEM,) + CORE_INCLUDE + SSL_INCLUDE + ZLIB_INCLUDE +
CARES_INCLUDE + ADDRESS_SORTING_INCLUDE)
EXTENSION_LIBRARIES = ()
@ -159,6 +190,12 @@ if not "win32" in sys.platform:
EXTENSION_LIBRARIES += ('m',)
if "win32" in sys.platform:
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 = (
('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),

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

@ -891,6 +891,7 @@ typedef struct client_channel_call_data {
grpc_closure pick_cancel_closure;
grpc_polling_entity* pollent;
bool pollent_added_to_interested_parties;
// Batches are added to this list when received from above.
// 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 on_complete(void* arg, grpc_error* error);
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);
//
@ -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
// 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) {
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_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(&calld->pick_closure, error);
}
// A wrapper around pick_done_locked() that is used in cases where
// either (a) the pick was deferred pending a resolver result or (b) the
// pick was done asynchronously. Removes the call's polling entity from
// chand->interested_parties before invoking pick_done_locked().
static void async_pick_done_locked(grpc_call_element* elem, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_polling_entity_del_from_pollset_set(calld->pollent,
chand->interested_parties);
pick_done_locked(elem, error);
}
namespace grpc_core {
// Note: This runs under the client_channel combiner, but will NOT be
// holding the call combiner.
static void pick_callback_cancel_locked(void* arg, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
channel_data* chand = static_cast<channel_data*>(elem->channel_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)) {
// Performs subchannel pick via LB policy.
class LbPicker {
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);
call_data* calld = static_cast<call_data*>(elem->call_data);
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: starting pick on lb_policy=%p",
chand, calld, chand->lb_policy.get());
}
chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error));
// 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)));
}
}
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback_cancel");
}
// Callback invoked by LoadBalancingPolicy::PickLocked() for async picks.
// Unrefs the LB policy and invokes async_pick_done_locked().
static void pick_callback_done_locked(void* arg, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
channel_data* chand = static_cast<channel_data*>(elem->channel_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: pick completed asynchronously", chand,
calld);
private:
// Callback invoked by LoadBalancingPolicy::PickLocked() for async picks.
// 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);
channel_data* chand = static_cast<channel_data*>(elem->channel_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: pick completed asynchronously",
chand, calld);
}
pick_done_locked(elem, GRPC_ERROR_REF(error));
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
}
async_pick_done_locked(elem, GRPC_ERROR_REF(error));
GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
}
// Note: This runs under the client_channel combiner, but will NOT be
// holding the call combiner.
static void CancelLocked(void* arg, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
channel_data* chand = static_cast<channel_data*>(elem->channel_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()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: cancelling pick from LB policy %p", chand,
calld, chand->lb_policy.get());
}
chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error));
}
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
// 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);
}
}
// 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.
@ -2776,215 +2868,164 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) {
}
}
// Starts a pick on chand->lb_policy.
// Returns true if pick is completed synchronously.
static bool pick_callback_start_locked(grpc_call_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
// Invoked once resolver results are available.
static void process_service_config_and_start_lb_pick_locked(
grpc_call_element* elem) {
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.
if (GPR_LIKELY(calld->num_attempts_completed == 0)) {
apply_service_config_to_call_locked(elem);
}
// If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this
// 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;
// Start LB pick.
grpc_core::LbPicker::StartLocked(elem);
}
typedef struct {
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
// holding the call combiner.
static void pick_after_resolver_result_cancel_locked(void* arg,
grpc_error* error) {
pick_after_resolver_result_args* args =
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);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: cancelling pick waiting for resolver result",
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 async_pick_done_locked() here -- we are
// essentially calling it here instead of calling it in
// pick_after_resolver_result_done_locked().
async_pick_done_locked(elem, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Pick cancelled", &error, 1));
}
static void pick_after_resolver_result_done_locked(void* arg,
grpc_error* error) {
pick_after_resolver_result_args* args =
static_cast<pick_after_resolver_result_args*>(arg);
if (GPR_UNLIKELY(args->finished)) {
/* cancelled, do nothing */
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "call cancelled before resolver result");
}
gpr_free(args);
return;
}
args->finished = true;
grpc_call_element* elem = args->elem;
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
namespace grpc_core {
// Handles waiting for a resolver result.
// Used only for the first call on an idle channel.
class ResolverResultWaiter {
public:
explicit ResolverResultWaiter(grpc_call_element* elem) : elem_(elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_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: resolver failed to return data",
gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring pick pending resolver result",
chand, calld);
}
async_pick_done_locked(elem, GRPC_ERROR_REF(error));
} else if (GPR_UNLIKELY(chand->resolver == nullptr)) {
// Shutting down.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand,
calld);
// Add closure to be run when a resolver result is available.
GRPC_CLOSURE_INIT(&done_closure_, &ResolverResultWaiter::DoneLocked, this,
grpc_combiner_scheduler(chand->combiner));
AddToWaitingList();
// Set cancellation closure, so that we abort if the call is cancelled.
GRPC_CLOSURE_INIT(&cancel_closure_, &ResolverResultWaiter::CancelLocked,
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);
}
// Invoked when a resolver result is available.
static void DoneLocked(void* arg, grpc_error* error) {
ResolverResultWaiter* self = static_cast<ResolverResultWaiter*>(arg);
// If CancelLocked() has already run, delete ourselves without doing
// anything. Note that the call stack may have already been destroyed,
// so it's not safe to access anything in elem_.
if (GPR_UNLIKELY(self->finished_)) {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "call cancelled before resolver result");
}
Delete(self);
return;
}
async_pick_done_locked(
elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
} else if (GPR_UNLIKELY(chand->lb_policy == nullptr)) {
// Transient resolver failure.
// If call has wait_for_ready=true, try again; otherwise, fail.
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;
if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) {
// Otherwise, process the resolver result.
grpc_call_element* elem = self->elem_;
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=true; trying again",
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data",
chand, calld);
}
pick_after_resolver_result_start_locked(elem);
pick_done_locked(elem, GRPC_ERROR_REF(error));
} else if (GPR_UNLIKELY(chand->resolver == nullptr)) {
// Shutting down.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand,
calld);
}
pick_done_locked(elem,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
} else if (GPR_UNLIKELY(chand->lb_policy == nullptr)) {
// Transient resolver failure.
// If call has wait_for_ready=true, try again; otherwise, fail.
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;
if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=true; trying again",
chand, calld);
}
// Re-add ourselves to the waiting list.
self->AddToWaitingList();
// Return early so that we don't set finished_ to true below.
return;
} else {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=false; failing",
chand, calld);
}
pick_done_locked(
elem,
grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
}
} else {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: resolver returned but no LB policy; "
"wait_for_ready=false; failing",
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing LB pick",
chand, calld);
}
async_pick_done_locked(
elem,
grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Name resolution failure"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
process_service_config_and_start_lb_pick_locked(elem);
}
} else {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing pick",
chand, calld);
self->finished_ = true;
}
// 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 (GPR_LIKELY(pick_callback_start_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);
// 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);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: cancelling call waiting for name "
"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;
}
}
static void pick_after_resolver_result_start_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 (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: deferring pick pending resolver result", chand,
calld);
}
pick_after_resolver_result_args* args =
static_cast<pick_after_resolver_result_args*>(gpr_zalloc(sizeof(*args)));
args->elem = elem;
GRPC_CLOSURE_INIT(&args->closure, pick_after_resolver_result_done_locked,
args, grpc_combiner_scheduler(chand->combiner));
grpc_closure_list_append(&chand->waiting_for_resolver_result_closures,
&args->closure, GRPC_ERROR_NONE);
grpc_call_combiner_set_notify_on_cancel(
calld->call_combiner,
GRPC_CLOSURE_INIT(&args->cancel_closure,
pick_after_resolver_result_cancel_locked, args,
grpc_combiner_scheduler(chand->combiner)));
}
grpc_call_element* elem_;
grpc_closure done_closure_;
grpc_closure cancel_closure_;
bool finished_ = false;
};
} // namespace grpc_core
static void start_pick_locked(void* arg, grpc_error* ignored) {
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->subchannel_call == nullptr);
if (GPR_LIKELY(chand->lb_policy != nullptr)) {
// We already have an LB policy, so ask it for a pick.
if (GPR_LIKELY(pick_callback_start_locked(elem))) {
// Pick completed synchronously.
pick_done_locked(elem, GRPC_ERROR_NONE);
return;
}
// We already have resolver results, so process the service config
// and start an LB pick.
process_service_config_and_start_lb_pick_locked(elem);
} else if (GPR_UNLIKELY(chand->resolver == nullptr)) {
pick_done_locked(elem,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
} 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,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Disconnected"));
return;
}
if (GPR_UNLIKELY(!chand->started_resolving)) {
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 "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 <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);
}
#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) {
char* old_peer_string = (char*)gpr_atm_full_xchg(
op_payload->send_initial_metadata.peer_string,
(gpr_atm)gpr_strdup(t->peer_string));
gpr_free(old_peer_string);
gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
(gpr_atm)t->peer_string);
}
}
@ -1569,10 +1567,8 @@ static void perform_stream_op_locked(void* stream_op,
s->trailing_metadata_available =
op_payload->recv_initial_metadata.trailing_metadata_available;
if (op_payload->recv_initial_metadata.peer_string != nullptr) {
char* old_peer_string = (char*)gpr_atm_full_xchg(
op_payload->recv_initial_metadata.peer_string,
(gpr_atm)gpr_strdup(t->peer_string));
gpr_free(old_peer_string);
gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string,
(gpr_atm)t->peer_string);
}
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/timeout_encoding.h"
#define HASH_FRAGMENT_1(x) ((x)&255)
#define HASH_FRAGMENT_2(x) ((x >> 8) & 255)
#define HASH_FRAGMENT_3(x) ((x >> 16) & 255)
#define HASH_FRAGMENT_4(x) ((x >> 24) & 255)
#define HASH_FRAGMENT_MASK (GRPC_CHTTP2_HPACKC_NUM_VALUES - 1)
#define HASH_FRAGMENT_1(x) ((x)&HASH_FRAGMENT_MASK)
#define HASH_FRAGMENT_2(x) \
(((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
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 */
#define MAX_DECODER_SPACE_USAGE 512
@ -135,7 +139,7 @@ static void inc_filter(uint8_t idx, uint32_t* sum, uint8_t* elems) {
} else {
int i;
*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;
(*sum) += elems[i];
}

@ -28,8 +28,9 @@
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
// This should be <= 8. We use 6 to save space.
#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 */
#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
/* 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.
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. */
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
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
#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** 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;
}
#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()) {
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_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);
/// 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) */
#if defined(GRPC_POSIX_SOCKET)
#if defined(GRPC_POSIX_SOCKET_EV_EPOLL1)
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
* NULL */
const grpc_event_engine_vtable* grpc_init_epoll1_linux(bool explicit_request) {
return nullptr;
}
#endif /* defined(GRPC_POSIX_SOCKET) */
#endif /* defined(GRPC_POSIX_SOCKET_EV_EPOLL1) */
#endif /* !defined(GRPC_LINUX_EPOLL) */

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

@ -20,7 +20,7 @@
#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"
@ -1769,4 +1769,4 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(bool explicit_request) {
return &vtable;
}
#endif
#endif /* GRPC_POSIX_SOCKET_EV_POLL */

@ -20,7 +20,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#ifdef GRPC_POSIX_SOCKET_EV
#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);
}
#endif // GRPC_POSIX_SOCKET
#endif // GRPC_POSIX_SOCKET_EV

@ -20,7 +20,7 @@
#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/iomgr/ev_posix.h"
@ -64,4 +64,4 @@ void grpc_set_default_iomgr_platform() {
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,
grpc_pollset_set* pss_dst) {
if (pollent->tag == GRPC_POLLS_POLLSET) {
GPR_ASSERT(pollent->pollent.pollset != nullptr);
grpc_pollset_set_add_pollset(pss_dst, pollent->pollent.pollset);
// 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);
}
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
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,
grpc_pollset_set* pss_dst) {
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);
grpc_pollset_set_del_pollset(pss_dst, pollent->pollent.pollset);
#endif
} else if (pollent->tag == GRPC_POLLS_POLLSET_SET) {
GPR_ASSERT(pollent->pollent.pollset_set != nullptr);
grpc_pollset_set_del_pollset_set(pss_dst, pollent->pollent.pollset_set);

@ -97,7 +97,26 @@
#define GRPC_MSG_IOVLEN_TYPE int
#define GRPC_POSIX_FORK 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
#endif
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_SYSCONF 1
#define GRPC_POSIX_WAKEUP_FD 1
@ -131,12 +150,30 @@
#endif
#if defined(GRPC_POSIX_SOCKET) + defined(GRPC_WINSOCK_SOCKET) + \
defined(GRPC_CUSTOM_SOCKET) != \
defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_CFSTREAM) != \
1
#error \
"Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET"
#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)
#error "Cannot define both GRPC_POSIX_HOST_NAME_MAX and GRPC_POSIX_SYSCONF"
#endif

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

@ -19,7 +19,7 @@
#include <grpc/support/port_platform.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"

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

@ -20,7 +20,7 @@
#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/gpr/useful.h"

@ -20,7 +20,7 @@
#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_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);
}
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_schedule_on_exec_ctx);
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};

@ -20,7 +20,7 @@
#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"

@ -20,7 +20,7 @@
#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/tcp_posix.h"
@ -70,7 +70,9 @@ struct grpc_tcp {
grpc_endpoint base;
grpc_fd* em_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 bytes_read_this_round;
gpr_refcount refcount;
@ -377,7 +379,6 @@ static void tcp_do_read(grpc_tcp* tcp) {
ssize_t read_bytes;
size_t i;
GPR_ASSERT(!tcp->finished_edge);
GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC);
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) {
grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
GPR_ASSERT(!tcp->finished_edge);
if (grpc_tcp_trace.enabled()) {
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_swap(incoming_buffer, &tcp->last_read_buffer);
TCP_REF(tcp, "read");
if (tcp->finished_edge) {
tcp->finished_edge = false;
if (tcp->is_first_read) {
/* Endpoint read called for the very first time. Register read callback with
* the polling engine */
tcp->is_first_read = false;
notify_on_read(tcp);
} 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);
}
}
@ -778,7 +785,8 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
tcp->min_read_chunk_size = tcp_min_read_chunk_size;
tcp->max_read_chunk_size = tcp_max_read_chunk_size;
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 */
gpr_ref_init(&tcp->refcount, 1);
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");
}
#endif
#endif /* GRPC_POSIX_SOCKET_TCP */

@ -25,7 +25,7 @@
#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"
@ -559,4 +559,4 @@ grpc_tcp_server_vtable grpc_posix_tcp_server_vtable = {
tcp_server_shutdown_starting_add,
tcp_server_unref,
tcp_server_shutdown_listeners};
#endif
#endif /* GRPC_POSIX_SOCKET_TCP_SERVER */

@ -20,7 +20,7 @@
#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"
@ -217,4 +217,4 @@ error:
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);
c->token_fetch_pending = false;
c->access_token_md = GRPC_MDELEM_REF(access_token_md);
c->token_expiration = status == GRPC_CREDENTIALS_OK
? grpc_core::ExecCtx::Get()->Now() + token_lifetime
: 0;
c->token_expiration =
status == GRPC_CREDENTIALS_OK
? 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 =
c->pending_requests;
c->pending_requests = nullptr;
@ -259,8 +261,10 @@ static bool oauth2_token_fetcher_get_request_metadata(
grpc_mdelem cached_access_token_md = GRPC_MDNULL;
gpr_mu_lock(&c->mu);
if (!GRPC_MDISNULL(c->access_token_md) &&
(c->token_expiration - grpc_core::ExecCtx::Get()->Now() >
refresh_threshold)) {
gpr_time_cmp(
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);
}
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;
gpr_ref_init(&c->base.refcount, 1);
gpr_mu_init(&c->mu);
c->token_expiration = 0;
c->token_expiration = gpr_inf_past(GPR_CLOCK_MONOTONIC);
c->fetch_func = fetch_func;
c->pollent =
grpc_polling_entity_create_from_pollset_set(grpc_pollset_set_create());

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

@ -29,6 +29,10 @@ const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name) {
grpc_json* child;
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 (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);
if (slice_len > n) {
sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n);
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
return;
} else if (slice_len == n) {
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
sb->count = idx;
return;
} else {
grpc_slice_buffer_add_indexed(garbage, slice);
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
grpc_slice_unref_internal(slice);
}
n -= slice_len;
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_channel* channel = c->channel;
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_INTERNAL_UNREF(channel, "call");
}

@ -184,7 +184,8 @@ void grpc_transport_set_pops(grpc_transport* transport, grpc_stream* stream,
nullptr) {
transport->vtable->set_pollset_set(transport, stream, pollset_set);
} 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
send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */
uint32_t send_initial_metadata_flags;
// If non-NULL, will be set by the transport to the peer string
// (a char*, which the caller takes ownership of).
// If non-NULL, will be set by the transport to the peer string (a char*).
// The transport retains ownership of the string.
// Note: This pointer may be used by the transport after the
// send_initial_metadata op is completed. It must remain valid
// until the call is destroyed.
// Note: When a transport sets this, it must free the previous
// value, if any.
gpr_atm* peer_string;
} 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
// Trailers-Only response.
bool* trailing_metadata_available;
// If non-NULL, will be set by the transport to the peer string
// (a char*, which the caller takes ownership of).
// If non-NULL, will be set by the transport to the peer string (a char*).
// The transport retains ownership of the string.
// Note: This pointer may be used by the transport after the
// recv_initial_metadata op is completed. It must remain valid
// until the call is destroyed.
// Note: When a transport sets this, it must free the previous
// value, if any.
gpr_atm* peer_string;
} recv_initial_metadata;

@ -39,8 +39,8 @@ static void do_plugin_list_init(void) {
}
ServerBuilder::ServerBuilder()
: max_receive_message_size_(-1),
max_send_message_size_(-1),
: max_receive_message_size_(INT_MIN),
max_send_message_size_(INT_MIN),
sync_server_settings_(SyncServerSettings()),
resource_quota_(nullptr),
generic_service_(nullptr) {
@ -186,10 +186,12 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
(*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_);
}
// The default message size is -1 (max), so no need to explicitly set it for
// -1.
if (max_send_message_size_ >= 0) {
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
// limitations under the License.
//
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
using grpc = global::Grpc.Core;

@ -20,7 +20,7 @@
// The canonical version of this proto can be found at
// 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
using grpc = global::Grpc.Core;

@ -19,7 +19,7 @@
//
// An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses.
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
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
// something at an instant of time) is the only metric type supported by the
// service.
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
using grpc = global::Grpc.Core;

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

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

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

@ -19,7 +19,7 @@
//
// Service exported by server reflection
//
#pragma warning disable 1591
#pragma warning disable 0414, 1591
#region Designer generated code
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
%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
@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
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
(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
# breaks the code generation.
$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|
s.name = 'BoringSSL'
version = '10.0.4'
version = '10.0.5'
s.version = version
s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
# 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
NDK) and a number of other apps/programs.
DESC
s.homepage = 'https://boringssl.googlesource.com/boringssl/'
s.documentation_url = 'https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html'
s.homepage = 'https://github.com/google/boringssl'
s.license = { :type => 'Mixed', :file => 'LICENSE' }
# "The name and email addresses of the library maintainers, not the Podspec maintainer."
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>
#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
+ (instancetype)completionQueue {
@ -33,7 +41,8 @@
- (instancetype)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
// 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) int keepaliveInterval;
@property(nonatomic) int keepaliveTimeout;
@property(nonatomic) id logContext;
/** The following properties should only be modified for testing: */

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

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

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

@ -36,6 +36,27 @@ GRPC_LOCAL_SRC = '../../..'
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(
CoreCronetEnd2EndTests
CronetUnitTests
@ -65,7 +86,7 @@ end
# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need.
pre_install do |installer|
# 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:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
@ -96,7 +117,11 @@ post_install do |installer|
# GPR_UNREACHABLE_CODE causes "Control may reach end of non-void
# function" warning
config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1'
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'
end
end
end
@ -104,7 +129,7 @@ post_install do |installer|
# the test target 'InteropTestsRemoteWithCronet'
# Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will
# 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|
if config.name == 'Cronet'
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"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -66,6 +67,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

@ -26,6 +26,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -57,6 +58,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "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"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@ -60,6 +61,7 @@
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "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 \
-workspace *.xcworkspace \
-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 "^$" -

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

@ -2,11 +2,14 @@
# Overview
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
**Prerequisite:**
###Prerequisite:
* `php` 5.5 or above, 7.0 or above
* `pecl`
* `composer`
@ -25,6 +28,10 @@ For PHP7:
```sh
$ 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:**
```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
```
**Install PECL on Mac:**
**Install PHP and PECL on Mac:**
```sh
$ brew install homebrew/php/php56-grpc
$ curl -O http://pear.php.net/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
```
## 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
sudo pecl install grpc
```
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.
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`
or specific version
```sh
extension=grpc.so
```
**Add the gRPC PHP library as a Composer dependency**
You need to add this to your project's `composer.json` file.
sudo pecl install grpc-1.12.0
```
"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
@ -103,16 +94,16 @@ Clone this repository
$ 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
$ cd grpc
$ git pull --recurse-submodules && git submodule update --init --recursive
$ git submodule update --init
$ make
$ sudo make install
```
### gRPC PHP extension
#### Build and install gRPC PHP extension
Compile the gRPC PHP extension
@ -124,44 +115,69 @@ $ make
$ 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
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git pull --recurse-submodules && git submodule update --init --recursive
extension=grpc.so
```
Run unit tests
**Add the gRPC PHP library as a Composer dependency**
```sh
$ cd grpc/src/php
$ ./bin/run_tests.sh
You need to add this to your project's `composer.json` file.
```
"require": {
"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,
as well as how to run the tests themselves.
## Install other prerequisites for both Mac OS X and Linux
### 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
$ cd grpc/src/php
$ composer install
```
If you don't have it already, you need to install the protobuf compiler
`protoc`, version 3.5.0+ (the newer the better) for the current gRPC version.
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
`protoc`, version 3.1.0+ (the newer the better).
grpc | protobuf
--- | ---
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
[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
commands, but this is risky because there is no easy way to uninstall /
@ -173,32 +189,44 @@ $ ./autogen.sh && ./configure && make
$ sudo make install
```
### 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
$ 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:
```
"require": {
"google/protobuf": "^v3.3.0"
"google/protobuf": "^v3.5.0"
}
```
```
### PHP Protoc Plugin
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
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:
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
$ 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

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

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

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

Loading…
Cancel
Save