Merge remote-tracking branch 'upstream/master' into threadpool

pull/19519/head
Yunjia Wang 5 years ago
commit 0141b18d66
  1. 1
      BUILD
  2. 1
      BUILD.gn
  3. 120
      CMakeLists.txt
  4. 62
      Makefile
  5. 16
      build.yaml
  6. 2
      doc/statuscodes.md
  7. 65
      examples/python/auth/BUILD.bazel
  8. 112
      examples/python/auth/README.md
  9. 31
      examples/python/auth/_credentials.py
  10. 19
      examples/python/auth/credentials/localhost.crt
  11. 27
      examples/python/auth/credentials/localhost.key
  12. 20
      examples/python/auth/credentials/root.crt
  13. 105
      examples/python/auth/customized_auth_client.py
  14. 110
      examples/python/auth/customized_auth_server.py
  15. 56
      examples/python/auth/test/_auth_example_test.py
  16. 1
      gRPC-C++.podspec
  17. 1
      grpc.def
  18. 25
      include/grpc/grpc_security.h
  19. 24
      include/grpcpp/completion_queue_impl.h
  20. 1
      include/grpcpp/impl/codegen/server_interface.h
  21. 1
      include/grpcpp/server_impl.h
  22. 3
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  23. 3
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  24. 27
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  25. 96
      src/core/ext/transport/chttp2/transport/hpack_parser.cc
  26. 12
      src/core/lib/gprpp/host_port.cc
  27. 11
      src/core/lib/gprpp/thd.h
  28. 26
      src/core/lib/gprpp/thd_posix.cc
  29. 10
      src/core/lib/gprpp/thd_windows.cc
  30. 5
      src/core/lib/iomgr/executor.cc
  31. 12
      src/core/lib/iomgr/iomgr_posix_cfstream.cc
  32. 4
      src/core/lib/security/credentials/credentials.h
  33. 8
      src/core/lib/security/credentials/jwt/json_token.cc
  34. 2
      src/core/lib/security/credentials/jwt/json_token.h
  35. 260
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  36. 16
      src/core/lib/security/credentials/oauth2/oauth2_credentials.h
  37. 24
      src/core/lib/security/util/json_util.cc
  38. 4
      src/core/lib/security/util/json_util.h
  39. 6
      src/core/lib/transport/metadata.h
  40. 172
      src/core/lib/transport/static_metadata.cc
  41. 5
      src/objective-c/GRPCClient/GRPCCall.m
  42. 2
      src/objective-c/manual_tests/main.m
  43. 7
      src/proto/grpc/testing/messages.proto
  44. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  45. 3
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  46. 9
      templates/CMakeLists.txt.template
  47. 1
      templates/Makefile.template
  48. 2
      templates/tools/dockerfile/interoptest/grpc_interop_dart/Dockerfile.template
  49. 19
      test/core/client_channel/resolvers/BUILD
  50. 46
      test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
  51. 36
      test/core/gprpp/host_port_test.cc
  52. 305
      test/core/security/credentials_test.cc
  53. 82
      test/core/security/fetch_oauth2.cc
  54. 4
      test/core/security/jwt_verifier_test.cc
  55. 15
      test/core/security/oauth2_utils.cc
  56. 1
      test/core/surface/public_headers_must_be_c89.c
  57. 49
      test/cpp/codegen/proto_utils_test.cc
  58. 6
      test/cpp/common/channel_arguments_test.cc
  59. 9
      test/cpp/end2end/client_lb_end2end_test.cc
  60. 12
      test/cpp/end2end/filter_end2end_test.cc
  61. 16
      test/cpp/end2end/grpclb_end2end_test.cc
  62. 9
      test/cpp/end2end/service_config_end2end_test.cc
  63. 16
      test/cpp/end2end/xds_end2end_test.cc
  64. 9
      test/cpp/grpclb/grpclb_api_test.cc
  65. 2
      test/cpp/interop/client.cc
  66. 7
      test/cpp/interop/client_helper.cc
  67. 26
      test/cpp/interop/interop_client.cc
  68. 2
      test/cpp/interop/interop_client.h
  69. 49
      test/cpp/naming/cancel_ares_query_test.cc
  70. 18
      test/cpp/server/server_builder_test.cc
  71. 11
      test/cpp/server/server_builder_with_socket_mutator_test.cc
  72. 9
      test/cpp/util/byte_buffer_test.cc
  73. 6
      test/cpp/util/slice_test.cc
  74. 6
      tools/codegen/core/gen_static_metadata.py
  75. 2
      tools/dockerfile/interoptest/grpc_interop_dart/Dockerfile
  76. 1
      tools/doxygen/Doxyfile.c++
  77. 1
      tools/doxygen/Doxyfile.c++.internal
  78. 4
      tools/interop_matrix/client_matrix.py
  79. 20
      tools/run_tests/generated/sources_and_headers.json
  80. 32
      tools/run_tests/generated/tests.json

