From ab74a8c86e51262f96a39c5698b520ffc92bc6cc Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Mon, 2 Oct 2017 14:56:11 -0700 Subject: Add grpc_endpoint_delete_from_pollset_set --- src/core/lib/iomgr/endpoint.cc | 6 ++++++ src/core/lib/iomgr/endpoint.h | 11 +++++++++-- src/core/lib/iomgr/tcp_posix.cc | 21 +++++++++++++++++---- src/core/lib/security/transport/secure_endpoint.cc | 8 ++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/endpoint.cc b/src/core/lib/iomgr/endpoint.cc index 37cce335ca..5eab1d3158 100644 --- a/src/core/lib/iomgr/endpoint.cc +++ b/src/core/lib/iomgr/endpoint.cc @@ -39,6 +39,12 @@ void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx, ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set); } +void grpc_endpoint_delete_from_pollset_set(grpc_exec_ctx* exec_ctx, + grpc_endpoint* ep, + grpc_pollset_set* pollset_set) { + ep->vtable->delete_from_pollset_set(exec_ctx, ep, pollset_set); +} + void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep, grpc_error* why) { ep->vtable->shutdown(exec_ctx, ep, why); diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h index 16ff0ab733..c91198a393 100644 --- a/src/core/lib/iomgr/endpoint.h +++ b/src/core/lib/iomgr/endpoint.h @@ -45,6 +45,8 @@ struct grpc_endpoint_vtable { grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset); + void (*delete_from_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, + grpc_pollset_set *pollset); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); grpc_resource_user *(*get_resource_user)(grpc_endpoint *ep); @@ -85,14 +87,19 @@ void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_error *why); void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep); -/* Add an endpoint to a pollset, so that when the pollset is polled, events from - this endpoint are considered */ +/* Add an endpoint to a pollset or pollset_set, so that when the pollset is + polled, events from this endpoint are considered */ void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset *pollset); void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set *pollset_set); +/* Delete an endpoint from a pollset_set */ +void grpc_endpoint_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset_set); + grpc_resource_user *grpc_endpoint_get_resource_user(grpc_endpoint *endpoint); struct grpc_endpoint { diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 7e271294fd..00077d95ea 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -706,6 +706,13 @@ static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd); } +static void tcp_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { + grpc_tcp *tcp = (grpc_tcp *)ep; + grpc_pollset_set_del_fd(exec_ctx, pollset_set, tcp->em_fd); +} + static char *tcp_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); @@ -721,10 +728,16 @@ static grpc_resource_user *tcp_get_resource_user(grpc_endpoint *ep) { return tcp->resource_user; } -static const grpc_endpoint_vtable vtable = { - tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, - tcp_shutdown, tcp_destroy, tcp_get_resource_user, tcp_get_peer, - tcp_get_fd}; +static const grpc_endpoint_vtable vtable = {tcp_read, + tcp_write, + tcp_add_to_pollset, + tcp_add_to_pollset_set, + tcp_delete_from_pollset_set, + tcp_shutdown, + tcp_destroy, + tcp_get_resource_user, + tcp_get_peer, + tcp_get_fd}; #define MAX_CHUNK_SIZE 32 * 1024 * 1024 diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc index ae5633b82c..859d04ae5a 100644 --- a/src/core/lib/security/transport/secure_endpoint.cc +++ b/src/core/lib/security/transport/secure_endpoint.cc @@ -379,6 +379,13 @@ static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set); } +static void endpoint_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *secure_ep, + grpc_pollset_set *pollset_set) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + grpc_endpoint_delete_from_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set); +} + static char *endpoint_get_peer(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; return grpc_endpoint_get_peer(ep->wrapped_ep); @@ -399,6 +406,7 @@ static const grpc_endpoint_vtable vtable = {endpoint_read, endpoint_write, endpoint_add_to_pollset, endpoint_add_to_pollset_set, + endpoint_delete_from_pollset_set, endpoint_shutdown, endpoint_destroy, endpoint_get_resource_user, -- cgit v1.2.3 From 01432b7cf3364077d711663fac8c1ef6d4b1d3f0 Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Mon, 2 Oct 2017 16:14:06 -0700 Subject: Fix windows and uv build --- src/core/lib/iomgr/tcp_uv.cc | 23 +++++++++++++++++++---- src/core/lib/iomgr/tcp_windows.cc | 18 ++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc index e311964dbc..99b9f1ea2d 100644 --- a/src/core/lib/iomgr/tcp_uv.cc +++ b/src/core/lib/iomgr/tcp_uv.cc @@ -304,6 +304,15 @@ static void uv_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, (void)pollset; } +static void uv_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pollset) { + // No-op. We're ignoring pollsets currently + (void)exec_ctx; + (void)ep; + (void)pollset; +} + static void shutdown_callback(uv_shutdown_t *req, int status) {} static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, @@ -340,10 +349,16 @@ static grpc_resource_user *uv_get_resource_user(grpc_endpoint *ep) { static int uv_get_fd(grpc_endpoint *ep) { return -1; } -static grpc_endpoint_vtable vtable = { - uv_endpoint_read, uv_endpoint_write, uv_add_to_pollset, - uv_add_to_pollset_set, uv_endpoint_shutdown, uv_destroy, - uv_get_resource_user, uv_get_peer, uv_get_fd}; +static grpc_endpoint_vtable vtable = {uv_endpoint_read, + uv_endpoint_write, + uv_add_to_pollset, + uv_add_to_pollset_set, + uv_delete_from_pollset_set, + uv_endpoint_shutdown, + uv_destroy, + uv_get_resource_user, + uv_get_peer, + uv_get_fd}; grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, grpc_resource_quota *resource_quota, diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index dc84e564a9..5aba5078a8 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -371,6 +371,10 @@ static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_iocp_add_socket(tcp->socket); } +static void win_delete_from_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *ep, + grpc_pollset_set *pss) {} + /* Initiates a shutdown of the TCP endpoint. This will queue abort callbacks for the potential read and write operations. It is up to the caller to guarantee this isn't called in parallel to a read or write request, so @@ -412,10 +416,16 @@ static grpc_resource_user *win_get_resource_user(grpc_endpoint *ep) { static int win_get_fd(grpc_endpoint *ep) { return -1; } -static grpc_endpoint_vtable vtable = { - win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, - win_shutdown, win_destroy, win_get_resource_user, win_get_peer, - win_get_fd}; +static grpc_endpoint_vtable vtable = {win_read, + win_write, + win_add_to_pollset, + win_add_to_pollset_set, + win_delete_from_pollset_set, + win_shutdown, + win_destroy, + win_get_resource_user, + win_get_peer, + win_get_fd}; grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, grpc_channel_args *channel_args, -- cgit v1.2.3 From 9b9a44e4dd1087a1cbdde3a3884cc7beea031d58 Mon Sep 17 00:00:00 2001 From: Justin Burke Date: Tue, 3 Oct 2017 18:09:41 -0700 Subject: Expose conversion of grpc to tsi cert pairs --- CMakeLists.txt | 31 ++++++++++ Makefile | 36 ++++++++++++ build.yaml | 10 ++++ .../security/credentials/ssl/ssl_credentials.cc | 60 +++++++++++--------- .../lib/security/credentials/ssl/ssl_credentials.h | 15 +++++ .../lib/security/transport/security_connector.cc | 7 ++- .../lib/security/transport/security_connector.h | 2 +- test/core/security/BUILD | 12 ++++ test/core/security/ssl_credentials_test.c | 66 ++++++++++++++++++++++ tools/run_tests/generated/sources_and_headers.json | 17 ++++++ tools/run_tests/generated/tests.json | 24 ++++++++ 11 files changed, 250 insertions(+), 30 deletions(-) create mode 100644 test/core/security/ssl_credentials_test.c (limited to 'src/core/lib') diff --git a/CMakeLists.txt b/CMakeLists.txt index 579621b090..3ac6c9b63d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -459,6 +459,7 @@ add_dependencies(buildtests_c grpc_json_token_test) endif() add_dependencies(buildtests_c grpc_jwt_verifier_test) add_dependencies(buildtests_c grpc_security_connector_test) +add_dependencies(buildtests_c grpc_ssl_credentials_test) if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c handshake_client) endif() @@ -7290,6 +7291,36 @@ target_link_libraries(grpc_security_connector_test gpr ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_ssl_credentials_test + test/core/security/ssl_credentials_test.c +) + + +target_include_directories(grpc_ssl_credentials_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp +) + +target_link_libraries(grpc_ssl_credentials_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + endif (gRPC_BUILD_TESTS) add_executable(grpc_verify_jwt diff --git a/Makefile b/Makefile index bb02c9bdf0..325c9123d9 100644 --- a/Makefile +++ b/Makefile @@ -1019,6 +1019,7 @@ grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token grpc_security_connector_test: $(BINDIR)/$(CONFIG)/grpc_security_connector_test +grpc_ssl_credentials_test: $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt handshake_client: $(BINDIR)/$(CONFIG)/handshake_client handshake_server: $(BINDIR)/$(CONFIG)/handshake_server @@ -1413,6 +1414,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_json_token_test \ $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \ $(BINDIR)/$(CONFIG)/grpc_security_connector_test \ + $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test \ $(BINDIR)/$(CONFIG)/handshake_client \ $(BINDIR)/$(CONFIG)/handshake_server \ $(BINDIR)/$(CONFIG)/hpack_parser_test \ @@ -1886,6 +1888,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test || ( echo test grpc_jwt_verifier_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_security_connector_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_security_connector_test || ( echo test grpc_security_connector_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_ssl_credentials_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test || ( echo test grpc_ssl_credentials_test failed ; exit 1 ) $(E) "[RUN] Testing handshake_client" $(Q) $(BINDIR)/$(CONFIG)/handshake_client || ( echo test handshake_client failed ; exit 1 ) $(E) "[RUN] Testing handshake_server" @@ -11119,6 +11123,38 @@ endif endif +GRPC_SSL_CREDENTIALS_TEST_SRC = \ + test/core/security/ssl_credentials_test.c \ + +GRPC_SSL_CREDENTIALS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_SSL_CREDENTIALS_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test: $(GRPC_SSL_CREDENTIALS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GRPC_SSL_CREDENTIALS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/security/ssl_credentials_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_ssl_credentials_test: $(GRPC_SSL_CREDENTIALS_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_SSL_CREDENTIALS_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_VERIFY_JWT_SRC = \ test/core/security/verify_jwt.c \ diff --git a/build.yaml b/build.yaml index e2faa438ab..d43d36f480 100644 --- a/build.yaml +++ b/build.yaml @@ -2540,6 +2540,16 @@ targets: - grpc - gpr_test_util - gpr +- name: grpc_ssl_credentials_test + build: test + language: c + src: + - test/core/security/ssl_credentials_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: grpc_verify_jwt build: tool language: c diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc index 290336adc0..8e47aebedb 100644 --- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc @@ -31,18 +31,21 @@ // SSL Channel Credentials. // -static void ssl_config_pem_key_cert_pair_destroy( - tsi_ssl_pem_key_cert_pair *kp) { +void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair *kp, + size_t num_key_cert_pairs) { if (kp == NULL) return; - gpr_free((void *)kp->private_key); - gpr_free((void *)kp->cert_chain); + for (size_t i = 0; i < num_key_cert_pairs; i++) { + gpr_free((void *)kp[i].private_key); + gpr_free((void *)kp[i].cert_chain); + } + gpr_free(kp); } static void ssl_destruct(grpc_exec_ctx *exec_ctx, grpc_channel_credentials *creds) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; gpr_free(c->config.pem_root_certs); - ssl_config_pem_key_cert_pair_destroy(&c->config.pem_key_cert_pair); + grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1); } static grpc_security_status ssl_create_security_connector( @@ -85,9 +88,11 @@ static void ssl_build_config(const char *pem_root_certs, if (pem_key_cert_pair != NULL) { GPR_ASSERT(pem_key_cert_pair->private_key != NULL); GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL); - config->pem_key_cert_pair.cert_chain = + config->pem_key_cert_pair = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc( + sizeof(tsi_ssl_pem_key_cert_pair)); + config->pem_key_cert_pair->cert_chain = gpr_strdup(pem_key_cert_pair->cert_chain); - config->pem_key_cert_pair.private_key = + config->pem_key_cert_pair->private_key = gpr_strdup(pem_key_cert_pair->private_key); } } @@ -117,11 +122,8 @@ grpc_channel_credentials *grpc_ssl_credentials_create( static void ssl_server_destruct(grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds) { grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; - size_t i; - for (i = 0; i < c->config.num_key_cert_pairs; i++) { - ssl_config_pem_key_cert_pair_destroy(&c->config.pem_key_cert_pairs[i]); - } - gpr_free(c->config.pem_key_cert_pairs); + grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pairs, + c->config.num_key_cert_pairs); gpr_free(c->config.pem_root_certs); } @@ -136,30 +138,36 @@ static grpc_security_status ssl_server_create_security_connector( static grpc_server_credentials_vtable ssl_server_vtable = { ssl_server_destruct, ssl_server_create_security_connector}; +tsi_ssl_pem_key_cert_pair *grpc_convert_grpc_to_tsi_cert_pairs( + const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs) { + tsi_ssl_pem_key_cert_pair *tsi_pairs = NULL; + if (num_key_cert_pairs > 0) { + GPR_ASSERT(pem_key_cert_pairs != NULL); + tsi_pairs = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc( + num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)); + } + for (size_t i = 0; i < num_key_cert_pairs; i++) { + GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); + GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); + tsi_pairs[i].cert_chain = gpr_strdup(pem_key_cert_pairs[i].cert_chain); + tsi_pairs[i].private_key = gpr_strdup(pem_key_cert_pairs[i].private_key); + } + return tsi_pairs; +} + static void ssl_build_server_config( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, grpc_ssl_server_config *config) { - size_t i; config->client_certificate_request = client_certificate_request; if (pem_root_certs != NULL) { config->pem_root_certs = gpr_strdup(pem_root_certs); } - if (num_key_cert_pairs > 0) { - GPR_ASSERT(pem_key_cert_pairs != NULL); - config->pem_key_cert_pairs = (tsi_ssl_pem_key_cert_pair *)gpr_zalloc( - num_key_cert_pairs * sizeof(tsi_ssl_pem_key_cert_pair)); - } + config->pem_key_cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( + pem_key_cert_pairs, num_key_cert_pairs); config->num_key_cert_pairs = num_key_cert_pairs; - for (i = 0; i < num_key_cert_pairs; i++) { - GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); - GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); - config->pem_key_cert_pairs[i].cert_chain = - gpr_strdup(pem_key_cert_pairs[i].cert_chain); - config->pem_key_cert_pairs[i].private_key = - gpr_strdup(pem_key_cert_pairs[i].private_key); - } } grpc_server_credentials *grpc_ssl_server_credentials_create( diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.h b/src/core/lib/security/credentials/ssl/ssl_credentials.h index b43c656cd7..42e425d9f1 100644 --- a/src/core/lib/security/credentials/ssl/ssl_credentials.h +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.h @@ -20,6 +20,10 @@ #include "src/core/lib/security/credentials/credentials.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { grpc_channel_credentials base; grpc_ssl_config config; @@ -30,4 +34,15 @@ typedef struct { grpc_ssl_server_config config; } grpc_ssl_server_credentials; +tsi_ssl_pem_key_cert_pair *grpc_convert_grpc_to_tsi_cert_pairs( + const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs); + +void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair *kp, + size_t num_key_cert_pairs); + +#ifdef __cplusplus +} +#endif + #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H */ diff --git a/src/core/lib/security/transport/security_connector.cc b/src/core/lib/security/transport/security_connector.cc index 80d9a7b77f..b050be2129 100644 --- a/src/core/lib/security/transport/security_connector.cc +++ b/src/core/lib/security/transport/security_connector.cc @@ -942,10 +942,11 @@ grpc_security_status grpc_ssl_channel_security_connector_create( c->overridden_target_name = gpr_strdup(overridden_target_name); } - has_key_cert_pair = config->pem_key_cert_pair.private_key != NULL && - config->pem_key_cert_pair.cert_chain != NULL; + has_key_cert_pair = config->pem_key_cert_pair != NULL && + config->pem_key_cert_pair->private_key != NULL && + config->pem_key_cert_pair->cert_chain != NULL; result = tsi_create_ssl_client_handshaker_factory( - has_key_cert_pair ? &config->pem_key_cert_pair : NULL, pem_root_certs, + has_key_cert_pair ? config->pem_key_cert_pair : NULL, pem_root_certs, ssl_cipher_suites(), alpn_protocol_strings, (uint16_t)num_alpn_protocols, &c->client_handshaker_factory); if (result != TSI_OK) { diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h index 216bb35e81..8287151f44 100644 --- a/src/core/lib/security/transport/security_connector.h +++ b/src/core/lib/security/transport/security_connector.h @@ -204,7 +204,7 @@ grpc_server_security_connector *grpc_fake_server_security_connector_create( /* Config for ssl clients. */ typedef struct { - tsi_ssl_pem_key_cert_pair pem_key_cert_pair; + tsi_ssl_pem_key_cert_pair *pem_key_cert_pair; char *pem_root_certs; } grpc_ssl_config; diff --git a/test/core/security/BUILD b/test/core/security/BUILD index dc41759922..83b1747648 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -91,6 +91,18 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "ssl_credentials_test", + srcs = ["ssl_credentials_test.c"], + language = "C", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ] +) + grpc_cc_binary( name = "create_jwt", srcs = ["create_jwt.c"], diff --git a/test/core/security/ssl_credentials_test.c b/test/core/security/ssl_credentials_test.c new file mode 100644 index 0000000000..3c838faa60 --- /dev/null +++ b/test/core/security/ssl_credentials_test.c @@ -0,0 +1,66 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "test/core/util/test_config.h" + +static void test_convert_grpc_to_tsi_cert_pairs() { + grpc_ssl_pem_key_cert_pair grpc_pairs[] = {{"private_key1", "cert_chain1"}, + {"private_key2", "cert_chain2"}, + {"private_key3", "cert_chain3"}}; + const size_t num_pairs = 3; + + { + tsi_ssl_pem_key_cert_pair *tsi_pairs = + grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, 0); + GPR_ASSERT(tsi_pairs == NULL); + } + + { + tsi_ssl_pem_key_cert_pair *tsi_pairs = + grpc_convert_grpc_to_tsi_cert_pairs(grpc_pairs, num_pairs); + + GPR_ASSERT(tsi_pairs != NULL); + for (size_t i = 0; i < num_pairs; i++) { + GPR_ASSERT(strncmp(grpc_pairs[i].private_key, tsi_pairs[i].private_key, + strlen(grpc_pairs[i].private_key)) == 0); + GPR_ASSERT(strncmp(grpc_pairs[i].cert_chain, tsi_pairs[i].cert_chain, + strlen(grpc_pairs[i].cert_chain)) == 0); + } + + grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_pairs, num_pairs); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + + test_convert_grpc_to_tsi_cert_pairs(); + + grpc_shutdown(); + return 0; +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7fa3d28834..46f4cb6532 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1219,6 +1219,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "grpc_ssl_credentials_test", + "src": [ + "test/core/security/ssl_credentials_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index da763725e6..15d38eb05b 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1535,6 +1535,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "grpc_ssl_credentials_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 1b1e8d61493e98aa96600d8639f52e0996e8c740 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 24 Oct 2017 11:15:17 +0200 Subject: unref resource quota on windows --- src/core/lib/iomgr/tcp_windows.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index dc84e564a9..ad939d3b50 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -442,6 +442,7 @@ grpc_endpoint *grpc_tcp_create(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket, tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); + grpc_resource_quota_unref_internal(exec_ctx, resource_quota); return &tcp->base; } -- cgit v1.2.3 From 42bd87e376913939850bfa78a3c7f96ce83af11e Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 20 Oct 2017 10:32:30 -0700 Subject: Adds gRPC Experimental CQ DoThenAsyncNext lambda API --- grpc.def | 2 + include/grpc++/impl/codegen/completion_queue.h | 39 +++++++++ include/grpc/grpc.h | 17 ++++ src/core/lib/surface/completion_queue.cc | 116 ++++++++++++++++++------- src/core/lib/surface/completion_queue.h | 3 + src/core/lib/surface/init.cc | 1 + src/cpp/common/completion_queue_cc.cc | 25 ++++++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 4 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 6 ++ test/core/surface/completion_queue_test.c | 76 ++++++++++++++++ test/cpp/end2end/async_end2end_test.cc | 111 ++++++++++++++++++++++- test/cpp/qps/client.h | 44 ++++------ test/cpp/qps/client_async.cc | 48 ++++++---- test/cpp/qps/client_sync.cc | 39 ++++++--- test/cpp/qps/server_async.cc | 31 ++++--- 15 files changed, 466 insertions(+), 96 deletions(-) (limited to 'src/core/lib') diff --git a/grpc.def b/grpc.def index 558be60c3c..e4281f3ab6 100644 --- a/grpc.def +++ b/grpc.def @@ -54,6 +54,8 @@ EXPORTS grpc_completion_queue_pluck grpc_completion_queue_shutdown grpc_completion_queue_destroy + grpc_completion_queue_thread_local_cache_init + grpc_completion_queue_thread_local_cache_flush grpc_alarm_create grpc_alarm_set grpc_alarm_cancel diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index ca757e2a9c..e2c0c29dca 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -109,6 +109,30 @@ class CompletionQueue : private GrpcLibraryCodegen { TIMEOUT ///< deadline was reached. }; + /// EXPERIMENTAL + /// First executes \a F, then reads from the queue, blocking up to + /// \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param F[in] Function to execute before calling AsyncNext on this queue. + /// \param tag[out] Upon sucess, updated to point to the event's tag. + /// \param ok[out] Upon sucess, true if read a regular event, false otherwise. + /// \param deadline[in] How long to block in wait for an event. + /// + /// \return The type of event read. + template + NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) { + CompletionQueueTLSCache cache = CompletionQueueTLSCache(this); + f(); + if (cache.Flush(tag, ok)) { + return GOT_EVENT; + } else { + return AsyncNext(tag, ok, deadline); + } + } + /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). /// Both \a tag and \a ok are updated upon success (if an event is available /// within the \a deadline). A \a tag points to an arbitrary location usually @@ -213,6 +237,21 @@ class CompletionQueue : private GrpcLibraryCodegen { const InputMessage& request, OutputMessage* result); + /// EXPERIMENTAL + /// Creates a Thread Local cache to store the first event + /// On this completion queue queued from this thread. Once + /// initialized, it must be flushed on the same thread. + class CompletionQueueTLSCache { + public: + CompletionQueueTLSCache(CompletionQueue* cq); + ~CompletionQueueTLSCache(); + bool Flush(void** tag, bool* ok); + + private: + CompletionQueue* cq_; + bool flushed_; + }; + NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); /// Wraps \a grpc_completion_queue_pluck. diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 1de289fba4..6df3b8086e 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -143,6 +143,23 @@ GRPCAPI void grpc_completion_queue_shutdown(grpc_completion_queue *cq); drained and no threads are executing grpc_completion_queue_next */ GRPCAPI void grpc_completion_queue_destroy(grpc_completion_queue *cq); +/*********** EXPERIMENTAL API ************/ +/** Initializes a thread local cache for \a cq. + * grpc_flush_cq_tls_cache() MUST be called on the same thread, + * with the same cq. + */ +GRPCAPI void grpc_completion_queue_thread_local_cache_init( + grpc_completion_queue *cq); + +/*********** EXPERIMENTAL API ************/ +/** Flushes the thread local cache for \a cq. + * Returns 1 if there was contents in the cache. If there was an event + * in \a cq tls cache, its tag is placed in tag, and ok is set to the + * event success. + */ +GRPCAPI int grpc_completion_queue_thread_local_cache_flush( + grpc_completion_queue *cq, void **tag, int *ok); + /** Create a completion queue alarm instance */ GRPCAPI grpc_alarm *grpc_alarm_create(void *reserved); diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 21664f03c8..5009f786e6 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/pollset.h" @@ -48,6 +49,14 @@ grpc_tracer_flag grpc_trace_cq_refcount = GRPC_TRACER_INITIALIZER(false, "cq_refcount"); #endif +// Specifies a cq thread local cache. +// The first event that occurs on a thread +// with a cq cache will go into that cache, and +// will only be returned on the thread that initialized the cache. +// NOTE: Only one event will ever be cached. +GPR_TLS_DECL(g_cached_event); +GPR_TLS_DECL(g_cached_cq); + typedef struct { grpc_pollset_worker **worker; void *tag; @@ -345,6 +354,46 @@ grpc_tracer_flag grpc_cq_event_timeout_trace = static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cq, grpc_error *error); +void grpc_cq_global_init() { + gpr_tls_init(&g_cached_event); + gpr_tls_init(&g_cached_cq); +} + +void grpc_completion_queue_thread_local_cache_init(grpc_completion_queue *cq) { + if ((grpc_completion_queue *)gpr_tls_get(&g_cached_cq) == nullptr) { + gpr_tls_set(&g_cached_event, (intptr_t)0); + gpr_tls_set(&g_cached_cq, (intptr_t)cq); + } +} + +int grpc_completion_queue_thread_local_cache_flush(grpc_completion_queue *cq, + void **tag, int *ok) { + grpc_cq_completion *storage = + (grpc_cq_completion *)gpr_tls_get(&g_cached_event); + int ret = 0; + if (storage != NULL && + (grpc_completion_queue *)gpr_tls_get(&g_cached_cq) == cq) { + *tag = storage->tag; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + storage->done(&exec_ctx, storage->done_arg, storage); + *ok = (storage->next & (uintptr_t)(1)) == 1; + ret = 1; + cq_next_data *cqd = (cq_next_data *)DATA_FROM_CQ(cq); + if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + GRPC_CQ_INTERNAL_REF(cq, "shutting_down"); + gpr_mu_lock(cq->mu); + cq_finish_shutdown_next(&exec_ctx, cq); + gpr_mu_unlock(cq->mu); + GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cq, "shutting_down"); + } + grpc_exec_ctx_finish(&exec_ctx); + } + gpr_tls_set(&g_cached_event, (intptr_t)0); + gpr_tls_set(&g_cached_cq, (intptr_t)0); + + return ret; +} + static void cq_event_queue_init(grpc_cq_event_queue *q) { gpr_mpscq_init(&q->queue); q->queue_lock = GPR_SPINLOCK_INITIALIZER; @@ -617,7 +666,6 @@ static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx, gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); } } - cq_next_data *cqd = (cq_next_data *)DATA_FROM_CQ(cq); int is_success = (error == GRPC_ERROR_NONE); @@ -628,44 +676,50 @@ static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx, cq_check_tag(cq, tag, true); /* Used in debug builds only */ - /* Add the completion to the queue */ - bool is_first = cq_event_queue_push(&cqd->queue, storage); - gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1); - - /* Since we do not hold the cq lock here, it is important to do an 'acquire' - load here (instead of a 'no_barrier' load) to match with the release store - (done via gpr_atm_full_fetch_add(pending_events, -1)) in cq_shutdown_next - */ - bool will_definitely_shutdown = gpr_atm_acq_load(&cqd->pending_events) == 1; - - if (!will_definitely_shutdown) { - /* Only kick if this is the first item queued */ - if (is_first) { - gpr_mu_lock(cq->mu); - grpc_error *kick_error = - cq->poller_vtable->kick(exec_ctx, POLLSET_FROM_CQ(cq), NULL); - gpr_mu_unlock(cq->mu); + if ((grpc_completion_queue *)gpr_tls_get(&g_cached_cq) == cq && + (grpc_cq_completion *)gpr_tls_get(&g_cached_event) == nullptr) { + gpr_tls_set(&g_cached_event, (intptr_t)storage); + } else { + /* Add the completion to the queue */ + bool is_first = cq_event_queue_push(&cqd->queue, storage); + gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1); + + /* Since we do not hold the cq lock here, it is important to do an 'acquire' + load here (instead of a 'no_barrier' load) to match with the release + store + (done via gpr_atm_full_fetch_add(pending_events, -1)) in cq_shutdown_next + */ + bool will_definitely_shutdown = gpr_atm_acq_load(&cqd->pending_events) == 1; + + if (!will_definitely_shutdown) { + /* Only kick if this is the first item queued */ + if (is_first) { + gpr_mu_lock(cq->mu); + grpc_error *kick_error = + cq->poller_vtable->kick(exec_ctx, POLLSET_FROM_CQ(cq), NULL); + gpr_mu_unlock(cq->mu); - if (kick_error != GRPC_ERROR_NONE) { - const char *msg = grpc_error_string(kick_error); - gpr_log(GPR_ERROR, "Kick failed: %s", msg); - GRPC_ERROR_UNREF(kick_error); + if (kick_error != GRPC_ERROR_NONE) { + const char *msg = grpc_error_string(kick_error); + gpr_log(GPR_ERROR, "Kick failed: %s", msg); + GRPC_ERROR_UNREF(kick_error); + } } - } - if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + GRPC_CQ_INTERNAL_REF(cq, "shutting_down"); + gpr_mu_lock(cq->mu); + cq_finish_shutdown_next(exec_ctx, cq); + gpr_mu_unlock(cq->mu); + GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "shutting_down"); + } + } else { GRPC_CQ_INTERNAL_REF(cq, "shutting_down"); + gpr_atm_rel_store(&cqd->pending_events, 0); gpr_mu_lock(cq->mu); cq_finish_shutdown_next(exec_ctx, cq); gpr_mu_unlock(cq->mu); GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "shutting_down"); } - } else { - GRPC_CQ_INTERNAL_REF(cq, "shutting_down"); - gpr_atm_rel_store(&cqd->pending_events, 0); - gpr_mu_lock(cq->mu); - cq_finish_shutdown_next(exec_ctx, cq); - gpr_mu_unlock(cq->mu); - GRPC_CQ_INTERNAL_UNREF(exec_ctx, cq, "shutting_down"); } GPR_TIMER_END("cq_end_op_for_next", 0); diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index 69d144bd95..c02bc5da07 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -70,6 +70,9 @@ void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc); #define GRPC_CQ_INTERNAL_UNREF(ec, cc, reason) grpc_cq_internal_unref(ec, cc) #endif +/* Initializes global variables used by completion queues */ +void grpc_cq_global_init(); + /* Flag that an operation is beginning: the completion channel will not finish shutdown until a corrensponding grpc_cq_end_* call is made. \a tag is currently used only in debug builds. Return true on success, and diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index b089da2c54..058e88f804 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -64,6 +64,7 @@ static void do_basic_init(void) { gpr_log_verbosity_init(); gpr_mu_init(&g_init_mu); grpc_register_built_in_plugins(); + grpc_cq_global_init(); g_initializations = 0; } diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index f34b0f3d58..4a2e2be688 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -71,4 +71,29 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( } } +CompletionQueue::CompletionQueueTLSCache::CompletionQueueTLSCache( + CompletionQueue* cq) + : cq_(cq), flushed_(false) { + grpc_completion_queue_thread_local_cache_init(cq_->cq_); +} + +CompletionQueue::CompletionQueueTLSCache::~CompletionQueueTLSCache() { + GPR_ASSERT(flushed_); +} + +bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) { + int res = 0; + void* res_tag; + flushed_ = true; + if (grpc_completion_queue_thread_local_cache_flush(cq_->cq_, &res_tag, + &res)) { + auto cq_tag = static_cast(res_tag); + *ok = res == 1; + if (cq_tag->FinalizeResult(tag, ok)) { + return true; + } + } + return false; +} + } // namespace grpc diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 70831494fa..cd1bd98abc 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -77,6 +77,8 @@ grpc_completion_queue_next_type grpc_completion_queue_next_import; grpc_completion_queue_pluck_type grpc_completion_queue_pluck_import; grpc_completion_queue_shutdown_type grpc_completion_queue_shutdown_import; grpc_completion_queue_destroy_type grpc_completion_queue_destroy_import; +grpc_completion_queue_thread_local_cache_init_type grpc_completion_queue_thread_local_cache_init_import; +grpc_completion_queue_thread_local_cache_flush_type grpc_completion_queue_thread_local_cache_flush_import; grpc_alarm_create_type grpc_alarm_create_import; grpc_alarm_set_type grpc_alarm_set_import; grpc_alarm_cancel_type grpc_alarm_cancel_import; @@ -385,6 +387,8 @@ void grpc_rb_load_imports(HMODULE library) { grpc_completion_queue_pluck_import = (grpc_completion_queue_pluck_type) GetProcAddress(library, "grpc_completion_queue_pluck"); grpc_completion_queue_shutdown_import = (grpc_completion_queue_shutdown_type) GetProcAddress(library, "grpc_completion_queue_shutdown"); grpc_completion_queue_destroy_import = (grpc_completion_queue_destroy_type) GetProcAddress(library, "grpc_completion_queue_destroy"); + grpc_completion_queue_thread_local_cache_init_import = (grpc_completion_queue_thread_local_cache_init_type) GetProcAddress(library, "grpc_completion_queue_thread_local_cache_init"); + grpc_completion_queue_thread_local_cache_flush_import = (grpc_completion_queue_thread_local_cache_flush_type) GetProcAddress(library, "grpc_completion_queue_thread_local_cache_flush"); grpc_alarm_create_import = (grpc_alarm_create_type) GetProcAddress(library, "grpc_alarm_create"); grpc_alarm_set_import = (grpc_alarm_set_type) GetProcAddress(library, "grpc_alarm_set"); grpc_alarm_cancel_import = (grpc_alarm_cancel_type) GetProcAddress(library, "grpc_alarm_cancel"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 868772cfc8..c7e78b70dc 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -212,6 +212,12 @@ extern grpc_completion_queue_shutdown_type grpc_completion_queue_shutdown_import typedef void(*grpc_completion_queue_destroy_type)(grpc_completion_queue *cq); extern grpc_completion_queue_destroy_type grpc_completion_queue_destroy_import; #define grpc_completion_queue_destroy grpc_completion_queue_destroy_import +typedef void(*grpc_completion_queue_thread_local_cache_init_type)(grpc_completion_queue *cq); +extern grpc_completion_queue_thread_local_cache_init_type grpc_completion_queue_thread_local_cache_init_import; +#define grpc_completion_queue_thread_local_cache_init grpc_completion_queue_thread_local_cache_init_import +typedef int(*grpc_completion_queue_thread_local_cache_flush_type)(grpc_completion_queue *cq, void **tag, int *ok); +extern grpc_completion_queue_thread_local_cache_flush_type grpc_completion_queue_thread_local_cache_flush_import; +#define grpc_completion_queue_thread_local_cache_flush grpc_completion_queue_thread_local_cache_flush_import typedef grpc_alarm *(*grpc_alarm_create_type)(void *reserved); extern grpc_alarm_create_type grpc_alarm_create_import; #define grpc_alarm_create grpc_alarm_create_import diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index e6372a379c..e4e4c9f1b2 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -158,6 +158,80 @@ static void test_cq_end_op(void) { } } +static void test_cq_tls_cache_full(void) { + grpc_event ev; + grpc_completion_queue *cc; + grpc_cq_completion completion; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + void *tag = create_test_tag(); + void *res_tag; + int ok; + + LOG_TEST("test_cq_tls_cache_full"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + exec_ctx = init_exec_ctx; // Reset exec_ctx + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + grpc_completion_queue_thread_local_cache_init(cc); + GPR_ASSERT(grpc_cq_begin_op(cc, tag)); + grpc_cq_end_op(&exec_ctx, cc, tag, GRPC_ERROR_NONE, + do_nothing_end_completion, NULL, &completion); + + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 1); + GPR_ASSERT(res_tag == tag); + GPR_ASSERT(ok); + + ev = grpc_completion_queue_next(cc, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + +static void test_cq_tls_cache_empty(void) { + grpc_completion_queue *cc; + grpc_cq_polling_type polling_types[] = { + GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; + grpc_completion_queue_attributes attr; + grpc_exec_ctx init_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_exec_ctx exec_ctx; + void *res_tag; + int ok; + + LOG_TEST("test_cq_tls_cache_empty"); + + attr.version = 1; + attr.cq_completion_type = GRPC_CQ_NEXT; + for (size_t i = 0; i < GPR_ARRAY_SIZE(polling_types); i++) { + exec_ctx = init_exec_ctx; // Reset exec_ctx + attr.cq_polling_type = polling_types[i]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, NULL); + + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 0); + grpc_completion_queue_thread_local_cache_init(cc); + GPR_ASSERT( + grpc_completion_queue_thread_local_cache_flush(cc, &res_tag, &ok) == 0); + shutdown_and_destroy(cc); + grpc_exec_ctx_finish(&exec_ctx); + } +} + static void test_shutdown_then_next_polling(void) { grpc_cq_polling_type polling_types[] = { GRPC_CQ_DEFAULT_POLLING, GRPC_CQ_NON_LISTENING, GRPC_CQ_NON_POLLING}; @@ -300,6 +374,8 @@ int main(int argc, char **argv) { test_cq_end_op(); test_pluck(); test_pluck_after_shutdown(); + test_cq_tls_cache_full(); + test_cq_tls_cache_empty(); grpc_shutdown(); return 0; } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 2a33e8ae11..b7634d0438 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -99,7 +99,7 @@ class PollingOverrider { class Verifier { public: - explicit Verifier(bool spin) : spin_(spin) {} + explicit Verifier(bool spin) : spin_(spin), lambda_run_(false) {} // Expect sets the expected ok value for a specific tag Verifier& Expect(int i, bool expect_ok) { return ExpectUnless(i, expect_ok, false); @@ -142,6 +142,18 @@ class Verifier { return detag(got_tag); } + template + CompletionQueue::NextStatus DoOnceThenAsyncNext( + CompletionQueue* cq, void** got_tag, bool* ok, T deadline, + std::function lambda) { + if (lambda_run_) { + return cq->AsyncNext(got_tag, ok, deadline); + } else { + lambda_run_ = true; + return cq->DoThenAsyncNext(lambda, got_tag, ok, deadline); + } + } + // Verify keeps calling Next until all currently set // expected tags are complete void Verify(CompletionQueue* cq) { Verify(cq, false); } @@ -154,6 +166,7 @@ class Verifier { Next(cq, ignore_ok); } } + // This version of Verify stops after a certain deadline void Verify(CompletionQueue* cq, std::chrono::system_clock::time_point deadline) { @@ -193,6 +206,47 @@ class Verifier { } } + // This version of Verify stops after a certain deadline, and uses the + // DoThenAsyncNext API + // to call the lambda + void Verify(CompletionQueue* cq, + std::chrono::system_clock::time_point deadline, + std::function lambda) { + if (expectations_.empty()) { + bool ok; + void* got_tag; + if (spin_) { + while (std::chrono::system_clock::now() < deadline) { + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::TIMEOUT); + } + } else { + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::TIMEOUT); + } + } else { + while (!expectations_.empty()) { + bool ok; + void* got_tag; + if (spin_) { + for (;;) { + GPR_ASSERT(std::chrono::system_clock::now() < deadline); + auto r = DoOnceThenAsyncNext( + cq, &got_tag, &ok, gpr_time_0(GPR_CLOCK_REALTIME), lambda); + if (r == CompletionQueue::TIMEOUT) continue; + if (r == CompletionQueue::GOT_EVENT) break; + gpr_log(GPR_ERROR, "unexpected result from AsyncNext"); + abort(); + } + } else { + EXPECT_EQ(DoOnceThenAsyncNext(cq, &got_tag, &ok, deadline, lambda), + CompletionQueue::GOT_EVENT); + } + GotTag(got_tag, ok, false); + } + } + } + private: void GotTag(void* got_tag, bool ok, bool ignore_ok) { auto it = expectations_.find(got_tag); @@ -226,6 +280,7 @@ class Verifier { std::map expectations_; std::map maybe_expectations_; bool spin_; + bool lambda_run_; }; bool plugin_has_sync_methods(std::unique_ptr& plugin) { @@ -490,6 +545,60 @@ TEST_P(AsyncEnd2endTest, AsyncNextRpc) { EXPECT_TRUE(recv_status.ok()); } +// Test a simple RPC using the async version of Next +TEST_P(AsyncEnd2endTest, DoThenAsyncNextRpc) { + ResetStub(); + + EchoRequest send_request; + EchoRequest recv_request; + EchoResponse send_response; + EchoResponse recv_response; + Status recv_status; + + ClientContext cli_ctx; + ServerContext srv_ctx; + grpc::ServerAsyncResponseWriter response_writer(&srv_ctx); + + send_request.set_message(GetParam().message_content); + std::unique_ptr> response_reader( + stub_->AsyncEcho(&cli_ctx, send_request, cq_.get())); + + std::chrono::system_clock::time_point time_now( + std::chrono::system_clock::now()); + std::chrono::system_clock::time_point time_limit( + std::chrono::system_clock::now() + std::chrono::seconds(10)); + Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now); + Verifier(GetParam().disable_blocking).Verify(cq_.get(), time_now); + + auto resp_writer_ptr = &response_writer; + auto lambda_2 = [&, this, resp_writer_ptr]() { + gpr_log(GPR_ERROR, "CALLED"); + service_->RequestEcho(&srv_ctx, &recv_request, resp_writer_ptr, cq_.get(), + cq_.get(), tag(2)); + }; + + Verifier(GetParam().disable_blocking) + .Expect(2, true) + .Verify(cq_.get(), time_limit, lambda_2); + EXPECT_EQ(send_request.message(), recv_request.message()); + + auto recv_resp_ptr = &recv_response; + auto status_ptr = &recv_status; + send_response.set_message(recv_request.message()); + auto lambda_3 = [&, this, resp_writer_ptr, send_response]() { + resp_writer_ptr->Finish(send_response, Status::OK, tag(3)); + }; + response_reader->Finish(recv_resp_ptr, status_ptr, tag(4)); + Verifier(GetParam().disable_blocking) + .Expect(3, true) + .Expect(4, true) + .Verify(cq_.get(), std::chrono::system_clock::time_point::max(), + lambda_3); + + EXPECT_EQ(send_response.message(), recv_response.message()); + EXPECT_TRUE(recv_status.ok()); +} + // Two pings and a final pong. TEST_P(AsyncEnd2endTest, SimpleClientStreaming) { ResetStub(); diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index abf755b393..9888c762f2 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -226,8 +226,6 @@ class Client { } virtual void DestroyMultithreading() = 0; - virtual void InitThreadFunc(size_t thread_idx) = 0; - virtual bool ThreadFunc(HistogramEntry* histogram, size_t thread_idx) = 0; void SetupLoadTest(const ClientConfig& config, size_t num_threads) { // Set up the load distribution based on the number of threads @@ -275,7 +273,6 @@ class Client { : std::bind(&Client::NextIssueTime, this, thread_idx); } - private: class Thread { public: Thread(Client* client, size_t idx) @@ -295,6 +292,16 @@ class Client { MergeStatusHistogram(statuses_, s); } + void UpdateHistogram(HistogramEntry* entry) { + std::lock_guard g(mu_); + if (entry->value_used()) { + histogram_.Add(entry->value()); + } + if (entry->status_used()) { + statuses_[entry->status()]++; + } + } + private: Thread(const Thread&); Thread& operator=(const Thread&); @@ -310,29 +317,8 @@ class Client { wait_loop++; } - client_->InitThreadFunc(idx_); - - for (;;) { - // run the loop body - HistogramEntry entry; - const bool thread_still_ok = client_->ThreadFunc(&entry, idx_); - // lock, update histogram if needed and see if we're done - std::lock_guard g(mu_); - if (entry.value_used()) { - histogram_.Add(entry.value()); - } - if (entry.status_used()) { - statuses_[entry.status()]++; - } - if (!thread_still_ok) { - gpr_log(GPR_ERROR, "Finishing client thread due to RPC error"); - } - if (!thread_still_ok || - static_cast(gpr_atm_acq_load(&client_->thread_pool_done_))) { - client_->CompleteThread(); - return; - } - } + client_->ThreadFunc(idx_, this); + client_->CompleteThread(); } std::mutex mu_; @@ -343,6 +329,12 @@ class Client { std::thread impl_; }; + bool ThreadCompleted() { + return static_cast(gpr_atm_acq_load(&thread_pool_done_)); + } + + virtual void ThreadFunc(size_t thread_idx, Client::Thread* t) = 0; + std::vector> threads_; std::unique_ptr timer_; diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 9ed4e0b355..b5c7208664 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -236,33 +236,47 @@ class AsyncClient : public ClientImpl { this->EndThreads(); // this needed for resolution } - void InitThreadFunc(size_t thread_idx) override final {} - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override final { + void ThreadFunc(size_t thread_idx, Client::Thread* t) override final { void* got_tag; bool ok; - if (cli_cqs_[cq_[thread_idx]]->Next(&got_tag, &ok)) { + HistogramEntry entry; + HistogramEntry* entry_ptr = &entry; + if (!cli_cqs_[cq_[thread_idx]]->Next(&got_tag, &ok)) { + return; + } + ClientRpcContext* ctx; + std::mutex* shutdown_mu = &shutdown_state_[thread_idx]->mutex; + do { + t->UpdateHistogram(entry_ptr); // Got a regular event, so process it - ClientRpcContext* ctx = ClientRpcContext::detag(got_tag); + ctx = ClientRpcContext::detag(got_tag); // Proceed while holding a lock to make sure that // this thread isn't supposed to shut down - std::lock_guard l(shutdown_state_[thread_idx]->mutex); + shutdown_mu->lock(); if (shutdown_state_[thread_idx]->shutdown) { ctx->TryCancel(); delete ctx; - return true; - } - if (!ctx->RunNextState(ok, entry)) { - // The RPC and callback are done, so clone the ctx - // and kickstart the new one - ctx->StartNewClone(cli_cqs_[cq_[thread_idx]].get()); - delete ctx; + while (cli_cqs_[cq_[thread_idx]]->Next(&got_tag, &ok)) { + ctx = ClientRpcContext::detag(got_tag); + ctx->TryCancel(); + delete ctx; + } + shutdown_mu->unlock(); + return; } - return true; - } else { - // queue is shutting down, so we must be done - return true; - } + } while (cli_cqs_[cq_[thread_idx]]->DoThenAsyncNext( + [&, ctx, ok, entry_ptr, shutdown_mu]() { + bool next_ok = ok; + if (!ctx->RunNextState(next_ok, entry_ptr)) { + // The RPC and callback are done, so clone the ctx + // and kickstart the new one + ctx->StartNewClone(cli_cqs_[cq_[thread_idx]].get()); + delete ctx; + } + shutdown_mu->unlock(); + }, + &got_tag, &ok, gpr_inf_future(GPR_CLOCK_REALTIME))); } std::vector> cli_cqs_; diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc index 94554a46b2..9f20b148eb 100644 --- a/test/cpp/qps/client_sync.cc +++ b/test/cpp/qps/client_sync.cc @@ -62,6 +62,25 @@ class SynchronousClient virtual ~SynchronousClient(){}; + virtual void InitThreadFuncImpl(size_t thread_idx) = 0; + virtual bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) = 0; + + void ThreadFunc(size_t thread_idx, Thread* t) override { + InitThreadFuncImpl(thread_idx); + for (;;) { + // run the loop body + HistogramEntry entry; + const bool thread_still_ok = ThreadFuncImpl(&entry, thread_idx); + t->UpdateHistogram(&entry); + if (!thread_still_ok) { + gpr_log(GPR_ERROR, "Finishing client thread due to RPC error"); + } + if (!thread_still_ok || ThreadCompleted()) { + return; + } + } + } + protected: // WaitToIssue returns false if we realize that we need to break out bool WaitToIssue(int thread_idx) { @@ -103,9 +122,9 @@ class SynchronousUnaryClient final : public SynchronousClient { } ~SynchronousUnaryClient() {} - void InitThreadFunc(size_t thread_idx) override {} + void InitThreadFuncImpl(size_t thread_idx) override {} - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override { + bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override { if (!WaitToIssue(thread_idx)) { return true; } @@ -192,13 +211,13 @@ class SynchronousStreamingPingPongClient final } } - void InitThreadFunc(size_t thread_idx) override { + void InitThreadFuncImpl(size_t thread_idx) override { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]); messages_issued_[thread_idx] = 0; } - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override { + bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override { if (!WaitToIssue(thread_idx)) { return true; } @@ -246,14 +265,14 @@ class SynchronousStreamingFromClientClient final } } - void InitThreadFunc(size_t thread_idx) override { + void InitThreadFuncImpl(size_t thread_idx) override { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx], &responses_[thread_idx]); last_issue_[thread_idx] = UsageTimer::Now(); } - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override { + bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override { // Figure out how to make histogram sensible if this is rate-paced if (!WaitToIssue(thread_idx)) { return true; @@ -282,13 +301,13 @@ class SynchronousStreamingFromServerClient final public: SynchronousStreamingFromServerClient(const ClientConfig& config) : SynchronousStreamingClient(config), last_recv_(num_threads_) {} - void InitThreadFunc(size_t thread_idx) override { + void InitThreadFuncImpl(size_t thread_idx) override { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); stream_[thread_idx] = stub->StreamingFromServer(&context_[thread_idx], request_); last_recv_[thread_idx] = UsageTimer::Now(); } - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override { + bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override { GPR_TIMER_SCOPE("SynchronousStreamingFromServerClient::ThreadFunc", 0); if (stream_[thread_idx]->Read(&responses_[thread_idx])) { double now = UsageTimer::Now(); @@ -328,11 +347,11 @@ class SynchronousStreamingBothWaysClient final } } - void InitThreadFunc(size_t thread_idx) override { + void InitThreadFuncImpl(size_t thread_idx) override { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); stream_[thread_idx] = stub->StreamingBothWays(&context_[thread_idx]); } - bool ThreadFunc(HistogramEntry* entry, size_t thread_idx) override { + bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override { // TODO (vjpai): Do this return true; } diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 4a82f98199..c1097cb8ee 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -194,23 +194,32 @@ class AsyncQpsServerTest final : public grpc::testing::Server { // Wait until work is available or we are shutting down bool ok; void *got_tag; - while (srv_cqs_[cq_[thread_idx]]->Next(&got_tag, &ok)) { - ServerRpcContext *ctx = detag(got_tag); + if (!srv_cqs_[cq_[thread_idx]]->Next(&got_tag, &ok)) { + return; + } + ServerRpcContext *ctx; + std::mutex *mu_ptr; + do { + ctx = detag(got_tag); // The tag is a pointer to an RPC context to invoke // Proceed while holding a lock to make sure that // this thread isn't supposed to shut down - std::lock_guard l(shutdown_state_[thread_idx]->mutex); + mu_ptr = &shutdown_state_[thread_idx]->mutex; + mu_ptr->lock(); if (shutdown_state_[thread_idx]->shutdown) { + mu_ptr->unlock(); return; } - std::lock_guard l2(*ctx); - const bool still_going = ctx->RunNextState(ok); - // if this RPC context is done, refresh it - if (!still_going) { - ctx->Reset(); - } - } - return; + } while (srv_cqs_[cq_[thread_idx]]->DoThenAsyncNext( + [&, ctx, ok, mu_ptr]() { + ctx->lock(); + if (!ctx->RunNextState(ok)) { + ctx->Reset(); + } + ctx->unlock(); + mu_ptr->unlock(); + }, + &got_tag, &ok, gpr_inf_future(GPR_CLOCK_REALTIME))); } class ServerRpcContext { -- cgit v1.2.3 From 6e5ce7288da316a6ceee84bd071b6bbddec21495 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 27 Oct 2017 09:37:41 -0700 Subject: Assume that subchannels start in state IDLE. --- include/grpc/impl/codegen/connectivity_state.h | 2 -- .../client_channel/lb_policy/grpclb/grpclb.cc | 2 -- .../lb_policy/pick_first/pick_first.cc | 6 ++-- .../lb_policy/round_robin/round_robin.cc | 2 +- .../client_channel/lb_policy/subchannel_list.cc | 41 +++++----------------- .../client_channel/lb_policy/subchannel_list.h | 2 +- src/core/ext/filters/client_channel/subchannel.h | 4 +-- src/core/lib/transport/connectivity_state.cc | 3 -- test/cpp/end2end/client_lb_end2end_test.cc | 4 +-- 9 files changed, 18 insertions(+), 48 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/impl/codegen/connectivity_state.h b/include/grpc/impl/codegen/connectivity_state.h index 545b4fdbcc..b70dbef356 100644 --- a/include/grpc/impl/codegen/connectivity_state.h +++ b/include/grpc/impl/codegen/connectivity_state.h @@ -25,8 +25,6 @@ extern "C" { /** Connectivity state of a channel. */ typedef enum { - /** channel has just been initialized */ - GRPC_CHANNEL_INIT = -1, /** channel is idle */ GRPC_CHANNEL_IDLE, /** channel is connecting */ diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index d6bdc13ba9..85e76e68b5 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -611,7 +611,6 @@ static void update_lb_connectivity_status_locked( case GRPC_CHANNEL_SHUTDOWN: GPR_ASSERT(rr_state_error != GRPC_ERROR_NONE); break; - case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_READY: @@ -1790,7 +1789,6 @@ static void glb_lb_channel_on_connectivity_changed_cb(grpc_exec_ctx *exec_ctx, // embedded RR policy. Note that the current RR policy, if any, will stay in // effect until an update from the new lb_call is received. switch (glb_policy->lb_channel_connectivity) { - case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_TRANSIENT_FAILURE: { /* resub. */ diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 9b5b9217af..f0c66c68e1 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -312,6 +312,10 @@ static void pf_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, exec_ctx, p->subchannel_list, "pf_update_includes_selected"); } p->subchannel_list = subchannel_list; + if (p->selected->connected_subchannel != NULL) { + sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF( + p->selected->connected_subchannel, "pf_update_includes_selected"); + } p->selected = sd; destroy_unselected_subchannels_locked(exec_ctx, p); // If there was a previously pending update (which may or may @@ -442,8 +446,6 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, } while (true) { switch (sd->curr_connectivity_state) { - case GRPC_CHANNEL_INIT: - GPR_UNREACHABLE_CODE(return ); case GRPC_CHANNEL_READY: { // Case 2. Promote p->latest_pending_subchannel_list to // p->subchannel_list. diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 488fd3c0ac..8f29c80130 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -334,6 +334,7 @@ static void update_state_counters_locked(grpc_lb_subchannel_data *sd) { GPR_ASSERT(subchannel_list->num_idle > 0); --subchannel_list->num_idle; } + sd->prev_connectivity_state = sd->curr_connectivity_state; if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) { ++subchannel_list->num_ready; } else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { @@ -451,7 +452,6 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe; // Update state counters and determine new overall state. update_state_counters_locked(sd); - sd->prev_connectivity_state = sd->curr_connectivity_state; const grpc_connectivity_state new_policy_connectivity_state = update_lb_connectivity_status_locked(exec_ctx, sd, GRPC_ERROR_REF(error)); // If the sd's new state is SHUTDOWN, unref the subchannel, and if the new diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc index 831d8ac255..08ea4f480b 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc @@ -137,34 +137,13 @@ grpc_lb_subchannel_list *grpc_lb_subchannel_list_create( } continue; } - grpc_error *error; - // Get the connectivity state of the subchannel. Already existing ones may - // be in a state other than INIT. - const grpc_connectivity_state subchannel_connectivity_state = - grpc_subchannel_check_connectivity(subchannel, &error); - if (error != GRPC_ERROR_NONE) { - // The subchannel is in error (e.g. shutting down). Ignore it. - if (GRPC_TRACER_ON(*tracer)) { - char *address_uri = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); - gpr_log(GPR_DEBUG, - "[%s %p] subchannel for address uri %s shutting down, ignoring", - tracer->name, subchannel_list->policy, address_uri); - gpr_free(address_uri); - } - GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannel, "new_sc_connectivity_error"); - GRPC_ERROR_UNREF(error); - continue; - } if (GRPC_TRACER_ON(*tracer)) { char *address_uri = grpc_sockaddr_to_uri(&addresses->addresses[i].address); gpr_log(GPR_DEBUG, "[%s %p] subchannel list %p index %" PRIuPTR - ": Created subchannel %p for address uri %s; " - "initial connectivity state: %s", + ": Created subchannel %p for address uri %s", tracer->name, p, subchannel_list, subchannel_index, subchannel, - address_uri, - grpc_connectivity_state_name(subchannel_connectivity_state)); + address_uri); gpr_free(address_uri); } grpc_lb_subchannel_data *sd = @@ -174,16 +153,11 @@ grpc_lb_subchannel_list *grpc_lb_subchannel_list_create( GRPC_CLOSURE_INIT(&sd->connectivity_changed_closure, connectivity_changed_cb, sd, grpc_combiner_scheduler(args->combiner)); - // Use some sentinel value outside of the range of - // grpc_connectivity_state to signal an undefined previous state. - sd->prev_connectivity_state = GRPC_CHANNEL_INIT; - sd->curr_connectivity_state = subchannel_connectivity_state; - sd->pending_connectivity_state_unsafe = subchannel_connectivity_state; - if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) { - sd->connected_subchannel = GRPC_CONNECTED_SUBCHANNEL_REF( - grpc_subchannel_get_connected_subchannel(sd->subchannel), - "ready_at_sl_creation"); - } + // We assume that the current state is IDLE. If not, we'll get a + // callback telling us that. + sd->prev_connectivity_state = GRPC_CHANNEL_IDLE; + sd->curr_connectivity_state = GRPC_CHANNEL_IDLE; + sd->pending_connectivity_state_unsafe = GRPC_CHANNEL_IDLE; sd->user_data_vtable = addresses->user_data_vtable; if (sd->user_data_vtable != NULL) { sd->user_data = @@ -191,6 +165,7 @@ grpc_lb_subchannel_list *grpc_lb_subchannel_list_create( } } subchannel_list->num_subchannels = subchannel_index; + subchannel_list->num_idle = subchannel_index; return subchannel_list; } diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 7ad22302ce..9d5984260f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -97,7 +97,7 @@ struct grpc_lb_subchannel_list { /** Index into subchannels of the one we're currently checking. * Used when connecting to subchannels serially instead of in parallel. */ // TODO(roth): When we have time, we can probably make this go away - // and the index dynamically by subtracting + // and compute the index dynamically by subtracting // subchannel_list->subchannels from the subchannel_data pointer. size_t checking_subchannel; diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 46b29f1fe0..1cd73f3ff4 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -127,8 +127,8 @@ void grpc_connected_subchannel_process_transport_op( grpc_connectivity_state grpc_subchannel_check_connectivity( grpc_subchannel *channel, grpc_error **error); -/** call notify when the connectivity state of a channel changes from *state. - Updates *state with the new state of the channel */ +/** Calls notify when the connectivity state of a channel becomes different + from *state. Updates *state with the new state of the channel. */ void grpc_subchannel_notify_on_state_change( grpc_exec_ctx *exec_ctx, grpc_subchannel *channel, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc index f328a6cdbb..652c26cf0a 100644 --- a/src/core/lib/transport/connectivity_state.cc +++ b/src/core/lib/transport/connectivity_state.cc @@ -29,8 +29,6 @@ grpc_tracer_flag grpc_connectivity_state_trace = const char *grpc_connectivity_state_name(grpc_connectivity_state state) { switch (state) { - case GRPC_CHANNEL_INIT: - return "INIT"; case GRPC_CHANNEL_IDLE: return "IDLE"; case GRPC_CHANNEL_CONNECTING: @@ -174,7 +172,6 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_name(state), reason, error, error_string); } switch (state) { - case GRPC_CHANNEL_INIT: case GRPC_CHANNEL_CONNECTING: case GRPC_CHANNEL_IDLE: case GRPC_CHANNEL_READY: diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index c236f76e89..805e5b1045 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -305,7 +305,7 @@ TEST_F(ClientLbEnd2endTest, PickFirstUpdates) { ports.clear(); SetNextResolution(ports); gpr_log(GPR_INFO, "****** SET none *******"); - grpc_connectivity_state channel_state = GRPC_CHANNEL_INIT; + grpc_connectivity_state channel_state; do { channel_state = channel_->GetState(true /* try to connect */); } while (channel_state == GRPC_CHANNEL_READY); @@ -481,7 +481,7 @@ TEST_F(ClientLbEnd2endTest, RoundRobinUpdates) { // An empty update will result in the channel going into TRANSIENT_FAILURE. ports.clear(); SetNextResolution(ports); - grpc_connectivity_state channel_state = GRPC_CHANNEL_INIT; + grpc_connectivity_state channel_state; do { channel_state = channel_->GetState(true /* try to connect */); } while (channel_state == GRPC_CHANNEL_READY); -- cgit v1.2.3 From c1d354d7f2621f467e2f37f36498c20e132c3a72 Mon Sep 17 00:00:00 2001 From: Justin Burke Date: Tue, 19 Sep 2017 15:06:01 -0700 Subject: Support SSL server certificate reloading. --- grpc.def | 6 + include/grpc/grpc_security.h | 74 +++++- include/grpc/grpc_security_constants.h | 7 + .../security/credentials/ssl/ssl_credentials.cc | 156 ++++++++++++- .../lib/security/credentials/ssl/ssl_credentials.h | 12 + .../lib/security/transport/security_connector.cc | 251 +++++++++++++++------ .../lib/security/transport/security_connector.h | 4 +- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 12 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 18 ++ 9 files changed, 456 insertions(+), 84 deletions(-) (limited to 'src/core/lib') diff --git a/grpc.def b/grpc.def index e4281f3ab6..eea12bdda5 100644 --- a/grpc.def +++ b/grpc.def @@ -132,8 +132,14 @@ EXPORTS grpc_metadata_credentials_create_from_plugin grpc_secure_channel_create grpc_server_credentials_release + grpc_ssl_server_certificate_config_create + grpc_ssl_server_certificate_config_destroy grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_ex + grpc_ssl_server_credentials_create_options_using_config + grpc_ssl_server_credentials_create_options_using_config_fetcher + grpc_ssl_server_credentials_options_destroy + grpc_ssl_server_credentials_create_with_options grpc_server_add_secure_http2_port grpc_call_set_credentials grpc_server_credentials_set_auth_metadata_processor diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 95b1447935..758aaf5b6c 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -316,6 +316,43 @@ typedef struct grpc_server_credentials grpc_server_credentials; */ GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds); +/** Server certificate config object holds the server's public certificates and + associated private keys, as well as any CA certificates needed for client + certificate validation (if applicable). Create using + grpc_ssl_server_certificate_config_create(). */ +typedef struct grpc_ssl_server_certificate_config + grpc_ssl_server_certificate_config; + +/** Creates a grpc_ssl_server_certificate_config object. + - pem_roots_cert is the NULL-terminated string containing the PEM encoding of + the client root certificates. This parameter may be NULL if the server does + not want the client to be authenticated with SSL. + - pem_key_cert_pairs is an array private key / certificate chains of the + server. This parameter cannot be NULL. + - num_key_cert_pairs indicates the number of items in the private_key_files + and cert_chain_files parameters. It must be at least 1. + - It is the caller's responsibility to free this object via + grpc_ssl_server_certificate_config_destroy(). */ +GRPCAPI grpc_ssl_server_certificate_config * +grpc_ssl_server_certificate_config_create( + const char *pem_root_certs, + const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs); + +/** Destroys a grpc_ssl_server_certificate_config object. */ +GRPCAPI void grpc_ssl_server_certificate_config_destroy( + grpc_ssl_server_certificate_config *config); + +/** Callback to retrieve updated SSL server certificates, private keys, and + trusted CAs (for client authentication). + - user_data parameter, if not NULL, contains opaque data to be used by the + callback. + - Use grpc_ssl_server_certificate_config_create to create the config. + - The caller assumes ownership of the config. */ +typedef grpc_ssl_certificate_config_reload_status ( + *grpc_ssl_server_certificate_config_callback)( + void *user_data, grpc_ssl_server_certificate_config **config); + /** Deprecated in favor of grpc_ssl_server_credentials_create_ex. Creates an SSL server_credentials object. - pem_roots_cert is the NULL-terminated string containing the PEM encoding of @@ -332,7 +369,8 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved); -/** Same as grpc_ssl_server_credentials_create method except uses +/** Deprecated in favor of grpc_ssl_server_credentials_create_with_options. + Same as grpc_ssl_server_credentials_create method except uses grpc_ssl_client_certificate_request_type enum to support more ways to authenticate client cerificates.*/ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex( @@ -341,6 +379,40 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex( grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved); +typedef struct grpc_ssl_server_credentials_options + grpc_ssl_server_credentials_options; + +/** Creates an options object using a certificate config. Use this method when + the certificates and keys of the SSL server will not change during the + server's lifetime. + - Takes ownership of the certificate_config parameter. */ +GRPCAPI grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config *certificate_config); + +/** Creates an options object using a certificate config fetcher. Use this + method to reload the certificates and keys of the SSL server without + interrupting the operation of the server. Initial certificate config will be + fetched during server initialization. + - user_data parameter, if not NULL, contains opaque data which will be passed + to the fetcher (see definition of + grpc_ssl_server_certificate_config_callback). */ +GRPCAPI grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config_fetcher( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config_callback cb, void *user_data); + +/** Destroys a grpc_ssl_server_credentials_options object. */ +GRPCAPI void grpc_ssl_server_credentials_options_destroy( + grpc_ssl_server_credentials_options *options); + +/** Creates an SSL server_credentials object using the provided options struct. + - Takes ownership of the options parameter. */ +GRPCAPI grpc_server_credentials * +grpc_ssl_server_credentials_create_with_options( + grpc_ssl_server_credentials_options *options); + /** --- Server-side secure ports. --- */ /** Add a HTTP2 over an encrypted link over tcp listener. diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h index fde300dfb1..60e167eb88 100644 --- a/include/grpc/grpc_security_constants.h +++ b/include/grpc/grpc_security_constants.h @@ -48,6 +48,13 @@ typedef enum { GRPC_SSL_ROOTS_OVERRIDE_FAIL } grpc_ssl_roots_override_result; +/** Callback results for dynamically loading a SSL certificate config. */ +typedef enum { + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED, + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW, + GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_FAIL +} grpc_ssl_certificate_config_reload_status; + typedef enum { /** Server does not request client certificate. A client can present a self signed or signed certificates if it wishes to do so and they would be diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc index 8e47aebedb..2085e2b8e7 100644 --- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc @@ -119,6 +119,12 @@ grpc_channel_credentials *grpc_ssl_credentials_create( // SSL Server Credentials. // +struct grpc_ssl_server_credentials_options { + grpc_ssl_client_certificate_request_type client_certificate_request; + grpc_ssl_server_certificate_config *certificate_config; + grpc_ssl_server_certificate_config_fetcher *certificate_config_fetcher; +}; + static void ssl_server_destruct(grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds) { grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; @@ -130,9 +136,7 @@ static void ssl_server_destruct(grpc_exec_ctx *exec_ctx, static grpc_security_status ssl_server_create_security_connector( grpc_exec_ctx *exec_ctx, grpc_server_credentials *creds, grpc_server_security_connector **sc) { - grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; - return grpc_ssl_server_security_connector_create(exec_ctx, creds, &c->config, - sc); + return grpc_ssl_server_security_connector_create(exec_ctx, creds, sc); } static grpc_server_credentials_vtable ssl_server_vtable = { @@ -170,6 +174,86 @@ static void ssl_build_server_config( config->num_key_cert_pairs = num_key_cert_pairs; } +grpc_ssl_server_certificate_config *grpc_ssl_server_certificate_config_create( + const char *pem_root_certs, + const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs) { + grpc_ssl_server_certificate_config *config = + (grpc_ssl_server_certificate_config *)gpr_zalloc( + sizeof(grpc_ssl_server_certificate_config)); + if (pem_root_certs != NULL) { + config->pem_root_certs = gpr_strdup(pem_root_certs); + } + if (num_key_cert_pairs > 0) { + GPR_ASSERT(pem_key_cert_pairs != NULL); + config->pem_key_cert_pairs = (grpc_ssl_pem_key_cert_pair *)gpr_zalloc( + num_key_cert_pairs * sizeof(grpc_ssl_pem_key_cert_pair)); + } + config->num_key_cert_pairs = num_key_cert_pairs; + for (size_t i = 0; i < num_key_cert_pairs; i++) { + GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); + GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); + config->pem_key_cert_pairs[i].cert_chain = + gpr_strdup(pem_key_cert_pairs[i].cert_chain); + config->pem_key_cert_pairs[i].private_key = + gpr_strdup(pem_key_cert_pairs[i].private_key); + } + return config; +} + +void grpc_ssl_server_certificate_config_destroy( + grpc_ssl_server_certificate_config *config) { + if (config == NULL) return; + for (size_t i = 0; i < config->num_key_cert_pairs; i++) { + gpr_free((void *)config->pem_key_cert_pairs[i].private_key); + gpr_free((void *)config->pem_key_cert_pairs[i].cert_chain); + } + gpr_free(config->pem_key_cert_pairs); + gpr_free(config->pem_root_certs); + gpr_free(config); +} + +grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config *config) { + grpc_ssl_server_credentials_options *options = NULL; + if (config == NULL) { + gpr_log(GPR_ERROR, "Certificate config must not be NULL."); + goto done; + } + options = (grpc_ssl_server_credentials_options *)gpr_zalloc( + sizeof(grpc_ssl_server_credentials_options)); + options->client_certificate_request = client_certificate_request; + options->certificate_config = config; +done: + return options; +} + +grpc_ssl_server_credentials_options * +grpc_ssl_server_credentials_create_options_using_config_fetcher( + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_certificate_config_callback cb, void *user_data) { + if (cb == NULL) { + gpr_log(GPR_ERROR, "Invalid certificate config callback parameter."); + return NULL; + } + + grpc_ssl_server_certificate_config_fetcher *fetcher = + (grpc_ssl_server_certificate_config_fetcher *)gpr_zalloc( + sizeof(grpc_ssl_server_certificate_config_fetcher)); + fetcher->cb = cb; + fetcher->user_data = user_data; + + grpc_ssl_server_credentials_options *options = + (grpc_ssl_server_credentials_options *)gpr_zalloc( + sizeof(grpc_ssl_server_credentials_options)); + options->client_certificate_request = client_certificate_request; + options->certificate_config_fetcher = fetcher; + + return options; +} + grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved) { @@ -186,8 +270,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create_ex( size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved) { - grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)gpr_zalloc( - sizeof(grpc_ssl_server_credentials)); GRPC_API_TRACE( "grpc_ssl_server_credentials_create_ex(" "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, " @@ -195,11 +277,67 @@ grpc_server_credentials *grpc_ssl_server_credentials_create_ex( 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs, client_certificate_request, reserved)); GPR_ASSERT(reserved == NULL); + + grpc_ssl_server_certificate_config *cert_config = + grpc_ssl_server_certificate_config_create( + pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs); + grpc_ssl_server_credentials_options *options = + grpc_ssl_server_credentials_create_options_using_config( + client_certificate_request, cert_config); + + return grpc_ssl_server_credentials_create_with_options(options); +} + +grpc_server_credentials *grpc_ssl_server_credentials_create_with_options( + grpc_ssl_server_credentials_options *options) { + grpc_server_credentials *retval = NULL; + grpc_ssl_server_credentials *c = NULL; + + if (options == NULL) { + gpr_log(GPR_ERROR, + "Invalid options trying to create SSL server credentials."); + goto done; + } + + if (options->certificate_config == NULL && + options->certificate_config_fetcher == NULL) { + gpr_log(GPR_ERROR, + "SSL server credentials options must specify either " + "certificate config or fetcher."); + goto done; + } else if (options->certificate_config_fetcher != NULL && + options->certificate_config_fetcher->cb == NULL) { + gpr_log(GPR_ERROR, "Certificate config fetcher callback must not be NULL."); + goto done; + } + + c = (grpc_ssl_server_credentials *)gpr_zalloc( + sizeof(grpc_ssl_server_credentials)); c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &ssl_server_vtable; - ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, - num_key_cert_pairs, client_certificate_request, - &c->config); - return &c->base; + + if (options->certificate_config_fetcher != NULL) { + c->config.client_certificate_request = options->client_certificate_request; + c->certificate_config_fetcher = *options->certificate_config_fetcher; + } else { + ssl_build_server_config(options->certificate_config->pem_root_certs, + options->certificate_config->pem_key_cert_pairs, + options->certificate_config->num_key_cert_pairs, + options->client_certificate_request, &c->config); + } + + retval = &c->base; + +done: + grpc_ssl_server_credentials_options_destroy(options); + return retval; +} + +void grpc_ssl_server_credentials_options_destroy( + grpc_ssl_server_credentials_options *o) { + if (o == NULL) return; + gpr_free(o->certificate_config_fetcher); + grpc_ssl_server_certificate_config_destroy(o->certificate_config); + gpr_free(o); } diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.h b/src/core/lib/security/credentials/ssl/ssl_credentials.h index 42e425d9f1..5542484aae 100644 --- a/src/core/lib/security/credentials/ssl/ssl_credentials.h +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.h @@ -29,9 +29,21 @@ typedef struct { grpc_ssl_config config; } grpc_ssl_credentials; +struct grpc_ssl_server_certificate_config { + grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs; + size_t num_key_cert_pairs; + char *pem_root_certs; +}; + +typedef struct { + grpc_ssl_server_certificate_config_callback cb; + void *user_data; +} grpc_ssl_server_certificate_config_fetcher; + typedef struct { grpc_server_credentials base; grpc_ssl_server_config config; + grpc_ssl_server_certificate_config_fetcher certificate_config_fetcher; } grpc_ssl_server_credentials; tsi_ssl_pem_key_cert_pair *grpc_convert_grpc_to_tsi_cert_pairs( diff --git a/src/core/lib/security/transport/security_connector.cc b/src/core/lib/security/transport/security_connector.cc index b050be2129..06160d0caa 100644 --- a/src/core/lib/security/transport/security_connector.cc +++ b/src/core/lib/security/transport/security_connector.cc @@ -34,6 +34,7 @@ #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" #include "src/core/lib/security/transport/lb_targets_info.h" #include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/security/transport/security_handshaker.h" @@ -277,6 +278,30 @@ grpc_security_connector *grpc_security_connector_find_in_args( return NULL; } +static tsi_client_certificate_request_type +get_tsi_client_certificate_request_type( + grpc_ssl_client_certificate_request_type grpc_request_type) { + switch (grpc_request_type) { + case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; + + default: + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + } +} + /* -- Fake implementation. -- */ typedef struct { @@ -533,6 +558,15 @@ typedef struct { tsi_ssl_server_handshaker_factory *server_handshaker_factory; } grpc_ssl_server_security_connector; +static bool server_connector_has_cert_config_fetcher( + grpc_ssl_server_security_connector *c) { + GPR_ASSERT(c != NULL); + grpc_ssl_server_credentials *server_creds = + (grpc_ssl_server_credentials *)c->base.server_creds; + GPR_ASSERT(server_creds != NULL); + return server_creds->certificate_config_fetcher.cb != NULL; +} + static void ssl_channel_destroy(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc) { grpc_ssl_channel_security_connector *c = @@ -573,7 +607,6 @@ static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx, tsi_result_to_string(result)); return; } - // Create handshakers. grpc_handshake_manager_add( handshake_mgr, @@ -581,12 +614,102 @@ static void ssl_channel_add_handshakers(grpc_exec_ctx *exec_ctx, exec_ctx, tsi_create_adapter_handshaker(tsi_hs), &sc->base)); } +static const char **fill_alpn_protocol_strings(size_t *num_alpn_protocols) { + GPR_ASSERT(num_alpn_protocols != NULL); + *num_alpn_protocols = grpc_chttp2_num_alpn_versions(); + const char **alpn_protocol_strings = + (const char **)gpr_malloc(sizeof(const char *) * (*num_alpn_protocols)); + for (size_t i = 0; i < *num_alpn_protocols; i++) { + alpn_protocol_strings[i] = grpc_chttp2_get_alpn_version_index(i); + } + return alpn_protocol_strings; +} + +/* Attempts to replace the server_handshaker_factory with a new factory using + * the provided grpc_ssl_server_certificate_config. Should new factory creation + * fail, the existing factory will not be replaced. Returns true on success (new + * factory created). */ +static bool try_replace_server_handshaker_factory( + grpc_ssl_server_security_connector *sc, + const grpc_ssl_server_certificate_config *config) { + if (config == NULL) { + gpr_log(GPR_ERROR, + "Server certificate config callback returned invalid (NULL) " + "config."); + return false; + } + gpr_log(GPR_DEBUG, "Using new server certificate config (%p).", config); + + size_t num_alpn_protocols = 0; + const char **alpn_protocol_strings = + fill_alpn_protocol_strings(&num_alpn_protocols); + tsi_ssl_pem_key_cert_pair *cert_pairs = grpc_convert_grpc_to_tsi_cert_pairs( + config->pem_key_cert_pairs, config->num_key_cert_pairs); + tsi_ssl_server_handshaker_factory *new_handshaker_factory = NULL; + grpc_ssl_server_credentials *server_creds = + (grpc_ssl_server_credentials *)sc->base.server_creds; + tsi_result result = tsi_create_ssl_server_handshaker_factory_ex( + cert_pairs, config->num_key_cert_pairs, config->pem_root_certs, + get_tsi_client_certificate_request_type( + server_creds->config.client_certificate_request), + ssl_cipher_suites(), alpn_protocol_strings, (uint16_t)num_alpn_protocols, + &new_handshaker_factory); + gpr_free(cert_pairs); + gpr_free((void *)alpn_protocol_strings); + + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + return false; + } + tsi_ssl_server_handshaker_factory_unref(sc->server_handshaker_factory); + sc->server_handshaker_factory = new_handshaker_factory; + return true; +} + +/* Attempts to fetch the server certificate config if a callback is available. + * Current certificate config will continue to be used if the callback returns + * an error. Returns true if new credentials were sucessfully loaded. */ +static bool try_fetch_ssl_server_credentials( + grpc_ssl_server_security_connector *sc) { + grpc_ssl_server_certificate_config *certificate_config = NULL; + bool status; + + GPR_ASSERT(sc != NULL); + if (!server_connector_has_cert_config_fetcher(sc)) return false; + + grpc_ssl_server_credentials *server_creds = + (grpc_ssl_server_credentials *)sc->base.server_creds; + grpc_ssl_certificate_config_reload_status cb_result = + server_creds->certificate_config_fetcher.cb( + server_creds->certificate_config_fetcher.user_data, + &certificate_config); + if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_UNCHANGED) { + gpr_log(GPR_DEBUG, "No change in SSL server credentials."); + status = false; + } else if (cb_result == GRPC_SSL_CERTIFICATE_CONFIG_RELOAD_NEW) { + status = try_replace_server_handshaker_factory(sc, certificate_config); + } else { + // Log error, continue using previously-loaded credentials. + gpr_log(GPR_ERROR, + "Failed fetching new server credentials, continuing to " + "use previously-loaded credentials."); + status = false; + } + + if (certificate_config != NULL) { + grpc_ssl_server_certificate_config_destroy(certificate_config); + } + return status; +} + static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, grpc_handshake_manager *handshake_mgr) { grpc_ssl_server_security_connector *c = (grpc_ssl_server_security_connector *)sc; // Instantiate TSI handshaker. + try_fetch_ssl_server_credentials(c); tsi_handshaker *tsi_hs = NULL; tsi_result result = tsi_ssl_server_handshaker_factory_create_handshaker( c->server_handshaker_factory, &tsi_hs); @@ -595,7 +718,6 @@ static void ssl_server_add_handshakers(grpc_exec_ctx *exec_ctx, tsi_result_to_string(result)); return; } - // Create handshakers. grpc_handshake_manager_add( handshake_mgr, @@ -857,31 +979,6 @@ grpc_slice grpc_get_default_ssl_roots_for_testing(void) { return compute_default_pem_root_certs_once(); } -static tsi_client_certificate_request_type -get_tsi_client_certificate_request_type( - grpc_ssl_client_certificate_request_type grpc_request_type) { - switch (grpc_request_type) { - case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; - - default: - // Is this a sane default - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - } -} - const char *grpc_get_default_ssl_roots(void) { /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in loading all the roots once for the lifetime of the process. */ @@ -897,18 +994,14 @@ grpc_security_status grpc_ssl_channel_security_connector_create( grpc_call_credentials *request_metadata_creds, const grpc_ssl_config *config, const char *target_name, const char *overridden_target_name, grpc_channel_security_connector **sc) { - size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); + size_t num_alpn_protocols = 0; const char **alpn_protocol_strings = - (const char **)gpr_malloc(sizeof(const char *) * num_alpn_protocols); + fill_alpn_protocol_strings(&num_alpn_protocols); tsi_result result = TSI_OK; grpc_ssl_channel_security_connector *c; - size_t i; const char *pem_root_certs; char *port; bool has_key_cert_pair; - for (i = 0; i < num_alpn_protocols; i++) { - alpn_protocol_strings[i] = grpc_chttp2_get_alpn_version_index(i); - } if (config == NULL || target_name == NULL) { gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); @@ -965,50 +1058,64 @@ error: return GRPC_SECURITY_ERROR; } +static grpc_ssl_server_security_connector * +grpc_ssl_server_security_connector_initialize( + grpc_server_credentials *server_creds) { + grpc_ssl_server_security_connector *c = + (grpc_ssl_server_security_connector *)gpr_zalloc( + sizeof(grpc_ssl_server_security_connector)); + gpr_ref_init(&c->base.base.refcount, 1); + c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; + c->base.base.vtable = &ssl_server_vtable; + c->base.add_handshakers = ssl_server_add_handshakers; + c->base.server_creds = grpc_server_credentials_ref(server_creds); + return c; +} + grpc_security_status grpc_ssl_server_security_connector_create( - grpc_exec_ctx *exec_ctx, grpc_server_credentials *server_creds, - const grpc_ssl_server_config *config, grpc_server_security_connector **sc) { - size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); - const char **alpn_protocol_strings = - (const char **)gpr_malloc(sizeof(const char *) * num_alpn_protocols); + grpc_exec_ctx *exec_ctx, grpc_server_credentials *gsc, + grpc_server_security_connector **sc) { tsi_result result = TSI_OK; - grpc_ssl_server_security_connector *c; - size_t i; + grpc_ssl_server_credentials *server_credentials = + (grpc_ssl_server_credentials *)gsc; + grpc_security_status retval = GRPC_SECURITY_OK; - for (i = 0; i < num_alpn_protocols; i++) { - alpn_protocol_strings[i] = grpc_chttp2_get_alpn_version_index(i); - } + GPR_ASSERT(server_credentials != NULL); + GPR_ASSERT(sc != NULL); - if (config == NULL || config->num_key_cert_pairs == 0) { - gpr_log(GPR_ERROR, "An SSL server needs a key and a cert."); - goto error; + grpc_ssl_server_security_connector *c = + grpc_ssl_server_security_connector_initialize(gsc); + if (server_connector_has_cert_config_fetcher(c)) { + // Load initial credentials from certificate_config_fetcher: + if (!try_fetch_ssl_server_credentials(c)) { + gpr_log(GPR_ERROR, "Failed loading SSL server credentials from fetcher."); + retval = GRPC_SECURITY_ERROR; + } + } else { + size_t num_alpn_protocols = 0; + const char **alpn_protocol_strings = + fill_alpn_protocol_strings(&num_alpn_protocols); + result = tsi_create_ssl_server_handshaker_factory_ex( + server_credentials->config.pem_key_cert_pairs, + server_credentials->config.num_key_cert_pairs, + server_credentials->config.pem_root_certs, + get_tsi_client_certificate_request_type( + server_credentials->config.client_certificate_request), + ssl_cipher_suites(), alpn_protocol_strings, + (uint16_t)num_alpn_protocols, &c->server_handshaker_factory); + gpr_free((void *)alpn_protocol_strings); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + retval = GRPC_SECURITY_ERROR; + } } - c = (grpc_ssl_server_security_connector *)gpr_zalloc( - sizeof(grpc_ssl_server_security_connector)); - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.base.vtable = &ssl_server_vtable; - c->base.server_creds = grpc_server_credentials_ref(server_creds); - result = tsi_create_ssl_server_handshaker_factory_ex( - config->pem_key_cert_pairs, config->num_key_cert_pairs, - config->pem_root_certs, get_tsi_client_certificate_request_type( - config->client_certificate_request), - ssl_cipher_suites(), alpn_protocol_strings, (uint16_t)num_alpn_protocols, - &c->server_handshaker_factory); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - ssl_server_destroy(exec_ctx, &c->base.base); - *sc = NULL; - goto error; + if (retval == GRPC_SECURITY_OK) { + *sc = &c->base; + } else { + if (c != NULL) ssl_server_destroy(exec_ctx, &c->base.base); + if (sc != NULL) *sc = NULL; } - c->base.add_handshakers = ssl_server_add_handshakers; - *sc = &c->base; - gpr_free((void *)alpn_protocol_strings); - return GRPC_SECURITY_OK; - -error: - gpr_free((void *)alpn_protocol_strings); - return GRPC_SECURITY_ERROR; + return retval; } diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h index 8287151f44..54a563bb2c 100644 --- a/src/core/lib/security/transport/security_connector.h +++ b/src/core/lib/security/transport/security_connector.h @@ -248,8 +248,8 @@ typedef struct { specific error code otherwise. */ grpc_security_status grpc_ssl_server_security_connector_create( - grpc_exec_ctx *exec_ctx, grpc_server_credentials *server_creds, - const grpc_ssl_server_config *config, grpc_server_security_connector **sc); + grpc_exec_ctx *exec_ctx, grpc_server_credentials *server_credentials, + grpc_server_security_connector **sc); /* Util. */ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index cd1bd98abc..843e05ab66 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -155,8 +155,14 @@ grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_impor 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; +grpc_ssl_server_certificate_config_create_type grpc_ssl_server_certificate_config_create_import; +grpc_ssl_server_certificate_config_destroy_type grpc_ssl_server_certificate_config_destroy_import; grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import; grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import; +grpc_ssl_server_credentials_create_options_using_config_type grpc_ssl_server_credentials_create_options_using_config_import; +grpc_ssl_server_credentials_create_options_using_config_fetcher_type grpc_ssl_server_credentials_create_options_using_config_fetcher_import; +grpc_ssl_server_credentials_options_destroy_type grpc_ssl_server_credentials_options_destroy_import; +grpc_ssl_server_credentials_create_with_options_type grpc_ssl_server_credentials_create_with_options_import; grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; grpc_call_set_credentials_type grpc_call_set_credentials_import; grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; @@ -465,8 +471,14 @@ void grpc_rb_load_imports(HMODULE library) { 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"); + grpc_ssl_server_certificate_config_create_import = (grpc_ssl_server_certificate_config_create_type) GetProcAddress(library, "grpc_ssl_server_certificate_config_create"); + grpc_ssl_server_certificate_config_destroy_import = (grpc_ssl_server_certificate_config_destroy_type) GetProcAddress(library, "grpc_ssl_server_certificate_config_destroy"); grpc_ssl_server_credentials_create_import = (grpc_ssl_server_credentials_create_type) GetProcAddress(library, "grpc_ssl_server_credentials_create"); grpc_ssl_server_credentials_create_ex_import = (grpc_ssl_server_credentials_create_ex_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_ex"); + grpc_ssl_server_credentials_create_options_using_config_import = (grpc_ssl_server_credentials_create_options_using_config_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_options_using_config"); + grpc_ssl_server_credentials_create_options_using_config_fetcher_import = (grpc_ssl_server_credentials_create_options_using_config_fetcher_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_options_using_config_fetcher"); + grpc_ssl_server_credentials_options_destroy_import = (grpc_ssl_server_credentials_options_destroy_type) GetProcAddress(library, "grpc_ssl_server_credentials_options_destroy"); + grpc_ssl_server_credentials_create_with_options_import = (grpc_ssl_server_credentials_create_with_options_type) GetProcAddress(library, "grpc_ssl_server_credentials_create_with_options"); grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port"); grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials"); grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index c7e78b70dc..998eef800e 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -446,12 +446,30 @@ extern grpc_secure_channel_create_type grpc_secure_channel_create_import; typedef void(*grpc_server_credentials_release_type)(grpc_server_credentials *creds); extern grpc_server_credentials_release_type grpc_server_credentials_release_import; #define grpc_server_credentials_release grpc_server_credentials_release_import +typedef grpc_ssl_server_certificate_config *(*grpc_ssl_server_certificate_config_create_type)(const char *pem_root_certs, const grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs); +extern grpc_ssl_server_certificate_config_create_type grpc_ssl_server_certificate_config_create_import; +#define grpc_ssl_server_certificate_config_create grpc_ssl_server_certificate_config_create_import +typedef void(*grpc_ssl_server_certificate_config_destroy_type)(grpc_ssl_server_certificate_config *config); +extern grpc_ssl_server_certificate_config_destroy_type grpc_ssl_server_certificate_config_destroy_import; +#define grpc_ssl_server_certificate_config_destroy grpc_ssl_server_certificate_config_destroy_import typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, int force_client_auth, void *reserved); extern grpc_ssl_server_credentials_create_type grpc_ssl_server_credentials_create_import; #define grpc_ssl_server_credentials_create grpc_ssl_server_credentials_create_import typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_ex_type)(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, size_t num_key_cert_pairs, grpc_ssl_client_certificate_request_type client_certificate_request, void *reserved); extern grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex_import; #define grpc_ssl_server_credentials_create_ex grpc_ssl_server_credentials_create_ex_import +typedef grpc_ssl_server_credentials_options *(*grpc_ssl_server_credentials_create_options_using_config_type)(grpc_ssl_client_certificate_request_type client_certificate_request, grpc_ssl_server_certificate_config *certificate_config); +extern grpc_ssl_server_credentials_create_options_using_config_type grpc_ssl_server_credentials_create_options_using_config_import; +#define grpc_ssl_server_credentials_create_options_using_config grpc_ssl_server_credentials_create_options_using_config_import +typedef grpc_ssl_server_credentials_options *(*grpc_ssl_server_credentials_create_options_using_config_fetcher_type)(grpc_ssl_client_certificate_request_type client_certificate_request, grpc_ssl_server_certificate_config_callback cb, void *user_data); +extern grpc_ssl_server_credentials_create_options_using_config_fetcher_type grpc_ssl_server_credentials_create_options_using_config_fetcher_import; +#define grpc_ssl_server_credentials_create_options_using_config_fetcher grpc_ssl_server_credentials_create_options_using_config_fetcher_import +typedef void(*grpc_ssl_server_credentials_options_destroy_type)(grpc_ssl_server_credentials_options *options); +extern grpc_ssl_server_credentials_options_destroy_type grpc_ssl_server_credentials_options_destroy_import; +#define grpc_ssl_server_credentials_options_destroy grpc_ssl_server_credentials_options_destroy_import +typedef grpc_server_credentials *(*grpc_ssl_server_credentials_create_with_options_type)(grpc_ssl_server_credentials_options *options); +extern grpc_ssl_server_credentials_create_with_options_type grpc_ssl_server_credentials_create_with_options_import; +#define grpc_ssl_server_credentials_create_with_options grpc_ssl_server_credentials_create_with_options_import typedef int(*grpc_server_add_secure_http2_port_type)(grpc_server *server, const char *addr, grpc_server_credentials *creds); extern grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; #define grpc_server_add_secure_http2_port grpc_server_add_secure_http2_port_import -- cgit v1.2.3 From 0961509ebf95263d89fdfa789248be401cbc56ac Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 31 Oct 2017 17:48:01 -0700 Subject: Add missing kick counter increment --- src/core/lib/iomgr/ev_epollex_linux.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index fa6d79cbfc..0809d574a9 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -577,7 +577,6 @@ static grpc_error *kick_one_worker(grpc_exec_ctx *exec_ctx, grpc_pollset_worker *specific_worker) { pollable *p = specific_worker->pollable_obj; grpc_core::mu_guard lock(&p->mu); - GRPC_STATS_INC_POLLSET_KICK(exec_ctx); GPR_ASSERT(specific_worker != NULL); if (specific_worker->kicked) { if (GRPC_TRACER_ON(grpc_polling_trace)) { @@ -619,6 +618,7 @@ static grpc_error *kick_one_worker(grpc_exec_ctx *exec_ctx, static grpc_error *pollset_kick(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *specific_worker) { + GRPC_STATS_INC_POLLSET_KICK(exec_ctx); if (GRPC_TRACER_ON(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "PS:%p kick %p tls_pollset=%p tls_worker=%p pollset.root_worker=%p", @@ -674,6 +674,7 @@ static grpc_error *pollset_kick_all(grpc_exec_ctx *exec_ctx, grpc_pollset_worker *w = pollset->root_worker; if (w != NULL) { do { + GRPC_STATS_INC_POLLSET_KICK(exec_ctx); append_error(&error, kick_one_worker(exec_ctx, w), err_desc); w = w->links[PWLINK_POLLSET].next; } while (w != pollset->root_worker); -- cgit v1.2.3