@ -222,6 +222,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -1031,6 +1031,7 @@ config("grpc_config") {
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -275,7 +275,8 @@ add_dependencies(buildtests_c compression_test)
add_dependencies(buildtests_c concurrent_connectivity_test)
add_dependencies(buildtests_c connection_refused_test)
add_dependencies(buildtests_c dns_resolver_connectivity_test)
add_dependencies(buildtests_c dns_resolver_cooldown_test)
add_dependencies(buildtests_c dns_resolver_cooldown_using_ares_resolver_test)
add_dependencies(buildtests_c dns_resolver_cooldown_using_native_resolver_test)
add_dependencies(buildtests_c dns_resolver_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c dualstack_socket_test)
@ -1366,6 +1367,9 @@ target_link_libraries(grpc
${_gRPC_ALLTARGETS_LIBRARIES}
gpr
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
@ -1765,6 +1769,9 @@ target_link_libraries(grpc_cronet
${_gRPC_ALLTARGETS_LIBRARIES}
gpr
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc_cronet "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
@ -2095,6 +2102,9 @@ target_link_libraries(grpc_test_util
gpr
grpc
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc_test_util "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc/support/alloc.h
@ -2426,6 +2436,9 @@ target_link_libraries(grpc_test_util_unsecure
gpr
grpc_unsecure
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc_test_util_unsecure "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc/support/alloc.h
@ -2780,6 +2793,9 @@ target_link_libraries(grpc_unsecure
${_gRPC_ALLTARGETS_LIBRARIES}
gpr
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc_unsecure "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc/impl/codegen/byte_buffer.h
@ -3167,6 +3183,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h
@ -3736,6 +3753,9 @@ target_link_libraries(grpc++_cronet
grpc_cronet
grpc
)
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(grpc++_cronet "-framework CoreFoundation")
endif()
foreach(_hdr
include/grpc++/alarm.h
@ -3789,6 +3809,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h
@ -4788,6 +4809,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h
@ -5776,58 +5798,6 @@ endif()
endif (gRPC_BUILD_CSHARP_EXT)
if (gRPC_BUILD_TESTS)
add_library(upb
third_party/upb/google/protobuf/descriptor.upb.c
third_party/upb/upb/decode.c
third_party/upb/upb/def.c
third_party/upb/upb/encode.c
third_party/upb/upb/handlers.c
third_party/upb/upb/msg.c
third_party/upb/upb/msgfactory.c
third_party/upb/upb/sink.c
third_party/upb/upb/table.c
third_party/upb/upb/upb.c
)
if(WIN32 AND MSVC)
set_target_properties(upb PROPERTIES COMPILE_PDB_NAME "upb"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/upb.pdb
DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(upb
PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
# avoid dependency on libstdc++
if (_gRPC_CORE_NOSTDCXX_FLAGS)
set_target_properties(upb PROPERTIES LINKER_LANGUAGE C)
# only use the flags for C++ source files
target_compile_options(upb PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_gRPC_CORE_NOSTDCXX_FLAGS}>)
endif()
target_link_libraries(upb
${_gRPC_SSL_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_library(bad_client_test
test/core/bad_client/bad_client.cc
)
@ -6882,12 +6852,46 @@ target_link_libraries(dns_resolver_connectivity_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(dns_resolver_cooldown_test
add_executable(dns_resolver_cooldown_using_ares_resolver_test
test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
)
target_include_directories(dns_resolver_cooldown_using_ares_resolver_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(dns_resolver_cooldown_using_ares_resolver_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
)
# avoid dependency on libstdc++
if (_gRPC_CORE_NOSTDCXX_FLAGS)
set_target_properties(dns_resolver_cooldown_using_ares_resolver_test PROPERTIES LINKER_LANGUAGE C)
target_compile_options(dns_resolver_cooldown_using_ares_resolver_test PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_gRPC_CORE_NOSTDCXX_FLAGS}>)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(dns_resolver_cooldown_using_native_resolver_test
test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
)
target_include_directories(dns_resolver_cooldown_test
target_include_directories(dns_resolver_cooldown_using_native_resolver_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
@ -6900,7 +6904,7 @@ target_include_directories(dns_resolver_cooldown_test
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(dns_resolver_cooldown_test
target_link_libraries(dns_resolver_cooldown_using_native_resolver_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
@ -6909,8 +6913,8 @@ target_link_libraries(dns_resolver_cooldown_test
# avoid dependency on libstdc++
if (_gRPC_CORE_NOSTDCXX_FLAGS)
set_target_properties(dns_resolver_cooldown_test PROPERTIES LINKER_LANGUAGE C)
target_compile_options(dns_resolver_cooldown_test PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_gRPC_CORE_NOSTDCXX_FLAGS}>)
set_target_properties(dns_resolver_cooldown_using_native_resolver_test PROPERTIES LINKER_LANGUAGE C)
target_compile_options(dns_resolver_cooldown_using_native_resolver_test PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${_gRPC_CORE_NOSTDCXX_FLAGS}>)
endif()
endif (gRPC_BUILD_TESTS)

@ -351,6 +351,7 @@ CFLAGS += -std=c99 -Wsign-conversion -Wconversion $(W_SHADOW) $(W_EXTRA_SEMI)
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
CXXFLAGS += -stdlib=libc++
LDFLAGS += -framework CoreFoundation
endif
CXXFLAGS += -Wnon-virtual-dtor
CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 -Wno-deprecated-declarations -Ithird_party/nanopb -DPB_FIELD_32BIT
@ -1015,7 +1016,8 @@ compression_test: $(BINDIR)/$(CONFIG)/compression_test
concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test
connection_refused_test: $(BINDIR)/$(CONFIG)/connection_refused_test
dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test
dns_resolver_cooldown_test: $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test
dns_resolver_cooldown_using_ares_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test
dns_resolver_cooldown_using_native_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test
dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test
dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
@ -1448,7 +1450,8 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/concurrent_connectivity_test \
$(BINDIR)/$(CONFIG)/connection_refused_test \
$(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test \
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test \
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test \
$(BINDIR)/$(CONFIG)/dns_resolver_test \
$(BINDIR)/$(CONFIG)/dualstack_socket_test \
$(BINDIR)/$(CONFIG)/endpoint_pair_test \
@ -1988,8 +1991,10 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/connection_refused_test || ( echo test connection_refused_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_connectivity_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test || ( echo test dns_resolver_connectivity_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_cooldown_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test || ( echo test dns_resolver_cooldown_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_cooldown_using_ares_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test || ( echo test dns_resolver_cooldown_using_ares_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_cooldown_using_native_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test || ( echo test dns_resolver_cooldown_using_native_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing dns_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/dns_resolver_test || ( echo test dns_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing dualstack_socket_test"
@ -5548,6 +5553,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \
@ -6178,6 +6184,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \
@ -7126,6 +7133,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \
@ -9653,34 +9661,66 @@ endif
endif
DNS_RESOLVER_COOLDOWN_TEST_SRC = \
DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_SRC = \
test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc \
DNS_RESOLVER_COOLDOWN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_COOLDOWN_TEST_SRC))))
DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test: openssl_dep_error
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test: $(DNS_RESOLVER_COOLDOWN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test: $(DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(DNS_RESOLVER_COOLDOWN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_test
$(Q) $(LD) $(LDFLAGS) $(DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_ares_resolver_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/dns_resolver_cooldown_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_dns_resolver_cooldown_test: $(DNS_RESOLVER_COOLDOWN_TEST_OBJS:.o=.dep)
deps_dns_resolver_cooldown_using_ares_resolver_test: $(DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(DNS_RESOLVER_COOLDOWN_TEST_OBJS:.o=.dep)
-include $(DNS_RESOLVER_COOLDOWN_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep)
endif
endif
DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_SRC = \
test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc \
DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test: $(DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/dns_resolver_cooldown_using_native_resolver_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/resolvers/dns_resolver_cooldown_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_dns_resolver_cooldown_using_native_resolver_test: $(DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(DNS_RESOLVER_COOLDOWN_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep)
endif
endif

@ -1369,6 +1369,7 @@ filegroups:
- include/grpcpp/channel_impl.h
- include/grpcpp/client_context.h
- include/grpcpp/completion_queue.h
- include/grpcpp/completion_queue_impl.h
- include/grpcpp/create_channel.h
- include/grpcpp/create_channel_impl.h
- include/grpcpp/create_channel_posix.h
@ -2402,7 +2403,7 @@ targets:
- gpr
exclude_iomgrs:
- uv
- name: dns_resolver_cooldown_test
- name: dns_resolver_cooldown_using_ares_resolver_test
build: test
language: c
src:
@ -2411,6 +2412,19 @@ targets:
- grpc_test_util
- grpc
- gpr
args:
- --resolver=ares
- name: dns_resolver_cooldown_using_native_resolver_test
build: test
language: c
src:
- test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
deps:
- grpc_test_util
- grpc
- gpr
args:
- --resolver=native
- name: dns_resolver_test
build: test
language: c

@ -71,4 +71,4 @@ The following status codes are never generated by the library:
- OUT_OF_RANGE
- DATA_LOSS
Applications that may wish to [retry](https:github.com/grpc/proposal/blob/master/A6-client-retries.md) failed RPCs must decide which status codes on which to retry. As shown in the table above, the gRPC library can generate the same status code for different cases. Server applications can also return those same status codes. Therefore, there is no fixed list of status codes on which it is appropriate to retry in all applications. As a result, individual applications must make their own determination as to which status codes should cause an RPC to be retried.
Applications that may wish to [retry](https://github.com/grpc/proposal/blob/master/A6-client-retries.md) failed RPCs must decide which status codes on which to retry. As shown in the table above, the gRPC library can generate the same status code for different cases. Server applications can also return those same status codes. Therefore, there is no fixed list of status codes on which it is appropriate to retry in all applications. As a result, individual applications must make their own determination as to which status codes should cause an RPC to be retried.

@ -0,0 +1,65 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
filegroup(
name = "_credentials_files",
testonly = 1,
srcs = [
"credentials/localhost.key",
"credentials/localhost.crt",
"credentials/root.crt",
],
)
py_library(
name = "_credentials",
testonly = 1,
srcs = ["_credentials.py"],
data = [":_credentials_files"],
)
py_binary(
name = "customized_auth_client",
testonly = 1,
srcs = ["customized_auth_client.py"],
deps = [
":_credentials",
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
],
)
py_binary(
name = "customized_auth_server",
testonly = 1,
srcs = ["customized_auth_server.py"],
deps = [
":_credentials",
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
],
)
py_test(
name = "_auth_example_test",
srcs = ["test/_auth_example_test.py"],
deps = [
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
":customized_auth_client",
":customized_auth_server",
":_credentials",
],
)

@ -0,0 +1,112 @@
# Authentication Extension Example in gRPC Python
## Check Our Guide First
For most common usage of authentication in gRPC Python, please see our
[Authentication](https://grpc.io/docs/guides/auth/) guide's Python section. The
Guide includes following scenarios:
1. Server SSL credential setup
2. Client SSL credential setup
3. Authenticate with Google using a JWT
4. Authenticate with Google using an Oauth2 token
Also, the guide talks about gRPC specific credential types.
### Channel credentials
Channel credentials are attached to a `Channel` object, the most common use case
are SSL credentials.
### Call credentials
Call credentials are attached to a `Call` object (corresponding to an RPC).
Under the hood, the call credentials is a function that takes in information of
the RPC and modify metadata through callback.
## About This Example
This example focuses on extending gRPC authentication mechanism:
1) Customize authentication plugin;
2) Composite client side credentials;
3) Validation through interceptor on server side.
## AuthMetadataPlugin: Manipulate metadata for each call
Unlike TLS/SSL based authentication, the authentication extension in gRPC Python
lives at a much higher level of networking. It relies on the transmission of
metadata (HTTP Header) between client and server, instead of alternating the
transport protocol.
gRPC Python provides a way to intercept an RPC and append authentication related
metadata through
[`AuthMetadataPlugin`](https://grpc.github.io/grpc/python/grpc.html#grpc.AuthMetadataPlugin).
Those in need of a custom authentication method may simply provide a concrete
implementation of the following interface:
```Python
class AuthMetadataPlugin:
"""A specification for custom authentication."""
def __call__(self, context, callback):
"""Implements authentication by passing metadata to a callback.
Implementations of this method must not block.
Args:
context: An AuthMetadataContext providing information on the RPC that
the plugin is being called to authenticate.
callback: An AuthMetadataPluginCallback to be invoked either
synchronously or asynchronously.
"""
```
Then pass the instance of the concrete implementation to
`grpc.metadata_call_credentials` function to be converted into a
`CallCredentials` object. Please NOTE that it is possible to pass a Python
function object directly, but we recommend to inherit from the base class to
ensure implementation correctness.
```Python
def metadata_call_credentials(metadata_plugin, name=None):
"""Construct CallCredentials from an AuthMetadataPlugin.
Args:
metadata_plugin: An AuthMetadataPlugin to use for authentication.
name: An optional name for the plugin.
Returns:
A CallCredentials.
"""
```
The `CallCredentials` object can be passed directly into an RPC like:
```Python
call_credentials = grpc.metadata_call_credentials(my_foo_plugin)
stub.FooRpc(request, credentials=call_credentials)
```
Or you can use `ChannelCredentials` and `CallCredentials` at the same time by
combining them:
```Python
channel_credentials = ...
call_credentials = ...
composite_credentials = grpc.composite_channel_credentials(
channel_credential,
call_credentials)
channel = grpc.secure_channel(server_address, composite_credentials)
```
It is also possible to apply multiple `CallCredentials` to a single RPC:
```Python
call_credentials_foo = ...
call_credentials_bar = ...
call_credentials = grpc.composite_call_credentials(
call_credentials_foo,
call_credentials_bar)
stub.FooRpc(request, credentials=call_credentials)
```

@ -0,0 +1,31 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Loading SSL credentials for gRPC Python authentication example."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
def _load_credential_from_file(filepath):
real_path = os.path.join(os.path.dirname(__file__), filepath)
with open(real_path, 'rb') as f:
return f.read()
SERVER_CERTIFICATE = _load_credential_from_file('credentials/localhost.crt')
SERVER_CERTIFICATE_KEY = _load_credential_from_file('credentials/localhost.key')
ROOT_CERTIFICATE = _load_credential_from_file('credentials/root.crt')

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFjCCAf4CCQCzrLIhrWa55zANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGR29vZ2xlMQ0wCwYDVQQL
DARnUlBDMCAXDTE5MDYyNDIyMjIzM1oYDzIxMTkwNTMxMjIyMjMzWjBWMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGR29vZ2xlMQ0w
CwYDVQQLDARnUlBDMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCtCW0TjugnIUu8BEVIYvdMP+/2GENQDjZhZ8eKR5C6
toDGbgjsDtt/GxISAg4cg70fIvy0XolnGPZodvfHDM4lJ7yHBOdZD8TXQoE6okR7
HZuLUJ20M0pXgWqtRewKRUjuYsSDXBnzLiZw1dcv9nGpo+Bqa8NonpiGRRpEkshF
D6T9KU9Ts/x+wMQBIra2Gj0UMh79jPhUuxcYAQA0JQGivnOtdwuPiumpnUT8j8h6
tWg5l01EsCZWJecCF85KnGpJEVYPyPqBqGsy0nGS9plGotOWF87+jyUQt+KD63xA
aBmTro86mKDDKEK4JvzjVeMGz2UbVcLPiiZnErTFaiXJAgMBAAEwDQYJKoZIhvcN
AQELBQADggEBAKsDgOPCWp5WCy17vJbRlgfgk05sVNIHZtzrmdswjBmvSg8MUpep
XqcPNUpsljAXsf9UM5IFEMRdilUsFGWvHjBEtNAW8WUK9UV18WRuU//0w1Mp5HAN
xUEKb4BoyZr65vlCnTR+AR5c9FfPvLibhr5qHs2RA8Y3GyLOcGqBWed87jhdQLCc
P1bxB+96le5JeXq0tw215lxonI2/3ZYVK4/ok9gwXrQoWm8YieJqitk/ZQ4S17/4
pynHtDfdxLn23EXeGx+UTxJGfpRmhEZdJ+MN7QGYoomzx5qS5XoYKxRNrDlirJpr
OqXIn8E1it+6d5gOZfuHawcNGhRLplE/pfA=
-----END CERTIFICATE-----

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEArQltE47oJyFLvARFSGL3TD/v9hhDUA42YWfHikeQuraAxm4I
7A7bfxsSEgIOHIO9HyL8tF6JZxj2aHb3xwzOJSe8hwTnWQ/E10KBOqJEex2bi1Cd
tDNKV4FqrUXsCkVI7mLEg1wZ8y4mcNXXL/ZxqaPgamvDaJ6YhkUaRJLIRQ+k/SlP
U7P8fsDEASK2tho9FDIe/Yz4VLsXGAEANCUBor5zrXcLj4rpqZ1E/I/IerVoOZdN
RLAmViXnAhfOSpxqSRFWD8j6gahrMtJxkvaZRqLTlhfO/o8lELfig+t8QGgZk66P
OpigwyhCuCb841XjBs9lG1XCz4omZxK0xWolyQIDAQABAoIBADeq/Kh6JT3RfGf0
h8WN8TlaqHxnueAbcmtL0+oss+cdp7gu1jf7X6o4r0uT1a5ew40s2Fe+wj2kzkE1
ZOlouTlC22gkr7j7Vbxa7PBMG/Pvxoa/XL0IczZLsGImSJXVTG1E4SvRiZeulTdf
1GbdxhtpWV1jZe5Wd4Na3+SHxF5S7m3PrHiZlYdz1ND+8XZs1NlL9+ej72qSFul9
t/QjMWJ9pky/Wad5abnRLRyOsg+BsgnXbkUy2rD89ZxFMLda9pzXo3TPyAlBHonr
mkEsE4eRMWMpjBM79JbeyDdHn/cs/LjAZrzeDf7ugXr2CHQpKaM5O0PsNHezJII9
L5kCfzECgYEA4M/rz1UP1/BJoSqigUlSs0tPAg8a5UlkVsh6Osuq72IPNo8qg/Fw
oV/IiIS+q+obRcFj1Od3PGdTpCJwW5dzd2fXBQGmGdj0HucnCrs13RtBh91JiF5i
y/YYI9KfgOG2ZT9gG68T0gTs6jRrS3Qd83npqjrkJqMOd7s00MK9tUcCgYEAxQq7
T541oCYHSBRIIb0IrR25krZy9caxzCqPDwOcuuhaCqCiaq+ATvOWlSfgecm4eH0K
PCH0xlWxG0auPEwm4pA8+/WR/XJwscPZMuoht1EoKy1his4eKx/s7hHNeO6KOF0V
Y/zqIiuZnEwUoKbn7EqqNFSTT65PJKyGsICJFG8CgYAfaw9yl1myfQNdQb8aQGwN
YJ33FLNWje427qeeZe5KrDKiFloDvI9YDjHRWnPnRL1w/zj7fSm9yFb5HlMDieP6
MQnsyjEzdY2QcA+VwVoiv3dmDHgFVeOKy6bOAtaFxYWfGr9MvygO9t9BT/gawGyb
JVORlc9i0vDnrMMR1dV7awKBgBpTWLtGc/u1mPt0Wj7HtsUKV6TWY32a0l5owTxM
S0BdksogtBJ06DukJ9Y9wawD23WdnyRxlPZ6tHLkeprrwbY7dypioOKvy4a0l+xJ
g7+uRCOgqIuXBkjUtx8HmeAyXp0xMo5tWArAsIFFWOwt4IadYygitJvMuh44PraO
NcJZAoGADEiV0dheXUCVr8DrtSom8DQMj92/G/FIYjXL8OUhh0+F+YlYP0+F8PEU
yYIWEqL/S5tVKYshimUXQa537JcRKsTVJBG/ZKD2kuqgOc72zQy3oplimXeJDCXY
h2eAQ0u8GN6tN9C4t8Kp4a3y6FGsxgu+UTxdnL3YQ+yHAVhtCzo=
-----END RSA PRIVATE KEY-----

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWTCCAkGgAwIBAgIJAPOConZMwykwMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29nbGUxDTAL
BgNVBAsMBGdSUEMwIBcNMTkwNjI0MjIyMDA3WhgPMjExOTA1MzEyMjIwMDdaMEIx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29n
bGUxDTALBgNVBAsMBGdSUEMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCwqei3TfyLidnQNDJ2lierMYo229K92DuORni7nSjJQ59Jc3dNMsmqGQJjCD8o
6mTlKM/oCbs27Wpx+OxcOLvT95j2kiDGca1fCvaMdguIod09SWiyMpv/hp0trLv7
NJIKHznath6rHYX2Ii3fZ1yCPzyQbEPSAA+GNpoNm1v1ZWmWKke9v7vLlS3inNlW
Mt9jepK7DrtbNZnVDjeItnppBSbVYRMxIyNHkepFbqXx5TpkCvl4M4XQZw9bfSxQ
i3WZ3q+T1Tw//OUdPNc+OfMhu0MA0QoMwikskP0NaIC3dbJZ5Ogx0RcnaB4E+9C6
O/znUEh3WuKVl5HXBF+UwWoFAgMBAAGjUDBOMB0GA1UdDgQWBBRm3JIgzgK4G97J
fbMGatWMZc7V3jAfBgNVHSMEGDAWgBRm3JIgzgK4G97JfbMGatWMZc7V3jAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCNiV8x41if094ry2srS0YucpiN
3rTPk08FOLsENTMYai524TGXJti1P6ofGr5KXCL0uxTByHE3fEiMMud2TIY5iHQo
Y4mzDTTcb+Q7yKHwYZMlcp6nO8W+NeY5t+S0JPHhb8deKWepcN2UpXBUYQLw7AiE
l96T9Gi+vC9h/XE5IVwHFQXTxf5UYzXtW1nfapvrOONg/ms41dgmrRKIi+knWfiJ
FdHpHX2sfDAoJtnpEISX+nxRGNVTLY64utXWm4yxaZJshvy2s8zWJgRg7rtwAhTT
Np9E9MnihXLEmDI4Co9XlLPJyZFmqImsbmVuKFeQOCiLAoPJaMI2lbi7fiTo
-----END CERTIFICATE-----

@ -0,0 +1,105 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Client of the Python example of customizing authentication mechanism."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import contextlib
import logging
import grpc
from examples import helloworld_pb2
from examples import helloworld_pb2_grpc
from examples.python.auth import _credentials
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_SERVER_ADDR_TEMPLATE = 'localhost:%d'
_SIGNATURE_HEADER_KEY = 'x-signature'
class AuthGateway(grpc.AuthMetadataPlugin):
def __call__(self, context, callback):
"""Implements authentication by passing metadata to a callback.
Implementations of this method must not block.
Args:
context: An AuthMetadataContext providing information on the RPC that
the plugin is being called to authenticate.
callback: An AuthMetadataPluginCallback to be invoked either
synchronously or asynchronously.
"""
# Example AuthMetadataContext object:
# AuthMetadataContext(
# service_url=u'https://localhost:50051/helloworld.Greeter',
# method_name=u'SayHello')
signature = context.method_name[::-1]
callback(((_SIGNATURE_HEADER_KEY, signature),), None)
@contextlib.contextmanager
def create_client_channel(addr):
# Call credential object will be invoked for every single RPC
call_credentials = grpc.metadata_call_credentials(
AuthGateway(), name='auth gateway')
# Channel credential will be valid for the entire channel
channel_credential = grpc.ssl_channel_credentials(
_credentials.ROOT_CERTIFICATE)
# Combining channel credentials and call credentials together
composite_credentials = grpc.composite_channel_credentials(
channel_credential,
call_credentials,
)
channel = grpc.secure_channel(addr, composite_credentials)
yield channel
def send_rpc(channel):
stub = helloworld_pb2_grpc.GreeterStub(channel)
request = helloworld_pb2.HelloRequest(name='you')
try:
response = stub.SayHello(request)
except grpc.RpcError as rpc_error:
_LOGGER.error('Received error: %s', rpc_error)
return rpc_error
else:
_LOGGER.info('Received message: %s', response)
return response
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--port',
nargs='?',
type=int,
default=50051,
help='the address of server')
args = parser.parse_args()
with create_client_channel(_SERVER_ADDR_TEMPLATE % args.port) as channel:
send_rpc(channel)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
main()

@ -0,0 +1,110 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Server of the Python example of customizing authentication mechanism."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import contextlib
import logging
import time
from concurrent import futures
import grpc
from examples import helloworld_pb2
from examples import helloworld_pb2_grpc
from examples.python.auth import _credentials
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_LISTEN_ADDRESS_TEMPLATE = 'localhost:%d'
_SIGNATURE_HEADER_KEY = 'x-signature'
class SignatureValidationInterceptor(grpc.ServerInterceptor):
def __init__(self):
def abort(ignored_request, context):
context.abort(grpc.StatusCode.UNAUTHENTICATED, 'Invalid signature')
self._abortion = grpc.unary_unary_rpc_method_handler(abort)
def intercept_service(self, continuation, handler_call_details):
# Example HandlerCallDetails object:
# _HandlerCallDetails(
# method=u'/helloworld.Greeter/SayHello',
# invocation_metadata=...)
method_name = handler_call_details.method.split('/')[-1]
expected_metadata = (_SIGNATURE_HEADER_KEY, method_name[::-1])
if expected_metadata in handler_call_details.invocation_metadata:
return continuation(handler_call_details)
else:
return self._abortion
class SimpleGreeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, unused_context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
@contextlib.contextmanager
def run_server(port):
# Bind interceptor to server
server = grpc.server(
futures.ThreadPoolExecutor(),
interceptors=(SignatureValidationInterceptor(),))
helloworld_pb2_grpc.add_GreeterServicer_to_server(SimpleGreeter(), server)
# Loading credentials
server_credentials = grpc.ssl_server_credentials(((
_credentials.SERVER_CERTIFICATE_KEY,
_credentials.SERVER_CERTIFICATE,
),))
# Pass down credentials
port = server.add_secure_port(_LISTEN_ADDRESS_TEMPLATE % port,
server_credentials)
server.start()
try:
yield port
finally:
server.stop(0)
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--port', nargs='?', type=int, default=50051, help='the listening port')
args = parser.parse_args()
with run_server(args.port) as port:
logging.info('Server is listening at port :%d', port)
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
main()

@ -0,0 +1,56 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test for gRPC Python authentication example."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import unittest
import grpc
from examples.python.auth import _credentials
from examples.python.auth import customized_auth_client
from examples.python.auth import customized_auth_server
_SERVER_ADDR_TEMPLATE = 'localhost:%d'
class AuthExampleTest(unittest.TestCase):
def test_successful_call(self):
with customized_auth_server.run_server(0) as port:
with customized_auth_client.create_client_channel(
_SERVER_ADDR_TEMPLATE % port) as channel:
customized_auth_client.send_rpc(channel)
# No unhandled exception raised, test passed!
def test_no_channel_credential(self):
with customized_auth_server.run_server(0) as port:
with grpc.insecure_channel(_SERVER_ADDR_TEMPLATE % port) as channel:
resp = customized_auth_client.send_rpc(channel)
self.assertEqual(resp.code(), grpc.StatusCode.UNAVAILABLE)
def test_no_call_credential(self):
with customized_auth_server.run_server(0) as port:
channel_credential = grpc.ssl_channel_credentials(
_credentials.ROOT_CERTIFICATE)
with grpc.secure_channel(_SERVER_ADDR_TEMPLATE % port,
channel_credential) as channel:
resp = customized_auth_client.send_rpc(channel)
self.assertEqual(resp.code(), grpc.StatusCode.UNAUTHENTICATED)
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -85,6 +85,7 @@ Pod::Spec.new do |s|
'include/grpcpp/channel_impl.h',
'include/grpcpp/client_context.h',
'include/grpcpp/completion_queue.h',
'include/grpcpp/completion_queue_impl.h',
'include/grpcpp/create_channel.h',
'include/grpcpp/create_channel_impl.h',
'include/grpcpp/create_channel_posix.h',

@ -111,6 +111,7 @@ EXPORTS
grpc_google_refresh_token_credentials_create
grpc_access_token_credentials_create
grpc_google_iam_credentials_create
grpc_sts_credentials_create
grpc_metadata_credentials_create_from_plugin
grpc_secure_channel_create
grpc_server_credentials_release

@ -328,6 +328,31 @@ GRPCAPI grpc_call_credentials* grpc_google_iam_credentials_create(
const char* authorization_token, const char* authority_selector,
void* reserved);
/** Options for creating STS Oauth Token Exchange credentials following the IETF
draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
Optional fields may be set to NULL. It is the responsibility of the caller to
ensure that the subject and actor tokens are refreshed on disk at the
specified paths. This API is used for experimental purposes for now and may
change in the future. */
typedef struct {
const char* sts_endpoint_url; /* Required. */
const char* resource; /* Optional. */
const char* audience; /* Optional. */
const char* scope; /* Optional. */
const char* requested_token_type; /* Optional. */
const char* subject_token_path; /* Required. */
const char* subject_token_type; /* Required. */
const char* actor_token_path; /* Optional. */
const char* actor_token_type; /* Optional. */
} grpc_sts_credentials_options;
/** Creates an STS credentials following the STS Token Exchanged specifed in the
IETF draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
This API is used for experimental purposes for now and may change in the
future. */
GRPCAPI grpc_call_credentials* grpc_sts_credentials_create(
const grpc_sts_credentials_options* options, void* reserved);
/** Callback function to be called by the metadata credentials plugin
implementation when the metadata is ready.
- user_data is the opaque pointer that was passed in the get_metadata method

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

@ -34,7 +34,6 @@ class Channel;
class CompletionQueue;
class ServerCompletionQueue;
class ServerCredentials;
class ServerContext;
} // namespace grpc_impl
namespace grpc {

@ -28,6 +28,7 @@
#include <grpc/compression.h>
#include <grpc/support/atm.h>
#include <grpcpp/channel_impl.h>
#include <grpcpp/completion_queue_impl.h>
#include <grpcpp/health_check_service_interface.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/codegen/client_interceptor.h>

@ -400,7 +400,8 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
grpc_timer_init(&next_resolution_timer_,
ExecCtx::Get()->Now() + ms_until_next_resolution,
&on_next_resolution_);
return;
}

@ -229,7 +229,8 @@ void NativeDnsResolver::MaybeStartResolvingLocked() {
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
grpc_timer_init(&next_resolution_timer_,
ExecCtx::Get()->Now() + ms_until_next_resolution,
&on_next_resolution_);
return;
}

@ -130,8 +130,9 @@ static void begin_frame(framer_state* st) {
space to add at least about_to_add bytes -- finishes the current frame if
needed */
static void ensure_space(framer_state* st, size_t need_bytes) {
if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
st->max_frame_size) {
if (GPR_LIKELY(st->output->length - st->output_length_at_start_of_frame +
need_bytes <=
st->max_frame_size)) {
return;
}
finish_frame(st, 0, 0);
@ -711,18 +712,28 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
}
for (size_t i = 0; i < extra_headers_size; ++i) {
grpc_mdelem md = *extra_headers[i];
uintptr_t static_index = grpc_chttp2_get_static_hpack_table_index(md);
if (static_index) {
emit_indexed(c, static_cast<uint32_t>(static_index), &st);
const bool is_static =
GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC;
uintptr_t static_index;
if (is_static &&
(static_index =
reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(md))
->StaticIndex()) < GRPC_CHTTP2_LAST_STATIC_ENTRY) {
emit_indexed(c, static_cast<uint32_t>(static_index + 1), &st);
} else {
hpack_enc(c, md, &st);
}
}
grpc_metadata_batch_assert_ok(metadata);
for (grpc_linked_mdelem* l = metadata->list.head; l; l = l->next) {
uintptr_t static_index = grpc_chttp2_get_static_hpack_table_index(l->md);
if (static_index) {
emit_indexed(c, static_cast<uint32_t>(static_index), &st);
const bool is_static =
GRPC_MDELEM_STORAGE(l->md) == GRPC_MDELEM_STORAGE_STATIC;
uintptr_t static_index;
if (is_static &&
(static_index = reinterpret_cast<grpc_core::StaticMetadata*>(
GRPC_MDELEM_DATA(l->md))
->StaticIndex()) < GRPC_CHTTP2_LAST_STATIC_ENTRY) {
emit_indexed(c, static_cast<uint32_t>(static_index + 1), &st);
} else {
hpack_enc(c, l->md, &st);
}

@ -622,33 +622,37 @@ static const uint8_t inverse_base64[256] = {
255,
};
static void GPR_ATTRIBUTE_NOINLINE on_hdr_log(grpc_mdelem md) {
char* k = grpc_slice_to_c_string(GRPC_MDKEY(md));
char* v = nullptr;
if (grpc_is_binary_header_internal(GRPC_MDKEY(md))) {
v = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX);
} else {
v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
}
gpr_log(
GPR_INFO,
"Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
grpc_slice_is_interned(GRPC_MDKEY(md)),
grpc_slice_is_interned(GRPC_MDVALUE(md)));
gpr_free(k);
gpr_free(v);
}
/* emission helpers */
static grpc_error* on_hdr(grpc_chttp2_hpack_parser* p, grpc_mdelem md,
int add_to_table) {
template <bool do_add>
static grpc_error* on_hdr(grpc_chttp2_hpack_parser* p, grpc_mdelem md) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
char* k = grpc_slice_to_c_string(GRPC_MDKEY(md));
char* v = nullptr;
if (grpc_is_binary_header_internal(GRPC_MDKEY(md))) {
v = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX);
} else {
v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
}
gpr_log(
GPR_INFO,
"Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
grpc_slice_is_interned(GRPC_MDKEY(md)),
grpc_slice_is_interned(GRPC_MDVALUE(md)));
gpr_free(k);
gpr_free(v);
on_hdr_log(md);
}
if (add_to_table) {
GPR_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED ||
GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC);
if (do_add) {
GPR_DEBUG_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED ||
GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC);
grpc_error* err = grpc_chttp2_hptbl_add(&p->table, md);
if (err != GRPC_ERROR_NONE) return err;
if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) return err;
}
if (p->on_header == nullptr) {
if (GPR_UNLIKELY(p->on_header == nullptr)) {
GRPC_MDELEM_UNREF(md);
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("on_header callback not set");
}
@ -765,7 +769,7 @@ static grpc_error* finish_indexed_field(grpc_chttp2_hpack_parser* p,
}
GRPC_MDELEM_REF(md);
GRPC_STATS_INC_HPACK_RECV_INDEXED();
grpc_error* err = on_hdr(p, md, 0);
grpc_error* err = on_hdr<false>(p, md);
if (err != GRPC_ERROR_NONE) return err;
return parse_begin(p, cur, end);
}
@ -798,11 +802,9 @@ static grpc_error* finish_lithdr_incidx(grpc_chttp2_hpack_parser* p,
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, true)),
1);
grpc_error* err = on_hdr<true>(
p, grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, true)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}
@ -813,10 +815,8 @@ static grpc_error* finish_lithdr_incidx_v(grpc_chttp2_hpack_parser* p,
const uint8_t* end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX_V();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, true)),
1);
on_hdr<true>(p, grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, true)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}
@ -865,11 +865,9 @@ static grpc_error* finish_lithdr_notidx(grpc_chttp2_hpack_parser* p,
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, false)),
0);
grpc_error* err = on_hdr<false>(
p, grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, false)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}
@ -879,11 +877,9 @@ static grpc_error* finish_lithdr_notidx_v(grpc_chttp2_hpack_parser* p,
const uint8_t* cur,
const uint8_t* end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX_V();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, false)),
0);
grpc_error* err = on_hdr<false>(
p, grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, false)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}
@ -932,11 +928,9 @@ static grpc_error* finish_lithdr_nvridx(grpc_chttp2_hpack_parser* p,
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, false)),
0);
grpc_error* err = on_hdr<false>(
p, grpc_mdelem_from_slices(grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value, false)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}
@ -946,11 +940,9 @@ static grpc_error* finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p,
const uint8_t* cur,
const uint8_t* end) {
GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX_V();
grpc_error* err =
on_hdr(p,
grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, false)),
0);
grpc_error* err = on_hdr<false>(
p, grpc_mdelem_from_slices(take_string(p, &p->key, true),
take_string(p, &p->value, false)));
if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err);
return parse_begin(p, cur, end);
}

@ -87,11 +87,19 @@ bool SplitHostPort(StringView name, StringView* host, StringView* port) {
bool SplitHostPort(StringView name, UniquePtr<char>* host,
UniquePtr<char>* port) {
GPR_DEBUG_ASSERT(host != nullptr && *host == nullptr);
GPR_DEBUG_ASSERT(port != nullptr && *port == nullptr);
StringView host_view;
StringView port_view;
const bool ret = SplitHostPort(name, &host_view, &port_view);
host->reset(host_view.empty() ? nullptr : host_view.dup().release());
port->reset(port_view.empty() ? nullptr : port_view.dup().release());
if (ret) {
// We always set the host, but port is set only when it's non-empty,
// to remain backward compatible with the old split_host_port API.
*host = host_view.dup();
if (!port_view.empty()) {
*port = port_view.dup();
}
}
return ret;
}
} // namespace grpc_core

@ -49,7 +49,7 @@ class Thread {
public:
class Options {
public:
Options() : joinable_(true), tracked_(true) {}
Options() : joinable_(true), tracked_(true), stack_size_(0) {}
/// Set whether the thread is joinable or detached.
Options& set_joinable(bool joinable) {
joinable_ = joinable;
@ -64,9 +64,18 @@ class Thread {
}
bool tracked() const { return tracked_; }
/// Sets thread stack size (in bytes). Sets to 0 will use the default stack
/// size which is 64KB for Windows threads and 2MB for Posix(x86) threads.
Options& set_stack_size(size_t bytes) {
stack_size_ = bytes;
return *this;
}
size_t stack_size() const { return stack_size_; }
private:
bool joinable_;
bool tracked_;
size_t stack_size_;
};
/// Default constructor only to allow use in structs that lack constructors
/// Does not produce a validly-constructed thread; must later

@ -31,6 +31,7 @@
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/fork.h"
@ -48,6 +49,26 @@ struct thd_arg {
bool tracked;
};
// TODO(yunjiaw): move this to a function-level static, or remove the use of a
// non-constexpr initializer when possible
const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
size_t RoundUpToPageSize(size_t size) {
return (size + page_size - 1) & ~(page_size - 1);
}
// Returns the minimum valid stack size that can be passed to
// pthread_attr_setstacksize.
size_t MinValidStackSize(size_t request_size) {
if (request_size < _SC_THREAD_STACK_MIN) {
request_size = _SC_THREAD_STACK_MIN;
}
// On some systems, pthread_attr_setstacksize() can fail if stacksize is
// not a multiple of the system page size.
return RoundUpToPageSize(request_size);
}
class ThreadInternalsPosix : public internal::ThreadInternalsInterface {
public:
ThreadInternalsPosix(const char* thd_name, void (*thd_body)(void* arg),
@ -79,6 +100,11 @@ class ThreadInternalsPosix : public internal::ThreadInternalsInterface {
0);
}
if (options.stack_size() != 0) {
size_t stack_size = MinValidStackSize(options.stack_size());
GPR_ASSERT(pthread_attr_setstacksize(&attr, stack_size) == 0);
}
*success =
(pthread_create(&pthread_id_, &attr,
[](void* v) -> void* {

@ -75,7 +75,15 @@ class ThreadInternalsWindows
return;
}
}
handle = CreateThread(nullptr, 64 * 1024, thread_body, info_, 0, nullptr);
if (options.stack_size() != 0) {
// Windows will round up the given stack_size value to nearest page.
handle = CreateThread(nullptr, options.stack_size(), thread_body, info_,
0, nullptr);
} else {
handle = CreateThread(nullptr, 64 * 1024, thread_body, info_, 0, nullptr);
}
if (handle == nullptr) {
destroy_thread();
*success = false;

@ -120,7 +120,10 @@ size_t Executor::RunClosures(const char* executor_name,
// thread itself, but this is the point where we could start seeing
// application-level callbacks. No need to create a new ExecCtx, though,
// since there already is one and it is flushed (but not destructed) in this
// function itself.
// function itself. The ApplicationCallbackExecCtx will have its callbacks
// invoked on its destruction, which will be after completing any closures in
// the executor's closure list (which were explicitly scheduled onto the
// executor).
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);

@ -78,9 +78,19 @@ static grpc_iomgr_platform_vtable vtable = {
void grpc_set_default_iomgr_platform() {
char* enable_cfstream = getenv(grpc_cfstream_env_var);
grpc_tcp_client_vtable* client_vtable = &grpc_posix_tcp_client_vtable;
// CFStream is enabled by default on iOS, and disabled by default on other
// platforms. Defaults can be overriden by setting the grpc_cfstream
// environment variable.
#if TARGET_OS_IPHONE
if (enable_cfstream == nullptr || enable_cfstream[0] == '1') {
client_vtable = &grpc_cfstream_client_vtable;
}
#else
if (enable_cfstream != nullptr && enable_cfstream[0] == '1') {
client_vtable = &grpc_cfstream_client_vtable;
}
#endif
grpc_set_tcp_client_impl(client_vtable);
grpc_set_tcp_server_impl(&grpc_posix_tcp_server_vtable);
grpc_set_timer_impl(&grpc_generic_timer_vtable);
@ -90,4 +100,6 @@ void grpc_set_default_iomgr_platform() {
grpc_set_iomgr_platform_vtable(&vtable);
}
bool grpc_iomgr_run_in_background() { return false; }
#endif /* GRPC_CFSTREAM_IOMGR */

@ -64,8 +64,8 @@ typedef enum {
#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
"/computeMetadata/v1/instance/service-accounts/default/token"
#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com"
#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token"
#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "oauth2.googleapis.com"
#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/token"
#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX \
"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \

@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/credentials/jwt/json_token.h"
#include <string.h>
@ -69,6 +70,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
BIO* bio = nullptr;
const char* prop_value;
int success = 0;
grpc_error* error = GRPC_ERROR_NONE;
memset(&result, 0, sizeof(grpc_auth_json_key));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
@ -77,7 +79,8 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
goto end;
}
prop_value = grpc_json_get_string_property(json, "type");
prop_value = grpc_json_get_string_property(json, "type", &error);
GRPC_LOG_IF_ERROR("JSON key parsing", error);
if (prop_value == nullptr ||
strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) {
goto end;
@ -92,7 +95,8 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
goto end;
}
prop_value = grpc_json_get_string_property(json, "private_key");
prop_value = grpc_json_get_string_property(json, "private_key", &error);
GRPC_LOG_IF_ERROR("JSON key parsing", error);
if (prop_value == nullptr) {
goto end;
}

@ -30,7 +30,7 @@
/* --- Constants. --- */
#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
#define GRPC_JWT_OAUTH2_AUDIENCE "https://oauth2.googleapis.com/token"
/* --- auth_json_key parsing. --- */

@ -22,14 +22,23 @@
#include <string.h>
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/surface/api_trace.h"
#include <grpc/grpc_security.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/uri/uri_parser.h"
//
// Auth Refresh Token.
//
@ -45,6 +54,7 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
grpc_auth_refresh_token result;
const char* prop_value;
int success = 0;
grpc_error* error = GRPC_ERROR_NONE;
memset(&result, 0, sizeof(grpc_auth_refresh_token));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
@ -53,7 +63,8 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
goto end;
}
prop_value = grpc_json_get_string_property(json, "type");
prop_value = grpc_json_get_string_property(json, "type", &error);
GRPC_LOG_IF_ERROR("Parsing refresh token", error);
if (prop_value == nullptr ||
strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) {
goto end;
@ -216,10 +227,12 @@ static void on_oauth2_token_fetcher_http_response(void* user_data,
void grpc_oauth2_token_fetcher_credentials::on_http_response(
grpc_credentials_metadata_request* r, grpc_error* error) {
grpc_mdelem access_token_md = GRPC_MDNULL;
grpc_millis token_lifetime;
grpc_millis token_lifetime = 0;
grpc_credentials_status status =
grpc_oauth2_token_fetcher_credentials_parse_server_response(
&r->response, &access_token_md, &token_lifetime);
error == GRPC_ERROR_NONE
? grpc_oauth2_token_fetcher_credentials_parse_server_response(
&r->response, &access_token_md, &token_lifetime)
: GRPC_CREDENTIALS_ERROR;
// Update cache and grab list of pending requests.
gpr_mu_lock(&mu_);
token_fetch_pending_ = false;
@ -234,14 +247,15 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response(
gpr_mu_unlock(&mu_);
// Invoke callbacks for all pending requests.
while (pending_request != nullptr) {
grpc_error* new_error = GRPC_ERROR_NONE;
if (status == GRPC_CREDENTIALS_OK) {
grpc_credentials_mdelem_array_add(pending_request->md_array,
access_token_md);
} else {
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token.", &error, 1);
}
GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, error);
GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, new_error);
grpc_polling_entity_del_from_pollset_set(
pending_request->pollent, grpc_polling_entity_pollset_set(&pollent_));
grpc_oauth2_pending_get_request_metadata* prev = pending_request;
@ -356,7 +370,8 @@ class grpc_compute_engine_token_fetcher_credentials
grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb,
grpc_millis deadline) override {
grpc_http_header header = {(char*)"Metadata-Flavor", (char*)"Google"};
grpc_http_header header = {const_cast<char*>("Metadata-Flavor"),
const_cast<char*>("Google")};
grpc_httpcli_request request;
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)GRPC_COMPUTE_ENGINE_METADATA_HOST;
@ -369,11 +384,14 @@ class grpc_compute_engine_token_fetcher_credentials
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials");
grpc_httpcli_get(http_context, pollent, resource_quota, &request, deadline,
GRPC_CLOSURE_CREATE(response_cb, metadata_req,
grpc_schedule_on_exec_ctx),
GRPC_CLOSURE_INIT(&http_get_cb_closure_, response_cb,
metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
}
private:
grpc_closure http_get_cb_closure_;
};
} // namespace
@ -401,8 +419,9 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
grpc_credentials_metadata_request* metadata_req,
grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb, grpc_millis deadline) {
grpc_http_header header = {(char*)"Content-Type",
(char*)"application/x-www-form-urlencoded"};
grpc_http_header header = {
const_cast<char*>("Content-Type"),
const_cast<char*>("application/x-www-form-urlencoded")};
grpc_httpcli_request request;
char* body = nullptr;
gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
@ -419,11 +438,11 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
extreme memory pressure. */
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
grpc_httpcli_post(
httpcli_context, pollent, resource_quota, &request, body, strlen(body),
deadline,
GRPC_CLOSURE_CREATE(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_httpcli_post(httpcli_context, pollent, resource_quota, &request, body,
strlen(body), deadline,
GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb,
metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
gpr_free(body);
}
@ -472,6 +491,207 @@ grpc_call_credentials* grpc_google_refresh_token_credentials_create(
.release();
}
//
// STS credentials.
//
namespace grpc_core {
namespace {
void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name,
const char* field) {
if (field == nullptr || strlen(field) == 0) return;
char* new_query;
gpr_asprintf(&new_query, "&%s=%s", field_name, field);
gpr_strvec_add(body_strvec, new_query);
}
grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
grpc_error* err = grpc_load_file(path, 1, token);
if (err != GRPC_ERROR_NONE) return err;
if (GRPC_SLICE_LENGTH(*token) == 0) {
gpr_log(GPR_ERROR, "Token file %s is empty", path);
err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Token file is empty.");
}
return err;
}
class StsTokenFetcherCredentials
: public grpc_oauth2_token_fetcher_credentials {
public:
StsTokenFetcherCredentials(grpc_uri* sts_url, // Ownership transferred.
const grpc_sts_credentials_options* options)
: sts_url_(sts_url),
resource_(gpr_strdup(options->resource)),
audience_(gpr_strdup(options->audience)),
scope_(gpr_strdup(options->scope)),
requested_token_type_(gpr_strdup(options->requested_token_type)),
subject_token_path_(gpr_strdup(options->subject_token_path)),
subject_token_type_(gpr_strdup(options->subject_token_type)),
actor_token_path_(gpr_strdup(options->actor_token_path)),
actor_token_type_(gpr_strdup(options->actor_token_type)) {}
~StsTokenFetcherCredentials() override { grpc_uri_destroy(sts_url_); }
private:
void fetch_oauth2(grpc_credentials_metadata_request* metadata_req,
grpc_httpcli_context* http_context,
grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb,
grpc_millis deadline) override {
char* body = nullptr;
size_t body_length = 0;
grpc_error* err = FillBody(&body, &body_length);
if (err != GRPC_ERROR_NONE) {
response_cb(metadata_req, err);
GRPC_ERROR_UNREF(err);
return;
}
grpc_http_header header = {
const_cast<char*>("Content-Type"),
const_cast<char*>("application/x-www-form-urlencoded")};
grpc_httpcli_request request;
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)sts_url_->authority;
request.http.path = (char*)sts_url_->path;
request.http.hdr_count = 1;
request.http.hdrs = &header;
request.handshaker = (strcmp(sts_url_->scheme, "https") == 0)
? &grpc_httpcli_ssl
: &grpc_httpcli_plaintext;
/* TODO(ctiller): Carry the resource_quota in ctx and share it with the host
channel. This would allow us to cancel an authentication query when under
extreme memory pressure. */
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
grpc_httpcli_post(
http_context, pollent, resource_quota, &request, body, body_length,
deadline,
GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb, metadata_req,
grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
gpr_free(body);
}
grpc_error* FillBody(char** body, size_t* body_length) {
*body = nullptr;
gpr_strvec body_strvec;
gpr_strvec_init(&body_strvec);
grpc_slice subject_token = grpc_empty_slice();
grpc_slice actor_token = grpc_empty_slice();
grpc_error* err = GRPC_ERROR_NONE;
auto cleanup = [&body, &body_length, &body_strvec, &subject_token,
&actor_token, &err]() {
if (err == GRPC_ERROR_NONE) {
*body = gpr_strvec_flatten(&body_strvec, body_length);
} else {
gpr_free(*body);
}
gpr_strvec_destroy(&body_strvec);
grpc_slice_unref_internal(subject_token);
grpc_slice_unref_internal(actor_token);
return err;
};
err = LoadTokenFile(subject_token_path_.get(), &subject_token);
if (err != GRPC_ERROR_NONE) return cleanup();
gpr_asprintf(
body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
subject_token_type_.get());
gpr_strvec_add(&body_strvec, *body);
MaybeAddToBody(&body_strvec, "resource", resource_.get());
MaybeAddToBody(&body_strvec, "audience", audience_.get());
MaybeAddToBody(&body_strvec, "scope", scope_.get());
MaybeAddToBody(&body_strvec, "requested_token_type",
requested_token_type_.get());
if (actor_token_path_ != nullptr) {
err = LoadTokenFile(actor_token_path_.get(), &actor_token);
if (err != GRPC_ERROR_NONE) return cleanup();
MaybeAddToBody(
&body_strvec, "actor_token",
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)));
MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get());
}
return cleanup();
}
grpc_uri* sts_url_;
grpc_closure http_post_cb_closure_;
grpc_core::UniquePtr<char> resource_;
grpc_core::UniquePtr<char> audience_;
grpc_core::UniquePtr<char> scope_;
grpc_core::UniquePtr<char> requested_token_type_;
grpc_core::UniquePtr<char> subject_token_path_;
grpc_core::UniquePtr<char> subject_token_type_;
grpc_core::UniquePtr<char> actor_token_path_;
grpc_core::UniquePtr<char> actor_token_type_;
};
} // namespace
grpc_error* ValidateStsCredentialsOptions(
const grpc_sts_credentials_options* options, grpc_uri** sts_url_out) {
struct GrpcUriDeleter {
void operator()(grpc_uri* uri) { grpc_uri_destroy(uri); }
};
*sts_url_out = nullptr;
InlinedVector<grpc_error*, 3> error_list;
UniquePtr<grpc_uri, GrpcUriDeleter> sts_url(
options->sts_endpoint_url != nullptr
? grpc_uri_parse(options->sts_endpoint_url, false)
: nullptr);
if (sts_url == nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid or missing STS endpoint URL"));
} else {
if (strcmp(sts_url->scheme, "https") != 0 &&
strcmp(sts_url->scheme, "http") != 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid URI scheme, must be https to http."));
}
}
if (options->subject_token_path == nullptr ||
strlen(options->subject_token_path) == 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"subject_token needs to be specified"));
}
if (options->subject_token_type == nullptr ||
strlen(options->subject_token_type) == 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"subject_token_type needs to be specified"));
}
if (error_list.empty()) {
*sts_url_out = sts_url.release();
return GRPC_ERROR_NONE;
} else {
return GRPC_ERROR_CREATE_FROM_VECTOR("Invalid STS Credentials Options",
&error_list);
}
}
} // namespace grpc_core
grpc_call_credentials* grpc_sts_credentials_create(
const grpc_sts_credentials_options* options, void* reserved) {
GPR_ASSERT(reserved == nullptr);
grpc_uri* sts_url;
grpc_error* error =
grpc_core::ValidateStsCredentialsOptions(options, &sts_url);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "STS Credentials creation failed. Error: %s.",
grpc_error_string(error));
GRPC_ERROR_UNREF(error);
return nullptr;
}
return grpc_core::MakeRefCounted<grpc_core::StsTokenFetcherCredentials>(
sts_url, options)
.release();
}
//
// Oauth2 Access Token credentials.
//

@ -21,8 +21,15 @@
#include <grpc/support/port_platform.h>
#include <grpc/grpc_security.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/uri/uri_parser.h"
// Constants.
#define GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING \
"grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=%" \
"s&subject_token_type=%s"
// auth_refresh_token parsing.
typedef struct {
@ -115,6 +122,7 @@ class grpc_google_refresh_token_credentials final
private:
grpc_auth_refresh_token refresh_token_;
grpc_closure http_post_cb_closure_;
};
// Access token credentials.
@ -148,4 +156,12 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
const struct grpc_http_response* response, grpc_mdelem* token_md,
grpc_millis* token_lifetime);
namespace grpc_core {
// Exposed for testing only. This function validates the options, ensuring that
// the required fields are set, and outputs the parsed URL of the STS token
// exchanged service.
grpc_error* ValidateStsCredentialsOptions(
const grpc_sts_credentials_options* options, grpc_uri** sts_url);
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */

@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/util/json_util.h"
#include <string.h>
@ -26,17 +27,27 @@
#include <grpc/support/string_util.h>
const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name) {
grpc_json* child;
const char* prop_name,
grpc_error** error) {
grpc_json* child = nullptr;
if (error != nullptr) *error = GRPC_ERROR_NONE;
for (child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
gpr_log(GPR_ERROR, "Invalid (null) JSON key encountered");
if (error != nullptr) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid (null) JSON key encountered");
}
return nullptr;
}
if (strcmp(child->key, prop_name) == 0) break;
}
if (child == nullptr || child->type != GRPC_JSON_STRING) {
gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name);
if (error != nullptr) {
char* error_msg;
gpr_asprintf(&error_msg, "Invalid or missing %s property.", prop_name);
*error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
}
return nullptr;
}
return child->value;
@ -45,7 +56,10 @@ const char* grpc_json_get_string_property(const grpc_json* json,
bool grpc_copy_json_string_property(const grpc_json* json,
const char* prop_name,
char** copied_value) {
const char* prop_value = grpc_json_get_string_property(json, prop_name);
grpc_error* error = GRPC_ERROR_NONE;
const char* prop_value =
grpc_json_get_string_property(json, prop_name, &error);
GRPC_LOG_IF_ERROR("Could not copy JSON property", error);
if (prop_value == nullptr) return false;
*copied_value = gpr_strdup(prop_value);
return true;

@ -23,6 +23,7 @@
#include <stdbool.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
// Constants.
@ -32,7 +33,8 @@
// Gets a child property from a json node.
const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name);
const char* prop_name,
grpc_error** error);
// Copies the value of the json child property specified by prop_name.
// Returns false if the property was not found.

@ -186,19 +186,21 @@ struct UserData {
class StaticMetadata {
public:
StaticMetadata(const grpc_slice& key, const grpc_slice& value)
: kv_({key, value}), hash_(0) {}
StaticMetadata(const grpc_slice& key, const grpc_slice& value, uintptr_t idx)
: kv_({key, value}), hash_(0), static_idx_(idx) {}
const grpc_mdelem_data& data() const { return kv_; }
void HashInit();
uint32_t hash() { return hash_; }
uintptr_t StaticIndex() { return static_idx_; }
private:
grpc_mdelem_data kv_;
/* private only data */
uint32_t hash_;
uintptr_t static_idx_;
};
class RefcountedMdBase {

@ -398,262 +398,262 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) {
grpc_core::StaticMetadata grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 0),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}},
{&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}),
{&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}, 1),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}},
{&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}),
{&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}, 2),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}},
{&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}),
{&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}, 3),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}},
{&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}),
{&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}, 4),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}},
{&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}),
{&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}, 5),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}},
{&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}),
{&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}, 6),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}),
{&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}, 7),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}),
{&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}, 8),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}),
{&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}, 9),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}),
{&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}, 10),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}),
{&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}, 11),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}),
{&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}, 12),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}},
{&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}),
{&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}, 13),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 14),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}},
{&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}),
{&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}, 15),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 16),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 17),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 18),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 19),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 20),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 21),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 22),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 23),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 24),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 25),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 26),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 27),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 28),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 29),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 30),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 31),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 32),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 33),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 34),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 35),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 36),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 37),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 38),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 39),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 40),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 41),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 42),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 43),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 44),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 45),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 46),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 47),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 48),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 49),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 50),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 51),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 52),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 53),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 54),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 55),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 56),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 57),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 58),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 59),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 60),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}},
{&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}),
{&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}, 61),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}},
{&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}),
{&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}, 62),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}},
{&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}),
{&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}, 63),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}},
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}),
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, 64),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}},
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}),
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, 65),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}},
{&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}),
{&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}, 66),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}},
{&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}),
{&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}, 67),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}},
{&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}),
{&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}, 68),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}},
{&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}),
{&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}, 69),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}},
{&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}),
{&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}, 70),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 71),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}},
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}),
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, 72),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}},
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}),
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, 73),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 74),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}},
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}),
{&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, 75),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}),
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, 76),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}),
{&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}, 77),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}),
{&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}, 78),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}),
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, 79),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}),
{&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}, 80),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}),
{&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}, 81),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}},
{&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}),
{&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}, 82),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}},
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}),
{&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, 83),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}},
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}),
{&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, 84),
grpc_core::StaticMetadata(
{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}},
{&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}),
{&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}, 85),
};
const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78,
79, 80, 81, 82};

@ -322,9 +322,6 @@ const char *kCFStreamVarName = "grpc_cfstream";
// Guarantees the code in {} block is invoked only once. See ref at:
// https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?language=objc
if (self == [GRPCCall self]) {
// Enable CFStream by default by do not overwrite if the user explicitly disables CFStream with
// environment variable "grpc_cfstream=0"
setenv(kCFStreamVarName, "1", 0);
grpc_init();
callFlags = [NSMutableDictionary dictionary];
}
@ -780,7 +777,7 @@ const char *kCFStreamVarName = "grpc_cfstream";
// Connectivity monitor is not required for CFStream
char *enableCFStream = getenv(kCFStreamVarName);
if (enableCFStream == nil || enableCFStream[0] != '1') {
if (enableCFStream != nil && enableCFStream[0] != '1') {
[GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)];
}
}

@ -21,8 +21,6 @@
int main(int argc, char* argv[]) {
@autoreleasepool {
// enable CFStream API
setenv("grpc_cfstream", "1", 1);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

@ -77,6 +77,9 @@ message SimpleRequest {
// Whether the server should expect this request to be compressed.
BoolValue expect_compressed = 8;
// Whether SimpleResponse should include server_id.
bool fill_server_id = 9;
}
// Unary response, as configured by the request.
@ -88,6 +91,10 @@ message SimpleResponse {
string username = 2;
// OAuth scope.
string oauth_scope = 3;
// Server ID. This must be unique among different server instances,
// but the same across all RPC's made to a particular server instance.
string server_id = 4;
}
// Client-streaming request.

@ -134,6 +134,7 @@ grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt
grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import;
grpc_access_token_credentials_create_type grpc_access_token_credentials_create_import;
grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import;
grpc_sts_credentials_create_type grpc_sts_credentials_create_import;
grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import;
grpc_secure_channel_create_type grpc_secure_channel_create_import;
grpc_server_credentials_release_type grpc_server_credentials_release_import;
@ -404,6 +405,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_google_refresh_token_credentials_create_import = (grpc_google_refresh_token_credentials_create_type) GetProcAddress(library, "grpc_google_refresh_token_credentials_create");
grpc_access_token_credentials_create_import = (grpc_access_token_credentials_create_type) GetProcAddress(library, "grpc_access_token_credentials_create");
grpc_google_iam_credentials_create_import = (grpc_google_iam_credentials_create_type) GetProcAddress(library, "grpc_google_iam_credentials_create");
grpc_sts_credentials_create_import = (grpc_sts_credentials_create_type) GetProcAddress(library, "grpc_sts_credentials_create");
grpc_metadata_credentials_create_from_plugin_import = (grpc_metadata_credentials_create_from_plugin_type) GetProcAddress(library, "grpc_metadata_credentials_create_from_plugin");
grpc_secure_channel_create_import = (grpc_secure_channel_create_type) GetProcAddress(library, "grpc_secure_channel_create");
grpc_server_credentials_release_import = (grpc_server_credentials_release_type) GetProcAddress(library, "grpc_server_credentials_release");

@ -377,6 +377,9 @@ extern grpc_access_token_credentials_create_type grpc_access_token_credentials_c
typedef grpc_call_credentials*(*grpc_google_iam_credentials_create_type)(const char* authorization_token, const char* authority_selector, void* reserved);
extern grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import;
#define grpc_google_iam_credentials_create grpc_google_iam_credentials_create_import
typedef grpc_call_credentials*(*grpc_sts_credentials_create_type)(const grpc_sts_credentials_options* options, void* reserved);
extern grpc_sts_credentials_create_type grpc_sts_credentials_create_import;
#define grpc_sts_credentials_create grpc_sts_credentials_create_import
typedef grpc_call_credentials*(*grpc_metadata_credentials_create_from_plugin_type)(grpc_metadata_credentials_plugin plugin, void* reserved);
extern grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import;
#define grpc_metadata_credentials_create_from_plugin grpc_metadata_credentials_create_from_plugin_import

@ -325,7 +325,7 @@
% for lib in libs:
% if lib.build in ["all", "protoc", "tool", "test", "private"] and not lib.boringssl:
% if not lib.get('build_system', []) or 'cmake' in lib.get('build_system', []):
% if not lib.name in ['ares', 'benchmark', 'z']: # we build these using CMake instead
% if not lib.name in ['ares', 'benchmark', 'upb', 'z']: # we build these using CMake instead
% if lib.build in ["test", "private"]:
if (gRPC_BUILD_TESTS)
${cc_library(lib)}
@ -467,6 +467,13 @@
)
endif (_gRPC_PLATFORM_ANDROID)
% endif
% if lib.name in ["grpc", "grpc_cronet", "grpc_test_util", \
"grpc_test_util_unsecure", "grpc_unsecure", \
"grpc++_cronet"]:
if (_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
target_link_libraries(${lib.name} "-framework CoreFoundation")
endif()
%endif
% if len(lib.get('public_headers', [])) > 0:
foreach(_hdr

@ -220,6 +220,7 @@
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
CXXFLAGS += -stdlib=libc++
LDFLAGS += -framework CoreFoundation
endif
% for arg in ['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'COREFLAGS', 'LDFLAGS', 'DEFINES']:
% if defaults.get('global', []).get(arg, None) is not None:

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM google/dart:2.0
FROM google/dart:2.3
# Upgrade Dart to version 2.
RUN apt-get update && apt-get upgrade -y dart

@ -19,9 +19,26 @@ grpc_package(name = "test/core/client_channel_resolvers")
licenses(["notice"]) # Apache v2
grpc_cc_test(
name = "dns_resolver_connectivity_test",
name = "dns_resolver_connectivity_using_ares_resolver_test",
srcs = ["dns_resolver_connectivity_test.cc"],
language = "C++",
args = [
"--resolver=ares",
],
deps = [
"//:gpr",
"//:grpc",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "dns_resolver_connectivity_using_native_resolver_test",
srcs = ["dns_resolver_connectivity_test.cc"],
language = "C++",
args = [
"--resolver=native",
],
deps = [
"//:gpr",
"//:grpc",

@ -101,12 +101,16 @@ static grpc_ares_request* test_dns_lookup_ares_locked(
addresses, check_grpclb, service_config_json, query_timeout_ms, combiner);
++g_resolution_count;
static grpc_millis last_resolution_time = 0;
grpc_millis now =
grpc_timespec_to_millis_round_up(gpr_now(GPR_CLOCK_MONOTONIC));
gpr_log(GPR_DEBUG,
"last_resolution_time:%" PRId64 " now:%" PRId64
" min_time_between:%d",
last_resolution_time, now, kMinResolutionPeriodForCheckMs);
if (last_resolution_time == 0) {
last_resolution_time =
grpc_timespec_to_millis_round_up(gpr_now(GPR_CLOCK_MONOTONIC));
} else {
grpc_millis now =
grpc_timespec_to_millis_round_up(gpr_now(GPR_CLOCK_MONOTONIC));
GPR_ASSERT(now - last_resolution_time >= kMinResolutionPeriodForCheckMs);
last_resolution_time = now;
}
@ -212,19 +216,46 @@ struct OnResolutionCallbackArg {
// Set to true by the last callback in the resolution chain.
static bool g_all_callbacks_invoked;
// It's interesting to run a few rounds of this test because as
// we run more rounds, the base starting time
// (i.e. ExecCtx g_start_time) gets further and further away
// from "Now()". Thus the more rounds ran, the more highlighted the
// difference is between absolute and relative times values.
static void on_fourth_resolution(OnResolutionCallbackArg* cb_arg) {
gpr_log(GPR_INFO, "4th: g_resolution_count: %d", g_resolution_count);
GPR_ASSERT(g_resolution_count == 4);
cb_arg->resolver.reset();
gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
gpr_mu_lock(g_iomgr_args.mu);
GRPC_LOG_IF_ERROR("pollset_kick",
grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
gpr_mu_unlock(g_iomgr_args.mu);
grpc_core::Delete(cb_arg);
g_all_callbacks_invoked = true;
}
static void on_third_resolution(OnResolutionCallbackArg* cb_arg) {
gpr_log(GPR_INFO, "3rd: g_resolution_count: %d", g_resolution_count);
GPR_ASSERT(g_resolution_count == 3);
cb_arg->result_handler->SetCallback(on_fourth_resolution, cb_arg);
cb_arg->resolver->RequestReresolutionLocked();
gpr_mu_lock(g_iomgr_args.mu);
GRPC_LOG_IF_ERROR("pollset_kick",
grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
gpr_mu_unlock(g_iomgr_args.mu);
}
static void on_second_resolution(OnResolutionCallbackArg* cb_arg) {
gpr_log(GPR_INFO, "2nd: g_resolution_count: %d", g_resolution_count);
// The resolution callback was not invoked until new data was
// available, which was delayed until after the cooldown period.
GPR_ASSERT(g_resolution_count == 2);
cb_arg->resolver.reset();
gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
cb_arg->result_handler->SetCallback(on_third_resolution, cb_arg);
cb_arg->resolver->RequestReresolutionLocked();
gpr_mu_lock(g_iomgr_args.mu);
GRPC_LOG_IF_ERROR("pollset_kick",
grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
gpr_mu_unlock(g_iomgr_args.mu);
grpc_core::Delete(cb_arg);
g_all_callbacks_invoked = true;
}
static void on_first_resolution(OnResolutionCallbackArg* cb_arg) {
@ -243,9 +274,7 @@ static void on_first_resolution(OnResolutionCallbackArg* cb_arg) {
static void start_test_under_combiner(void* arg, grpc_error* error) {
OnResolutionCallbackArg* res_cb_arg =
static_cast<OnResolutionCallbackArg*>(arg);
res_cb_arg->result_handler = grpc_core::New<ResultHandler>();
grpc_core::ResolverFactory* factory =
grpc_core::ResolverRegistry::LookupResolverFactory("dns");
grpc_uri* uri = grpc_uri_parse(res_cb_arg->uri_str, 0);
@ -300,7 +329,6 @@ int main(int argc, char** argv) {
grpc_set_resolver_impl(&test_resolver);
test_cooldown();
{
grpc_core::ExecCtx exec_ctx;
GRPC_COMBINER_UNREF(g_combiner, "test");

@ -48,11 +48,47 @@ static void test_join_host_port_garbage(void) {
join_host_port_expect("::]", 107, "[::]]:107");
}
static void split_host_port_expect(const char* name, const char* host,
const char* port, bool ret) {
grpc_core::UniquePtr<char> actual_host;
grpc_core::UniquePtr<char> actual_port;
const bool actual_ret =
grpc_core::SplitHostPort(name, &actual_host, &actual_port);
GPR_ASSERT(actual_ret == ret);
if (host == nullptr) {
GPR_ASSERT(actual_host == nullptr);
} else {
GPR_ASSERT(strcmp(host, actual_host.get()) == 0);
}
if (port == nullptr) {
GPR_ASSERT(actual_port == nullptr);
} else {
GPR_ASSERT(strcmp(port, actual_port.get()) == 0);
}
}
static void test_split_host_port() {
split_host_port_expect("", "", nullptr, true);
split_host_port_expect("[a:b]", "a:b", nullptr, true);
split_host_port_expect("1.2.3.4", "1.2.3.4", nullptr, true);
split_host_port_expect("a:b:c::", "a:b:c::", nullptr, true);
split_host_port_expect("[a:b]:30", "a:b", "30", true);
split_host_port_expect("1.2.3.4:30", "1.2.3.4", "30", true);
split_host_port_expect(":30", "", "30", true);
}
static void test_split_host_port_invalid() {
split_host_port_expect("[a:b", nullptr, nullptr, false);
split_host_port_expect("[a:b]30", nullptr, nullptr, false);
}
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
test_join_host_port();
test_join_host_port_garbage();
test_split_host_port();
test_split_host_port_invalid();
return 0;
}

@ -24,8 +24,8 @@
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc_security.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -34,13 +34,16 @@
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/tmpfile.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/credentials/composite/composite_credentials.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/uri/uri_parser.h"
#include "test/core/util/test_config.h"
using grpc_core::internal::grpc_flush_cached_google_default_credentials;
@ -99,15 +102,27 @@ static const char valid_oauth2_json_response[] =
" \"expires_in\":3599, "
" \"token_type\":\"Bearer\"}";
static const char valid_sts_json_response[] =
"{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
" \"expires_in\":3599, "
" \"issued_token_type\":\"urn:ietf:params:oauth:token-type:access_token\", "
" \"token_type\":\"Bearer\"}";
static const char test_scope[] = "perm1 perm2";
static const char test_signed_jwt[] =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
"U0MDcyZTViYTdmZDkwODg2YzcifQ";
static const char test_signed_jwt_token_type[] =
"urn:ietf:params:oauth:token-type:id_token";
static const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
static const char test_service_url[] = "https://foo.com/foo.v1";
static const char other_test_service_url[] = "https://bar.com/bar.v1";
static const char test_sts_endpoint_url[] =
"https://foo.com:5555/v1/token-exchange";
static const char test_method[] = "ThisIsNotAMethod";
/* -- Global state flags. -- */
@ -657,11 +672,11 @@ static int refresh_token_httpcli_post_success(
return 1;
}
static int refresh_token_httpcli_post_failure(
const grpc_httpcli_request* request, const char* body, size_t body_size,
grpc_millis deadline, grpc_closure* on_done,
grpc_httpcli_response* response) {
validate_refresh_token_http_request(request, body, body_size);
static int token_httpcli_post_failure(const grpc_httpcli_request* request,
const char* body, size_t body_size,
grpc_millis deadline,
grpc_closure* on_done,
grpc_httpcli_response* response) {
*response = http_response(403, "Not Authorized.");
GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
return 1;
@ -676,7 +691,7 @@ static void test_refresh_token_creds_success(void) {
grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
test_refresh_token_str, nullptr);
/* First request: http get should be called. */
/* First request: http put should be called. */
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
@ -707,10 +722,279 @@ static void test_refresh_token_creds_failure(void) {
grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
test_refresh_token_str, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_failure);
token_httpcli_post_failure);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
}
static void test_valid_sts_creds_options(void) {
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_uri* sts_url;
grpc_error* error =
grpc_core::ValidateStsCredentialsOptions(&valid_options, &sts_url);
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(sts_url != nullptr);
grpc_core::StringView host;
grpc_core::StringView port;
GPR_ASSERT(grpc_core::SplitHostPort(sts_url->authority, &host, &port));
GPR_ASSERT(host.cmp("foo.com") == 0);
GPR_ASSERT(port.cmp("5555") == 0);
grpc_uri_destroy(sts_url);
}
static void test_invalid_sts_creds_options(void) {
grpc_sts_credentials_options invalid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
nullptr, // subject_token_path (Required)
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_uri* url_should_be_null;
grpc_error* error = grpc_core::ValidateStsCredentialsOptions(
&invalid_options, &url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
nullptr, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
nullptr, // sts_endpoint_url (Required)
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
"not_a_valid_uri", // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
"ftp://ftp.is.not.a.valid.scheme/bar", // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
}
static void validate_sts_token_http_request(const grpc_httpcli_request* request,
const char* body,
size_t body_size) {
// Check that the body is constructed properly.
GPR_ASSERT(body != nullptr);
GPR_ASSERT(body_size != 0);
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
char* get_url_equivalent;
gpr_asprintf(&get_url_equivalent, "%s?%s", test_sts_endpoint_url, body);
grpc_uri* url = grpc_uri_parse(get_url_equivalent, false);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "resource"), "resource") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "audience"), "audience") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "scope"), "scope") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "requested_token_type"),
"requested_token_type") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token"),
test_signed_jwt) == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token_type"),
test_signed_jwt_token_type) == 0);
GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token") == nullptr);
GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token_type") == nullptr);
grpc_uri_destroy(url);
gpr_free(get_url_equivalent);
// Check the rest of the request.
GPR_ASSERT(strcmp(request->host, "foo.com:5555") == 0);
GPR_ASSERT(strcmp(request->http.path, "/v1/token-exchange") == 0);
GPR_ASSERT(request->http.hdr_count == 1);
GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
GPR_ASSERT(strcmp(request->http.hdrs[0].value,
"application/x-www-form-urlencoded") == 0);
}
static int sts_token_httpcli_post_success(const grpc_httpcli_request* request,
const char* body, size_t body_size,
grpc_millis deadline,
grpc_closure* on_done,
grpc_httpcli_response* response) {
validate_sts_token_http_request(request, body, body_size);
*response = http_response(200, valid_sts_json_response);
GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
return 1;
}
static char* write_tmp_jwt_file(void) {
char* path;
FILE* tmp = gpr_tmpfile(test_signed_jwt_path_prefix, &path);
GPR_ASSERT(path != nullptr);
GPR_ASSERT(tmp != nullptr);
size_t jwt_length = strlen(test_signed_jwt);
GPR_ASSERT(fwrite(test_signed_jwt, 1, jwt_length, tmp) == jwt_length);
fclose(tmp);
return path;
}
static void test_sts_creds_success(void) {
grpc_core::ExecCtx exec_ctx;
expected_md emd[] = {
{"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
test_signed_jwt_path, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds =
grpc_sts_credentials_create(&valid_options, nullptr);
/* First request: http put should be called. */
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
sts_token_httpcli_post_success);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
/* Second request: the cached token should be served directly. */
state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void test_sts_creds_load_token_failure(void) {
grpc_core::ExecCtx exec_ctx;
request_metadata_state* state = make_request_metadata_state(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token."),
nullptr, 0);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
"invalid_path", // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds = grpc_sts_credentials_create(&options, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void test_sts_creds_http_failure(void) {
grpc_core::ExecCtx exec_ctx;
request_metadata_state* state = make_request_metadata_state(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token."),
nullptr, 0);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
test_signed_jwt_path, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds =
grpc_sts_credentials_create(&valid_options, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
token_httpcli_post_failure);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void validate_jwt_encode_and_sign_params(
@ -1288,6 +1572,11 @@ int main(int argc, char** argv) {
test_compute_engine_creds_failure();
test_refresh_token_creds_success();
test_refresh_token_creds_failure();
test_valid_sts_creds_options();
test_invalid_sts_creds_options();
test_sts_creds_success();
test_sts_creds_load_token_failure();
test_sts_creds_http_failure();
test_jwt_creds_lifetime();
test_jwt_creds_success();
test_jwt_creds_signing_failure();

@ -26,33 +26,82 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/util/json_util.h"
#include "test/core/security/oauth2_utils.h"
#include "test/core/util/cmdline.h"
static grpc_sts_credentials_options sts_options_from_json(grpc_json* json) {
grpc_sts_credentials_options options;
memset(&options, 0, sizeof(options));
grpc_error* error = GRPC_ERROR_NONE;
options.sts_endpoint_url =
grpc_json_get_string_property(json, "sts_endpoint_url", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.resource = grpc_json_get_string_property(json, "resource", nullptr);
options.audience = grpc_json_get_string_property(json, "audience", nullptr);
options.scope = grpc_json_get_string_property(json, "scope", nullptr);
options.requested_token_type =
grpc_json_get_string_property(json, "requested_token_type", nullptr);
options.subject_token_path =
grpc_json_get_string_property(json, "subject_token_path", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.subject_token_type =
grpc_json_get_string_property(json, "subject_token_type", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.actor_token_path =
grpc_json_get_string_property(json, "actor_token_path", nullptr);
options.actor_token_type =
grpc_json_get_string_property(json, "actor_token_type", nullptr);
return options;
}
static grpc_call_credentials* create_sts_creds(const char* json_file_path) {
grpc_slice sts_options_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(json_file_path, 1, &sts_options_slice)));
grpc_json* json = grpc_json_parse_string(
reinterpret_cast<char*>(GRPC_SLICE_START_PTR(sts_options_slice)));
if (json == nullptr) {
gpr_log(GPR_ERROR, "Invalid json");
return nullptr;
}
grpc_sts_credentials_options options = sts_options_from_json(json);
grpc_call_credentials* result =
grpc_sts_credentials_create(&options, nullptr);
grpc_json_destroy(json);
gpr_slice_unref(sts_options_slice);
return result;
}
static grpc_call_credentials* create_refresh_token_creds(
const char* json_refresh_token_file_path) {
grpc_slice refresh_token;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file",
grpc_load_file(json_refresh_token_file_path, 1, &refresh_token)));
return grpc_google_refresh_token_credentials_create(
grpc_call_credentials* result = grpc_google_refresh_token_credentials_create(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(refresh_token),
nullptr);
gpr_slice_unref(refresh_token);
return result;
}
int main(int argc, char** argv) {
grpc_call_credentials* creds = nullptr;
char* json_key_file_path = nullptr;
const char* json_sts_options_file_path = nullptr;
const char* json_refresh_token_file_path = nullptr;
char* token = nullptr;
int use_gce = 0;
char* scope = nullptr;
gpr_cmdline* cl = gpr_cmdline_create("fetch_oauth2");
gpr_cmdline_add_string(cl, "json_refresh_token",
"File path of the json refresh token.",
&json_refresh_token_file_path);
gpr_cmdline_add_string(cl, "json_sts_options",
"File path of the json sts options.",
&json_sts_options_file_path);
gpr_cmdline_add_flag(
cl, "gce",
"Get a token from the GCE metadata server (only works in GCE).",
@ -61,18 +110,20 @@ int main(int argc, char** argv) {
grpc_init();
if (json_key_file_path != nullptr &&
if (json_sts_options_file_path != nullptr &&
json_refresh_token_file_path != nullptr) {
gpr_log(GPR_ERROR,
"--json_key and --json_refresh_token are mutually exclusive.");
gpr_log(
GPR_ERROR,
"--json_sts_options and --json_refresh_token are mutually exclusive.");
exit(1);
}
if (use_gce) {
if (json_key_file_path != nullptr || scope != nullptr) {
if (json_sts_options_file_path != nullptr ||
json_refresh_token_file_path != nullptr) {
gpr_log(GPR_INFO,
"Ignoring json key and scope to get a token from the GCE "
"metadata server.");
"Ignoring json refresh token or sts options to get a token from "
"the GCE metadata server.");
}
creds = grpc_google_compute_engine_credentials_create(nullptr);
if (creds == nullptr) {
@ -88,8 +139,19 @@ int main(int argc, char** argv) {
json_refresh_token_file_path);
exit(1);
}
} else if (json_sts_options_file_path != nullptr) {
creds = create_sts_creds(json_sts_options_file_path);
if (creds == nullptr) {
gpr_log(GPR_ERROR,
"Could not create sts creds. %s does probably not contain a "
"valid json for sts options.",
json_sts_options_file_path);
exit(1);
}
} else {
gpr_log(GPR_ERROR, "Missing --gce or --json_refresh_token option.");
gpr_log(
GPR_ERROR,
"Missing --gce, --json_sts_options, or --json_refresh_token option.");
exit(1);
}
GPR_ASSERT(creds != nullptr);

@ -128,9 +128,9 @@ static const char good_openid_config[] =
" \"issuer\": \"https://accounts.google.com\","
" \"authorization_endpoint\": "
"\"https://accounts.google.com/o/oauth2/v2/auth\","
" \"token_endpoint\": \"https://www.googleapis.com/oauth2/v4/token\","
" \"token_endpoint\": \"https://oauth2.googleapis.com/token\","
" \"userinfo_endpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\","
" \"revocation_endpoint\": \"https://accounts.google.com/o/oauth2/revoke\","
" \"revocation_endpoint\": \"https://oauth2.googleapis.com/revoke\","
" \"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\""
"}";

@ -63,14 +63,17 @@ static void on_oauth2_response(void* arg, grpc_error* error) {
gpr_mu_unlock(request->mu);
}
static void do_nothing(void* unused, grpc_error* error) {}
static void destroy_after_shutdown(void* pollset, grpc_error* error) {
grpc_pollset_destroy(reinterpret_cast<grpc_pollset*>(pollset));
gpr_free(pollset);
}
char* grpc_test_fetch_oauth2_token_with_credentials(
grpc_call_credentials* creds) {
oauth2_request request;
memset(&request, 0, sizeof(request));
grpc_core::ExecCtx exec_ctx;
grpc_closure do_nothing_closure;
grpc_closure destroy_after_shutdown_closure;
grpc_auth_metadata_context null_ctx = {"", "", nullptr, nullptr};
grpc_pollset* pollset =
@ -79,8 +82,8 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
request.pops = grpc_polling_entity_create_from_pollset(pollset);
request.is_done = false;
GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, nullptr,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&destroy_after_shutdown_closure, destroy_after_shutdown,
pollset, grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request,
grpc_schedule_on_exec_ctx);
@ -107,8 +110,6 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
gpr_mu_unlock(request.mu);
grpc_pollset_shutdown(grpc_polling_entity_pollset(&request.pops),
&do_nothing_closure);
gpr_free(grpc_polling_entity_pollset(&request.pops));
&destroy_after_shutdown_closure);
return request.token;
}

@ -171,6 +171,7 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_google_refresh_token_credentials_create);
printf("%lx", (unsigned long) grpc_access_token_credentials_create);
printf("%lx", (unsigned long) grpc_google_iam_credentials_create);
printf("%lx", (unsigned long) grpc_sts_credentials_create);
printf("%lx", (unsigned long) grpc_metadata_credentials_create_from_plugin);
printf("%lx", (unsigned long) grpc_secure_channel_create);
printf("%lx", (unsigned long) grpc_server_credentials_release);

@ -49,7 +49,18 @@ class GrpcByteBufferPeer {
ByteBuffer* bb_;
};
class ProtoUtilsTest : public ::testing::Test {};
class ProtoUtilsTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
// Ensure the ProtoBufferWriter internals are initialized.
grpc::internal::GrpcLibraryInitializer init;
init.summon();
grpc::GrpcLibraryCodegen lib;
grpc_init();
}
static void TearDownTestCase() { grpc_shutdown(); }
};
// Regression test for a memory corruption bug where a series of
// ProtoBufferWriter Next()/Backup() invocations could result in a dangling
@ -136,36 +147,46 @@ void BufferWriterTest(int block_size, int total_size, int backup_size) {
grpc_byte_buffer_reader_destroy(&reader);
}
TEST(WriterTest, TinyBlockTinyBackup) {
class WriterTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
grpc::internal::GrpcLibraryInitializer init;
init.summon();
grpc::GrpcLibraryCodegen lib;
// Ensure the ProtoBufferWriter internals are initialized.
grpc_init();
}
static void TearDownTestCase() { grpc_shutdown(); }
};
TEST_F(WriterTest, TinyBlockTinyBackup) {
for (int i = 2; i < static_cast<int> GRPC_SLICE_INLINED_SIZE; i++) {
BufferWriterTest(i, 256, 1);
}
}
TEST(WriterTest, SmallBlockTinyBackup) { BufferWriterTest(64, 256, 1); }
TEST_F(WriterTest, SmallBlockTinyBackup) { BufferWriterTest(64, 256, 1); }
TEST(WriterTest, SmallBlockNoBackup) { BufferWriterTest(64, 256, 0); }
TEST_F(WriterTest, SmallBlockNoBackup) { BufferWriterTest(64, 256, 0); }
TEST(WriterTest, SmallBlockFullBackup) { BufferWriterTest(64, 256, 64); }
TEST_F(WriterTest, SmallBlockFullBackup) { BufferWriterTest(64, 256, 64); }
TEST(WriterTest, LargeBlockTinyBackup) { BufferWriterTest(4096, 8192, 1); }
TEST_F(WriterTest, LargeBlockTinyBackup) { BufferWriterTest(4096, 8192, 1); }
TEST(WriterTest, LargeBlockNoBackup) { BufferWriterTest(4096, 8192, 0); }
TEST_F(WriterTest, LargeBlockNoBackup) { BufferWriterTest(4096, 8192, 0); }
TEST(WriterTest, LargeBlockFullBackup) { BufferWriterTest(4096, 8192, 4096); }
TEST_F(WriterTest, LargeBlockFullBackup) { BufferWriterTest(4096, 8192, 4096); }
TEST(WriterTest, LargeBlockLargeBackup) { BufferWriterTest(4096, 8192, 4095); }
TEST_F(WriterTest, LargeBlockLargeBackup) {
BufferWriterTest(4096, 8192, 4095);
}
} // namespace
} // namespace internal
} // namespace grpc
int main(int argc, char** argv) {
// Ensure the ProtoBufferWriter internals are initialized.
grpc::internal::GrpcLibraryInitializer init;
init.summon();
grpc::GrpcLibraryCodegen lib;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -84,6 +84,10 @@ class ChannelArgumentsTest : public ::testing::Test {
channel_args.SetChannelArgs(args);
}
static void SetUpTestCase() { grpc_init(); }
static void TearDownTestCase() { grpc_shutdown(); }
grpc::string GetDefaultUserAgentPrefix() {
std::ostringstream user_agent_prefix;
user_agent_prefix << "grpc-c++/" << Version();
@ -252,8 +256,6 @@ TEST_F(ChannelArgumentsTest, SetUserAgentPrefix) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -141,6 +141,12 @@ class ClientLbEnd2endTest : public ::testing::Test {
creds_(new SecureChannelCredentials(
grpc_fake_transport_security_credentials_create())) {}
static void SetUpTestCase() {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
}
void SetUp() override {
grpc_init();
response_generator_ =
@ -1481,9 +1487,6 @@ TEST_F(ClientLbInterceptTrailingMetadataTest, InterceptsRetriesEnabled) {
} // namespace grpc
int main(int argc, char** argv) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(argc, argv);
const auto result = RUN_ALL_TESTS();

@ -121,6 +121,12 @@ class FilterEnd2endTest : public ::testing::Test {
protected:
FilterEnd2endTest() : server_host_("localhost") {}
static void SetUpTestCase() {
gpr_log(GPR_ERROR, "In SetUpTestCase");
grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>(
"test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
}
void SetUp() override {
int port = grpc_pick_unused_port_or_die();
server_address_ << server_host_ << ":" << port;
@ -321,11 +327,6 @@ TEST_F(FilterEnd2endTest, SimpleBidiStreaming) {
EXPECT_EQ(1, GetConnectionCounterValue());
}
void RegisterFilter() {
grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>(
"test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
}
} // namespace
} // namespace testing
} // namespace grpc
@ -333,6 +334,5 @@ void RegisterFilter() {
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
grpc::testing::RegisterFilter();
return RUN_ALL_TESTS();
}

@ -374,6 +374,15 @@ class GrpclbEnd2endTest : public ::testing::Test {
client_load_reporting_interval_seconds_(
client_load_reporting_interval_seconds) {}
static void SetUpTestCase() {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
grpc_init();
}
static void TearDownTestCase() { grpc_shutdown(); }
void SetUp() override {
response_generator_ =
grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
@ -1003,7 +1012,7 @@ TEST_F(SingleBalancerTest, SecureNamingDeathTest) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
// Make sure that we blow up (via abort() from the security connector) when
// the name from the balancer doesn't match expectations.
ASSERT_DEATH(
ASSERT_DEATH_IF_SUPPORTED(
{
ResetStub(0, kApplicationTargetName_ + ";lb");
SetNextResolution({AddressData{balancers_[0]->port_, true, "woops"}});
@ -1990,13 +1999,8 @@ TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) {
} // namespace grpc
int main(int argc, char** argv) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
grpc_init();
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
const auto result = RUN_ALL_TESTS();
grpc_shutdown();
return result;
}

@ -119,6 +119,12 @@ class ServiceConfigEnd2endTest : public ::testing::Test {
creds_(new SecureChannelCredentials(
grpc_fake_transport_security_credentials_create())) {}
static void SetUpTestCase() {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
}
void SetUp() override {
grpc_init();
response_generator_ =
@ -611,9 +617,6 @@ TEST_F(ServiceConfigEnd2endTest,
} // namespace grpc
int main(int argc, char** argv) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(argc, argv);
const auto result = RUN_ALL_TESTS();

@ -370,6 +370,15 @@ class XdsEnd2endTest : public ::testing::Test {
client_load_reporting_interval_seconds_(
client_load_reporting_interval_seconds) {}
static void SetUpTestCase() {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
grpc_init();
}
static void TearDownTestCase() { grpc_shutdown(); }
void SetUp() override {
response_generator_ =
grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
@ -788,7 +797,7 @@ TEST_F(SingleBalancerTest, SecureNamingDeathTest) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
// Make sure that we blow up (via abort() from the security connector) when
// the name from the balancer doesn't match expectations.
ASSERT_DEATH(
ASSERT_DEATH_IF_SUPPORTED(
{
ResetStub(0, kApplicationTargetName_ + ";lb");
SetNextResolution({},
@ -1401,13 +1410,8 @@ class SingleBalancerWithClientLoadReportingTest : public XdsEnd2endTest {
} // namespace grpc
int main(int argc, char** argv) {
// Make the backup poller poll very frequently in order to pick up
// updates from all the subchannels's FDs.
GPR_GLOBAL_CONFIG_SET(grpc_client_channel_backup_poll_interval_ms, 1);
grpc_init();
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
const auto result = RUN_ALL_TESTS();
grpc_shutdown();
return result;
}

@ -31,7 +31,12 @@ namespace {
using grpc::lb::v1::LoadBalanceRequest;
using grpc::lb::v1::LoadBalanceResponse;
class GrpclbTest : public ::testing::Test {};
class GrpclbTest : public ::testing::Test {
protected:
static void SetUpTestCase() { grpc_init(); }
static void TearDownTestCase() { grpc_shutdown(); }
};
grpc::string Ip4ToPackedString(const char* ip_str) {
struct in_addr ip4;
@ -128,8 +133,6 @@ TEST_F(GrpclbTest, ParseResponseServerList) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -222,6 +222,8 @@ int main(int argc, char** argv) {
&grpc::testing::InteropClient::DoTimeoutOnSleepingServer, &client);
actions["empty_stream"] =
std::bind(&grpc::testing::InteropClient::DoEmptyStream, &client);
actions["pick_first_unary"] =
std::bind(&grpc::testing::InteropClient::DoPickFirstUnary, &client);
if (FLAGS_use_tls) {
actions["compute_engine_creds"] =
std::bind(&grpc::testing::InteropClient::DoComputeEngineCreds, &client,

@ -105,6 +105,13 @@ std::shared_ptr<Channel> CreateChannelForTestCase(
creds = FLAGS_custom_credentials_type == "google_default_credentials"
? nullptr
: AccessTokenCredentials(GetOauth2AccessToken());
} else if (test_case == "pick_first_unary") {
ChannelArguments channel_args;
// allow the LB policy to be configured with service config
channel_args.SetInt(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION, 0);
return CreateTestChannel(host_port, FLAGS_custom_credentials_type,
FLAGS_server_host_override, !FLAGS_use_test_ca,
creds, channel_args);
}
if (FLAGS_custom_credentials_type.empty()) {
transport_security security_type =

@ -948,6 +948,32 @@ bool InteropClient::DoCacheableUnary() {
return true;
}
bool InteropClient::DoPickFirstUnary() {
const int rpcCount = 100;
SimpleRequest request;
SimpleResponse response;
std::string server_id;
request.set_fill_server_id(true);
for (int i = 0; i < rpcCount; i++) {
ClientContext context;
Status s = serviceStub_.Get()->UnaryCall(&context, request, &response);
if (!AssertStatusOk(s, context.debug_error_string())) {
return false;
}
if (i == 0) {
server_id = response.server_id();
continue;
}
if (response.server_id() != server_id) {
gpr_log(GPR_ERROR, "#%d rpc hits server_id %s, expect server_id %s", i,
response.server_id().c_str(), server_id.c_str());
return false;
}
}
gpr_log(GPR_DEBUG, "pick first unary successfully finished");
return true;
}
bool InteropClient::DoCustomMetadata() {
const grpc::string kEchoInitialMetadataKey("x-grpc-test-echo-initial");
const grpc::string kInitialMetadataValue("test_initial_metadata_value");

@ -69,6 +69,8 @@ class InteropClient {
bool DoUnimplementedMethod();
bool DoUnimplementedService();
bool DoCacheableUnary();
// all requests are sent to one server despite multiple servers are resolved
bool DoPickFirstUnary();
// The following interop test are not yet part of the interop spec, and are
// not implemented cross-language. They are considered experimental for now,

@ -176,7 +176,32 @@ void TestCancelActiveDNSQuery(ArgsStruct* args) {
ArgsFinish(args);
}
TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
class CancelDuringAresQuery : public ::testing::Test {
protected:
static void SetUpTestCase() {
GPR_GLOBAL_CONFIG_SET(grpc_dns_resolver, "ares");
// Sanity check the time that it takes to run the test
// including the teardown time (the teardown
// part of the test involves cancelling the DNS query,
// which is the main point of interest for this test).
overall_deadline = grpc_timeout_seconds_to_deadline(4);
grpc_init();
}
static void TearDownTestCase() {
grpc_shutdown();
if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), overall_deadline) > 0) {
gpr_log(GPR_ERROR, "Test took too long");
abort();
}
}
private:
static gpr_timespec overall_deadline;
};
gpr_timespec CancelDuringAresQuery::overall_deadline;
TEST_F(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
grpc_core::ExecCtx exec_ctx;
ArgsStruct args;
ArgsInit(&args);
@ -215,7 +240,7 @@ void MaybePollArbitraryPollsetTwice() {}
#endif
TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
TEST_F(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
grpc_core::ExecCtx exec_ctx;
ArgsStruct args;
ArgsInit(&args);
@ -351,18 +376,18 @@ void TestCancelDuringActiveQuery(
EndTest(client, cq);
}
TEST(CancelDuringAresQuery,
TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) {
TEST_F(CancelDuringAresQuery,
TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) {
TestCancelDuringActiveQuery(NONE /* don't set query timeouts */);
}
TEST(
TEST_F(
CancelDuringAresQuery,
TestHitDeadlineAndDestroyChannelDuringAresResolutionWithQueryTimeoutIsGraceful) {
TestCancelDuringActiveQuery(SHORT /* set short query timeout */);
}
TEST(
TEST_F(
CancelDuringAresQuery,
TestHitDeadlineAndDestroyChannelDuringAresResolutionWithZeroQueryTimeoutIsGraceful) {
TestCancelDuringActiveQuery(ZERO /* disable query timeouts */);
@ -373,18 +398,6 @@ TEST(
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
::testing::InitGoogleTest(&argc, argv);
GPR_GLOBAL_CONFIG_SET(grpc_dns_resolver, "ares");
// Sanity check the time that it takes to run the test
// including the teardown time (the teardown
// part of the test involves cancelling the DNS query,
// which is the main point of interest for this test).
gpr_timespec overall_deadline = grpc_timeout_seconds_to_deadline(4);
grpc_init();
auto result = RUN_ALL_TESTS();
grpc_shutdown();
if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), overall_deadline) > 0) {
gpr_log(GPR_ERROR, "Test took too long");
abort();
}
return result;
}

@ -44,13 +44,19 @@ const grpc::string& GetPort() {
return g_port;
}
TEST(ServerBuilderTest, NoOp) { ServerBuilder b; }
class ServerBuilderTest : public ::testing::Test {
protected:
static void SetUpTestCase() { grpc_init(); }
TEST(ServerBuilderTest, CreateServerNoPorts) {
static void TearDownTestCase() { grpc_shutdown(); }
};
TEST_F(ServerBuilderTest, NoOp) { ServerBuilder b; }
TEST_F(ServerBuilderTest, CreateServerNoPorts) {
ServerBuilder().RegisterService(&g_service).BuildAndStart()->Shutdown();
}
TEST(ServerBuilderTest, CreateServerOnePort) {
TEST_F(ServerBuilderTest, CreateServerOnePort) {
ServerBuilder()
.RegisterService(&g_service)
.AddListeningPort(GetPort(), InsecureServerCredentials())
@ -58,7 +64,7 @@ TEST(ServerBuilderTest, CreateServerOnePort) {
->Shutdown();
}
TEST(ServerBuilderTest, CreateServerRepeatedPort) {
TEST_F(ServerBuilderTest, CreateServerRepeatedPort) {
ServerBuilder()
.RegisterService(&g_service)
.AddListeningPort(GetPort(), InsecureServerCredentials())
@ -67,7 +73,7 @@ TEST(ServerBuilderTest, CreateServerRepeatedPort) {
->Shutdown();
}
TEST(ServerBuilderTest, CreateServerRepeatedPortWithDisallowedReusePort) {
TEST_F(ServerBuilderTest, CreateServerRepeatedPortWithDisallowedReusePort) {
EXPECT_EQ(ServerBuilder()
.RegisterService(&g_service)
.AddListeningPort(GetPort(), InsecureServerCredentials())
@ -82,8 +88,6 @@ TEST(ServerBuilderTest, CreateServerRepeatedPortWithDisallowedReusePort) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -86,7 +86,14 @@ class MockSocketMutatorServerBuilderOption : public grpc::ServerBuilderOption {
MockSocketMutator* mock_socket_mutator_;
};
TEST(ServerBuilderWithSocketMutatorTest, CreateServerWithSocketMutator) {
class ServerBuilderWithSocketMutatorTest : public ::testing::Test {
protected:
static void SetUpTestCase() { grpc_init(); }
static void TearDownTestCase() { grpc_shutdown(); }
};
TEST_F(ServerBuilderWithSocketMutatorTest, CreateServerWithSocketMutator) {
auto address = "localhost:" + std::to_string(grpc_pick_unused_port_or_die());
auto mock_socket_mutator = new MockSocketMutator();
std::unique_ptr<grpc::ServerBuilderOption> mock_socket_mutator_builder_option(
@ -109,8 +116,6 @@ TEST(ServerBuilderWithSocketMutatorTest, CreateServerWithSocketMutator) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -36,7 +36,12 @@ namespace {
const char* kContent1 = "hello xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char* kContent2 = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy world";
class ByteBufferTest : public ::testing::Test {};
class ByteBufferTest : public ::testing::Test {
protected:
static void SetUpTestCase() { grpc_init(); }
static void TearDownTestCase() { grpc_shutdown(); }
};
TEST_F(ByteBufferTest, CopyCtor) {
ByteBuffer buffer1;
@ -121,8 +126,6 @@ TEST_F(ByteBufferTest, SerializationMakesCopy) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -33,6 +33,10 @@ const char* kContent = "hello xxxxxxxxxxxxxxxxxxxx world";
class SliceTest : public ::testing::Test {
protected:
static void SetUpTestCase() { grpc_init(); }
static void TearDownTestCase() { grpc_shutdown(); }
void CheckSliceSize(const Slice& s, const grpc::string& content) {
EXPECT_EQ(content.size(), s.size());
}
@ -132,8 +136,6 @@ TEST_F(SliceTest, Cslice) {
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -550,9 +550,9 @@ print >> C, '}'
print >> C
print >> C, 'grpc_core::StaticMetadata grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {'
for a, b in all_elems:
print >> C, 'grpc_core::StaticMetadata(%s,%s),' % (slice_def(str_idx(a)),
slice_def(str_idx(b)))
for idx, (a, b) in enumerate(all_elems):
print >> C, 'grpc_core::StaticMetadata(%s,%s, %d),' % (
slice_def(str_idx(a)), slice_def(str_idx(b)), idx)
print >> C, '};'
print >> H, 'typedef enum {'

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM google/dart:2.0
FROM google/dart:2.3
# Upgrade Dart to version 2.
RUN apt-get update && apt-get upgrade -y dart

@ -930,6 +930,7 @@ include/grpcpp/channel.h \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \

@ -931,6 +931,7 @@ include/grpcpp/channel.h \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \

@ -284,9 +284,9 @@ LANG_RELEASE_MATRIX = {
('v1.16.0', ReleaseInfo(testcases_file='php__v1.0.1')),
('v1.17.1', ReleaseInfo(testcases_file='php__v1.0.1')),
('v1.18.0', ReleaseInfo()),
# v1.19 and v1.20 were deliberately ommitted here because of an issue.
# See https://github.com/grpc/grpc/issues/18264
('v1.21.4', ReleaseInfo()),
# TODO:https://github.com/grpc/grpc/issues/18264
# Error in above issues needs to be resolved.
]),
'csharp':
OrderedDict([

@ -392,7 +392,23 @@
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "dns_resolver_cooldown_test",
"name": "dns_resolver_cooldown_using_ares_resolver_test",
"src": [
"test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "dns_resolver_cooldown_using_native_resolver_test",
"src": [
"test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc"
],
@ -10420,6 +10436,7 @@
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",
@ -10547,6 +10564,7 @@
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -484,7 +484,35 @@
"uses_polling": true
},
{
"args": [],
"args": [
"--resolver=ares"
],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "dns_resolver_cooldown_using_ares_resolver_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [
"--resolver=native"
],
"benchmark": false,
"ci_platforms": [
"linux",
@ -498,7 +526,7 @@
"flaky": false,
"gtest": false,
"language": "c",
"name": "dns_resolver_cooldown_test",
"name": "dns_resolver_cooldown_using_native_resolver_test",
"platforms": [
"linux",
"mac",

Loading…
Cancel
Save